Skip to content

Conversation

@nina-kollman
Copy link
Contributor

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

Important

Introduces an interactive chatbot application and enhances Traceloop SDK with association tracking for better trace management.

  • New Features:
    • Added sample_chatbot_interactive.ts for an interactive chatbot application with terminal interface, real-time streaming, and integrated tools for calculations and data retrieval.
    • Introduced association tracking in traceloop-sdk with Associations class and AssociationProperty enum in associations.ts.
  • SDK Enhancements:
    • TraceloopClient in traceloop-client.ts now includes associations for managing trace associations.
    • setAssociationProperties function in association.ts for setting properties on spans and propagating to child spans.
    • span-processor.ts updated to handle association properties during span processing.
  • Testing:
    • Added associations.test.ts to test association setting and propagation across spans.

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


Summary by CodeRabbit

  • New Features

    • Interactive terminal chatbot sample with live-streaming responses, basic built-in tools (calculator, time, weather), session/user IDs, history controls, and automatic interaction summaries.
    • SDK association tracking to attach and propagate session, user, and customer identifiers across traces and child spans.
  • Tests

    • Added tests validating association propagation and behavior across tasks and workflows.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 28, 2025

📝 Walkthrough

Walkthrough

Adds an associations feature to the Traceloop SDK for tracking customer/user/session IDs across spans and integrates it into a new interactive CLI chatbot sample that sets and uses session/user associations during conversations.

Changes

Cohort / File(s) Change Summary
Associations API Module
packages/traceloop-sdk/src/lib/associations/associations.ts
New enum AssociationProperty, Association type, and Associations class with set() to convert tuples to property map and call setAssociationProperties.
SDK Client & Exports
packages/traceloop-sdk/src/lib/client/traceloop-client.ts, packages/traceloop-sdk/src/lib/node-server-sdk.ts
Added associations: Associations public member to TraceloopClient; re-exported Associations, AssociationProperty, and Association from node-server-sdk.
Tracing: association utilities
packages/traceloop-sdk/src/lib/tracing/association.ts
Added in-memory span-association store with TTL, functions getSpanAssociationProperties, setSpanAssociationPropertiesForInheritance, cleanupExpiredSpanAssociationProperties, and setAssociationProperties to attach/propagate properties.
Tracing: span processor
packages/traceloop-sdk/src/lib/tracing/span-processor.ts
Merge parent/context association properties on span start, store merged properties for inheritance, emit per-property span attributes, and run cleanup on span end.
Tests
packages/traceloop-sdk/test/associations.test.ts
New tests validating association propagation, updates, inheritance, and coverage of all AssociationProperty values across task/workflow spans.
Interactive Chatbot Sample
packages/sample-app/src/sample_chatbot_interactive.ts
New readline-based CLI app InteractiveChatbot: session/user association handling, conversation history, streaming OpenAI responses (gpt-4o / gpt-4o-mini), tools (calculator, weather, time), summaries, and Traceloop association calls.
Sample App script
packages/sample-app/package.json
Added run:chatbot_interactive npm script to build and run the new chatbot.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant App as InteractiveChatbot
    participant Client as TraceloopClient
    participant Span as CurrentSpan
    participant Store as AssocStore
    participant OpenAI as OpenAI API

    User->>App: enter message (creates sessionId/userId)
    App->>Client: client.associations.set([SESSION_ID, userId])
    Client->>Client: setAssociationProperties(properties)
    Client->>Span: attach TRACELOOP_ASSOCIATION_PROPERTIES
    Client->>Store: setSpanAssociationPropertiesForInheritance(spanId, properties)

    App->>OpenAI: stream response (gpt-4o) with conversation + tools
    OpenAI-->>App: streamed tokens
    App->>App: collect tokens, call tools (calculator/weather/time) as needed

    Note over Span,Store: Child spans inherit properties
    participant Child as ChildSpan
    Child->>Store: getSpanAssociationProperties(parentSpanId)
    Store-->>Child: parent properties
    Child->>Child: merge and attach attributes
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

