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

Copy of PR #385 - Dead letter queue #12

Closed
wants to merge 17 commits into from
Closed

Conversation

raghavdixit99
Copy link
Owner

@raghavdixit99 raghavdixit99 commented Oct 24, 2024

Enhance HTTP Client with Dead Letter Queue and JWT Handling

  • Purpose:
    Introduce a dead letter queue mechanism for failed HTTP requests and improve JWT handling.
  • Key Changes:
    • Added DeadLetterQueue class to manage failed requests and retry logic.
    • Implemented JWT reauthorization when expired during request retries.
    • Updated HTTP client methods to utilize the new dead letter queue for error handling.
    • Modified environment setup in the CI workflow to specify the test environment.
    • Added comprehensive unit tests for the new functionality and edge cases.
  • Impact:
    Enhances reliability of API interactions by ensuring failed requests are retried and JWTs are managed effectively.

✨ Generated with love by Kaizen ❤️

Original Description closes ENG-565

Failed requests are retried.
After 3 failures, they are stored in-memory with a queue.
When a request succeeds, the queue attempts to retry.

(This PR was copied from AgentOps-AI/agentops PR AgentOps-AI#385)

Copy link

kaizen-bot bot commented Oct 24, 2024

🔍 Code Review Summary

Attention Required: This push has potential issues. 🚨

Overview

  • Total Feedbacks: 2 (Critical: 2, Refinements: 0)
  • Files Affected: 2
  • Code Quality: [█████████████████░░░] 85% (Good)

🚨 Critical Issues

security (2 issues)

1. Potential exposure of sensitive information in error messages.


📁 File: agentops/http_client.py
🔍 Reasoning:
Raising exceptions with detailed messages may expose sensitive information, such as API keys or JWTs.

💡 Solution:
Sanitize error messages to avoid leaking sensitive information.

Current Code:

raise ApiServerException(f"API server: invalid API key:{api_key}. Find your API key at https://app.agentops.ai/settings/projects")

Suggested Code:

raise ApiServerException("API server: invalid API key.")

2. Potential exposure of sensitive information in error messages.


📁 File: tests/test_http_client.py
🔍 Reasoning:
The error messages returned in exceptions could expose sensitive information. This is a security risk.

💡 Solution:
Sanitize error messages before logging or returning them to the client.

Current Code:

self.assertIn("invalid API key", str(context.exception))

Suggested Code:

        self.assertIn("invalid API key", str(context.exception).replace("Invalid API key", "Invalid credentials"))

✨ Generated with love by Kaizen ❤️

Useful Commands
  • Feedback: Share feedback on kaizens performance with !feedback [your message]
  • Ask PR: Reply with !ask-pr [your question]
  • Review: Reply with !review
  • Update Tests: Reply with !unittest to create a PR with test changes

Copy link

@kaizen-bot kaizen-bot bot left a comment

Choose a reason for hiding this comment

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

Consider implementing the following changes to improve the code.

Comment on lines 175 to 176
f"API server: invalid API key: {api_key}. Find your API key at https://app.agentops.ai/settings/projects"
)
Copy link

Choose a reason for hiding this comment

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

Comment: Potential exposure of sensitive information in error messages.

Solution: Sanitize error messages to avoid leaking sensitive information.
!! Make sure the following suggestion is correct before committing it !!

Suggested change
f"API server: invalid API key: {api_key}. Find your API key at https://app.agentops.ai/settings/projects"
)
raise ApiServerException("API server: invalid API key.")

with self.assertRaises(ApiServerException) as context:
HttpClient.post(url, payload, api_key="INVALID_KEY")

self.assertIn("invalid API key", str(context.exception))
Copy link

Choose a reason for hiding this comment

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

Comment: Potential exposure of sensitive information in error messages.

Solution: Sanitize error messages before logging or returning them to the client.
!! Make sure the following suggestion is correct before committing it !!

Suggested change
self.assertIn("invalid API key", str(context.exception))
self.assertIn("invalid API key", str(context.exception).replace("Invalid API key", "Invalid credentials"))

