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 #435 - make start_session non blocking #23

Closed
wants to merge 24 commits into from

Conversation

raghavdixit99
Copy link
Owner

@raghavdixit99 raghavdixit99 commented Oct 25, 2024

Enhance AgentOps Initialization and Session Management

  • Purpose:
    Improve the initialization process and session management in the AgentOps client.
  • Key Changes:
    • Added _initialize_autogen_logger method to configure logging for autogen.
    • Introduced a callback mechanism in the Session class to handle post-initialization actions.
    • Updated session creation to manage pre-initialized agents more effectively.
    • Refactored logging error messages for better clarity during session initialization failures.
    • Adjusted test fixtures to ensure proper isolation and functionality.
  • Impact:
    These changes enhance the reliability and maintainability of the AgentOps client, particularly in session handling and logging.

✨ Generated with love by Kaizen ❤️

Original Description ## 📥 Pull Request

📘 Description
Make start session non-blocking

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

Copy link

kaizen-bot bot commented Oct 25, 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 API keys.


📁 File: agentops/client.py
🔍 Reasoning:
The code does not validate or sanitize API keys before using them, which could lead to exposure or misuse.

💡 Solution:
Implement validation for API keys to ensure they are in the expected format and not empty before use.

Current Code:

if self._config.api_key is None:

Suggested Code:

         if not self._config.api_key or not isinstance(self._config.api_key, str):

2. Unnecessary thread creation in session management.


📁 File: agentops/session.py
🔍 Reasoning:
Creating a new thread for each session can lead to resource exhaustion under heavy load.

💡 Solution:
Consider using a thread pool or asynchronous programming to manage sessions more efficiently.

Current Code:

self.thread = threading.Thread(target=self._run, args=(callback,))

Suggested Code:

        self.thread = concurrent.futures.ThreadPoolExecutor().submit(self._run, callback)

✨ 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.

@@ -87,16 +87,13 @@ def initialize(self) -> Union[Session, None]:
return

self.unsuppress_logs()

if self._config.api_key is None:
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 API keys.

Solution: Implement validation for API keys to ensure they are in the expected format and not empty before use.
!! Make sure the following suggestion is correct before committing it !!

Suggested change
if self._config.api_key is None:
if not self._config.api_key or not isinstance(self._config.api_key, str):

self.stop_flag = threading.Event()
self.thread = threading.Thread(target=self._run)
self.thread = threading.Thread(target=self._run, args=(callback,))
Copy link

Choose a reason for hiding this comment

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

Comment: Unnecessary thread creation in session management.

Solution: Consider using a thread pool or asynchronous programming to manage sessions more efficiently.
!! Make sure the following suggestion is correct before committing it !!

Suggested change
self.thread = threading.Thread(target=self._run, args=(callback,))
self.thread = concurrent.futures.ThreadPoolExecutor().submit(self._run, callback)

Copy link

Entelligence AI Bot Icon Entelligence AI Bot v4

Summary

Purpose:
Enhance session management and logging mechanisms in the AgentOps library.

Key Changes:

  • New Feature: Introduced a callback function for session start to streamline session lifecycle.
  • Enhancement: Improved error handling during session start for more reliable outcomes.
  • Refactor: Removed redundant code and whitespace to streamline and simplify codebase.
  • Test: Updated pytest fixtures for more robust testing and improved request history assertions.

Impact:
Streamlines session lifecycle, enhances logging capabilities, and ensures more reliable testing outcomes.

Copy link

Entelligence AI Bot Icon Entelligence AI Bot v4

Walkthrough

This update enhances the AgentOps library by refining session management and logging mechanisms. Key changes include the introduction of a callback function for session initialization, improved error handling during session start, and the removal of redundant code. Additionally, the test suite has been updated to ensure more robust testing with automatic fixture application and improved request history assertions. These modifications aim to streamline the session lifecycle, enhance logging capabilities, and ensure more reliable testing outcomes.

Changes

