Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Athena: Add LLM token usage tracking #9554

Conversation

FelixTJDietrich
Copy link
Contributor

@FelixTJDietrich FelixTJDietrich commented Oct 21, 2024

Checklist

General

Server

  • Important: I implemented the changes with a very good performance and prevented too many (unnecessary) and too complex database calls.
  • I strictly followed the principle of data economy for all database calls.
  • I strictly followed the server coding and design guidelines.
  • I added multiple integration tests (Spring) related to the features (with a high test coverage).
  • I added pre-authorization annotations according to the guidelines and checked the course groups for all new REST Calls (security).
  • I documented the Java code using JavaDoc style.

Motivation

We want to track the token usage for Athena.

Description

Stores token usage of Athena from the response meta field for feedback generation requests.

Follow-up Issues

  • Extend Athena to send costPerMillionInputToken, costPerMillionOutputToken
  • Update Artemis Athena adapter to also store those fields
  • Refactor to save meta for each request

Steps for Testing

You'd need to request feedback using Athena and check the database tables if the calls are correctly stored.

This can be done locally.

Testserver States

Note

These badges show the state of the test servers.
Green = Currently available, Red = Currently locked
Click on the badges to get to the test servers.







Review Progress

Performance Review

  • I (as a reviewer) confirm that the client changes (in particular related to REST calls and UI responsiveness) are implemented with a very good performance even for very large courses with more than 2000 students.
  • I (as a reviewer) confirm that the server changes (in particular related to database calls) are implemented with a very good performance even for very large courses with more than 2000 students.

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Exam Mode Test

  • Test 1
  • Test 2

Performance Tests

  • Test 1
  • Test 2

Test Coverage

Screenshots

Summary by CodeRabbit

  • New Features

    • Introduced ResponseMetaDTO to encapsulate metadata related to responses from the Athena service.
    • Added LLMRequest and LLMServiceType to manage requests and service types for large language models.
    • Implemented LLMTokenUsageService for tracking token usage within the system.
    • Enhanced IrisChatWebsocketDTO to include token information for improved WebSocket communication.
  • Bug Fixes

    • Updated various service methods to ensure correct handling of token usage and response metadata.
  • Tests

    • Added integration tests for tracking token usage in chat sessions, ensuring accurate data capture and storage.
  • Documentation

    • Updated method signatures and documentation to reflect changes in parameters and functionality related to token usage and response handling.

@FelixTJDietrich FelixTJDietrich requested a review from a team as a code owner October 21, 2024 17:11
@github-actions github-actions bot added tests server Pull requests that update Java code. (Added Automatically!) database Pull requests that update the database. (Added Automatically!). Require a CRITICAL deployment. athena Pull requests that affect the corresponding module core Pull requests that affect the corresponding module iris Pull requests that affect the corresponding module labels Oct 21, 2024
@FelixTJDietrich FelixTJDietrich changed the base branch from develop to feature/track-usage-of-iris-requests October 21, 2024 17:12
Copy link

coderabbitai bot commented Oct 21, 2024

Walkthrough

This pull request introduces several new classes and modifications to existing services and DTOs, primarily to enhance the handling of token usage for large language models (LLMs) within the Artemis system. Key additions include the ResponseMetaDTO, LLMRequest, and LLMTokenUsageRequest classes, along with updates to various services to incorporate these new data structures. The changes facilitate the tracking of LLM token usage and integrate this functionality into feedback mechanisms and chat services.

Changes

File Change Summary
src/main/java/de/tum/cit/aet/artemis/athena/dto/ResponseMetaDTO.java New file defining ResponseMetaDTO with fields for metadata related to responses, including a nested TotalUsage record.
src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaFeedbackSuggestionsService.java Modifications include new imports, a private field for LLMTokenUsageService, an updated constructor, and changes to response DTOs to include ResponseMetaDTO. New method storeTokenUsage added for managing token usage.
src/main/java/de/tum/cit/aet/artemis/core/domain/LLMRequest.java New record class LLMRequest added to encapsulate properties related to LLM requests.
src/main/java/de/tum/cit/aet/artemis/core/domain/LLMServiceType.java New enum LLMServiceType added with constants for different LLM services.
src/main/java/de/tum/cit/aet/artemis/core/domain/LLMTokenUsageRequest.java New class LLMTokenUsageRequest added as a JPA entity for tracking token usage, with various fields and annotations for database mapping.
src/main/java/de/tum/cit/aet/artemis/core/domain/LLMTokenUsageTrace.java New class LLMTokenUsageTrace added as a JPA entity for tracing token usage, with fields for service type and relationships to token usage requests.
src/main/java/de/tum/cit/aet/artemis/core/repository/LLMTokenUsageRequestRepository.java New interface for managing LLMTokenUsageRequest entities, extending ArtemisJpaRepository.
src/main/java/de/tum/cit/aet/artemis/core/repository/LLMTokenUsageTraceRepository.java New interface for managing LLMTokenUsageTrace entities, extending ArtemisJpaRepository.
src/main/java/de/tum/cit/aet/artemis/core/service/LLMTokenUsageService.java New service class for managing LLM token usage, with methods for saving usage and appending requests to traces.
src/main/java/de/tum/cit/aet/artemis/iris/dto/IrisChatWebsocketDTO.java Updated to include a new parameter List<LLMRequest> tokens in the record and constructor.
src/main/java/de/tum/cit/aet/artemis/iris/service/IrisCompetencyGenerationService.java Constructor updated to include new dependencies and method handleStatusUpdate modified to accept CompetencyExtractionJob.
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/PyrisStatusUpdateService.java Method handleStatusUpdate updated to accept CompetencyExtractionJob instead of separate parameters.
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/dto/chat/PyrisChatStatusUpdateDTO.java Updated to include a new field tokens for tracking LLM requests.
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/dto/competency/PyrisCompetencyStatusUpdateDTO.java Updated to include a new field tokens for tracking LLM requests.
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/dto/data/PyrisLLMCostDTO.java New data transfer object for model cost calculations introduced.
src/test/java/de/tum/cit/aet/artemis/iris/IrisChatTokenTrackingIntegrationTest.java New integration test suite for tracking token usage in chat sessions.
src/test/java/de/tum/cit/aet/artemis/iris/IrisChatWebsocketTest.java Updated test method to reflect changes in IrisChatWebsocketDTO constructor.
src/test/java/de/tum/cit/aet/artemis/iris/IrisCompetencyGenerationIntegrationTest.java Updated test to use CompetencyExtractionJob for handling status updates.
src/test/java/de/tum/cit/aet/artemis/iris/IrisTextExerciseChatMessageIntegrationTest.java Updated test method to include an additional parameter in the sendStatus method.