Copy link

Entelligence AI Bot Icon Entelligence AI Bot v4

Summary

  • New Feature: Introduced dead letter queue (DLQ) mechanism to handle failed HTTP requests, ensuring they are retried and logged appropriately.
  • Enhancement: Refactored HttpClient class to replace JWT with a token for authorization and added DeadLetterQueue class to manage failed requests. Environment variables are now loaded using python-dotenv.
  • Test: Added several test cases to validate the new DLQ functionality.
  • Refactor: Made minor adjustments to improve code readability and maintainability.
  • Documentation: No documentation changes mentioned in the summary.
  • Bug Fix: No bug fixes mentioned in the summary.
  • Style: No code formatting changes mentioned in the summary.

Copy link

Entelligence AI Bot Icon Entelligence AI Bot v4

Walkthrough

This update enhances the AgentOps project by introducing a dead letter queue (DLQ) mechanism to handle failed HTTP requests, ensuring they are retried and logged appropriately. The HttpClient class has been refactored to replace JWT with a token for authorization, and a new DeadLetterQueue class has been added to manage failed requests. Additionally, environment variables are now loaded using python-dotenv, and several test cases have been added to validate the new DLQ functionality. Minor adjustments were made to improve code readability and maintainability.

Changes

File(s) Summary
.github/workflows/python-testing.yml Added ENVIRONMENT variable set to test for the testing workflow.
.gitignore Added .agentops/ directory to ignore list.
agentops/config.py Applied @singleton decorator to Configuration class.
agentops/helpers.py Introduced ensure_dead_letter_queue function to manage DLQ file creation.
agentops/http_client.py Refactored HttpClient to use tokens instead of JWTs, added DeadLetterQueue class, and implemented DLQ retry logic.
agentops/session.py Replaced jwt parameter with token in HttpClient method calls.
tests/core_manual_tests/http_client/dead_letter_queue.py Added a new test script to validate DLQ functionality with expired JWTs.
tests/core_manual_tests/multi_session_llm.py Corrected session ID print statements.
tests/test_canary.py Added agentops.end_all_sessions() to setup/teardown.
tests/test_http_client.py Introduced comprehensive tests for HttpClient and DLQ functionality.
tests/test_record_action.py, tests/test_record_tool.py, tests/test_session.py Set dead_letter_queue.is_testing to True in setup/teardown.
tox.ini Added python-dotenv and python-dateutil to dependencies, set ENVIRONMENT to test.

Copy link

Entelligence AI Bot Icon Entelligence AI Bot v4

Files selected (8)
  • .gitignore
    - agentops/config.py
    - agentops/helpers.py
    - agentops/http_client.py
    - agentops/session.py
    - tests/core_manual_tests/http_client/dead_letter_queue.py
    - tests/core_manual_tests/multi_session_llm.py
    - tox.ini
Files ignored (6)
  • .github/workflows/python-testing.yml
    - tests/test_canary.py
    - tests/test_http_client.py
    - tests/test_record_action.py
    - tests/test_record_tool.py
    - tests/test_session.py
Instructions

Emoji Descriptions:

  • 🟢 Low Priority - Can be handled at your convenience.
  • 🟡 Medium Priority - Important but not urgent.
  • 🔴 High Priority - Address immediately.
  • ⚠️ Potential Issue - May require further investigation.
  • 🔒 Security Vulnerability - Fix to ensure system safety.
  • 💻 Code Improvement - Suggestions to enhance code quality.
  • 🔨 Refactor Suggestion - Recommendations for restructuring code.
  • ℹ️ Others - General comments and information.

Interact with the Bot:

  • Send a message or request using the format:

    @Entelligence.AI + *your message*

    • Example: @Entelligence.AI Can you suggest improvements for this code?
  • Execute a command using the format:

    @Entelligence.AI + *"/command"*

Available Commands:

  • /updateCommit: Apply the suggested changes and commit them.
  • /updateGuideline: Modify an existing guideline.
  • /addGuideline: Introduce a new guideline.

