feat: implement OpenTelemetry instrumentation for aggregates - #45
Conversation
PR SummaryIntroduces full OpenTelemetry tracing for aggregates and consolidates tracing utilities.
Written by Cursor Bugbot for commit 839010f. This will update automatically on new commits. Configure here. |
|
Note Other AI code review bot(s) detectedCodeRabbit 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. WalkthroughAdds OpenTelemetry aggregate execute instrumentation and shared Helpers; refactors EventHandler to use Helpers; exposes aggregate configuration in setup; adds tests, factories, and test router to validate aggregate tracing and context propagation. Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Client/Command
participant Router as Commanded Router
participant Aggregate as Aggregate Executor
participant Telemetry as Telemetry Emitter
participant OTel as OTel Aggregate Handler
participant Tracer as OTEL Tracer
participant Span as Span
Client->>Router: dispatch(command)
Router->>Aggregate: execute(command)
Aggregate->>Telemetry: emit [:commanded, :aggregate, :execute, :start]
Telemetry->>OTel: handle start event
OTel->>OTel: extract_trace_context(metadata)
OTel->>Tracer: start_consumer_span("execute <aggregate>")
Tracer->>Span: create(name, attributes)
Aggregate->>Aggregate: apply events
Aggregate->>Telemetry: emit [:commanded, :aggregate, :execute, :stop]
Telemetry->>OTel: handle stop event
OTel->>Span: set_attribute(event.count)
OTel->>Span: end()
alt Exception occurs
Aggregate-->>Telemetry: emit [:commanded, :aggregate, :execute, :exception]
Telemetry->>OTel: handle exception event
OTel->>Span: set_attribute(error.*)
OTel->>Span: set_status(error)
OTel->>Span: end()
end
Router-->>Client: result
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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 |
4c8e219 to
287c8d8
Compare
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
287c8d8 to
839010f
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
test/support/factory.ex (1)
116-190: Align projector-specificrecorded_eventdefaults withevent_type.
build_recorded_event(:account_projector|:transaction_projector, opts)overridesevent_typetoMyApp.Events.*andstream_idbut leavesdatadefaulting toTestDomain.AccountOpenedfrom the generic builder. This creates a mismatch where the recorded event'sevent_typestring does not correspond to its actualdatastruct, which can cause confusing failures if tests or helpers inspectrecorded_event.data. Provide projector-specific defaultdatastructures (or require callers to pass them explicitly) to keep the event type and data struct in sync.
🧹 Nitpick comments (1)
lib/commanded/opentelemetry/helpers.ex (1)
39-60: Unreachable exception clause due to pattern matching order.
%{__struct__: _}matches exceptions too, so the%{__exception__: true}clause never runs. Consider reordering or removing the redundant clause to avoid dead code.♻️ Suggested reorder to avoid the dead clause
-def to_error_type(%{__struct__: module}, _tracer_id), do: to_string(module) - -def to_error_type(%{__exception__: true} = exception, _tracer_id), - do: to_string(exception.__struct__) +def to_error_type(%{__exception__: true} = exception, _tracer_id), + do: to_string(exception.__struct__) + +def to_error_type(%{__struct__: module}, _tracer_id), do: to_string(module)
Signed-off-by: Yordis Prieto yordis.prieto@gmail.com