Skip to content

Conversation

@nina-kollman
Copy link
Contributor

@nina-kollman nina-kollman commented Dec 21, 2025

  • I have added tests that cover my changes.
  • If adding a new instrumentation or changing an existing one, I've added screenshots from some observability platform showing the change.
  • PR name follows conventional commits format: feat(instrumentation): ... or fix(instrumentation): ....
  • (If applicable) I have updated the documentation accordingly.

Important

Introduces Associations for trace management, a Gemini-based chatbot, and tests for association propagation in Traceloop SDK.

  • New Features:
    • Added Associations class and AssociationProperty enum in associations.py for managing trace associations.
    • Integrated association propagation into tracing and client for enriching span attributes (customer, user, session).
    • Added a Gemini-based chatbot in gemini_chatbot.py with tool-backed weather, time, and knowledge queries.
  • Tests:
    • Added tests in test_associations.py to verify associations are propagated as span attributes across task and workflow traces.
  • Client Updates:
    • Updated Client class in client.py to include Associations for managing trace associations.

This description was created by Ellipsis for 97dd21a. You can customize this summary. It will automatically update as commits are pushed.


Summary by CodeRabbit

  • New Features

    • Added a Gemini-based chatbot with integrated tools for weather lookup, time retrieval, and knowledge base search.
    • Added associations API to track user, customer, and session identities in observability traces.
  • Tests

    • Added test suite for associations functionality.
  • Chores

    • Updated .gitignore for development files.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 21, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

The changes introduce a new Gemini-based chatbot module with tool support and Traceloop observability integration, while extending the Traceloop SDK with an associations feature for trace metadata management. New test coverage validates the associations functionality, and configuration is updated to exclude development files.

Changes

Cohort / File(s) Summary
Gemini Chatbot Implementation
packages/sample-app/sample_app/chats/gemini_chatbot.py
New chatbot module with three tool functions (weather, time, knowledge base search), tool wrappers with Gemini function declarations, execute_function() for tool routing, and process_message() workflow for stateful conversation management with tool invocation loops. Includes interactive main() entry point and in-memory data simulation.
Traceloop Associations Core
packages/traceloop-sdk/traceloop/sdk/associations/associations.py
New module defining AssociationProperty enum (CUSTOMER_ID, USER_ID, SESSION_ID), Association type alias, and Associations class with static set() method for propagating trace metadata to the tracing layer.
Traceloop SDK Integration
packages/traceloop-sdk/traceloop/sdk/associations/__init__.py, packages/traceloop-sdk/traceloop/sdk/__init__.py, packages/traceloop-sdk/traceloop/sdk/client/client.py
Package initializer re-exports associations API; top-level SDK namespace imports AssociationProperty; Client class extended with new associations attribute initialized in __init__.
Traceloop Associations Tests
packages/traceloop-sdk/tests/test_associations.py
New test module with client_with_exporter fixture and four test cases validating single/multiple association creation, in-workflow association setting, and span attribute propagation.
Configuration
.gitignore
Added packages/sample-app/sample_app/development/ to ignore development files.

Sequence Diagrams

sequenceDiagram
    participant User
    participant ChatBot as process_message()
    participant GeminiAPI as Gemini API
    participant Tool as Tool Functions
    
    User->>ChatBot: user_message
    ChatBot->>ChatBot: add user message to history
    loop Tool Invocation Loop
        ChatBot->>GeminiAPI: generate_content(history, tools)
        alt Tool Call Returned
            GeminiAPI-->>ChatBot: tool_use response
            ChatBot->>ChatBot: extract function_name & args
            ChatBot->>Tool: execute_function()
            Tool-->>ChatBot: result string
            ChatBot->>ChatBot: append call + result to history
        else Text Response Returned
            GeminiAPI-->>ChatBot: text response
            ChatBot->>ChatBot: finalize response
            ChatBot-->>User: assistant message + history
            break End Conversation
            end
        end
    end