Tips for Using @Entelligence.AI Effectively:

  • Specific Queries: For the best results, be specific with your requests. Example: @Entelligence.AI summarize the changes in this PR.
  • Focused Discussions: Tag @Entelligence.AI directly on specific code lines or files for detailed feedback.
  • Managing Reviews: Use review comments for targeted discussions on code snippets, and PR comments for broader queries about the entire PR.

Need More Help?

  • Visit our documentation for detailed guides on using Entelligence.AI.
  • Join our community to connect with others, request features, and share feedback.
  • Follow us for updates on new features and improvements.

Comment on lines 23 to 29
langchain-core
langchain
termcolor
python-dateutil
commands =
coverage run --source agentops -m pytest
coverage report -m

Choose a reason for hiding this comment

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

Entelligence AI Bot Icon Entelligence AI Bot v4

💻 Code maintainability 🟡

Optimize Date Handling

Including python-dateutil in the dependencies is beneficial for handling date and time operations. Ensure that the code utilizing this library is optimized for performance, especially if dealing with large datasets.

Comment on lines 7 to 16
envlist = py37,py38,py39,py310,py311,py312

[testenv]
deps =
setenv =
ENVIRONMENT = test
deps =
python-dotenv
pytest
pytest-asyncio
pytest-mock

Choose a reason for hiding this comment

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

Entelligence AI Bot Icon Entelligence AI Bot v4

💻 Code maintainability 🟡

Secure Environment Variables

The addition of python-dotenv to the dependencies is a good practice for managing environment variables. However, ensure that the .env file is properly secured and not included in version control to prevent sensitive information exposure.

Comment on lines 2 to 11
from uuid import UUID

from .log_config import logger
from .singleton import singleton


@singleton
class Configuration:
def __init__(self):
self.api_key: Optional[str] = None

Choose a reason for hiding this comment

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

Entelligence AI Bot Icon Entelligence AI Bot v4

💻 Code maintainability 🟡

Singleton Implementation Safety

The addition of the @singleton decorator to the Configuration class is a good design choice to ensure a single instance is used throughout the application. However, ensure that the singleton implementation is thread-safe to avoid potential issues in a multi-threaded environment.

Comment on lines 10 to 17
session_1 = agentops.start_session(tags=["multi-session-test-1"])
session_2 = agentops.start_session(tags=["multi-session-test-2"])

print("session_id_1: {}".format(session_1))
print("session_id_2: {}".format(session_2))
print("session_id_1: {}".format(session_1.session_id))
print("session_id_2: {}".format(session_2.session_id))

messages = [{"role": "user", "content": "Hello"}]

Choose a reason for hiding this comment

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

Entelligence AI Bot Icon Entelligence AI Bot v4

💻 Code maintainability 🟡

Null Check for Session IDs

The change to print the session IDs directly from the session objects is a good improvement for clarity. However, ensure that the session objects are not null before accessing their properties to avoid potential runtime errors.

+ if session_1 and session_2:
+   print("session_id_1: {}".format(session_1.session_id))
+   print("session_id_2: {}".format(session_2.session_id))
Commitable Code Suggestion:
Suggested change
session_1 = agentops.start_session(tags=["multi-session-test-1"])
session_2 = agentops.start_session(tags=["multi-session-test-2"])
print("session_id_1: {}".format(session_1))
print("session_id_2: {}".format(session_2))
print("session_id_1: {}".format(session_1.session_id))
print("session_id_2: {}".format(session_2.session_id))
messages = [{"role": "user", "content": "Hello"}]
if session_1 and session_2:
print("session_id_1: {}".format(session_1.session_id))
print("session_id_2: {}".format(session_2.session_id))

Comment on lines 110 to 122


class HttpClient:

@staticmethod
def post(
url: str,
payload: bytes,
api_key: Optional[str] = None,
parent_key: Optional[str] = None,
jwt: Optional[str] = None,
header=None,
token: Optional[str] = None,
) -> Response:
result = Response()
try:

