Skip to content

Conversation

@yordis
Copy link
Member

@yordis yordis commented Jan 1, 2026

Signed-off-by: Yordis Prieto yordis.prieto@gmail.com

@cursor
Copy link

cursor bot commented Jan 1, 2026

PR Summary

Adds first-class OpenTelemetry tracing integration for Commanded event processing.

  • New Commanded.OpenTelemetry module to attach telemetry handlers and create spans for event.handle and event.batch with configurable :span_relationship (:link, :child, :none) and tracer name
  • Implements Commanded.OpenTelemetry.EventHandler, ...Helper, and ...CommandedAttributes to generate spans, set attributes (OTel SemConv + commanded.*), handle errors/exceptions, and support span links/parenting
  • Enhances Commanded.Middleware.TraceContextPropagator with docs/specs to inject W3C traceparent/tracestate into command metadata
  • Adds required deps: opentelemetry_api, opentelemetry_telemetry, opentelemetry_semantic_conventions, and nimble_options; updates docs grouping and dialyzer config
  • Documentation: explanation and a new how-to guide for setup and span relationship configuration
  • Tests: comprehensive OTel setup, helper, and event handler coverage; adds OTel test case harness

Written by Cursor Bugbot for commit 3c15139. This will update automatically on new commits. Configure here.

@coderabbitai
Copy link

coderabbitai bot commented Jan 1, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

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.


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.

❤️ Share

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

@yordis yordis force-pushed the feat-add-event-handler-otel branch 2 times, most recently from 2f6c832 to af578fb Compare January 1, 2026 20:47
@yordis yordis force-pushed the feat-add-event-handler-otel branch 4 times, most recently from 3ca5650 to 97028f5 Compare January 1, 2026 21:40
@yordis yordis force-pushed the feat-add-event-handler-otel branch from 97028f5 to 8126b0e Compare January 1, 2026 21:55
@yordis yordis force-pushed the feat-add-event-handler-otel branch from 8126b0e to a62a126 Compare January 1, 2026 22:17
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
@yordis yordis force-pushed the feat-add-event-handler-otel branch from a62a126 to 07798dd Compare January 2, 2026 03:22
yordis added 3 commits January 1, 2026 23:12
Updated the OpenTelemetry event handler to use `attach_many` for single and batch event handlers, reducing redundancy. Adjusted tests to reflect the new handler structure, ensuring proper verification of telemetry events.
Updated the `mix.exs` file to make OpenTelemetry dependencies required instead of optional. Enhanced the documentation to reflect these changes and ensured the OpenTelemetry module integrates seamlessly with Commanded for distributed tracing.
for handler <- :telemetry.list_handlers([]) do
:telemetry.detach(handler.id)
end
end)
Copy link

Choose a reason for hiding this comment

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

Test cleanup uses wrong telemetry handler query

The on_exit callback uses :telemetry.list_handlers([]) which lists handlers for the event named [] (an empty list), not all handlers. This cleanup is ineffective. The individual test files correctly use explicit event names like [:commanded, :event, :handle, :start] in their detach_handlers/0 functions. The same pattern should be used here.

Fix in Cursor Fix in Web

def safe_context_propagation(metadata) when is_map(metadata) do
headers = build_headers_from_metadata(metadata)
if headers != [], do: :otel_propagator_text_map.extract(headers)
end
Copy link

Choose a reason for hiding this comment

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

Context leakage in child span relationship mode

The safe_context_propagation function uses :otel_propagator_text_map.extract/1 which modifies the current process context as a side effect. When an event with a traceparent is processed, that trace context persists in the process dictionary. If a subsequent event has no traceparent, safe_context_propagation returns nil without clearing the old context, causing the new event's span to incorrectly become a child of the previous event's trace. This results in incorrect trace relationships in the tracing backend. The fix would be to use extract_to/2 like extract_span_context_for_link does, extracting into a fresh context without modifying the process dictionary.

Additional Locations (1)

Fix in Cursor Fix in Web

yordis added 3 commits January 2, 2026 03:06
…ontext handling

Deleted the migration guide for `commanded-ecto-projections` as Ecto projection support is now built-in. Refactored the OpenTelemetry event handler and helper functions to streamline context propagation, ensuring clarity in parent-child span relationships. Updated tests to reflect changes in context handling.
Added new span relationship modes for OpenTelemetry setup, allowing for more flexible tracing configurations. Introduced a detach function to clean up telemetry handlers, enabling reconfiguration during tests. Updated documentation and tests to reflect these changes, ensuring clarity in usage and functionality.
&__MODULE__.batch_telemetry_event/4,
config
)
end
Copy link

Choose a reason for hiding this comment

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

Setup ignores first telemetry attach result

The setup/1 function's spec declares it returns :ok | {:error, :already_exists}, but the implementation ignores the return value of the first :telemetry.attach_many call for single event handlers (line 29-38). Only the second attach_many result (for batch handlers) is returned. If the first attach_many fails with {:error, :already_exists} but the second succeeds, the function incorrectly returns :ok. Conversely, if the first succeeds but the second fails, the function returns an error while leaving single event handlers attached, creating inconsistent state. The function should use a with construct to properly check both results.

Fix in Cursor Fix in Web

…ed attributes

Enhanced the OpenTelemetry event handler tests by replacing hardcoded values with realistic UUIDs for event IDs, stream IDs, causation, and correlation IDs. Updated attribute assertions to reflect the new structure and naming conventions for projectors. Improved error handling tests to simulate realistic scenarios, ensuring better coverage and accuracy in telemetry data.
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