I hop through spans with nimble feet, 🐇
Associations make each trace complete,
Session, user, customer in a line,
Parent to child, their values shine,
A chatbot hums — traced and sweet.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'fix(tracing): Add association property' is vague and generic. It lacks specificity about what was added—whether it's about adding a single property, a feature, or an entire subsystem for managing associations. Consider a more descriptive title that reflects the scope of changes, such as 'feat(tracing): Add association properties for session and user tracking' or 'feat: Add Associations API for managing trace associations'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ 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.

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 8e687cf in 1 minute and 41 seconds. Click for details.
  • Reviewed 845 lines of code in 8 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/src/sample_chatbot_interactive.ts:129
  • Draft comment:
    Using eval for math expressions can be risky even with sanitization. Consider using a dedicated math parser for improved security.
  • 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% This comment is about a security concern with using eval(). While the code does sanitize the input, the comment is suggesting a code quality improvement - using a dedicated math parser library instead. However, I need to consider: 1) This is a sample app (packages/sample-app), not production code, 2) The comment is somewhat speculative about security risks ("can be risky"), 3) The rules say comments suggesting code quality refactors are good if actionable and clear. The comment is actionable (use a math parser library) but it's for a sample/demo app where eval() with sanitization might be acceptable for demonstration purposes. The comment doesn't point to a definite bug or issue, just a potential security improvement. This is a sample app meant for demonstration purposes, not production code. The eval() usage with sanitization might be intentionally simple for educational purposes. The comment is somewhat speculative ("can be risky") rather than pointing to a definite issue. It's also not clear if this level of security is necessary for a sample application. While it's a sample app, it could still set a bad example for developers who might copy this pattern. However, the rules emphasize only keeping comments with STRONG EVIDENCE of being correct and necessary. This is more of a best practice suggestion than a clear code issue, and for sample/demo code, the simpler eval approach might be intentionally chosen for clarity. This comment suggests a security improvement but is speculative ("can be risky") rather than pointing to a definite bug. Given this is sample/demo code and the rules require STRONG EVIDENCE that a comment is necessary, this falls into the category of a "nice to have" suggestion rather than a required change. The comment should be deleted.
2. packages/traceloop-sdk/src/lib/tracing/span-processor.ts:322
  • Draft comment:
    Randomly triggering cleanup with Math.random()<0.01 may not be robust in high-throughput scenarios. Consider a scheduled or more deterministic cleanup strategy.
  • Reason this comment was not posted:
    Comment was on unchanged code.
3. packages/traceloop-sdk/src/lib/tracing/association.ts:38
  • Draft comment:
    The generic signature in withAssociationProperties seems overly complex. Consider simplifying the constraint to avoid potential recursive type issues.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
4. packages/traceloop-sdk/src/lib/tracing/association.ts:2
  • Draft comment:
    Typo: The identifier 'ASSOCATION_PROPERTIES_KEY' seems to be misspelled. It likely should be 'ASSOCIATION_PROPERTIES_KEY'. Please verify and correct if necessary.
  • Reason this comment was not posted:
    Comment was on unchanged code.
5. packages/traceloop-sdk/src/lib/tracing/span-processor.ts:206
  • Draft comment:
    The constant name 'ASSOCATION_PROPERTIES_KEY' might be a typographical error. Consider checking if it should be 'ASSOCIATION_PROPERTIES_KEY'.
  • Reason this comment was not posted:
    Comment was on unchanged code.

Workflow ID: wflow_Iv22M3podC7M5HNs

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

Copy link
Contributor

@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 (2)
packages/traceloop-sdk/test/associations.test.ts (1)

34-43: Consider adding test coverage for client.associations.set() API.

The tests use traceloop.setAssociationProperties(), but the new Associations class exposes a different API via client.associations.set([[prop, value], ...]). Consider adding at least one test that exercises the tuple-based API to ensure both paths work correctly.

packages/traceloop-sdk/src/lib/associations/associations.ts (1)

15-15: Consider allowing custom association properties.

The Association type restricts property names to the AssociationProperty enum. While this provides type safety, users may need custom association properties beyond the predefined ones. Consider if the API should also accept arbitrary string keys for extensibility.

🔎 Example extensible type
// Allow both enum values and custom strings
export type Association = [AssociationProperty | string, string];
📜 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 f480743 and 8e687cf.

📒 Files selected for processing (8)
  • packages/sample-app/package.json
  • packages/sample-app/src/sample_chatbot_interactive.ts
  • packages/traceloop-sdk/src/lib/associations/associations.ts
  • packages/traceloop-sdk/src/lib/client/traceloop-client.ts
  • packages/traceloop-sdk/src/lib/node-server-sdk.ts
  • packages/traceloop-sdk/src/lib/tracing/association.ts
  • packages/traceloop-sdk/src/lib/tracing/span-processor.ts
  • packages/traceloop-sdk/test/associations.test.ts