Possibly related PRs

Suggested labels

tests, server, client, ready to merge, maintainer-approved, assessment, programming

Suggested reviewers

  • LeonWehrhahn
  • iyannsch
  • eceeeren
  • julian-christl

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.

Actionable comments posted: 30

🧹 Outside diff range and nitpick comments (22)
src/main/java/de/tum/cit/aet/artemis/core/domain/LLMServiceType.java (1)

1-8: LGTM! Consider enhancing the documentation.

The LLMServiceType enum is well-structured and follows the coding guidelines. It adheres to the single responsibility principle and uses appropriate naming conventions. The class-level comment provides a clear description of the enum's purpose.

Consider adding brief descriptions for each enum constant to provide more context:

public enum LLMServiceType {
    /** Represents the IRIS LLM service. */
    IRIS,
    /** Represents the ATHENA LLM service. */
    ATHENA
}

This addition would enhance the documentation and make it easier for developers to understand the specific purpose of each service type.

src/main/java/de/tum/cit/aet/artemis/core/domain/LLMRequest.java (1)

1-4: Add Javadoc comments to improve documentation.

To enhance code readability and maintainability, consider adding Javadoc comments for the LLMRequest record and its fields. This will provide clear documentation for other developers who might use this record.

Here's a suggested Javadoc comment structure:

/**
 * Represents a request for a Large Language Model (LLM) operation.
 *
 * @param model The name or identifier of the LLM model.
 * @param numInputTokens The number of input tokens for the request.
 * @param costPerMillionInputToken The cost per million input tokens.
 * @param numOutputTokens The number of output tokens generated.
 * @param costPerMillionOutputToken The cost per million output tokens.
 * @param pipelineId The identifier of the pipeline used for this request.
 */
public record LLMRequest(String model, int numInputTokens, BigDecimal costPerMillionInputToken, int numOutputTokens, BigDecimal costPerMillionOutputToken, String pipelineId) {
}
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/dto/data/PyrisLLMCostDTO.java (1)

1-4: LGTM! Consider adding Javadoc for better documentation.

The PyrisLLMCostDTO record is well-structured and follows the coding guidelines. It uses appropriate types for its fields and adheres to the single responsibility principle by focusing solely on LLM cost data.

Consider adding Javadoc to the record and its fields for improved documentation. Here's a suggestion:

/**
 * Data Transfer Object for PyrisLLM cost information.
 */
public record PyrisLLMCostDTO(
    /** Information about the model used. */
    String modelInfo,
    /** Number of input tokens. */
    int numInputTokens,
    /** Cost per input token. */
    float costPerInputToken,
    /** Number of output tokens. */
    int numOutputTokens,
    /** Cost per output token. */
    float costPerOutputToken,
    /** Information about the pipeline used. */
    String pipeline
) {}
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/job/SessionBasedPyrisJob.java (1)

3-5: LGTM: Clear and concise Javadoc comment.

The Javadoc comment effectively describes the purpose of the interface. Consider adding a brief explanation of what a "session" means in this context for improved clarity.

src/main/java/de/tum/cit/aet/artemis/core/repository/LLMTokenUsageTraceRepository.java (1)

11-14: LGTM: Interface declaration and annotations are correct.

The interface is well-defined and follows the coding guidelines. It correctly extends ArtemisJpaRepository and is properly annotated. The empty interface is acceptable as it inherits standard CRUD operations.

Consider adding a brief Javadoc comment to describe the purpose of this repository interface. For example:

/**
 * Repository interface for managing LLMTokenUsageTrace entities.
 * Provides CRUD operations and custom queries if needed.
 */
@Profile(PROFILE_CORE)
@Repository
public interface LLMTokenUsageTraceRepository extends ArtemisJpaRepository<LLMTokenUsageTrace, Long> {
}
src/main/java/de/tum/cit/aet/artemis/core/repository/LLMTokenUsageRequestRepository.java (1)