File(s) Summary
agentops/__init__.py Added initialization of the autogen logger and removed unnecessary whitespace.
agentops/client.py Replaced _initialize_partner_framework with _initialize_autogen_logger and added a callback function for session start.
agentops/host_env.py Simplified the retrieval of installed package metadata.
agentops/http_client.py Removed unnecessary whitespace in the post method.
agentops/session.py Introduced a callback mechanism for session start, improved error handling, and refined session management logic.
tests/test_agent.py, tests/test_canary.py, tests/test_events.py, tests/test_pre_init.py, tests/test_record_action.py, tests/test_record_tool.py, tests/test_session.py, tests/test_teardown.py Updated pytest fixtures to have a function scope and added automatic application where necessary. Improved request history assertions in tests.

Copy link

Entelligence AI Bot Icon Entelligence AI Bot v4

Files selected (5)
  • agentops/init.py
    - agentops/client.py
    - agentops/host_env.py
    - agentops/http_client.py
    - agentops/session.py
Files ignored (8)
  • tests/test_agent.py
    - tests/test_canary.py
    - tests/test_events.py
    - tests/test_pre_init.py
    - tests/test_record_action.py
    - tests/test_record_tool.py
    - tests/test_session.py
    - tests/test_teardown.py
Instructions

Emoji Descriptions:

  • ⚠️ 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 22 to 28

if "autogen" in sys.modules:
Client().configure(instrument_llm_calls=False)
Client()._initialize_autogen_logger()
Client().add_default_tags(["autogen"])

if "crewai" in sys.modules:

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

Initialize Autogen Logger for Enhanced Logging

The addition of _initialize_autogen_logger() ensures that the logging mechanism is set up correctly when the autogen module is present. This change enhances the logging capabilities, allowing for better tracking and debugging of operations related to the autogen module.

Commitable Code Suggestion:
Suggested change
if "autogen" in sys.modules:
Client().configure(instrument_llm_calls=False)
Client()._initialize_autogen_logger()
Client().add_default_tags(["autogen"])
if "crewai" in sys.modules:
+ Client()._initialize_autogen_logger()

Comment on lines 94 to 99
)

self._handle_unclean_exits()
self._initialize_partner_framework()

self._initialized = True

if self._config.instrument_llm_calls:
Copy link

@github-actions github-actions bot Oct 25, 2024

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

ℹ️ Logic Error

Potential Missing Initialization Logic

The removal of _initialize_partner_framework() without a replacement or alternative initialization logic could lead to missing setup steps for partner frameworks. Ensure that any necessary initialization previously handled by this method is now covered elsewhere in the code.

Commitable Code Suggestion:
Suggested change
)
self._handle_unclean_exits()
self._initialize_partner_framework()
self._initialized = True
if self._config.instrument_llm_calls:
def initialize(self) -> Union[Session, None]:
)
self._handle_unclean_exits()
- self._initialize_partner_framework()
-
self._initialized = True
if self._config.instrument_llm_calls:
<br>
</details>

Comment on lines 61 to 73
"errors": 0,
"apis": 0,
}

self.is_running = False
active_sessions.append(self)
self.stop_flag = threading.Event()
self.thread = threading.Thread(target=self._run)
self.thread = threading.Thread(target=self._run, args=(callback,))
self.thread.daemon = True
self.thread.start()

self.is_running = self._start_session()
if self.is_running == False:
self.stop_flag.set()
self.thread.join(timeout=1)