Loading
sequenceDiagram
    participant App as Application
    participant Client as Traceloop Client
    participant Associations as Associations API
    participant TracingLayer as Tracing Layer
    participant SpanExporter as OpenTelemetry
    
    App->>Client: initialize()
    Client->>Associations: Associations()
    
    App->>Associations: set([(SESSION_ID, "123"), (USER_ID, "user_a")])
    Associations->>TracingLayer: set_association_properties({...})
    TracingLayer->>SpanExporter: apply properties to active spans
    SpanExporter-->>TracingLayer: attributes set
    
    App->>Client: start workflow/task
    Client->>SpanExporter: create span with association attributes
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Hops with glee through traces bright,
Gemini bots chat through the night,
Associations bind and flow,
Customer, user, session glow—
Observability's delight!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'fix(tracing): Add association property' partially relates to the changeset—it mentions adding an association property, which is accurate, but it undersells the broader scope of the change, which includes a complete Gemini chatbot implementation and association system integration across the SDK. The title focuses on only one aspect of a multi-faceted changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch nk/association

Comment @coderabbitai help to get the list of available commands and usage tips.

@nina-kollman nina-kollman changed the title Nk/association fix(tracing): Add association property Dec 21, 2025
@nina-kollman nina-kollman marked this pull request as ready for review December 21, 2025 08:47
Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed everything up to 8c2987c in 1 minute and 52 seconds. Click for details.
  • Reviewed 538 lines of code in 7 files
  • Skipped 0 files when reviewing.
  • Skipped posting 5 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. packages/sample-app/sample_app/chats/gemini_chatbot.py:129
  • Draft comment:
    Using associations.set to tag the conversation is good. Consider adding input validation for the conversation_id to avoid empty or malformed values.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% This is a new file being added, so all the code is technically new. The comment is suggesting defensive programming by adding validation. However, looking at the actual usage in main(), the conversation_id is always generated as a UUID string, so it will never be empty or malformed in practice. The comment is speculative - it's suggesting to guard against a problem that doesn't exist in the current code. The function could theoretically be called from elsewhere with bad input, but that's speculative. According to the rules, I should not keep speculative comments like "If X, then Y is an issue" - I should only comment if it's definitely an issue. There's no evidence of actual misuse here. The comment could be valid if this function is part of a public API that could be called from other places with arbitrary input. I might be missing context about whether this function is intended to be called from other modules or if it's only used internally within this file. The validation could prevent runtime errors if someone calls this function incorrectly. Even if the function could be called from elsewhere, the comment is still speculative because there's no evidence in the current code that it will be called with invalid input. The only caller in this file (main()) always passes a valid UUID. The rules explicitly state not to make speculative comments. This is a "consider adding" suggestion for defensive programming, not a clear bug or issue. This comment should be deleted. It's a speculative suggestion for defensive programming without evidence of an actual issue. The only usage in the code always passes a valid UUID string, and there's no indication that invalid input will be passed. This violates the rule against speculative comments.
2. packages/traceloop-sdk/tests/test_associations.py:60
  • Draft comment:
    The tests correctly set and assert associations. Note that span order is assumed; consider verifying spans based on attributes rather than fixed order for increased robustness.
  • Reason this comment was not posted:
    Confidence changes required: 50% <= threshold 50% None
3. packages/traceloop-sdk/traceloop/sdk/associations/associations.py:44
  • Draft comment:
    Ensure get_value returns a dict before updating associations to prevent potential type errors. Consider adding a type check or fallback logic.
  • Reason this comment was not posted:
    Comment looked like it was already resolved.
4. packages/traceloop-sdk/traceloop/sdk/client/client.py:72
  • Draft comment:
    Initialization of associations in the client constructor is straightforward and ensures associations are available in subsequent operations.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
5. packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py:352
  • Draft comment:
    Associations are correctly applied to spans in default_span_processor_on_start. For extra safety, consider prefixing association keys to avoid any collision with other span attributes.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% This is a code quality suggestion about the new associations feature. The comment points out that the keys from the associations dictionary are being used directly as span attribute names without any namespace/prefix. This could indeed cause collisions if the associations dictionary contains keys that match existing span attribute names. Looking at the pattern in the codebase, other similar features do use prefixes (association_properties, prompt_template_variables). However, I need to consider: 1) Is this definitely about changed code? Yes, lines 352-357 are new additions. 2) Is this actionable? Yes, it's a clear suggestion to add prefixing. 3) Is this speculative or definite? It's somewhat speculative - it says "consider" and talks about avoiding "any collision" which is a potential issue, not a definite one. The comment doesn't prove there IS a collision, just that there COULD be one. The comment is somewhat speculative - it uses "consider" and talks about avoiding potential collisions rather than pointing to a definite issue. Without knowing what keys are actually in the associations dictionary or what the intended use case is, we can't be certain this is a problem. Perhaps the associations feature is intentionally designed to allow setting arbitrary span attributes without prefixes. While the comment is somewhat speculative, it's a reasonable code quality concern based on the established patterns in the codebase. However, the rules state "Do NOT make speculative comments, such as 'If X, then Y is an issue', Only comment if it is definitely an issue." The word "consider" and the phrase "to avoid any collision" make this a speculative suggestion rather than a definite issue. Without more context about the intended design of the associations feature, we cannot be certain this is incorrect. This comment should be deleted. While it raises a reasonable code quality concern, it is speculative in nature ("consider...to avoid any collision") rather than pointing to a definite issue. The rules explicitly state not to make speculative comments. Without evidence that collisions will actually occur or that this design is incorrect, we should assume the author implemented it correctly.

Workflow ID: wflow_ZvxkHXwf5pprlvcm

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

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.

Actionable comments posted: 3

🧹 Nitpick comments (3)
packages/traceloop-sdk/traceloop/sdk/__init__.py (1)

34-34: Re-export import flagged as unused by Flake8.

The import is intentionally a re-export for public API access, but Flake8 reports it as unused (F401). To silence the linter and make the intent explicit, consider adding an __all__ declaration or using an explicit re-export pattern.

🔎 Proposed fix
 from traceloop.sdk.client.client import Client
-from traceloop.sdk.associations.associations import AssociationProperty
+from traceloop.sdk.associations.associations import AssociationProperty  # noqa: F401

Alternatively, define __all__ at module level to explicitly declare public exports.

packages/traceloop-sdk/traceloop/sdk/associations/__init__.py (1)

1-7: LGTM! Clean package re-export structure.

The file correctly exposes the public API for the associations module. The __all__ list is functional but could be sorted alphabetically per Ruff's RUF022 recommendation.

🔎 Optional: Sort __all__ alphabetically
-__all__ = ["Associations", "AssociationProperty", "Association"]
+__all__ = ["Association", "AssociationProperty", "Associations"]
packages/sample-app/sample_app/chats/gemini_chatbot.py (1)

221-223: Consider narrowing the exception type.

Catching bare Exception (Ruff BLE001) can mask unexpected errors. For a sample app this may be acceptable, but consider catching more specific exceptions like google.genai.errors.APIError or similar.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0fc7340 and 8c2987c.

📒 Files selected for processing (7)
  • packages/sample-app/sample_app/chats/gemini_chatbot.py (1 hunks)
  • packages/traceloop-sdk/tests/test_associations.py (1 hunks)
  • packages/traceloop-sdk/traceloop/sdk/__init__.py (1 hunks)
  • packages/traceloop-sdk/traceloop/sdk/associations/__init__.py (1 hunks)
  • packages/traceloop-sdk/traceloop/sdk/associations/associations.py (1 hunks)
  • packages/traceloop-sdk/traceloop/sdk/client/client.py (3 hunks)
  • packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Store API keys only in environment variables/secure vaults; never hardcode secrets in code
Use Flake8 for code linting and adhere to its rules

Files:

  • packages/traceloop-sdk/traceloop/sdk/associations/__init__.py
  • packages/traceloop-sdk/traceloop/sdk/client/client.py
  • packages/traceloop-sdk/tests/test_associations.py
  • packages/traceloop-sdk/traceloop/sdk/__init__.py
  • packages/traceloop-sdk/traceloop/sdk/associations/associations.py
  • packages/sample-app/sample_app/chats/gemini_chatbot.py
  • packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py
🧠 Learnings (1)
📚 Learning: 2025-08-04T15:23:44.799Z
Learnt from: nina-kollman
Repo: traceloop/openllmetry PR: 3219
File: packages/traceloop-sdk/tests/datasets/mock_objects.py:105-106
Timestamp: 2025-08-04T15:23:44.799Z
Learning: In the traceloop-sdk project, directly accessing private attributes like _client is acceptable in test mock objects and utilities, even though it breaks encapsulation principles, because it's isolated to test code and not production code.

Applied to files:

  • packages/traceloop-sdk/traceloop/sdk/__init__.py
🧬 Code graph analysis (4)
packages/traceloop-sdk/traceloop/sdk/associations/__init__.py (1)
packages/traceloop-sdk/traceloop/sdk/associations/associations.py (2)
  • Associations (22-54)
  • AssociationProperty (9-15)
packages/traceloop-sdk/traceloop/sdk/client/client.py (1)
packages/traceloop-sdk/traceloop/sdk/associations/associations.py (1)
  • Associations (22-54)
packages/traceloop-sdk/tests/test_associations.py (3)
packages/traceloop-sdk/traceloop/sdk/__init__.py (2)
  • Traceloop (37-268)
  • init (49-199)
packages/traceloop-sdk/traceloop/sdk/associations/associations.py (1)
  • AssociationProperty (9-15)
packages/traceloop-sdk/traceloop/sdk/utils/in_memory_span_exporter.py (4)
  • export (45-51)
  • InMemorySpanExporter (22-61)
  • clear (35-38)
  • get_finished_spans (40-43)
packages/traceloop-sdk/traceloop/sdk/__init__.py (1)
packages/traceloop-sdk/traceloop/sdk/associations/associations.py (1)
  • AssociationProperty (9-15)
🪛 Flake8 (7.3.0)
packages/traceloop-sdk/traceloop/sdk/__init__.py

[error] 34-34: 'traceloop.sdk.associations.associations.AssociationProperty' imported but unused

(F401)

🪛 Ruff (0.14.8)
packages/traceloop-sdk/traceloop/sdk/associations/__init__.py

7-7: __all__ is not sorted

Apply an isort-style sorting to __all__

(RUF022)

packages/sample-app/sample_app/chats/gemini_chatbot.py

221-221: Do not catch blind exception: Exception

(BLE001)

🔇 Additional comments (9)
packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py (1)

352-356: LGTM! Association enrichment follows existing patterns.

The code correctly reads associations from context and applies them as span attributes, consistent with the handling of other context values (workflow_name, agent_name, entity_path). The stringification with str(value) ensures attribute values are safe for OpenTelemetry.

packages/traceloop-sdk/traceloop/sdk/client/client.py (1)

9-9: LGTM! Clean integration of Associations into Client.

The Associations attribute follows the existing pattern established by other client features (user_feedback, datasets, etc.), providing a consistent API surface for users to access via client.associations.set(...).

Also applies to: 30-30, 72-72

packages/traceloop-sdk/tests/test_associations.py (4)

48-73: Test coverage for single association is well-structured.

The test properly validates that associations set before workflow execution propagate to both task and workflow spans.


76-111: Good coverage for multiple associations.

The test validates that all three associations propagate correctly to both span types.


114-146: Tests associations set within workflow context.

This validates the important use case of setting associations mid-workflow.


149-171: Comprehensive test for all enum values.

Good validation that all AssociationProperty enum members work correctly.

packages/traceloop-sdk/traceloop/sdk/associations/associations.py (1)

22-53: Well-structured Associations class with clear API.

The implementation correctly:

  • Merges new associations with existing context values
  • Attaches updated associations to OpenTelemetry context
  • Sets attributes on the current span for immediate visibility

The docstring provides helpful usage examples.

packages/sample-app/sample_app/chats/gemini_chatbot.py (2)

53-108: Tool declarations are well-structured.

The function declarations follow the Gemini API pattern correctly with proper schema definitions.


124-187: Workflow implementation demonstrates associations API effectively.

The process_message function correctly uses the new associations API to attach conversation IDs to spans, providing good observability for multi-turn conversations.

Copy link
Contributor

@ellipsis-dev ellipsis-dev 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

Changes requested ❌

Reviewed 1af680b in 2 minutes and 4 seconds. Click for details.
  • Reviewed 103 lines of code in 3 files
  • Skipped 0 files when reviewing.
  • Skipped posting 2 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. packages/sample-app/sample_app/chats/gemini_chatbot.py:128
  • Draft comment:
    Inline comment is outdated—update 'conversation_id' to 'session_id' to match the code change.
  • Reason this comment was not posted:
    Comment was on unchanged code.
2. packages/sample-app/sample_app/chats/gemini_chatbot.py:125
  • Draft comment:
    Update the function docstring to reference 'session_id' instead of the outdated 'chat_id'.
  • Reason this comment was not posted:
    Comment was on unchanged code.

Workflow ID: wflow_oIcBnmvFwCTrKM8n

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

spans = exporter.get_finished_spans()
workflow_span = spans[0]

assert workflow_span.attributes["session_id"] == "conv-1"
Copy link
Contributor

Choose a reason for hiding this comment

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

The test sets two SESSION_ID associations ("conv-1" then "session-4"), but the implementation overwrites duplicates. Adjust the assertions to expect only the final value.

Suggested change
assert workflow_span.attributes["session_id"] == "conv-1"

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.

Actionable comments posted: 2

♻️ Duplicate comments (2)
packages/sample-app/sample_app/chats/gemini_chatbot.py (2)

11-11: Handle potential None from Traceloop.init().

This issue was previously raised and remains unresolved. Line 129 will raise AttributeError if traceloop is None.


150-176: Add bounds checking for response access.

This issue was previously raised and remains unresolved. Direct indexing of response.candidates[0].content.parts[0] can raise IndexError for empty or malformed responses.

🧹 Nitpick comments (3)
packages/traceloop-sdk/traceloop/sdk/associations/associations.py (1)

24-53: Consider adding input validation for association values.

The method doesn't validate that association values are non-empty. While OpenTelemetry context is typically thread-local (mitigating concurrency concerns), adding a simple check for empty strings could improve robustness.

🔎 Optional: Add validation for empty values
     @staticmethod
     def set(associations: Sequence[Association]) -> None:
         """
         Set associations that will be added directly to all spans in the current context.

         Args:
             associations: A sequence of (property, value) tuples

         Example:
             # Single association
             traceloop.associations.set([(AssociationProperty.SESSION_ID, "conv-123")])

             # Multiple associations
             traceloop.associations.set([
                 (AssociationProperty.USER_ID, "user-456"),
                 (AssociationProperty.SESSION_ID, "session-789")
             ])
         """
+        # Validate inputs
+        for prop, value in associations:
+            if not value or not value.strip():
+                raise ValueError(f"Association value for {prop.value} cannot be empty")
+        
         # Store all associations in context
         current_associations: dict[str, str] = get_value(ASSOCIATIONS_KEY) or {}  # type: ignore
         for prop, value in associations:
             current_associations[prop.value] = value

         attach(set_value(ASSOCIATIONS_KEY, current_associations))

         # Also set directly on the current span
         span = trace.get_current_span()
         if span and span.is_recording():
             for prop, value in associations:
                 span.set_attribute(prop.value, value)
packages/sample-app/sample_app/chats/gemini_chatbot.py (2)

138-187: Add error handling and loop safeguards to prevent infinite loops.

The while True loop lacks error handling for API failures and has no maximum iteration limit. If the Gemini API consistently returns malformed responses or the model gets stuck in a tool-calling loop, this could run indefinitely.

🔎 Proposed safeguards
     # Keep trying until we get a final response (handle tool calls)
+    max_iterations = 10
+    iteration = 0
-    while True:
+    while iteration < max_iterations:
+        iteration += 1
+        
         # Generate content with tools
-        response = client.models.generate_content(
-            model="gemini-2.0-flash-exp",
-            contents=conversation_history,
-            config=types.GenerateContentConfig(
-                tools=[weather_tool, time_tool, knowledge_tool],
-                temperature=0.7,
-            )
-        )
+        try:
+            response = client.models.generate_content(
+                model="gemini-2.0-flash-exp",
+                contents=conversation_history,
+                config=types.GenerateContentConfig(
+                    tools=[weather_tool, time_tool, knowledge_tool],
+                    temperature=0.7,
+                )
+            )
+        except Exception as e:
+            return f"Error generating response: {e}", conversation_history

         # Check if the model wants to use a tool
-        if response.candidates[0].content.parts[0].function_call:
+        if (response.candidates and 
+            response.candidates[0].content.parts and
+            response.candidates[0].content.parts[0].function_call):
             function_call = response.candidates[0].content.parts[0].function_call
             function_name = function_call.name
             function_args = dict(function_call.args)

             print(f"[Tool Call]: {function_name}({function_args})")

             # Execute the function
-            function_result = execute_function(function_name, function_args)
+            try:
+                function_result = execute_function(function_name, function_args)
+            except Exception as e:
+                function_result = f"Error executing function: {e}"
+                
             print(f"[Tool Result]: {function_result}")

             # Add the model's function call to history
             conversation_history.append({
                 "role": "model",
                 "parts": [{"function_call": function_call}]
             })

             # Add the function result to history
             conversation_history.append({
                 "role": "user",
                 "parts": [{
                     "function_response": types.FunctionResponse(
                         name=function_name,
                         response={"result": function_result}
                     )
                 }]
             })
         else:
             # Got a text response, we're done with this turn
             assistant_message = response.text

             # Add assistant response to conversation history
             conversation_history.append({
                 "role": "model",
                 "parts": [{"text": assistant_message}]
             })

             return assistant_message, conversation_history
+    
+    # Max iterations reached
+    return "Maximum conversation turns reached. Please try rephrasing your question.", conversation_history

216-223: Consider more specific exception handling.

The broad Exception catch (flagged by Ruff BLE001) is acceptable for a sample application to maintain conversation flow, but consider catching specific exceptions (e.g., genai.APIError, ValueError) separately for better error diagnostics.

🔎 Optional: More specific exception handling
         # Process the message
         try:
             assistant_message, conversation_history = process_message(
                 chat_id, user_message, conversation_history
             )
             print(f"\nAssistant: {assistant_message}")
+        except (KeyError, ValueError, AttributeError) as e:
+            print(f"\nConfiguration Error: {e}")
+            print("Please check your setup and try again.")
+            break
         except Exception as e:
             print(f"\nError: {e}")
             print("Please try again.")
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8c2987c and 1af680b.

📒 Files selected for processing (3)
  • packages/sample-app/sample_app/chats/gemini_chatbot.py (1 hunks)
  • packages/traceloop-sdk/tests/test_associations.py (1 hunks)
  • packages/traceloop-sdk/traceloop/sdk/associations/associations.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/traceloop-sdk/tests/test_associations.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Store API keys only in environment variables/secure vaults; never hardcode secrets in code
Use Flake8 for code linting and adhere to its rules

Files:

  • packages/sample-app/sample_app/chats/gemini_chatbot.py
  • packages/traceloop-sdk/traceloop/sdk/associations/associations.py
🪛 Ruff (0.14.8)
packages/sample-app/sample_app/chats/gemini_chatbot.py

221-221: Do not catch blind exception: Exception

(BLE001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Test Packages (3.11)
  • GitHub Check: Test Packages (3.12)
  • GitHub Check: Test Packages (3.10)
  • GitHub Check: Build Packages (3.11)
  • GitHub Check: Lint
🔇 Additional comments (8)
packages/traceloop-sdk/traceloop/sdk/associations/associations.py (3)

1-6: LGTM!

Imports are appropriate and the constant follows Python naming conventions.


9-14: LGTM!

The str, Enum inheritance pattern enables direct string comparison and JSON serialization, which is appropriate for span attributes.


17-18: LGTM!

Clean type alias definition using modern Python syntax.

packages/sample-app/sample_app/chats/gemini_chatbot.py (5)

1-8: LGTM!

All necessary imports are present and properly organized.


17-49: LGTM!

The tool functions are appropriately simplified for demonstration purposes. The implementations use mock data and basic logic suitable for a sample application.


52-108: LGTM!

Tool declarations are correctly structured with appropriate schemas, descriptions, and required parameters matching the function implementations.


111-121: LGTM!

The function routing logic is clear and handles unknown functions gracefully by returning an error message.


226-227: LGTM!

Standard entry point pattern correctly implemented.

Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed 302fa80 in 25 seconds. Click for details.
  • Reviewed 12 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 1 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. packages/traceloop-sdk/tests/test_associations.py:165
  • Draft comment:
    The test now checks that duplicate SESSION_ID values are overwritten (last wins). Please ensure that this behavior is documented in the associations API.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% This comment is asking the PR author to ensure documentation, which is not allowed by the rules. It doesn't provide a specific code suggestion or ask for a specific test to be written.

Workflow ID: wflow_zkbIX8xi7GqSaRsv

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Copy link
Contributor

@galkleinman galkleinman left a comment

Choose a reason for hiding this comment

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

Looking good!

associations = get_value("associations")
if associations is not None:
for key, value in associations.items():
span.set_attribute(key, str(value))
Copy link
Contributor

Choose a reason for hiding this comment

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

store in association-properties attribute

Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed 97dd21a in 1 minute and 53 seconds. Click for details.
  • Reviewed 151 lines of code in 3 files
  • Skipped 1 files when reviewing.
  • Skipped posting 3 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. packages/traceloop-sdk/tests/test_associations.py:73
  • Draft comment:
    Updated assertions now use the new association property key prefix (from SpanAttributes.TRACELOOP_ASSOCIATION_PROPERTIES). Consider extracting a helper for constructing these keys to reduce repetition.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 30% vs. threshold = 50% The comment is suggesting a refactor to reduce repetition, which is explicitly mentioned as a good type of comment in the rules ("Comments that suggest code quality refactors are good! But only if they are actionable and clear."). The suggestion is actionable - the author could create a helper function like def get_association_key(property_name): return f"{SpanAttributes.TRACELOOP_ASSOCIATION_PROPERTIES}.{property_name}". The comment is about changed code (the new assertion format). However, I need to consider if this is "obvious or unimportant" - the repetition is clear, but whether it's worth refactoring in a test file is debatable. Test files often have more repetition than production code, and the current format is explicit and readable. The comment doesn't require a code change, it's more of a suggestion. This is a test file, and test files typically prioritize explicitness and readability over DRY principles. The repetition might actually make the tests clearer and easier to understand. Additionally, the comment says "Consider" which is somewhat soft and doesn't clearly require a change - this might violate the rule about not commenting unless there is clearly a code change required. While test files do allow more repetition, the pattern is repeated 15+ times in this file, which is significant. A helper function would make the tests more maintainable if the key format changes again in the future. However, the use of "Consider" does make this more of a suggestion than a required change, which could violate the rule about only commenting when a code change is clearly required. The comment suggests a reasonable refactor, but uses soft language ("Consider") that doesn't clearly require a change. Given the rule that comments should only be made when there is clearly a code change required, and considering that test file repetition is often acceptable, this comment should be deleted.
2. packages/traceloop-sdk/traceloop/sdk/associations/associations.py:39
  • Draft comment:
    Refactored Associations.set to convert the input to a dict and delegate to set_association_properties. This simplifies context and span updates. Ensure consumers relying on the old 'associations' key update accordingly.
  • Reason this comment was not posted:
    Comment looked like it was already resolved.
3. packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py:349
  • Draft comment:
    The legacy block handling 'associations' in default_span_processor_on_start has been removed in favor of using 'association_properties'. Confirm that all spans (workflow/task) now correctly receive attributes via the updated mechanism.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is asking the PR author to confirm that the new mechanism correctly applies attributes to all spans. This is a request for confirmation of behavior, which violates the rule against asking the author to confirm their intention or ensure behavior is intended.

Workflow ID: wflow_3bdOqcheylcFXOaA

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/traceloop-sdk/traceloop/sdk/associations/associations.py (1)

22-41: Consider validating association values.

The method accepts any string value without validation. Consider adding checks for empty strings or None values to ensure meaningful association data, especially since these associations will be used for tracing and debugging.

🔎 Proposed validation enhancement
     # Convert associations to a dict and use set_association_properties
-    properties = {prop.value: value for prop, value in associations}
+    properties = {}
+    for prop, value in associations:
+        if not value or not value.strip():
+            raise ValueError(f"Association value for {prop.value} cannot be empty")
+        properties[prop.value] = value
     set_association_properties(properties)
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 302fa80 and 97dd21a.

📒 Files selected for processing (3)
  • .gitignore
  • packages/traceloop-sdk/tests/test_associations.py
  • packages/traceloop-sdk/traceloop/sdk/associations/associations.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/traceloop-sdk/tests/test_associations.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Store API keys only in environment variables/secure vaults; never hardcode secrets in code
Use Flake8 for code linting and adhere to its rules

Files:

  • packages/traceloop-sdk/traceloop/sdk/associations/associations.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Test Packages (3.10)
  • GitHub Check: Lint
  • GitHub Check: Test Packages (3.12)
  • GitHub Check: Test Packages (3.11)
  • GitHub Check: Build Packages (3.11)
🔇 Additional comments (4)
.gitignore (1)

184-185: LGTM!

The addition of the development files ignore rule follows existing .gitignore conventions and is appropriately organized under a new comment section.

packages/traceloop-sdk/traceloop/sdk/associations/associations.py (3)

1-3: LGTM!

The imports are clean and appropriate for the module's functionality.


6-11: LGTM!

The enum follows Python best practices for string enums and provides clear, standard property names for tracing associations.


14-15: LGTM!

The type alias clearly defines the association structure and improves code readability.

@nina-kollman nina-kollman merged commit 9290933 into main Dec 27, 2025
12 checks passed
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