11-13: LGTM: Interface declaration and annotations are correct.

The interface is well-defined and follows the correct naming convention. The annotations @Profile(PROFILE_CORE) and @Repository are appropriately used. Extending ArtemisJpaRepository with the correct entity type and ID type is good.

Consider adding a brief Javadoc comment to describe the purpose of this repository interface. For example:

/**
 * Repository interface for managing LLMTokenUsageRequest entities.
 * This interface provides CRUD operations for LLMTokenUsageRequest objects.
 */
@Profile(PROFILE_CORE)
@Repository
public interface LLMTokenUsageRequestRepository extends ArtemisJpaRepository<LLMTokenUsageRequest, Long> {
}
src/main/java/de/tum/cit/aet/artemis/athena/dto/ResponseMetaDTO.java (1)

13-14: LGTM: Well-structured DTO using Java record.

The ResponseMetaDTO record is well-defined and follows good practices for DTOs. It adheres to the single responsibility principle and uses appropriate types for its fields.

Consider expanding the Javadoc comment to briefly describe the purpose of each field in the record. This would enhance the documentation and make it easier for other developers to understand the DTO's structure.

src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/job/CourseChatJob.java (1)

12-12: LGTM! Consider enhancing the documentation.

The change from PyrisJob to SessionBasedPyrisJob is appropriate and aligns with the session-based nature of the job. The implementation is concise and follows good practices.

Consider updating the class-level documentation to reflect the change to SessionBasedPyrisJob and briefly explain the significance of the sessionId field. This would improve code clarity for future developers.

src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/job/ExerciseChatJob.java (1)

13-13: LGTM! Consider adding a brief Javadoc for the new interface.

The change from PyrisJob to SessionBasedPyrisJob aligns well with the PR objectives for LLM token usage tracking. The inclusion of sessionId in the record is consistent with this change.

Consider adding a brief Javadoc comment for the SessionBasedPyrisJob interface to explain its purpose and how it differs from the general PyrisJob. This would enhance code documentation and maintainability.

src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/dto/competency/PyrisCompetencyStatusUpdateDTO.java (2)

17-17: Javadoc updated correctly, minor grammatical fix needed.

The new parameter description is clear and informative. However, there's a small grammatical error.

Please apply this minor correction:

- * @param tokens List of token usages send by Pyris for tracking the token usage and cost
+ * @param tokens List of token usages sent by Pyris for tracking the token usage and cost

20-20: Record updated correctly, consider adding a @Nonnull annotation.

The addition of the tokens parameter aligns with the PR objectives and follows the coding guidelines. The record is well-structured and uses appropriate annotations.

For consistency and to prevent potential null pointer exceptions, consider adding a @Nonnull annotation to the tokens parameter:

- public record PyrisCompetencyStatusUpdateDTO(List<PyrisStageDTO> stages, List<PyrisCompetencyRecommendationDTO> result, List<LLMRequest> tokens) {
+ public record PyrisCompetencyStatusUpdateDTO(List<PyrisStageDTO> stages, List<PyrisCompetencyRecommendationDTO> result, @Nonnull List<LLMRequest> tokens) {

This change would ensure that the tokens list is always non-null, which aligns with best practices for null safety.

src/main/java/de/tum/cit/aet/artemis/iris/dto/IrisChatWebsocketDTO.java (2)

35-37: LGTM: Constructor updated correctly with a minor suggestion.

The constructor changes are consistent with the record declaration update and maintain the existing functionality. They follow the coding guidelines by using constructor injection and keeping the code simple.

Consider breaking the long constructor parameter list into multiple lines for improved readability:

public IrisChatWebsocketDTO(
        @Nullable IrisMessage message,
        IrisRateLimitService.IrisRateLimitInformation rateLimitInfo,
        List<PyrisStageDTO> stages,
        List<String> suggestions,
        List<LLMRequest> tokens
) {
    this(determineType(message), message, rateLimitInfo, stages, suggestions, tokens);
}

Line range hint 1-79: Summary: Changes align well with PR objectives and coding guidelines.

The modifications to IrisChatWebsocketDTO effectively implement the tracking of LLM token usage as intended in the PR objectives. The changes maintain consistency with existing code structure and adhere to the project's coding guidelines. The addition of the tokens parameter enhances the DTO's capability to transfer LLM token usage data, which is crucial for the new feature being implemented.

As the system evolves to include more LLM-related features, consider creating a separate DTO for LLM-specific data if the amount of data grows significantly. This would help maintain the single responsibility principle and keep the IrisChatWebsocketDTO focused on its primary purpose.

src/test/java/de/tum/cit/aet/artemis/iris/IrisChatWebsocketTest.java (1)

56-56: Enhance test to verify the new parameter.

While the test has been updated to include the new parameter in the IrisChatWebsocketDTO constructor, it doesn't explicitly verify this new field. Consider enhancing the test to ensure the new parameter is correctly handled.

You could modify the test to include a non-empty list for the new parameter and verify that it's correctly passed to the sendMessageToUser method. For example:

List<LLMRequest> mockTokens = List.of(new LLMRequest("test", 10));
irisChatWebsocketService.sendMessage(irisSession, message, mockTokens);
verify(websocketMessagingService, times(1)).sendMessageToUser(eq(TEST_PREFIX + "student1"), eq("/topic/iris/" + irisSession.getId()),
        eq(new IrisChatWebsocketDTO(message, new IrisRateLimitService.IrisRateLimitInformation(0, -1, 0), List.of(), List.of(), mockTokens)));

This change would make the test more robust and ensure that the new functionality is correctly tested.

src/test/java/de/tum/cit/aet/artemis/iris/IrisCompetencyGenerationIntegrationTest.java (1)

70-73: LGTM: Test updated to reflect API changes.

The test has been correctly updated to use the new CompetencyExtractionJob object, which aligns with the changes in the IrisCompetencyGenerationService API. The test remains focused and specific to the functionality being tested.

Consider adding a comment explaining the purpose of the null argument in the PyrisCompetencyStatusUpdateDTO constructor for better clarity.

🧰 Tools
🪛 ast-grep

[warning] 72-72: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (job, new PyrisCompetencyStatusUpdateDTO(stages, recommendations, null))
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 72-72: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (job, new PyrisCompetencyStatusUpdateDTO(stages, recommendations, null))
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration

src/test/java/de/tum/cit/aet/artemis/iris/IrisTextExerciseChatMessageIntegrationTest.java (1)

401-401: LGTM. Consider adding a TODO comment for token usage.

The addition of the null parameter to PyrisChatStatusUpdateDTO aligns with the PR objective of implementing LLM token usage tracking. However, it might be beneficial to add a TODO comment explaining why this parameter is currently null and when it will be implemented.

Consider adding a TODO comment like this:

-        request.postWithoutResponseBody("/api/public/pyris/pipelines/text-exercise-chat/runs/" + jobId + "/status", new PyrisChatStatusUpdateDTO(result, stages, suggestions, null),
+        // TODO: Implement token usage tracking once the feature is fully developed
+        request.postWithoutResponseBody("/api/public/pyris/pipelines/text-exercise-chat/runs/" + jobId + "/status", new PyrisChatStatusUpdateDTO(result, stages, suggestions, null),
                 HttpStatus.OK, headers);
🧰 Tools
🪛 ast-grep

[warning] 400-401: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: ("/api/public/pyris/pipelines/text-exercise-chat/runs/" + jobId + "/status", new PyrisChatStatusUpdateDTO(result, stages, suggestions, null),
HttpStatus.OK, headers)
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 400-401: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: ("/api/public/pyris/pipelines/text-exercise-chat/runs/" + jobId + "/status", new PyrisChatStatusUpdateDTO(result, stages, suggestions, null),
HttpStatus.OK, headers)
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration

src/main/java/de/tum/cit/aet/artemis/core/domain/LLMTokenUsageRequest.java (1)

3-11: Avoid unused imports and maintain import order

Ensure that all imported packages are necessary. Additionally, follow the standard import ordering: Java standard library imports, third-party library imports, and finally, project-specific imports.

Consider organizing the imports like this:

 package de.tum.cit.aet.artemis.core.domain;

+import com.fasterxml.jackson.annotation.JsonInclude;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import org.hibernate.annotations.Cache;
+import org.hibernate.annotations.CacheConcurrencyStrategy;

 // Remove any unused imports if present
src/main/java/de/tum/cit/aet/artemis/iris/service/websocket/IrisChatWebsocketService.java (1)

65-65: Correct grammatical error in Javadoc comment

The Javadoc for @param tokens should be "token usage and cost sent by Pyris" instead of "token usage and cost send by Pyris".

src/main/java/de/tum/cit/aet/artemis/iris/service/IrisCompetencyGenerationService.java (1)

78-85: Ensure consistent use of explicit type declarations

In line 84, var is used for the variable declaration. For consistency and readability, consider using an explicit type declaration:

-var user = userRepository.findById(job.userId()).orElseThrow();
+User user = userRepository.findById(job.userId()).orElseThrow();
src/main/java/de/tum/cit/aet/artemis/iris/service/session/AbstractIrisChatSessionService.java (1)

87-113: Ensure proper management of entries in traces to prevent memory leaks

Entries in the traces map are added and removed based on the job ID. Ensure that all entries are removed when no longer needed to prevent the map from growing indefinitely, which could lead to memory leaks over time.

src/main/java/de/tum/cit/aet/artemis/iris/service/session/IrisExerciseChatSessionService.java (1)

155-158: Add unit tests for setLLMTokenUsageParameters method

Consider adding unit tests for the new setLLMTokenUsageParameters method to verify its functionality and handle potential edge cases.

src/test/java/de/tum/cit/aet/artemis/iris/IrisChatTokenTrackingIntegrationTest.java (1)

225-229: Specify thrown exceptions for clarity

The method sendStatus declares a general throws Exception, which can obscure the specific exceptions that might be thrown. For better clarity and exception handling, consider specifying the exact exceptions that can occur, such as IOException or HttpClientErrorException.

🧰 Tools
🪛 ast-grep

[warning] 225-225: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (Map.of("Authorization", List.of("Bearer " + jobId)))
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 226-227: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: ("/api/public/pyris/pipelines/tutor-chat/runs/" + jobId + "/status", new PyrisChatStatusUpdateDTO(result, stages, null, tokens),
HttpStatus.OK, headers)
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 225-225: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (Map.of("Authorization", List.of("Bearer " + jobId)))
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 226-227: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: ("/api/public/pyris/pipelines/tutor-chat/runs/" + jobId + "/status", new PyrisChatStatusUpdateDTO(result, stages, null, tokens),
HttpStatus.OK, headers)
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration

🛑 Comments failed to post (30)
src/main/java/de/tum/cit/aet/artemis/core/domain/LLMRequest.java (1)

3-3: 🛠️ Refactor suggestion

Consider using BigDecimal for cost-related fields.

For the costPerMillionInputToken and costPerMillionOutputToken fields, consider using java.math.BigDecimal instead of float. BigDecimal is more suitable for representing currency and performing precise decimal calculations, which is crucial for cost-related data.

Here's the suggested change:

- public record LLMRequest(String model, int numInputTokens, float costPerMillionInputToken, int numOutputTokens, float costPerMillionOutputToken, String pipelineId) {
+ public record LLMRequest(String model, int numInputTokens, BigDecimal costPerMillionInputToken, int numOutputTokens, BigDecimal costPerMillionOutputToken, String pipelineId) {

Don't forget to add the necessary import:

import java.math.BigDecimal;
src/main/java/de/tum/cit/aet/artemis/athena/dto/ResponseMetaDTO.java (1)

15-17: 🛠️ Refactor suggestion

Consider using primitives and BigDecimal for improved efficiency and precision.

The TotalUsage record is well-structured, but consider the following suggestions:

  1. If null values are not needed for these fields, using primitive types (int and float) instead of wrapper classes could improve performance.
  2. For the cost field, consider using BigDecimal instead of Float to ensure precise financial calculations.

Here's a potential refactoring:

public record TotalUsage(int numInputTokens, int numOutputTokens, int numTotalTokens, BigDecimal cost) {
}

Make sure to import java.math.BigDecimal if you decide to use it.

src/test/java/de/tum/cit/aet/artemis/iris/IrisChatWebsocketTest.java (1)

56-56: 💡 Codebase verification

Missing verification of the new parameter in IrisChatTokenTrackingIntegrationTest.java.

The integration test does not verify the new List.of() parameter in the IrisChatWebsocketDTO constructor, which may lead to incomplete test coverage.

🔗 Analysis chain

LGTM! Consider additional integration tests.

The change correctly updates the IrisChatWebsocketDTO constructor call to include the new parameter. This aligns with the coding guidelines and maintains the test's integrity.

As per the retrieved learning, consider implementing additional tests for the new field in a separate integration test class, such as IrisChatTokenTrackingIntegrationTest. This would ensure comprehensive coverage of the new functionality.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if an integration test for the new field exists
fd -e java -p 'IrisChatTokenTrackingIntegrationTest'

Length of output: 136


Script:

#!/bin/bash
# Check for usage of List.of() in IrisChatTokenTrackingIntegrationTest.java
grep -E 'List\.of\(\)' src/test/java/de/tum/cit/aet/artemis/iris/IrisChatTokenTrackingIntegrationTest.java

Length of output: 108


Script:

#!/bin/bash
# Search for IrisChatWebsocketDTO constructor calls with multiple parameters
grep -E 'new IrisChatWebsocketDTO\s*\(.*\)' src/test/java/de/tum/cit/aet/artemis/iris/IrisChatTokenTrackingIntegrationTest.java

Length of output: 129

src/main/java/de/tum/cit/aet/artemis/core/domain/LLMTokenUsageRequest.java (4)

28-30: ⚠️ Potential issue

Use BigDecimal instead of float for monetary values

Using float for monetary values can lead to precision and rounding errors due to floating-point representation. It is recommended to use BigDecimal for precise monetary calculations.

Apply this diff to change the data types:

 @Column(name = "cost_per_million_input_tokens")
-    private float costPerMillionInputTokens;
+    private BigDecimal costPerMillionInputTokens;

 @Column(name = "cost_per_million_output_tokens")
-    private float costPerMillionOutputTokens;
+    private BigDecimal costPerMillionOutputTokens;

Remember to update the getter and setter methods accordingly to reflect the new data type.

Also applies to: 34-36


68-70: ⚠️ Potential issue

Inconsistent parameter name in setter setCostPerMillionOutputTokens

The parameter name costPerMillionOutputToken (singular) does not match the field name costPerMillionOutputTokens (plural). For consistency and clarity, the parameter name should be updated to costPerMillionOutputTokens.

Apply this diff to fix the parameter name:

 public void setCostPerMillionOutputTokens(float costPerMillionOutputToken) {
-    this.costPerMillionOutputTokens = costPerMillionOutputToken;
+    this.costPerMillionOutputTokens = costPerMillionOutputTokens;
 }

+// Updated method signature
+public void setCostPerMillionOutputTokens(float costPerMillionOutputTokens) {
+    this.costPerMillionOutputTokens = costPerMillionOutputTokens;
+}

Committable suggestion was skipped due to low confidence.


60-62: ⚠️ Potential issue

Inconsistent parameter name in setter setCostPerMillionInputTokens

The parameter name costPerMillionInputToken (singular) does not match the field name costPerMillionInputTokens (plural). For consistency and clarity, the parameter name should be updated to costPerMillionInputTokens.

Apply this diff to fix the parameter name:

 public void setCostPerMillionInputTokens(float costPerMillionInputToken) {
-    this.costPerMillionInputTokens = costPerMillionInputToken;
+    this.costPerMillionInputTokens = costPerMillionInputTokens;
 }

+// Updated method signature
+public void setCostPerMillionInputTokens(float costPerMillionInputTokens) {
+    this.costPerMillionInputTokens = costPerMillionInputTokens;
+}

Committable suggestion was skipped due to low confidence.


19-94: 🛠️ Refactor suggestion

Consider adding constructor injection for immutability

To enhance the immutability of the class and adhere to the dependency injection principle, consider adding constructor parameters for required fields. This could make the class instances immutable once created.

Here's how you might modify the class:

 public class LLMTokenUsageRequest extends DomainObject {

+    // Constructor with required fields
+    public LLMTokenUsageRequest(String model, String servicePipelineId, int numInputTokens, BigDecimal costPerMillionInputTokens, int numOutputTokens, BigDecimal costPerMillionOutputTokens, LLMTokenUsageTrace trace) {
+        this.model = model;
+        this.servicePipelineId = servicePipelineId;
+        this.numInputTokens = numInputTokens;
+        this.costPerMillionInputTokens = costPerMillionInputTokens;
+        this.numOutputTokens = numOutputTokens;
+        this.costPerMillionOutputTokens = costPerMillionOutputTokens;
+        this.trace = trace;
+    }

     // Existing fields and methods...
 }

Committable suggestion was skipped due to low confidence.

src/main/java/de/tum/cit/aet/artemis/core/domain/LLMTokenUsageTrace.java (3)

41-41: ⚠️ Potential issue

Fix inconsistent data types for 'userId' field and its getter/setter.

The userId field is declared as Long, but the getter and setter use the primitive long. This inconsistency may lead to NullPointerException if userId is null.

Apply this diff to align the data types:

Option 1: If userId should never be null, change the field to use the primitive long:

-    private Long userId;
+    private long userId;

     public long getUserId() {
         return userId;
     }

     public void setUserId(long userId) {
         this.userId = userId;
     }

Option 2: If userId can be null, update the getter and setter to use Long:

     public long getUserId() {
-        return userId;
+        return userId;
     }

     public void setUserId(long userId) {
-        this.userId = userId;
+        this.userId = userId;
     }

Ensure consistency between the field and its accessor methods.

Also applies to: 77-83


43-44: 🛠️ Refactor suggestion

Consider using @CreationTimestamp for the 'time' field.

Initializing the time field with ZonedDateTime.now() may lead to unexpected results if the entity is not immediately persisted or if the object is reused. Using @CreationTimestamp ensures that the timestamp is automatically set when the entity is saved to the database.

Apply this diff:

+    @CreationTimestamp
     @Column(name = "time")
-    private ZonedDateTime time = ZonedDateTime.now();
+    private ZonedDateTime time;

Remember to import org.hibernate.annotations.CreationTimestamp.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    @CreationTimestamp
    @Column(name = "time")
    private ZonedDateTime time;

93-99: ⚠️ Potential issue

Ensure consistent method naming for 'llmRequests' getters and setters.

The getter and setter methods for llmRequests have inconsistent naming conventions. The getter is getLLMRequests(), while the setter is setLlmRequests(). This inconsistency may cause issues with frameworks that rely on JavaBean naming conventions.

Apply this diff to standardize the method names:

Option 1: Use getLlmRequests() and setLlmRequests() to match the field name:

-    public Set<LLMTokenUsageRequest> getLLMRequests() {
+    public Set<LLMTokenUsageRequest> getLlmRequests() {
         return llmRequests;
     }

     public void setLlmRequests(Set<LLMTokenUsageRequest> llmRequests) {
         this.llmRequests = llmRequests;
     }

Option 2: Use getLLMRequests() and setLLMRequests() to capitalize LLM:

     public Set<LLMTokenUsageRequest> getLLMRequests() {
         return llmRequests;
     }

-    public void setLlmRequests(Set<LLMTokenUsageRequest> llmRequests) {
+    public void setLLMRequests(Set<LLMTokenUsageRequest> llmRequests) {
         this.llmRequests = llmRequests;
     }

Choose one option to maintain consistency and adhere to naming conventions.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    public Set<LLMTokenUsageRequest> getLLMRequests() {
        return llmRequests;
    }

    public void setLLMRequests(Set<LLMTokenUsageRequest> llmRequests) {
        this.llmRequests = llmRequests;
    }
src/main/java/de/tum/cit/aet/artemis/iris/service/websocket/IrisChatWebsocketService.java (4)

45-45: 🛠️ Refactor suggestion

Avoid passing multiple nulls to the constructor

Passing multiple null values to IrisChatWebsocketDTO reduces code readability and increases the risk of errors. Consider implementing the Builder pattern or providing overloaded constructors to handle optional parameters more gracefully.


56-56: 🛠️ Refactor suggestion

Eliminate method calls with multiple null arguments

Invoking sendStatusUpdate with null values for suggestions and tokens decreases code clarity. Provide overloaded methods or use optional parameters to enhance readability and maintainability.


67-67: 🛠️ Refactor suggestion

Reduce parameter count in sendStatusUpdate method

The sendStatusUpdate method now has four parameters, increasing complexity and the potential for errors. Consider encapsulating related parameters into a data transfer object (DTO) or using a builder to simplify the method signature.


71-71: ⚠️ Potential issue

Avoid passing null to constructors

Passing null as an argument when constructing IrisChatWebsocketDTO can lead to NullPointerExceptions and reduces code clarity. Refactor the constructor or use patterns that handle optional fields more effectively.

Apply this suggested refactor:

- var payload = new IrisChatWebsocketDTO(null, rateLimitInfo, stages, suggestions, tokens);
+ var payload = IrisChatWebsocketDTO.builder()
+     .rateLimitInfo(rateLimitInfo)
+     .stages(stages)
+     .suggestions(suggestions)
+     .tokens(tokens)
+     .build();

Committable suggestion was skipped due to low confidence.

src/main/java/de/tum/cit/aet/artemis/iris/service/session/AbstractIrisChatSessionService.java (3)

34-34: ⚠️ Potential issue

Potential concurrency issue with non-thread-safe HashMap

The traces HashMap is accessed in a concurrent context but is not thread-safe. If multiple threads interact with this map, it could lead to data inconsistency or race conditions. Consider using a ConcurrentHashMap to ensure thread safety.


73-116: 🛠️ Refactor suggestion

Consider splitting handleStatusUpdate into smaller methods for clarity

The handleStatusUpdate method handles multiple responsibilities, such as message processing, token usage tracking, and updating suggestions. To adhere to the single responsibility principle and improve readability, consider refactoring this method by extracting parts of the logic into separate private methods.

🧰 Tools
🪛 ast-grep

[warning] 77-77: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (new IrisTextMessageContent(statusUpdate.result()))
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 77-77: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (new IrisTextMessageContent(statusUpdate.result()))
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


77-78: ⚠️ Potential issue

Ensure sanitization of statusUpdate.result() to prevent security vulnerabilities

The statusUpdate.result() may contain user-generated or external content. Before creating a new IrisTextMessageContent with this content, ensure that it is properly sanitized or escaped to prevent security issues like cross-site scripting (XSS) attacks.

🧰 Tools
🪛 ast-grep

[warning] 77-77: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (new IrisTextMessageContent(statusUpdate.result()))
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 77-77: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (new IrisTextMessageContent(statusUpdate.result()))
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration

src/main/java/de/tum/cit/aet/artemis/core/service/LLMTokenUsageService.java (4)

49-49: 🛠️ Refactor suggestion

Consider making the saveLLMTokenUsage method asynchronous as per the TODO comment.

The TODO comment suggests that this method should ideally be executed asynchronously to prevent blocking the main thread, especially if the database operation is time-consuming. Implementing it asynchronously can improve the application's performance and responsiveness. Consider using Spring's @Async annotation or other asynchronous execution mechanisms.

Would you like assistance in implementing asynchronous processing for this method?


77-77: 🛠️ Refactor suggestion

Consider making the appendRequestsToTrace method asynchronous as per the TODO comment.

Similarly, the TODO comment indicates that this method should be executed asynchronously. Making this method asynchronous can enhance performance by freeing up resources and allowing other processes to run concurrently.

Would you like assistance in making this method execute asynchronously?


79-80: ⚠️ Potential issue

Avoid using peek for side-effects; use map instead.

As with the previous instance, using peek for side-effects is not recommended. Refactor to use map to modify and transform the elements appropriately.

Consider refactoring the code as follows:

- var requestSet = requests.stream().map(LLMTokenUsageService::convertLLMRequestToLLMTokenUsageRequest)
-         .peek(llmTokenUsageRequest -> llmTokenUsageRequest.setTrace(trace))
-         .collect(Collectors.toSet());
+ var requestSet = requests.stream()
+         .map(llmRequest -> {
+             LLMTokenUsageRequest usageRequest = LLMTokenUsageService.convertLLMRequestToLLMTokenUsageRequest(llmRequest);
+             usageRequest.setTrace(trace);
+             return usageRequest;
+         })
+         .collect(Collectors.toSet());
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

        var requestSet = requests.stream()
                .map(llmRequest -> {
                    LLMTokenUsageRequest usageRequest = LLMTokenUsageService.convertLLMRequestToLLMTokenUsageRequest(llmRequest);
                    usageRequest.setTrace(trace);
                    return usageRequest;
                })
                .collect(Collectors.toSet());

60-61: ⚠️ Potential issue

Avoid using peek for side-effects; use map instead.

The peek method is intended for debugging and should not be used to perform side-effects like modifying elements. Using map is more appropriate when you need to transform elements, especially when the transformation includes side-effects.

Consider refactoring the code as follows:

- llmTokenUsageTrace.setLlmRequests(llmRequests.stream().map(LLMTokenUsageService::convertLLMRequestToLLMTokenUsageRequest)
-         .peek(llmTokenUsageRequest -> llmTokenUsageRequest.setTrace(llmTokenUsageTrace)).collect(Collectors.toSet()));
+ llmTokenUsageTrace.setLlmRequests(llmRequests.stream()
+         .map(llmRequest -> {
+             LLMTokenUsageRequest usageRequest = LLMTokenUsageService.convertLLMRequestToLLMTokenUsageRequest(llmRequest);
+             usageRequest.setTrace(llmTokenUsageTrace);
+             return usageRequest;
+         })
+         .collect(Collectors.toSet()));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

        llmTokenUsageTrace.setLlmRequests(llmRequests.stream()
                .map(llmRequest -> {
                    LLMTokenUsageRequest usageRequest = LLMTokenUsageService.convertLLMRequestToLLMTokenUsageRequest(llmRequest);
                    usageRequest.setTrace(llmTokenUsageTrace);
                    return usageRequest;
                })
                .collect(Collectors.toSet()));
src/main/java/de/tum/cit/aet/artemis/iris/service/session/IrisExerciseChatSessionService.java (2)

60-65: 🛠️ Refactor suggestion

Constructor has too many parameters

The constructor now has twelve parameters, which can make the code harder to maintain and test. Consider refactoring to reduce the number of parameters, possibly by grouping related services into composite objects or utilizing a dependency injection framework to manage dependencies more efficiently.


155-158: ⚠️ Potential issue

Ensure safe access to exercise to prevent potential NullPointerException

To prevent a possible NullPointerException, ensure that exercise.getCourseViaExerciseGroupOrCourseMember() does not return null before calling getId(). Consider adding a null check or handling potential null values appropriately.

src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaFeedbackSuggestionsService.java (2)

169-181: ⚠️ Potential issue

Potential ClassCastException when casting to StudentParticipation

At line 174, the code casts submission.getParticipation() to StudentParticipation without an instance check. This could lead to a ClassCastException if the participation is not of type StudentParticipation, such as when it's a TeacherParticipation.

Consider verifying the instance before casting:

Participation participation = submission.getParticipation();
Long userId = null;
if (participation instanceof StudentParticipation studentParticipation) {
    userId = studentParticipation.getStudent().map(User::getId).orElse(null);
}

This ensures safe casting and prevents potential runtime exceptions.


66-66: ⚠️ Potential issue

Typo in parameter documentation

There's a typo in the documentation for athenaDTOConverterService: "exrcises" should be "exercises".

Apply this diff to fix the typo:

- * @param athenaDTOConverterService Service to convert exrcises and submissions to DTOs
+ * @param athenaDTOConverterService Service to convert exercises and submissions to DTOs
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

     * @param athenaDTOConverterService Service to convert exercises and submissions to DTOs
src/test/java/de/tum/cit/aet/artemis/iris/IrisChatTokenTrackingIntegrationTest.java (5)

155-157: 🛠️ Refactor suggestion

Improve test method name for specificity

The method testTokenTrackingSavedExerciseChat can be renamed to more specifically describe the test scenario. A name like shouldSaveTokenUsageWhenExerciseChatMessageIsStored would provide clearer insight into the test's intention.


171-173: 🛠️ Refactor suggestion

Make test method name more descriptive

To enhance clarity, consider renaming testTokenTrackingExerciseChatWithPipelineFail to shouldTrackTokensWhenPipelineFailsDuringExerciseChat to accurately reflect the test scenario and expected outcome.


79-119: 🛠️ Refactor suggestion

Avoid direct database access in tests

The initTestCase method directly interacts with repositories to manipulate the database, which is discouraged by the guideline avoid_db_access: true for test files. Direct database access can slow down tests and make them less reliable. Consider using mock repositories or test utilities that simulate database operations to improve test performance and maintainability.


124-135: 🛠️ Refactor suggestion

Refactor duplicated code in test methods

The setup and execution logic in testTokenTrackingHandledExerciseChat and testTokenTrackingExerciseChatWithPipelineFail are largely similar. To adhere to the DRY (Don't Repeat Yourself) principle and improve maintainability, consider extracting common code into helper methods or setup functions. This refactoring will reduce duplication and make future updates easier.

Also applies to: 174-185

🧰 Tools
🪛 ast-grep

[warning] 127-127: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (new PyrisStageDTO("DoneTest", 10, PyrisStageState.DONE, "Done"))
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 127-127: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (new PyrisStageDTO("DoneTest", 10, PyrisStageState.DONE, "Done"))
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


121-123: 🛠️ Refactor suggestion

Enhance test method naming for clarity

The test method testTokenTrackingHandledExerciseChat could be renamed to more precisely reflect its purpose. Consider renaming it to shouldTrackTokensWhenHandlingExerciseChat for better readability and to clearly indicate the expected behavior being tested.

Copy link
Member

@alexjoham alexjoham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code looks good to me! Approved!

@bassner bassner added this to the 7.6.2 milestone Oct 22, 2024
@bassner bassner merged commit cc127af into feature/track-usage-of-iris-requests Oct 22, 2024
17 of 39 checks passed
@bassner bassner deleted the feature/athena/track-token-usage-new branch October 22, 2024 08:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
athena Pull requests that affect the corresponding module core Pull requests that affect the corresponding module database Pull requests that update the database. (Added Automatically!). Require a CRITICAL deployment. iris Pull requests that affect the corresponding module server Pull requests that update Java code. (Added Automatically!) tests
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

3 participants