def set_video(self, video: str) -> None:
"""
Sets a url to the video recording of the session.

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

ℹ️ Logic Error

Ensure Session Stops if Initialization Fails

The removal of the initial session start check and immediate stop flag setting could lead to the session thread running even if the session fails to start. This could result in unnecessary resource usage and potential errors.

+        self.is_running = self._start_session()
+        if self.is_running == False:
+            self.stop_flag.set()
+            self.thread.join(timeout=1)
Commitable Code Suggestion:
Suggested change
"errors": 0,
"apis": 0,
}
self.is_running = False
active_sessions.append(self)
self.stop_flag = threading.Event()
self.thread = threading.Thread(target=self._run)
self.thread = threading.Thread(target=self._run, args=(callback,))
self.thread.daemon = True
self.thread.start()
self.is_running = self._start_session()
if self.is_running == False:
self.stop_flag.set()
self.thread.join(timeout=1)
def set_video(self, video: str) -> None:
"""
Sets a url to the video recording of the session.
self.is_running = self._start_session()
if self.is_running == False:
self.stop_flag.set()
self.thread.join(timeout=1)

Comment on lines 321 to 328
self._pre_init_queue["agents"].append(
{"name": name, "agent_id": agent_id}
)
session.create_agent(name=name, agent_id=agent_id)
else:
session.create_agent(name=name, agent_id=agent_id)

return agent_id

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

ℹ️ Logic Error

Conditional Agent Creation Logic

The addition of an else block for session.create_agent() ensures that agents are only created when the session is running. Verify that this logic does not inadvertently skip agent creation in scenarios where it is required.

Commitable Code Suggestion:

@@ -305,7 +321,8 @@ def create_agent(
self._pre_init_queue["agents"].append(
{"name": name, "agent_id": agent_id}
)

  •        session.create_agent(name=name, agent_id=agent_id)
    
  •        else:
    
  •            session.create_agent(name=name, agent_id=agent_id)
    
       return agent_id
    

Comment on lines 47 to 57


def get_installed_packages():

try:
return {
# TODO: test
# TODO: add to opt out
"Installed Packages": {
dist.metadata["Name"]: dist.version
dist.metadata.get("Name"): dist.metadata.get("Version")
for dist in importlib.metadata.distributions()
}
}

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 Improvement

Use of get Method for Safe Metadata Access

The change from using direct dictionary access to using the get method for retrieving metadata values is a good practice. It prevents potential KeyError exceptions if the keys 'Name' or 'Version' are not present in the metadata. However, consider adding a default value to the get method to handle cases where the metadata might be missing these keys.

+                dist.metadata.get("Name", "Unknown"): dist.metadata.get("Version", "Unknown")
Commitable Code Suggestion:
Suggested change
def get_installed_packages():
try:
return {
# TODO: test
# TODO: add to opt out
"Installed Packages": {
dist.metadata["Name"]: dist.version
dist.metadata.get("Name"): dist.metadata.get("Version")
for dist in importlib.metadata.distributions()
}
}
dist.metadata.get("Name", "Unknown"): dist.metadata.get("Version", "Unknown")

Comment on lines 81 to 89

if jwt is not None:
JSON_HEADER["Authorization"] = f"Bearer {jwt}"

res = request_session.post(
url, data=payload, headers=JSON_HEADER, timeout=20
)

result.parse(res)
except requests.exceptions.Timeout:
result.code = 408

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

ℹ️ Error Handling

Add Logging for Timeout Exceptions

The current implementation catches a requests.exceptions.Timeout exception and sets the result code to 408. Consider adding logging for this exception to provide more context when a timeout occurs, which can aid in debugging and monitoring.

         except requests.exceptions.Timeout:
+            logging.error(f"Request to {url} timed out.")
             result.code = 408
Commitable Code Suggestion:
Suggested change
if jwt is not None:
JSON_HEADER["Authorization"] = f"Bearer {jwt}"
res = request_session.post(
url, data=payload, headers=JSON_HEADER, timeout=20
)
result.parse(res)
except requests.exceptions.Timeout:
result.code = 408
except requests.exceptions.Timeout:
logging.error(f"Request to {url} timed out.")
result.code = 408

Comment on lines 361 to 379
elif event_type == "apis":
self.event_counts["apis"] += 1

def _run(self) -> None:
def _run(self, callback: Optional[Callable[["Session"], None]] = None) -> None:
self.is_running = self._start_session()

if callback:
callback(self)

if self.is_running == False:
self.stop_flag.set()
self.thread.join(timeout=1)

while not self.stop_flag.is_set():
time.sleep(self.config.max_wait_time / 1000)
if self.queue:
if self.queue and self.jwt is not None:
self._flush_queue()

def create_agent(self, name, agent_id):

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

Ensure Non-blocking Callback Execution

The addition of a callback function in the _run method is beneficial for extensibility. However, ensure that the callback execution does not block the main thread, which could delay session operations.

Comment on lines 232 to 261
if tags is not None:
session_tags.update(tags)

def _start_session_callback(session: Session):
if session.is_running:
if len(self._pre_init_queue["agents"]) > 0:
for agent_args in self._pre_init_queue["agents"]:
session.create_agent(
name=agent_args["name"], agent_id=agent_args["agent_id"]
)
self._pre_init_queue["agents"] = []

logger.info(
colored(
f"\x1b[34mSession Replay: https://app.agentops.ai/drilldown?session_id={session.session_id}\x1b[0m",
"blue",
)
)
else:
self._sessions.remove(session)

session = Session(
session_id=session_id,
tags=list(session_tags),
host_env=get_host_env(self._config.env_data_opt_out),
config=self._config,
callback=_start_session_callback,
)

if not session.is_running:

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 Callback Usage for Session Initialization

The introduction of _start_session_callback improves session management by handling pre-initialized agents and logging session replay links. However, ensure that the callback is only set when necessary to avoid unnecessary overhead in session creation.

Commitable Code Suggestion:

@@ -235,11 +232,30 @@ def start_session( if tags is not None: session_tags.update(tags) + def _start_session_callback(session: Session): + if session.is_running: + if len(self._pre_init_queue["agents"]) > 0: + for agent_args in self._pre_init_queue["agents"]: + session.create_agent( + name=agent_args["name"], agent_id=agent_args["agent_id"] + ) + self._pre_init_queue["agents"] = [] + + logger.info( + colored( + f"\x1b[34mSession Replay: https://app.agentops.ai/drilldown?session_id={session.session_id}\x1b[0m", + "blue", + ) + ) + else: + self._sessions.remove(session) + session = Session( session_id=session_id, tags=list(session_tags), host_env=get_host_env(self._config.env_data_opt_out), config=self._config, + callback=_start_session_callback, ) if not session.is_running:

Comment on lines 271 to 291
self.config.parent_key,
)
except ApiServerException as e:
return logger.error(f"Could not start session - {e}")
logger.error(f"Could not start session - {e}")
return False

logger.debug(res.body)

if res.code != 200:
logger.error(f"Could not start session - server error")
return False

jwt = res.body.get("jwt", None)
self.jwt = jwt
if jwt is None:
logger.error(
f"Could not start session - server could not authenticate your API Key"
)
return False

session_url = res.body.get(

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

🔒 Security Suggestion

Sanitize Error Messages in Logs

The error handling for session start has been improved, but ensure that sensitive information is not logged. Consider sanitizing error messages to prevent potential exposure of sensitive data.

Commitable Code Suggestion:

@@ -274,16 +271,21 @@ def _start_session(self):
self.config.parent_key,
)
except ApiServerException as e:

  •            return logger.error(f"Could not start session - {e}")
    
  •            logger.error(f"Could not start session - {e}")
    
  •            return False
    
           logger.debug(res.body)
    
           if res.code != 200:
    
  •            logger.error(f"Could not start session - server error")
               return False
    
           jwt = res.body.get("jwt", None)
           self.jwt = jwt
           if jwt is None:
    
  •            logger.error(
    
  •                f"Could not start session - server could not authenticate your API Key"
    
  •            )
               return False
    
           session_url = res.body.get(
    

@raghavdixit99 raghavdixit99 deleted the move-start-session-to-thread branch October 25, 2024 19:07
@raghavdixit99 raghavdixit99 restored the move-start-session-to-thread branch October 25, 2024 19:08
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.

3 participants