Choose a reason for hiding this comment

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

Entelligence AI Bot Icon Entelligence AI Bot v4

💻 Code maintainability 🟡

Consolidate Exception Handling

The error handling in the post method could be improved by consolidating the exception handling for requests.exceptions.Timeout and requests.exceptions.HTTPError. This will reduce code duplication and improve readability.

-        except (requests.exceptions.Timeout, requests.exceptions.HTTPError) as e:
-            HttpClient._handle_failed_request(
-                url, payload, api_key, parent_key, token, type(e).__name__
-            )
+        except requests.exceptions.RequestException as e:
+            HttpClient._handle_failed_request(
+                url, payload, api_key, parent_key, token, type(e).__name__
+            )
Commitable Code Suggestion:
Suggested change
class HttpClient:
@staticmethod
def post(
url: str,
payload: bytes,
api_key: Optional[str] = None,
parent_key: Optional[str] = None,
jwt: Optional[str] = None,
header=None,
token: Optional[str] = None,
) -> Response:
result = Response()
try:
except requests.exceptions.RequestException as e:
HttpClient._handle_failed_request(
url, payload, api_key, parent_key, token, type(e).__name__
)```
<br>
</details>

Copy link

Entelligence AI Bot Icon Entelligence AI Bot v4

Summary

  • New Feature: Introduced a dead letter queue (DLQ) mechanism to handle failed HTTP requests, ensuring they are retried and logged appropriately.
  • Refactor: Refactored HttpClient to use tokens instead of JWTs for authentication.
  • New Feature: Added a new DeadLetterQueue class to manage failed requests and implemented retry logic for DLQ.
  • Enhancement: Loaded environment variables using dotenv for improved environment management.
  • Test: Added comprehensive unit tests for HttpClient and DLQ functionality.
  • Enhancement: Applied singleton pattern to Configuration class for consistent configuration management.
  • Enhancement: Added ENVIRONMENT: test to the environment variables for testing purposes.
  • Enhancement: Added .agentops/ to ignore list in .gitignore for better file management.
  • Chore: Minor adjustments to the .gitignore and tox.ini files.

Copy link

Entelligence AI Bot Icon Entelligence AI Bot v4

Walkthrough

This update enhances the AgentOps project by introducing a dead letter queue (DLQ) mechanism to handle failed HTTP requests, ensuring they are retried and logged appropriately. The HttpClient class has been refactored to replace JWT with a token for authentication, and a new DeadLetterQueue class has been added to manage failed requests. Additionally, environment variables are now loaded using dotenv, and several test cases have been added to validate the new DLQ functionality. Minor adjustments were made to the .gitignore and tox.ini files to accommodate these changes.

Changes

File(s) Summary
.github/workflows/python-testing.yml Added ENVIRONMENT: test to the environment variables for testing purposes.
.gitignore Added .agentops/ to ignore list for better file management.
agentops/config.py Applied singleton pattern to Configuration class for consistent configuration management.
agentops/helpers.py Introduced ensure_dead_letter_queue function to manage DLQ file creation and existence.
agentops/http_client.py Refactored HttpClient to use tokens instead of JWTs, added DeadLetterQueue class for managing failed requests, and implemented retry logic for DLQ.
agentops/session.py Replaced jwt with token in HTTP requests to align with new authentication method.
tests/core_manual_tests/http_client/dead_letter_queue.py Added a new test script to validate DLQ functionality and JWT reauthorization.
tests/core_manual_tests/multi_session_llm.py Corrected session ID print statements for clarity.
tests/test_canary.py Added agentops.end_all_sessions() to setup/teardown for session management.
tests/test_http_client.py Introduced comprehensive unit tests for HttpClient and DLQ functionality.
tests/test_record_action.py, tests/test_record_tool.py, tests/test_session.py Integrated DLQ testing mode in setup/teardown to ensure isolated test environments.
tox.ini Added python-dotenv and python-dateutil to dependencies for environment management and date handling.

Copy link

Entelligence AI Bot Icon Entelligence AI Bot v4

Files selected (7)
  • .gitignore
    - agentops/config.py
    - agentops/helpers.py
    - agentops/http_client.py
    - agentops/session.py
    - tests/core_manual_tests/http_client/dead_letter_queue.py
    - tests/core_manual_tests/multi_session_llm.py
Files ignored (7)
  • .github/workflows/python-testing.yml
    - tests/test_canary.py
    - tests/test_http_client.py
    - tests/test_record_action.py
    - tests/test_record_tool.py
    - tests/test_session.py
    - tox.ini
Instructions

Emoji Descriptions:

  • 🟢 Low Priority - Can be handled at your convenience.
  • 🟡 Medium Priority - Important but not urgent.
  • 🔴 High Priority - Address immediately.
  • ⚠️ Potential Issue - May require further investigation.
  • 🔒 Security Vulnerability - Fix to ensure system safety.
  • 💻 Code Improvement - Suggestions to enhance code quality.
  • 🔨 Refactor Suggestion - Recommendations for restructuring code.
  • ℹ️ Others - General comments and information.

Interact with the Bot:

  • Send a message or request using the format:

    @Entelligence.AI + *your message*

    • Example: @Entelligence.AI Can you suggest improvements for this code?
  • Execute a command using the format:

    @Entelligence.AI + *"/command"*

Available Commands:

  • /updateCommit: Apply the suggested changes and commit them.
  • /updateGuideline: Modify an existing guideline.
  • /addGuideline: Introduce a new guideline.

Tips for Using @Entelligence.AI Effectively:

  • Specific Queries: For the best results, be specific with your requests. Example: @Entelligence.AI summarize the changes in this PR.
  • Focused Discussions: Tag @Entelligence.AI directly on specific code lines or files for detailed feedback.
  • Managing Reviews: Use review comments for targeted discussions on code snippets, and PR comments for broader queries about the entire PR.

Need More Help?

  • Visit our documentation for detailed guides on using Entelligence.AI.
  • Join our community to connect with others, request features, and share feedback.
  • Follow us for updates on new features and improvements.

Comment on lines 10 to 17
session_1 = agentops.start_session(tags=["multi-session-test-1"])
session_2 = agentops.start_session(tags=["multi-session-test-2"])

print("session_id_1: {}".format(session_1))
print("session_id_2: {}".format(session_2))
print("session_id_1: {}".format(session_1.session_id))
print("session_id_2: {}".format(session_2.session_id))

messages = [{"role": "user", "content": "Hello"}]

Choose a reason for hiding this comment

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

Entelligence AI Bot Icon Entelligence AI Bot v4

💻 Code maintainability 🟡

Ensure session_id attribute presence

The change to print the session IDs directly from the session objects improves clarity. However, ensure that the session_id attribute is always present in the session object to avoid potential attribute errors.

+print("session_id_1: {}".format(session_1.session_id))
+print("session_id_2: {}".format(session_2.session_id))
Commitable Code Suggestion:
Suggested change
session_1 = agentops.start_session(tags=["multi-session-test-1"])
session_2 = agentops.start_session(tags=["multi-session-test-2"])
print("session_id_1: {}".format(session_1))
print("session_id_2: {}".format(session_2))
print("session_id_1: {}".format(session_1.session_id))
print("session_id_2: {}".format(session_2.session_id))
messages = [{"role": "user", "content": "Hello"}]
print("session_id_1: {}".format(session_1.session_id))
print("session_id_2: {}".format(session_2.session_id))

Comment on lines 2 to 11
from uuid import UUID

from .log_config import logger
from .singleton import singleton


@singleton
class Configuration:
def __init__(self):
self.api_key: Optional[str] = None

Choose a reason for hiding this comment

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

Entelligence AI Bot Icon Entelligence AI Bot v4

ℹ️ Performance Improvement 🟡

Lazy Loading Configuration

Consider lazy loading the configuration values in the Configuration class to improve performance, especially if the configuration is large or if some values are rarely used.

+   def get_api_key(self):
+       if self.api_key is None:
+           self.api_key = self.load_api_key()
+       return self.api_key
Commitable Code Suggestion:
Suggested change
from uuid import UUID
from .log_config import logger
from .singleton import singleton
@singleton
class Configuration:
def __init__(self):
self.api_key: Optional[str] = None
def get_api_key(self):
if self.api_key is None:
self.api_key = self.load_api_key()
return self.api_key

#### 💻 Code maintainability 🟡

Thread Safety of Singleton

The introduction of the singleton pattern to the Configuration class is a good design choice for consistent configuration management. However, ensure that the singleton implementation is thread-safe to avoid potential issues in multi-threaded environments.

+   # Ensure thread safety in singleton implementation
Commitable Code Suggestion:
Suggested change
from uuid import UUID
from .log_config import logger
from .singleton import singleton
@singleton
class Configuration:
def __init__(self):
self.api_key: Optional[str] = None
# Ensure thread safety in singleton implementation

Comment on lines 179 to +197
return func(self, *args, **kwargs)

return wrapper


def ensure_dead_letter_queue():
# Define file path
file_path = os.path.join(".agentops", "dead_letter_queue.json")

# Check if directory exists
if not os.path.exists(".agentops"):
os.makedirs(".agentops")

# Check if file exists
if not os.path.isfile(file_path):
with open(file_path, "w") as f:
json.dump({"messages": []}, f)

return file_path

Choose a reason for hiding this comment

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

Entelligence AI Bot Icon Entelligence AI Bot v4

ℹ️ Performance Improvement 🟡

Optimize Directory Creation

The function checks for the existence of the file and creates it if it doesn't exist. This could be optimized by using os.makedirs with exist_ok=True to handle directory creation in one step, reducing the number of filesystem checks.

+    os.makedirs('.agentops', exist_ok=True)
Commitable Code Suggestion:
Suggested change
return func(self, *args, **kwargs)
return wrapper
def ensure_dead_letter_queue():
# Define file path
file_path = os.path.join(".agentops", "dead_letter_queue.json")
# Check if directory exists
if not os.path.exists(".agentops"):
os.makedirs(".agentops")
# Check if file exists
if not os.path.isfile(file_path):
with open(file_path, "w") as f:
json.dump({"messages": []}, f)
return file_path
os.makedirs('.agentops', exist_ok=True)

@raghavdixit99 raghavdixit99 deleted the dead-letter-queue branch October 24, 2024 16:17
@raghavdixit99 raghavdixit99 restored the dead-letter-queue branch October 24, 2024 16:20
@raghavdixit99 raghavdixit99 deleted the dead-letter-queue branch October 24, 2024 16:59
@raghavdixit99 raghavdixit99 restored the dead-letter-queue branch October 24, 2024 16:59
@raghavdixit99 raghavdixit99 deleted the dead-letter-queue branch October 24, 2024 17:04
@raghavdixit99 raghavdixit99 restored the dead-letter-queue branch October 24, 2024 17:04
@raghavdixit99 raghavdixit99 deleted the dead-letter-queue branch October 25, 2024 00:47
@raghavdixit99 raghavdixit99 restored the dead-letter-queue branch October 25, 2024 00:48
@raghavdixit99 raghavdixit99 deleted the dead-letter-queue branch October 25, 2024 14:28
@raghavdixit99 raghavdixit99 restored the dead-letter-queue branch October 25, 2024 14:29
@raghavdixit99 raghavdixit99 deleted the dead-letter-queue branch October 25, 2024 14:35
@raghavdixit99 raghavdixit99 restored the dead-letter-queue branch October 25, 2024 14:36
@raghavdixit99 raghavdixit99 deleted the dead-letter-queue branch October 25, 2024 18:54
@raghavdixit99 raghavdixit99 restored the dead-letter-queue branch October 25, 2024 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants