Skip to content

feat: implement OpenTelemetry instrumentation for application - #46

Merged
yordis merged 1 commit into
mainfrom
otel-app
Jan 18, 2026
Merged

yordis merged 1 commit into
mainfrom
otel-app

Conversation

@yordis

@yordis yordis commented Jan 17, 2026 •

Copy link
Copy Markdown
Member

No description provided.

@cursor

cursor Bot commented Jan 17, 2026 •

Copy link
Copy Markdown

PR Summary

Adds application-level tracing for command dispatch with OpenTelemetry and updates configuration/tests accordingly.

  • New Commanded.OpenTelemetry.Application attaches to [:commanded, :application, :dispatch, :start|:stop|:exception] to create consumer spans, set OTel semconv/code/commanded attributes, attach context from metadata, and record errors/exceptions with status
  • Commanded.OpenTelemetry.setup/1 gains application option; application: :disabled disables dispatch tracing
  • New application_test.exs validates span attributes, error statuses, and exception events; Factory extended with builders for application dispatch metadata/events; OpenTelemetryCase teardown detaches new handlers
  • Minor test hygiene: ensure handlers detached before Aggregate.setup/0

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

@coderabbitai

coderabbitai Bot commented Jan 17, 2026 •

Copy link
Copy Markdown

Warning

Rate limit exceeded

@yordis has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 4 minutes and 26 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between cea7eab and b5e979f.

📒 Files selected for processing (6)
  • lib/commanded/opentelemetry.ex
  • lib/commanded/opentelemetry/application.ex
  • test/opentelemetry/aggregate_test.exs
  • test/opentelemetry/application_test.exs
  • test/support/factory.ex
  • test/support/opentelemetry_case.ex

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

Adds OpenTelemetry instrumentation for Commanded application dispatch: registers telemetry handlers for dispatch start/stop/exception, extracts/propagates trace context, starts/ends consumer spans with messaging/code/commanded attributes, and records errors/exceptions and span status.

Changes

Cohort / File(s) Summary
Application OTEL module
lib/commanded/opentelemetry/application.ex
New module registering telemetry handlers and implementing handle_telemetry_event/4 for [:commanded, :application, :dispatch, ...]: extracts trace context from metadata, starts consumer spans named dispatch {handler}, sets messaging/code/commanded attributes, records errors/exceptions, and ends spans.
OpenTelemetry entrypoint
lib/commanded/opentelemetry.ex
Added alias Commanded.OpenTelemetry.Application (OTelApplication), extended NimbleOptions schema with :application option, and updated setup/1 to invoke OTelApplication.setup() when enabled.
Tests
test/opentelemetry/application_test.exs
New ExUnit tests that verify telemetry handlers are attached idempotently and that dispatch start/stop/exception produce expected spans, attributes, error statuses, and recorded exception events.
Test factories / telemetry helpers
test/support/factory.ex
Added builders: build_application_dispatch_metadata/1, build_application_dispatch_stop_metadata/1, build_application_dispatch_exception_metadata/1, and build_telemetry_event/2 clauses for :application_dispatch_{start,stop,exception} to simulate events in tests.

Sequence Diagram(s)

sequenceDiagram
    participant App as Commanded App
    participant Telemetry as Telemetry Handler
    participant OTEL as OpenTelemetry API
    participant Span as Span Context

    App->>Telemetry: emit [:commanded, :application, :dispatch, :start] (meta)
    Telemetry->>OTEL: extract trace context from meta
    OTEL->>Span: start consumer span "dispatch {handler}" with attributes
    note right of Span: messaging, code, commanded attrs

    App->>Telemetry: emit [:commanded, :application, :dispatch, :stop] (meta)
    Telemetry->>Span: restore span, record error attrs if present
    Span->>Span: set status / end

    rect rgba(255, 0, 0, 0.5)
    App->>Telemetry: emit [:commanded, :application, :dispatch, :exception] (kind, reason, stacktrace)
    Telemetry->>Span: restore span, set exception attrs, record exception, set error status
    Span->>Span: end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐇 I hop through spans where commands take flight,
I stitch the traces from start to night-time light.
Errors I mark, exceptions I log,
Breadcrumbs of context through Commanded’s fog.
Hooray—now every dispatch shines bright! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description is vague and generic, containing only placeholder-like bullet points ('feat: add application otel', 'aaaa', 'aaa') that don't convey meaningful information about the changeset. Provide a clear description explaining what OpenTelemetry instrumentation is being added, why it's needed, and how it integrates with the application dispatch flow.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: adding OpenTelemetry instrumentation for the application dispatch flow.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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 changed the title otel app feat: implement OpenTelemetry instrumentation for application Jan 17, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Comment thread lib/commanded/opentelemetry/application.ex
Comment thread test/support/factory.ex

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Comment thread lib/commanded/opentelemetry/application.ex
@yordis
yordis marked this pull request as ready for review January 18, 2026 00:25
@yordis
yordis force-pushed the otel-app branch 2 times, most recently from e1da358 to cea7eab Compare January 18, 2026 00:32

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@test/opentelemetry/application_test.exs`:
- Around line 273-276: Replace the raw tuple pattern matching when inspecting
span events with the public record syntax and conversion utilities: use
:otel_events.list(events) to get events, find the exception event using the
event record pattern (e.g., event(name: :exception) or matching event(name: n)
and checking n == :exception) instead of matching {:event, ...}, then extract
attributes via the event(attributes: exc_attrs) record and convert to a map with
:otel_attributes.map(exc_attrs). Update references to the variables
exception_event and attrs_map accordingly so tests use event(...) records and
:otel_attributes.map/1 rather than raw tuple destructuring.
🧹 Nitpick comments (2)
test/opentelemetry/application_test.exs (2)

52-63: Consider adding an idempotent_setup or guard.

The "fail fast" behavior via MatchError is documented here as intentional, but in production this could cause issues if setup/0 is accidentally called twice during application startup. Consider whether a guard check or explicit error with a helpful message would be more user-friendly.


108-112: Redundant setup block.

This nested setup duplicates the outer setup block (lines 10-17). The detach and setup are already performed before each test by the outer setup.

♻️ Suggested fix

Remove this redundant setup block since the outer setup already handles handler initialization:

 describe "error handling" do
-  setup do
-    detach_handlers()
-    OTelApplication.setup()
-    :ok
-  end
-
   test "sets error status when dispatch returns error in stop" do

Comment thread test/opentelemetry/application_test.exs
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
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.

1 participant