🧰 Additional context used
📓 Path-based instructions (4)
packages/*/package.json

📄 CodeRabbit inference engine (CLAUDE.md)

Use workspace:* for intra-repo package dependencies in package.json

Files:

  • packages/sample-app/package.json
packages/{instrumentation-*,traceloop-sdk}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Import AI/LLM semantic attribute constants from @traceloop/ai-semantic-conventions rather than hardcoding strings

Files:

  • packages/traceloop-sdk/src/lib/associations/associations.ts
  • packages/traceloop-sdk/src/lib/client/traceloop-client.ts
  • packages/traceloop-sdk/src/lib/node-server-sdk.ts
  • packages/traceloop-sdk/test/associations.test.ts
  • packages/traceloop-sdk/src/lib/tracing/span-processor.ts
  • packages/traceloop-sdk/src/lib/tracing/association.ts
packages/traceloop-sdk/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

packages/traceloop-sdk/**/*.{ts,tsx}: Use the provided decorators (@workflow, @task, @agent) for workflow/task/agent spans instead of re-implementing them
For manual LLM operations, use trace.withLLMSpan from @traceloop/node-server-sdk

Files:

  • packages/traceloop-sdk/src/lib/associations/associations.ts
  • packages/traceloop-sdk/src/lib/client/traceloop-client.ts
  • packages/traceloop-sdk/src/lib/node-server-sdk.ts
  • packages/traceloop-sdk/test/associations.test.ts
  • packages/traceloop-sdk/src/lib/tracing/span-processor.ts
  • packages/traceloop-sdk/src/lib/tracing/association.ts
packages/traceloop-sdk/src/lib/node-server-sdk.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Register new instrumentation packages during SDK initialization

Files:

  • packages/traceloop-sdk/src/lib/node-server-sdk.ts
🧠 Learnings (9)
📚 Learning: 2025-08-24T22:08:07.023Z
Learnt from: CR
Repo: traceloop/openllmetry-js PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T22:08:07.023Z
Learning: Applies to packages/{instrumentation-*,traceloop-sdk}/**/*.{ts,tsx} : Import AI/LLM semantic attribute constants from traceloop/ai-semantic-conventions rather than hardcoding strings

Applied to files:

  • packages/traceloop-sdk/src/lib/associations/associations.ts
  • packages/traceloop-sdk/src/lib/client/traceloop-client.ts
  • packages/traceloop-sdk/src/lib/node-server-sdk.ts
  • packages/traceloop-sdk/test/associations.test.ts
  • packages/traceloop-sdk/src/lib/tracing/span-processor.ts
  • packages/traceloop-sdk/src/lib/tracing/association.ts
  • packages/sample-app/src/sample_chatbot_interactive.ts
📚 Learning: 2025-08-24T22:08:07.023Z
Learnt from: CR
Repo: traceloop/openllmetry-js PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T22:08:07.023Z
Learning: Applies to packages/traceloop-sdk/**/*.{ts,tsx} : For manual LLM operations, use trace.withLLMSpan from traceloop/node-server-sdk

Applied to files:

  • packages/traceloop-sdk/src/lib/associations/associations.ts
  • packages/traceloop-sdk/src/lib/client/traceloop-client.ts
  • packages/traceloop-sdk/src/lib/node-server-sdk.ts
  • packages/traceloop-sdk/test/associations.test.ts
  • packages/traceloop-sdk/src/lib/tracing/span-processor.ts
  • packages/traceloop-sdk/src/lib/tracing/association.ts
📚 Learning: 2025-08-24T22:08:07.023Z
Learnt from: CR
Repo: traceloop/openllmetry-js PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T22:08:07.023Z
Learning: Applies to packages/traceloop-sdk/src/lib/node-server-sdk.ts : Register new instrumentation packages during SDK initialization

Applied to files:

  • packages/traceloop-sdk/src/lib/client/traceloop-client.ts
  • packages/traceloop-sdk/src/lib/node-server-sdk.ts
📚 Learning: 2025-08-24T22:08:07.023Z
Learnt from: CR
Repo: traceloop/openllmetry-js PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T22:08:07.023Z
Learning: Applies to packages/instrumentation-*/**/*.{ts,tsx} : Instrumentations must create spans with appropriate AI/LLM semantic attributes for calls they wrap

Applied to files:

  • packages/traceloop-sdk/src/lib/node-server-sdk.ts
  • packages/traceloop-sdk/src/lib/tracing/span-processor.ts
  • packages/traceloop-sdk/src/lib/tracing/association.ts
📚 Learning: 2025-08-24T22:08:07.023Z
Learnt from: CR
Repo: traceloop/openllmetry-js PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T22:08:07.023Z
Learning: Applies to packages/instrumentation-*/**/*.{ts,tsx} : Do not implement anonymous telemetry collection in instrumentation packages; telemetry is collected only in the SDK

Applied to files:

  • packages/traceloop-sdk/src/lib/node-server-sdk.ts
  • packages/traceloop-sdk/src/lib/tracing/span-processor.ts
📚 Learning: 2025-08-24T22:08:07.023Z
Learnt from: CR
Repo: traceloop/openllmetry-js PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T22:08:07.023Z
Learning: Applies to packages/instrumentation-*/**/*.{ts,tsx} : Instrumentations must extract request/response data and token usage from wrapped calls

Applied to files:

  • packages/traceloop-sdk/src/lib/node-server-sdk.ts
📚 Learning: 2025-08-24T22:08:07.023Z
Learnt from: CR
Repo: traceloop/openllmetry-js PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T22:08:07.023Z
Learning: Applies to packages/instrumentation-*/**/*.{ts,tsx} : Instrumentation classes must extend InstrumentationBase and register hooks using InstrumentationModuleDefinition

Applied to files:

  • packages/traceloop-sdk/src/lib/node-server-sdk.ts
  • packages/traceloop-sdk/src/lib/tracing/span-processor.ts
📚 Learning: 2025-08-24T22:08:07.023Z
Learnt from: CR
Repo: traceloop/openllmetry-js PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T22:08:07.023Z
Learning: Applies to packages/traceloop-sdk/**/*.{ts,tsx} : Use the provided decorators (workflow, task, agent) for workflow/task/agent spans instead of re-implementing them

Applied to files:

  • packages/traceloop-sdk/test/associations.test.ts
  • packages/traceloop-sdk/src/lib/tracing/span-processor.ts
  • packages/traceloop-sdk/src/lib/tracing/association.ts
📚 Learning: 2025-08-24T22:08:07.023Z
Learnt from: CR
Repo: traceloop/openllmetry-js PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T22:08:07.023Z
Learning: Applies to packages/ai-semantic-conventions/src/SemanticAttributes.ts : Define all AI/LLM span attribute constants in packages/ai-semantic-conventions/src/SemanticAttributes.ts

Applied to files:

  • packages/traceloop-sdk/src/lib/tracing/span-processor.ts
  • packages/traceloop-sdk/src/lib/tracing/association.ts
🧬 Code graph analysis (5)
packages/traceloop-sdk/src/lib/client/traceloop-client.ts (1)
packages/traceloop-sdk/src/lib/associations/associations.ts (1)
  • Associations (20-46)
packages/traceloop-sdk/test/associations.test.ts (2)
packages/traceloop-sdk/test/test-setup.ts (2)
  • getSharedExporter (37-39)
  • initializeSharedTraceloop (23-35)
packages/ai-semantic-conventions/src/SemanticAttributes.ts (1)
  • SpanAttributes (17-58)
packages/traceloop-sdk/src/lib/tracing/span-processor.ts (2)
packages/traceloop-sdk/src/lib/tracing/tracing.ts (1)
  • ASSOCATION_PROPERTIES_KEY (7-9)
packages/traceloop-sdk/src/lib/tracing/association.ts (3)
  • getSpanAssociationProperties (13-17)
  • setSpanAssociationPropertiesForInheritance (19-27)
  • cleanupExpiredSpanAssociationProperties (29-36)
packages/traceloop-sdk/src/lib/tracing/association.ts (1)
packages/ai-semantic-conventions/src/SemanticAttributes.ts (1)
  • SpanAttributes (17-58)
packages/sample-app/src/sample_chatbot_interactive.ts (1)
packages/traceloop-sdk/src/lib/tracing/decorators.ts (1)
  • tool (287-293)
🪛 Biome (2.1.2)
packages/sample-app/src/sample_chatbot_interactive.ts

[error] 129-129: eval() exposes to security risks and performance issues.

See the MDN web docs for more details.
Refactor the code so that it doesn't need to call eval().

(lint/security/noGlobalEval)

🪛 GitHub Actions: CI
packages/traceloop-sdk/test/associations.test.ts

[warning] 1-1: Prettier formatting issue detected. Run 'pnpm prettier --write' to fix formatting in this file.

packages/traceloop-sdk/src/lib/tracing/span-processor.ts

[warning] 1-1: Prettier formatting issue detected. Run 'pnpm prettier --write' to fix formatting in this file.

packages/sample-app/src/sample_chatbot_interactive.ts

[warning] 1-1: Prettier formatting issue detected. Run 'pnpm prettier --write' to fix formatting in this file.

🔇 Additional comments (16)
packages/sample-app/package.json (1)

46-46: LGTM!

The new script follows the established pattern for sample app scripts in this file.

packages/traceloop-sdk/src/lib/node-server-sdk.ts (1)

70-71: LGTM!

The new exports properly separate named exports from type exports and follow the existing patterns in this file.

packages/traceloop-sdk/src/lib/client/traceloop-client.ts (1)

7-7: LGTM!

The Associations integration follows the established pattern for client members like userFeedback, datasets, and evaluator.

Also applies to: 33-33, 53-53

packages/traceloop-sdk/test/associations.test.ts (2)

1-279: Good test coverage for association propagation.

The tests comprehensively cover single associations, multiple associations, all enum values, and mid-workflow updates. The assertions correctly verify that association properties propagate to both task and workflow spans.


22-22: No initialization order concern.

sharedMemoryExporter is created synchronously at module load time in test-setup.ts (line 24: export const sharedMemoryExporter = new InMemorySpanExporter()), not lazily during initialization. Calling getSharedExporter() at line 22 is safe and returns an already-instantiated exporter. The before() hook only initializes the SDK with this pre-existing exporter.

Likely an incorrect or invalid review comment.

packages/traceloop-sdk/src/lib/tracing/span-processor.ts (3)

24-28: LGTM!

The new imports properly bring in the association utilities needed for span processing.


203-235: LGTM!

The association property handling correctly:

  1. Retrieves context-level properties (from decorators)
  2. Retrieves inherited properties from the parent span
  3. Merges them with proper precedence (context overrides inherited)
  4. Stores merged properties for child span inheritance
  5. Sets span attributes using the semantic conventions constant

322-325: LGTM!

The probabilistic cleanup (1% chance) for expired span association properties follows the same pattern as agent name cleanup, preventing memory leaks from the in-memory map.

packages/traceloop-sdk/src/lib/associations/associations.ts (1)

1-46: LGTM!

Clean implementation of the Associations API with:

  • Well-documented AssociationProperty enum for type-safe property names
  • Tuple-based Association type for structured input
  • Simple delegation to the underlying setAssociationProperties function

The JSDoc examples are helpful for users understanding the API.

packages/traceloop-sdk/src/lib/tracing/association.ts (3)

1-3: LGTM!

The imports correctly use @traceloop/ai-semantic-conventions for SpanAttributes as per coding guidelines.


5-36: LGTM!

The in-memory store for span association properties is well-designed:

  • Uses Map with span ID as key for O(1) lookups
  • TTL-based cleanup prevents unbounded memory growth
  • Clean separation of get/set/cleanup functions

63-96: Verify behavior when no active span exists.

The function silently does nothing when there's no active span (line 72 check). This is reasonable for defensive programming, but users might expect an error or warning if they call setAssociationProperties outside of a span context. Consider whether a warning log would help users debug misconfigured tracing.

packages/sample-app/src/sample_chatbot_interactive.ts (4)

9-12: LGTM!

Clean initialization of the Traceloop client with appropriate configuration for a sample app.


43-77: LGTM!

Good use of the @traceloop.task decorator for the summary generation, following the coding guidelines for workflow/task spans.


79-93: LGTM!

Good demonstration of the new associations API with proper fallback to the standalone function if the client is not available.


233-290: LGTM!

Clean CLI implementation with proper handling of commands, graceful exit, and error handling.

Comment on lines +125 to +137
execute: async ({ expression }) => {
try {
// Simple safe eval for basic math (only allow numbers and operators)
const sanitized = expression.replace(/[^0-9+\-*/().\s]/g, "");
const result = eval(sanitized);
console.log(
`\n${colors.yellow}🔧 Calculator: ${expression} = ${result}${colors.reset}`,
);
return { result, expression };
} catch (error) {
return { error: "Invalid mathematical expression" };
}
},
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Replace eval() with a safer arithmetic parser.

The static analysis correctly flags eval() as a security risk. While the sanitization at line 128 removes most dangerous characters, eval() can still be exploited (e.g., via __proto__ manipulation in some contexts). For a sample app, consider using a simple arithmetic parser or a library like mathjs.

🔎 Suggested safer alternative
+// Simple arithmetic parser for basic operations
+function safeEvaluate(expression: string): number {
+  // Only allow numbers, operators, parentheses, and decimals
+  const sanitized = expression.replace(/[^0-9+\-*/().\s]/g, "");
+  if (!sanitized || sanitized !== expression.replace(/\s/g, "").replace(/[^0-9+\-*/().]/g, "")) {
+    throw new Error("Invalid expression");
+  }
+  // Use Function constructor as slightly safer alternative, or use mathjs
+  return new Function(`return ${sanitized}`)() as number;
+}

 execute: async ({ expression }) => {
   try {
-    // Simple safe eval for basic math (only allow numbers and operators)
-    const sanitized = expression.replace(/[^0-9+\-*/().\s]/g, "");
-    const result = eval(sanitized);
+    const result = safeEvaluate(expression);
     console.log(
       `\n${colors.yellow}🔧 Calculator: ${expression} = ${result}${colors.reset}`,
     );
     return { result, expression };
   } catch (error) {
     return { error: "Invalid mathematical expression" };
   }
 },

Alternatively, add mathjs as a dependency for robust expression parsing.

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

Suggested change
execute: async ({ expression }) => {
try {
// Simple safe eval for basic math (only allow numbers and operators)
const sanitized = expression.replace(/[^0-9+\-*/().\s]/g, "");
const result = eval(sanitized);
console.log(
`\n${colors.yellow}🔧 Calculator: ${expression} = ${result}${colors.reset}`,
);
return { result, expression };
} catch (error) {
return { error: "Invalid mathematical expression" };
}
},
// Simple arithmetic parser for basic operations
function safeEvaluate(expression: string): number {
// Only allow numbers, operators, parentheses, and decimals
const sanitized = expression.replace(/[^0-9+\-*/().\s]/g, "");
if (!sanitized || sanitized !== expression.replace(/\s/g, "").replace(/[^0-9+\-*/().]/g, "")) {
throw new Error("Invalid expression");
}
// Use Function constructor as slightly safer alternative, or use mathjs
return new Function(`return ${sanitized}`)() as number;
}
execute: async ({ expression }) => {
try {
const result = safeEvaluate(expression);
console.log(
`\n${colors.yellow}🔧 Calculator: ${expression} = ${result}${colors.reset}`,
);
return { result, expression };
} catch (error) {
return { error: "Invalid mathematical expression" };
}
},
🧰 Tools
🪛 Biome (2.1.2)

[error] 129-129: eval() exposes to security risks and performance issues.

See the MDN web docs for more details.
Refactor the code so that it doesn't need to call eval().

(lint/security/noGlobalEval)

🤖 Prompt for AI Agents
In packages/sample-app/src/sample_chatbot_interactive.ts around lines 125–137,
the current implementation uses eval() on a sanitized string which is a security
risk; replace eval with a safe arithmetic evaluator: add mathjs as a dependency
(or implement a small expression parser), import the evaluate function, call
evaluate(sanitized) instead of eval, catch and return parse/eval errors
unchanged, and retain or tighten the sanitization to only allow digits,
whitespace, basic operators and parentheses; ensure no global scope access or
function injection is possible and update error messages accordingly.

Comment on lines +180 to +186
execute: async ({ timezone }) => {
const now = new Date();
const options: Intl.DateTimeFormatOptions = {
timeZone: timezone,
dateStyle: "full",
timeStyle: "long",
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Handle invalid timezone gracefully.

If an invalid timezone string is passed to toLocaleString, it will throw a RangeError. Consider wrapping in try-catch or validating the timezone.

🔎 Suggested fix
 execute: async ({ timezone }) => {
   const now = new Date();
-  const options: Intl.DateTimeFormatOptions = {
-    timeZone: timezone,
-    dateStyle: "full",
-    timeStyle: "long",
-  };
-  const formatted = now.toLocaleString("en-US", options);
+  let formatted: string;
+  try {
+    const options: Intl.DateTimeFormatOptions = {
+      timeZone: timezone,
+      dateStyle: "full",
+      timeStyle: "long",
+    };
+    formatted = now.toLocaleString("en-US", options);
+  } catch {
+    formatted = now.toLocaleString("en-US", {
+      dateStyle: "full",
+      timeStyle: "long",
+    });
+  }
   console.log(
     `\n${colors.yellow}🔧 Time: ${formatted}${colors.reset}`,
   );
🤖 Prompt for AI Agents
In packages/sample-app/src/sample_chatbot_interactive.ts around lines 180 to
186, the call to toLocaleString with the provided timezone can throw a
RangeError for invalid timezone identifiers; wrap the formatting in a try-catch
(or validate the timezone beforehand) and fall back to a safe default (e.g., UTC
or server local time) while logging or returning a clear message about the
invalid timezone. Ensure the catch handles RangeError specifically and does not
swallow other exceptions, and update the returned/used value to the fallback
when an error occurs.

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 c417b43 in 35 seconds. Click for details.
  • Reviewed 342 lines of code in 3 files
  • Skipped 0 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/sample-app/src/sample_chatbot_interactive.ts:244
  • Draft comment:
    Formatting update: The console.log calls for Session and User IDs were simplified (removed extra newlines) to improve readability without any change in functionality.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
2. packages/traceloop-sdk/src/lib/tracing/span-processor.ts:207
  • Draft comment:
    Minor formatting improvements: The union type cast for association properties and the multi-line formatting for setSpanAssociationPropertiesForInheritance enhance readability without affecting functionality.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
3. packages/traceloop-sdk/test/associations.test.ts:34
  • Draft comment:
    Test file formatting: The callbacks for setting association properties now use consistent multi-line formatting with trailing commas. This change improves readability without impacting test logic.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None

Workflow ID: wflow_GXa9qRn0Mtj0lT6R

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

Copy link
Contributor

@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: 0

♻️ Duplicate comments (2)
packages/sample-app/src/sample_chatbot_interactive.ts (2)

125-137: Replace eval() with a safer arithmetic parser.

The use of eval() remains a security risk despite sanitization. This issue was previously identified and a safer alternative using a dedicated parser or mathjs library was recommended.


180-187: Handle invalid timezone gracefully.

The call to toLocaleString with an unvalidated timezone can throw a RangeError. This issue was previously identified with a recommendation to wrap in try-catch. Consider implementing the suggested error handling.

🧹 Nitpick comments (1)
packages/sample-app/src/sample_chatbot_interactive.ts (1)

82-93: Consider simplifying the association API usage.

The code demonstrates both the new client.associations.set() API and the fallback setAssociationProperties() function. Since client is initialized synchronously at module level (line 9), it should always be available, making the else branch unreachable in practice.

For a sample app, this dual demonstration is acceptable, but consider adding a comment explaining that the else branch is shown for completeness or removing it for clarity.

🔎 Optional simplification
 async processMessage(userMessage: string): Promise<string> {
   // Set associations for tracing
-  if (client) {
-    client.associations.set([
-      [traceloop.AssociationProperty.SESSION_ID, this.sessionId],
-      [traceloop.AssociationProperty.USER_ID, this.userId],
-    ]);
-  } else {
-    // Fallback to standalone function if no client
-    traceloop.setAssociationProperties({
-      [traceloop.AssociationProperty.SESSION_ID]: this.sessionId,
-      [traceloop.AssociationProperty.USER_ID]: this.userId,
-    });
-  }
+  client.associations.set([
+    [traceloop.AssociationProperty.SESSION_ID, this.sessionId],
+    [traceloop.AssociationProperty.USER_ID, this.userId],
+  ]);
📜 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 8e687cf and c417b43.

📒 Files selected for processing (3)
  • packages/sample-app/src/sample_chatbot_interactive.ts
  • packages/traceloop-sdk/src/lib/tracing/span-processor.ts
  • packages/traceloop-sdk/test/associations.test.ts
🧰 Additional context used
📓 Path-based instructions (2)
packages/{instrumentation-*,traceloop-sdk}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Import AI/LLM semantic attribute constants from @traceloop/ai-semantic-conventions rather than hardcoding strings

Files:

  • packages/traceloop-sdk/src/lib/tracing/span-processor.ts
  • packages/traceloop-sdk/test/associations.test.ts
packages/traceloop-sdk/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

packages/traceloop-sdk/**/*.{ts,tsx}: Use the provided decorators (@workflow, @task, @agent) for workflow/task/agent spans instead of re-implementing them
For manual LLM operations, use trace.withLLMSpan from @traceloop/node-server-sdk

Files:

  • packages/traceloop-sdk/src/lib/tracing/span-processor.ts
  • packages/traceloop-sdk/test/associations.test.ts
🧠 Learnings (6)
📚 Learning: 2025-08-24T22:08:07.023Z
Learnt from: CR
Repo: traceloop/openllmetry-js PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T22:08:07.023Z
Learning: Applies to packages/traceloop-sdk/**/*.{ts,tsx} : Use the provided decorators (workflow, task, agent) for workflow/task/agent spans instead of re-implementing them

Applied to files:

  • packages/traceloop-sdk/src/lib/tracing/span-processor.ts
  • packages/traceloop-sdk/test/associations.test.ts
  • packages/sample-app/src/sample_chatbot_interactive.ts
📚 Learning: 2025-08-24T22:08:07.023Z
Learnt from: CR
Repo: traceloop/openllmetry-js PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T22:08:07.023Z
Learning: Applies to packages/instrumentation-*/**/*.{ts,tsx} : Instrumentations must create spans with appropriate AI/LLM semantic attributes for calls they wrap

Applied to files:

  • packages/traceloop-sdk/src/lib/tracing/span-processor.ts
📚 Learning: 2025-08-24T22:08:07.023Z
Learnt from: CR
Repo: traceloop/openllmetry-js PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T22:08:07.023Z
Learning: Applies to packages/{instrumentation-*,traceloop-sdk}/**/*.{ts,tsx} : Import AI/LLM semantic attribute constants from traceloop/ai-semantic-conventions rather than hardcoding strings

Applied to files:

  • packages/traceloop-sdk/src/lib/tracing/span-processor.ts
  • packages/traceloop-sdk/test/associations.test.ts
  • packages/sample-app/src/sample_chatbot_interactive.ts
📚 Learning: 2025-08-24T22:08:07.023Z
Learnt from: CR
Repo: traceloop/openllmetry-js PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T22:08:07.023Z
Learning: Applies to packages/traceloop-sdk/**/*.{ts,tsx} : For manual LLM operations, use trace.withLLMSpan from traceloop/node-server-sdk

Applied to files:

  • packages/traceloop-sdk/src/lib/tracing/span-processor.ts
  • packages/traceloop-sdk/test/associations.test.ts
  • packages/sample-app/src/sample_chatbot_interactive.ts
📚 Learning: 2025-08-24T22:08:07.023Z
Learnt from: CR
Repo: traceloop/openllmetry-js PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T22:08:07.023Z
Learning: Applies to packages/ai-semantic-conventions/src/SemanticAttributes.ts : Define all AI/LLM span attribute constants in packages/ai-semantic-conventions/src/SemanticAttributes.ts

Applied to files:

  • packages/traceloop-sdk/src/lib/tracing/span-processor.ts
📚 Learning: 2025-08-24T22:08:07.023Z
Learnt from: CR
Repo: traceloop/openllmetry-js PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T22:08:07.023Z
Learning: Applies to packages/instrumentation-*/**/*.{ts,tsx} : Do not implement anonymous telemetry collection in instrumentation packages; telemetry is collected only in the SDK

Applied to files:

  • packages/traceloop-sdk/src/lib/tracing/span-processor.ts
🧬 Code graph analysis (3)
packages/traceloop-sdk/src/lib/tracing/span-processor.ts (2)
packages/traceloop-sdk/src/lib/tracing/tracing.ts (1)
  • ASSOCATION_PROPERTIES_KEY (7-9)
packages/traceloop-sdk/src/lib/tracing/association.ts (3)
  • getSpanAssociationProperties (13-17)
  • setSpanAssociationPropertiesForInheritance (19-27)
  • cleanupExpiredSpanAssociationProperties (29-36)
packages/traceloop-sdk/test/associations.test.ts (2)
packages/traceloop-sdk/test/test-setup.ts (2)
  • getSharedExporter (37-39)
  • initializeSharedTraceloop (23-35)
packages/ai-semantic-conventions/src/SemanticAttributes.ts (1)
  • SpanAttributes (17-58)
packages/sample-app/src/sample_chatbot_interactive.ts (1)
packages/traceloop-sdk/src/lib/tracing/decorators.ts (1)
  • tool (287-293)
🪛 Biome (2.1.2)
packages/sample-app/src/sample_chatbot_interactive.ts

[error] 129-129: eval() exposes to security risks and performance issues.

See the MDN web docs for more details.
Refactor the code so that it doesn't need to call eval().

(lint/security/noGlobalEval)

🔇 Additional comments (7)
packages/traceloop-sdk/src/lib/tracing/span-processor.ts (3)

24-28: LGTM! Clean import of association utilities.

The imported functions integrate well with the existing span processing logic and follow the same patterns established for agent name handling.


203-240: LGTM! Solid association properties merging and propagation logic.

The implementation correctly:

  • Retrieves association properties from both context (decorator/API) and parent span (inheritance)
  • Merges with proper precedence (context overrides inherited)
  • Stores merged properties for child spans to inherit
  • Sets span attributes with the correct prefix for telemetry

The merge semantics ensure that explicit calls to setAssociationProperties or decorator-provided properties take precedence over inherited values, while still propagating parent associations down the trace tree.


327-330: LGTM! Cleanup properly prevents memory leaks.

The probabilistic cleanup of expired association properties mirrors the existing agent name cleanup pattern and will prevent unbounded memory growth over time.

packages/traceloop-sdk/test/associations.test.ts (1)

24-291: LGTM! Comprehensive test coverage for associations feature.

The test suite thoroughly validates:

  • Single and multiple association properties
  • Propagation to both task and workflow spans
  • All AssociationProperty enum values
  • Mid-workflow updates and merge semantics

The test at lines 222-290 is particularly valuable as it confirms that association property updates correctly affect subsequent child spans while preserving the final merged state on the workflow span.

packages/sample-app/src/sample_chatbot_interactive.ts (3)

43-77: LGTM! Proper use of task decorator.

The generateSummary method correctly uses the @traceloop.task decorator to create a traced task span, complying with the coding guidelines for workflow/task spans.


139-170: LGTM! Clear simulation for demonstration purposes.

The simulated weather tool is appropriate for a sample application, with console logging that makes it clear the data is not real.


233-286: LGTM! Well-structured interactive CLI with proper error handling.

The readline-based interface properly handles user commands, errors, and graceful shutdown. The try-catch around processMessage ensures the CLI remains responsive even if individual interactions fail.

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