[AIG-632] Add OpenTelemetry tracing#45
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (4)
📝 WalkthroughWalkthroughThis PR adds comprehensive opt-in OpenTelemetry tracing to aistack: a new observability module and re-exports, config types and Zod schemas, OpenTelemetry dependencies, span wrappers (sync/async), and instrumentation across agent lifecycle, review loops, memory operations, consensus gates, and MCP tool handlers, plus docs and tests. ChangesOpenTelemetry Tracing Implementation
Sequence DiagramsequenceDiagram
participant Client
participant traceAsync as traceAsync(config,name,attrs,fn)
participant NodeSDK
participant Tracer
participant Span
participant Exporter
Client->>traceAsync: invoke traced operation
traceAsync->>traceAsync: check if tracing enabled
alt Tracing Enabled
traceAsync->>NodeSDK: ensure initialized
NodeSDK->>Tracer: get tracer
Tracer->>Span: start span with sanitized attrs
Span->>Client: execute callback within span context
Client-->>Span: return result or throw error
Span->>Exporter: record/export span
Span-->>traceAsync: end span
else Tracing Disabled
traceAsync->>Client: execute callback directly (no span)
end
traceAsync-->>Client: return result or propagate error
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
tests/unit/config.test.tsParsing error: "parserOptions.project" has been provided for Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
package.json (1)
58-62: ⚖️ Poor tradeoffConsider making OTel SDK packages opt-in via
optionalDependencies+ lazy import.Tracing is disabled by default, but
@opentelemetry/sdk-node(and its transitive tree) is a sizable harddependencyshipped to every consumer of this published library. The repo already usesoptionalDependenciesfor similarly heavy/opt-in features (@e2b/code-interpreter,@xenova/transformers). Ifsrc/observability/tracing.tsimports these lazily only when tracing is enabled, moving the SDK packages tooptionalDependencieswould keep@opentelemetry/api(lightweight, always-safe) as the only hard dep.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@package.json` around lines 58 - 62, Move the heavy OpenTelemetry SDK packages from "dependencies" to "optionalDependencies" in package.json and change src/observability/tracing.ts to lazily import the SDK only when tracing is enabled; keep `@opentelemetry/api` as a regular dependency, update package.json entries "`@opentelemetry/exporter-trace-otlp-http`", "`@opentelemetry/resources`", "`@opentelemetry/sdk-node`", and "`@opentelemetry/sdk-trace-base`" to optionalDependencies, then modify functions in tracing.ts that initialize tracing (e.g., the tracer initialization/bootstrap function) to use dynamic import(...) for the SDK modules and guard execution behind the existing tracing-enabled flag so consumers who don't opt into optional deps won't download or execute the heavy SDK.tests/unit/config.test.ts (1)
277-315: ⚡ Quick winConsider adding a case for when both
otelandtracingblocks are supplied.Current cases cover
otel-only andtracing-only, but not precedence when both are present — exactly the path affected by the merge concern flagged insrc/utils/config.ts. A combined-block assertion would lock in the intended precedence.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/unit/config.test.ts` around lines 277 - 315, Add a unit test in tests/unit/config.test.ts that calls validateConfig with both observability.tracing and observability.otel present and assert the intended precedence behavior (i.e., supply conflicting values like tracing.exporter = 'otlp' with tracing.otlpEndpoint = 'http://tracing:4318/v1/traces' and otel.endpoint = 'http://otel:4318/v1/traces' and then expect validateConfig to be valid and that the resulting merged config uses the tracing values); reference validateConfig, observability.tracing and observability.otel in the test so the merge path in src/utils/config.ts is exercised and locked in.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/observability/tracing.ts`:
- Around line 95-134: Wrap the synchronous setup in initializeTracing with a
try/catch and add a terminal failure flag (e.g., tracingFailed) checked at the
top to short-circuit future calls; specifically, check tracingFailed early and
return false, then try resolving resolveTracingConfig, creating the exporter via
createSpanExporter, constructing the NodeSDK and calling sdk.start() inside the
try block, and on any thrown error log the error, call shutdownTracing() (or
shutdown any partially-initialized sdk), set tracingFailed = true and ensure
sdkStarted remains false, then return false so we don't repeatedly retry or spam
logs; keep existing sdkStarted and shutdownRegistered logic but only set them
after successful startup.
In `@src/utils/config.ts`:
- Around line 267-276: ObservabilityConfigSchema currently spreads
TracingConfigSchema.parse({}) first, causing Tracing defaults to overwrite
explicit observability.otel values; change the transform to merge values so otel
and explicit tracing win and then run TracingConfigSchema.parse on that merged
object — e.g., build a mergedTracing object using ...(config.otel ?? {}) then
...(config.tracing ?? {}) (so otel and tracing override defaults), and return
tracing: TracingConfigSchema.parse(mergedTracing) while keeping the outer
transform structure; update the transform in ObservabilityConfigSchema
accordingly to ensure defaults are applied by TracingConfigSchema.parse only
after merging.
---
Nitpick comments:
In `@package.json`:
- Around line 58-62: Move the heavy OpenTelemetry SDK packages from
"dependencies" to "optionalDependencies" in package.json and change
src/observability/tracing.ts to lazily import the SDK only when tracing is
enabled; keep `@opentelemetry/api` as a regular dependency, update package.json
entries "`@opentelemetry/exporter-trace-otlp-http`", "`@opentelemetry/resources`",
"`@opentelemetry/sdk-node`", and "`@opentelemetry/sdk-trace-base`" to
optionalDependencies, then modify functions in tracing.ts that initialize
tracing (e.g., the tracer initialization/bootstrap function) to use dynamic
import(...) for the SDK modules and guard execution behind the existing
tracing-enabled flag so consumers who don't opt into optional deps won't
download or execute the heavy SDK.
In `@tests/unit/config.test.ts`:
- Around line 277-315: Add a unit test in tests/unit/config.test.ts that calls
validateConfig with both observability.tracing and observability.otel present
and assert the intended precedence behavior (i.e., supply conflicting values
like tracing.exporter = 'otlp' with tracing.otlpEndpoint =
'http://tracing:4318/v1/traces' and otel.endpoint = 'http://otel:4318/v1/traces'
and then expect validateConfig to be valid and that the resulting merged config
uses the tracing values); reference validateConfig, observability.tracing and
observability.otel in the test so the merge path in src/utils/config.ts is
exercised and locked in.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 01042444-9d8d-45b1-926d-8a3d4a6d081f
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (15)
docs/OBSERVABILITY.mdpackage.jsonsrc/agents/spawner.tssrc/coordination/review-loop.tssrc/index.tssrc/mcp/server.tssrc/mcp/tools/task-tools.tssrc/memory/index.tssrc/observability/index.tssrc/observability/tracing.tssrc/tasks/consensus-service.tssrc/types.tssrc/utils/config.tstests/unit/config.test.tstests/unit/observability/tracing.test.ts
Summary
observability.otelwithendpointalias plusobservability.tracing.otlpEndpointfor programmatic/backward-compatible config.Validation
npm run typechecknpx vitest run tests/unit/observability/tracing.test.ts tests/unit/config.test.ts tests/unit/consensus-service.test.ts tests/unit/memory-agent-scoping.test.tsnpm run test:unitnpx vitest run --config vitest.integration.config.ts --reporter=dotnpm run buildnpm run lint(passes with existing warnings outside this change)git diff --checkSummary by CodeRabbit
New Features
Documentation
Tests
Chores