Skip to content

fix: preserve active OTel context in application dispatch - #54

Merged
yordis merged 1 commit into
mainfrom
fix-otel-1
Feb 26, 2026
Merged

yordis merged 1 commit into
mainfrom
fix-otel-1

Conversation

@yordis

@yordis yordis commented Feb 26, 2026

Copy link
Copy Markdown
Member

Summary

  • Application dispatch runs in the caller's process (unlike aggregate execute which runs in a separate GenServer). Calling Helpers.attach_ctx/1 unconditionally was destroying the active parent span context (e.g., gRPC/HTTP handler span), replacing it with either extracted traceparent headers or an empty context.
  • Replaced with maybe_attach_ctx/1 which checks for a valid span via :otel_span.is_valid/1 before deciding whether to extract from metadata.

Test plan

  • Active parent span + no traceparent → dispatch becomes child of parent
  • Active parent span + traceparent in metadata → dispatch becomes child of active span (not extracted traceparent)
  • No active parent + no metadata → starts new trace
  • No active parent + traceparent in metadata → uses traceparent as parent

@cursor

cursor Bot commented Feb 26, 2026 •

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches tracing context management across dispatch/aggregate/event handler telemetry; mistakes could break span parentage or link semantics, though covered by new unit and E2E tests.

Overview
Fixes OpenTelemetry context propagation so application dispatch spans no longer clobber an already-active parent span context (e.g., an incoming HTTP/gRPC request) by stopping unconditional context attachment on [:commanded, :application, :dispatch, :start].

Refactors propagation utilities by replacing attach_ctx/1 with Helpers.extract_propagated_ctx/1 (returns {links, ctx} without mutating process state) plus Helpers.clear_ctx/0, and updates aggregate execute + event handler instrumentation to consistently either attach extracted context (child mode) or create span links while clearing stale context (link/none modes). Adds unit + end-to-end tests asserting correct parent/child vs link behavior and verifying dispatch telemetry metadata does not include traceparent at :start.

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

@coderabbitai

coderabbitai Bot commented Feb 26, 2026 •

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Replaces unconditional metadata-based OTEL context attachment with an explicit extract/clear/attach flow: helpers now expose extract_propagated_ctx/1 and clear_ctx/0; aggregate and event handler use extracted context (attach if present, else clear); application no longer attaches metadata-derived context during dispatch start; tests added (unit + e2e).

Changes

Cohort / File(s) Summary
Helpers API
lib/commanded/opentelemetry/helpers.ex
Removed attach_ctx/*; added extract_propagated_ctx/1 and clear_ctx/0; made header-building and extraction internals private; extraction returns {links, ctx} or {[], :undefined} without attaching.
Application dispatch
lib/commanded/opentelemetry/application.ex
Removed direct attach of trace context from dispatch metadata; dispatch start no longer injects metadata-derived context.
Aggregate instrumentation
lib/commanded/opentelemetry/aggregate.ex
Replaced direct attach with Helpers.extract_propagated_ctx/1; if ctx is :undefined call Helpers.clear_ctx/0, else attach via :otel_ctx.attach/1.
Event handler instrumentation
lib/commanded/opentelemetry/event_handler.ex
Unified propagate/clear behavior for :link/:child/:none modes using extract_propagated_ctx/1; explicit attach or clear; removed private span-context helper.
Unit tests for helpers
test/opentelemetry/helpers_test.exs
New tests for extract_propagated_ctx/1 and clear_ctx/0: traceparent parsing, link extraction, context validity, and integration scenarios.
Application tests (unit & e2e)
test/opentelemetry/application_test.exs, test/opentelemetry/application_e2e_test.exs
Added tests validating dispatch span parentage with an active span, new-trace behavior without a parent, and a full HTTP → dispatch → aggregate → event-handler end-to-end trace/link assertions.

Sequence Diagram(s)

sequenceDiagram
    actor Client
    participant HTTP as "HTTP/span (root)"
    participant Router as "Router / Middleware"
    participant Dispatcher as "Dispatch span"
    participant Aggregate as "Aggregate span"
    participant Handler as "EventHandler span"

    rect rgba(200,200,255,0.5)
    Client->>HTTP: incoming request (creates HTTP span)
    end

    rect rgba(200,255,200,0.5)
    HTTP->>Router: invoke command (middleware injects traceparent into metadata)
    Router->>Dispatcher: start dispatch (child of HTTP if active)
    end

    rect rgba(255,230,200,0.5)
    Dispatcher->>Aggregate: call aggregate (metadata passed)
    Aggregate->>Aggregate: call Helpers.extract_propagated_ctx(metadata)
    Aggregate->>Aggregate: attach extracted ctx OR call Helpers.clear_ctx()
    Aggregate->>Handler: persist event (handler receives metadata)
    end

    rect rgba(255,200,200,0.5)
    Handler->>Handler: attach propagated ctx (child) OR clear and start new trace + add link back
    Handler-->>Client: finish
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐇 I sniffed the trace in metadata breeze,

If a parent was near I bowed with ease,
Else I cleared, or linked back the track—
Little hops keep spans tidy, never slack.
Hop on, traces! 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: preserve active OTel context in application dispatch' directly and clearly summarizes the main change: fixing context preservation in dispatch operations.
Description check ✅ Passed The description is clearly related to the changeset, explaining the problem (unconditional attach_ctx destroying parent span), the solution (maybe_attach_ctx checking for valid span), and provides specific test cases.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-otel-1

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.

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

🧹 Nitpick comments (3)
.github/workflows/release-please.yml (1)

21-21: Pin GitHub Action to an immutable commit SHA.

Line 21 uses a floating major tag (@v4), which can change over time. Prefer SHA pinning for reproducibility and supply-chain safety.

Proposed change
-        uses: googleapis/release-please-action@v4
+        uses: googleapis/release-please-action@c3fc4de07084f75a2b61a5b933069bda6edf3d5c
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release-please.yml at line 21, Replace the floating tag
"uses: googleapis/release-please-action@v4" with an immutable commit SHA for the
googleapis/release-please-action action: locate the latest stable commit SHA in
the action's repository (or the commit you want to pin), and update the workflow
entry to use that SHA instead of "@v4" (e.g., "uses:
googleapis/release-please-action@<commit-sha>"). Ensure the SHA you pick is
documented in the repo or PR so future maintainers know why it was pinned and
consider regularly updating the pinned SHA via CI or an automated
dependabot-style workflow.
test/opentelemetry/application_test.exs (2)

439-450: Consider extracting encode_traceparent/1 into shared test support.

This helper duplicates logic already present in test/opentelemetry/aggregate_test.exs (Lines 599-609). Moving it to shared test support would reduce drift risk.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/opentelemetry/application_test.exs` around lines 439 - 450, The helper
encode_traceparent/1 is duplicated across tests; extract it into a shared test
support module (e.g., an OpentelemetryTestHelpers module) and replace the local
definitions in application_test.exs and aggregate_test.exs with calls/imports to
that helper; update test/support to define encode_traceparent/1 (mirroring the
existing implementation) and add the support module to ExUnit configuration so
both tests can call encode_traceparent/1 without duplication.

155-175: Strengthen the precedence test by using a conflicting traceparent.

Right now the metadata traceparent is derived from the same active span context, so this can still pass if metadata extraction incorrectly wins. Use a different/foreign traceparent and assert the dispatch span still chooses the active parent.

Suggested test hardening diff
-          traceparent = encode_traceparent(ctx)
+          {foreign_trace_id, foreign_span_id, traceparent} =
+            Tracer.with_span "foreign.request" do
+              foreign_ctx = Tracer.current_span_ctx()
+              {
+                :otel_span.trace_id(foreign_ctx),
+                :otel_span.span_id(foreign_ctx),
+                encode_traceparent(foreign_ctx)
+              }
+            end
@@
-          {parent_trace_id, parent_span_id}
+          {parent_trace_id, parent_span_id, foreign_trace_id, foreign_span_id}
         end
@@
-      assert dispatch_parent_span_id == parent_span_id,
+      assert dispatch_parent_span_id == parent_span_id,
              "Dispatch span should be a child of the active span, not the extracted traceparent."
+
+      refute dispatch_trace_id == foreign_trace_id
+      refute dispatch_parent_span_id == foreign_span_id

Also applies to: 191-196

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/opentelemetry/application_test.exs` around lines 155 - 175, The test
"dispatch span becomes a child even when traceparent is in metadata" currently
injects a traceparent derived from the same active span; change it to inject a
conflicting/foreign traceparent so we can assert the active process span still
wins. Specifically, when using Tracer.with_span and encode_traceparent to build
metadata via Factory.build_application_dispatch_metadata, replace the encoded
traceparent with one generated from a different/new span or a manually
constructed traceparent with a different trace_id/span_id, then assert the
dispatch span chooses the Tracer.with_span context (active parent). Apply the
same change to the similar test around lines 191-196 to harden that assertion as
well.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.github/workflows/release-please.yml:
- Line 21: Replace the floating tag "uses: googleapis/release-please-action@v4"
with an immutable commit SHA for the googleapis/release-please-action action:
locate the latest stable commit SHA in the action's repository (or the commit
you want to pin), and update the workflow entry to use that SHA instead of "@v4"
(e.g., "uses: googleapis/release-please-action@<commit-sha>"). Ensure the SHA
you pick is documented in the repo or PR so future maintainers know why it was
pinned and consider regularly updating the pinned SHA via CI or an automated
dependabot-style workflow.

In `@test/opentelemetry/application_test.exs`:
- Around line 439-450: The helper encode_traceparent/1 is duplicated across
tests; extract it into a shared test support module (e.g., an
OpentelemetryTestHelpers module) and replace the local definitions in
application_test.exs and aggregate_test.exs with calls/imports to that helper;
update test/support to define encode_traceparent/1 (mirroring the existing
implementation) and add the support module to ExUnit configuration so both tests
can call encode_traceparent/1 without duplication.
- Around line 155-175: The test "dispatch span becomes a child even when
traceparent is in metadata" currently injects a traceparent derived from the
same active span; change it to inject a conflicting/foreign traceparent so we
can assert the active process span still wins. Specifically, when using
Tracer.with_span and encode_traceparent to build metadata via
Factory.build_application_dispatch_metadata, replace the encoded traceparent
with one generated from a different/new span or a manually constructed
traceparent with a different trace_id/span_id, then assert the dispatch span
chooses the Tracer.with_span context (active parent). Apply the same change to
the similar test around lines 191-196 to harden that assertion as well.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7a96983 and b6d840c.

📒 Files selected for processing (3)
  • .github/workflows/release-please.yml
  • lib/commanded/opentelemetry/application.ex
  • test/opentelemetry/application_test.exs

Comment thread test/opentelemetry/application_test.exs Outdated

@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

🧹 Nitpick comments (1)
test/opentelemetry/application_test.exs (1)

439-449: Consider extracting encode_traceparent/1 to a shared test helper.

This function is duplicated in test/opentelemetry/aggregate_test.exs (lines 599-609). Consider moving it to a shared test support module to reduce duplication.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/opentelemetry/application_test.exs` around lines 439 - 449, The
encode_traceparent/1 helper is duplicated across test modules; extract it into a
single shared test support module (e.g., create a module like
OpentelemetryTestHelpers with a public encode_traceparent/1 function), move the
implementation there (preserving the :otel_span.trace_id/1, :otel_span.span_id/1
and trace_flags logic), update the test modules to call or import
OpentelemetryTestHelpers.encode_traceparent/1 instead of defining it locally,
and ensure the support module is loaded for tests (require importing or adding
it via test_helper setup so both test suites use the shared helper).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/opentelemetry/application_test.exs`:
- Around line 155-196: The test encodes the traceparent from the same context
(ctx) used to extract parent_trace_id and parent_span_id, so both the active
span and traceparent metadata contain identical IDs. This means the assertions
will pass regardless of whether the dispatch span actually uses the active span
or the extracted traceparent. To properly verify that the active span is
preferred, generate a traceparent from a different trace context (not from ctx)
and pass that as the traceparent in the metadata. This way, if the
implementation incorrectly uses the extracted traceparent instead of the active
span, the assertions will fail as intended.

---

Nitpick comments:
In `@test/opentelemetry/application_test.exs`:
- Around line 439-449: The encode_traceparent/1 helper is duplicated across test
modules; extract it into a single shared test support module (e.g., create a
module like OpentelemetryTestHelpers with a public encode_traceparent/1
function), move the implementation there (preserving the :otel_span.trace_id/1,
:otel_span.span_id/1 and trace_flags logic), update the test modules to call or
import OpentelemetryTestHelpers.encode_traceparent/1 instead of defining it
locally, and ensure the support module is loaded for tests (require importing or
adding it via test_helper setup so both test suites use the shared helper).

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b6d840c and 6eb9032.

📒 Files selected for processing (2)
  • lib/commanded/opentelemetry/application.ex
  • test/opentelemetry/application_test.exs

Comment thread test/opentelemetry/application_test.exs Outdated
Comment thread lib/commanded/opentelemetry/application.ex Outdated
@yordis
yordis force-pushed the fix-otel-1 branch 2 times, most recently from cbdf3da to e1a325b Compare February 26, 2026 05:29

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/opentelemetry/helpers_test.exs`:
- Around line 172-181: The test calls an undefined function span_ctx/2 to get
trace_flags; replace that call with the proper OpenTelemetry accessor
:otel_span.trace_flags(span_ctx) to retrieve trace flags, updating
encode_traceparent/1 in test/opentelemetry/helpers_test.exs (function
encode_traceparent), and the identical occurrences in
test/opentelemetry/event_handler_test.exs and
test/opentelemetry/aggregate_test.exs so they all use
:otel_span.trace_flags(span_ctx) instead of span_ctx(span_ctx, :trace_flags).

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6eb9032 and cbdf3da.

📒 Files selected for processing (7)
  • lib/commanded/opentelemetry/aggregate.ex
  • lib/commanded/opentelemetry/application.ex
  • lib/commanded/opentelemetry/event_handler.ex
  • lib/commanded/opentelemetry/helpers.ex
  • test/opentelemetry/application_e2e_test.exs
  • test/opentelemetry/application_test.exs
  • test/opentelemetry/helpers_test.exs
💤 Files with no reviewable changes (1)
  • lib/commanded/opentelemetry/application.ex

Comment thread test/opentelemetry/helpers_test.exs

@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

🧹 Nitpick comments (2)
test/opentelemetry/application_e2e_test.exs (2)

163-168: The 1-second timeout in collect_all_spans may cause slow test execution.

This helper waits the full timeout before returning, which adds 1 second to test duration. Combined with the Process.sleep(200), test execution is artificially extended. Consider using a shorter timeout or implementing early exit when no more spans are expected.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/opentelemetry/application_e2e_test.exs` around lines 163 - 168, The
helper collect_all_spans currently blocks for 1_000ms on the receive after
clause which adds unnecessary delay to tests; change its behavior by reducing
the after timeout to a much smaller value (e.g., 50-100ms) or implement an
early-exit strategy: accept an expected span count parameter (or poll until no
message seen for a short backoff) and return as soon as that count is collected,
updating calls to collect_all_spans accordingly (reference the
collect_all_spans/1 function and any test calls that rely on it, and consider
also reducing or removing the separate Process.sleep(200) where tests wait).

79-79: Consider replacing Process.sleep with a deterministic wait mechanism.

Using Process.sleep(200) makes this test potentially flaky, especially under varying system loads. While I understand it's waiting for async span emission, consider using a more deterministic approach like polling with a bounded retry or using a test helper that waits for specific spans to appear.

💡 Example approach using a polling helper
-      Process.sleep(200)
-
-      spans = collect_all_spans()
+      spans = await_spans(expected_count: 4, timeout: 2000)

Where await_spans polls until the expected number of spans is received or timeout is reached:

defp await_spans(opts) do
  expected = Keyword.get(opts, :expected_count, 1)
  timeout = Keyword.get(opts, :timeout, 2000)
  await_spans([], expected, System.monotonic_time(:millisecond) + timeout)
end

defp await_spans(acc, expected, deadline) when length(acc) >= expected, do: Enum.reverse(acc)
defp await_spans(acc, expected, deadline) do
  remaining = deadline - System.monotonic_time(:millisecond)
  if remaining <= 0 do
    Enum.reverse(acc)
  else
    receive do
      {:span, s} -> await_spans([s | acc], expected, deadline)
    after
      min(100, remaining) -> await_spans(acc, expected, deadline)
    end
  end
end
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/opentelemetry/application_e2e_test.exs` at line 79, Replace the flaky
Process.sleep(200) call with a deterministic polling helper: remove
Process.sleep/1 and call a helper like await_spans(expected_count: 1, timeout:
2000) (or await_spans() with defaults) that polls until the expected spans
arrive; implement await_spans/1 plus internal clauses await_spans(acc, expected,
deadline) and a receive/after loop (as in the example) so the test waits
deterministically for {:span, s} messages instead of sleeping.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/opentelemetry/application_e2e_test.exs`:
- Around line 98-108: The assertion block around span(handle_span, :trace_id),
span(handle_span, :parent_span_id), :otel_links.list(span(handle_span, :links)),
and the link(...) assertions is misformatted and failing CI; reformat that
entire block (either run mix format or adjust spacing/line breaks) so it matches
Elixir formatter expectations—ensure the pipeline/assert indentation and string
concatenation for the last assert remain valid and that lines with
span(handle_span, :parent_span_id) and the link(...) assertions are properly
indented and line-broken consistent with mix format.

---

Nitpick comments:
In `@test/opentelemetry/application_e2e_test.exs`:
- Around line 163-168: The helper collect_all_spans currently blocks for 1_000ms
on the receive after clause which adds unnecessary delay to tests; change its
behavior by reducing the after timeout to a much smaller value (e.g., 50-100ms)
or implement an early-exit strategy: accept an expected span count parameter (or
poll until no message seen for a short backoff) and return as soon as that count
is collected, updating calls to collect_all_spans accordingly (reference the
collect_all_spans/1 function and any test calls that rely on it, and consider
also reducing or removing the separate Process.sleep(200) where tests wait).
- Line 79: Replace the flaky Process.sleep(200) call with a deterministic
polling helper: remove Process.sleep/1 and call a helper like
await_spans(expected_count: 1, timeout: 2000) (or await_spans() with defaults)
that polls until the expected spans arrive; implement await_spans/1 plus
internal clauses await_spans(acc, expected, deadline) and a receive/after loop
(as in the example) so the test waits deterministically for {:span, s} messages
instead of sleeping.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cbdf3da and e1a325b.

📒 Files selected for processing (7)
  • lib/commanded/opentelemetry/aggregate.ex
  • lib/commanded/opentelemetry/application.ex
  • lib/commanded/opentelemetry/event_handler.ex
  • lib/commanded/opentelemetry/helpers.ex
  • test/opentelemetry/application_e2e_test.exs
  • test/opentelemetry/application_test.exs
  • test/opentelemetry/helpers_test.exs
💤 Files with no reviewable changes (1)
  • lib/commanded/opentelemetry/application.ex
🚧 Files skipped from review as they are similar to previous changes (3)
  • test/opentelemetry/application_test.exs
  • test/opentelemetry/helpers_test.exs
  • lib/commanded/opentelemetry/aggregate.ex

Comment thread test/opentelemetry/application_e2e_test.exs Outdated

@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 force-pushed the fix-otel-1 branch 2 times, most recently from beff3b1 to d816bf9 Compare February 26, 2026 05:56

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

♻️ Duplicate comments (1)
test/opentelemetry/helpers_test.exs (1)

172-182: ⚠️ Potential issue | 🔴 Critical

span_ctx/2 is undefined — this will fail to compile.

Line 175 calls span_ctx(span_ctx, :trace_flags) but no such function exists. The OpenTelemetry Erlang API doesn't provide a direct accessor for trace_flags.

Proposed fix — use hardcoded flag for sampled traces
  defp encode_traceparent(span_ctx) do
    trace_id = :otel_span.trace_id(span_ctx)
    span_id = :otel_span.span_id(span_ctx)
-   trace_flags = span_ctx(span_ctx, :trace_flags)
+   # Sampled flag = 1 (spans created via Tracer.with_span are sampled by default in tests)
+   trace_flags = 1

    hex_trace_id = :io_lib.format("~32.16.0b", [trace_id]) |> IO.iodata_to_binary()
    hex_span_id = :io_lib.format("~16.16.0b", [span_id]) |> IO.iodata_to_binary()
    hex_flags = :io_lib.format("~2.16.0b", [trace_flags]) |> IO.iodata_to_binary()

    "00-#{hex_trace_id}-#{hex_span_id}-#{hex_flags}"
  end
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/opentelemetry/helpers_test.exs` around lines 172 - 182, The call to
span_ctx(span_ctx, :trace_flags) in encode_traceparent is invalid; instead set
trace_flags to a known value (e.g., 1 for sampled) or obtain it via a supported
API; update encode_traceparent to compute trace_flags as an integer (use 1 for
sampled traces) and keep the rest of the hex formatting logic using trace_id =
:otel_span.trace_id(span_ctx) and span_id = :otel_span.span_id(span_ctx) so
hex_flags uses that integer.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@test/opentelemetry/helpers_test.exs`:
- Around line 172-182: The call to span_ctx(span_ctx, :trace_flags) in
encode_traceparent is invalid; instead set trace_flags to a known value (e.g., 1
for sampled) or obtain it via a supported API; update encode_traceparent to
compute trace_flags as an integer (use 1 for sampled traces) and keep the rest
of the hex formatting logic using trace_id = :otel_span.trace_id(span_ctx) and
span_id = :otel_span.span_id(span_ctx) so hex_flags uses that integer.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e1a325b and d816bf9.

📒 Files selected for processing (7)
  • lib/commanded/opentelemetry/aggregate.ex
  • lib/commanded/opentelemetry/application.ex
  • lib/commanded/opentelemetry/event_handler.ex
  • lib/commanded/opentelemetry/helpers.ex
  • test/opentelemetry/application_e2e_test.exs
  • test/opentelemetry/application_test.exs
  • test/opentelemetry/helpers_test.exs
💤 Files with no reviewable changes (1)
  • lib/commanded/opentelemetry/application.ex

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
@yordis
yordis merged commit 4185ca1 into main Feb 26, 2026
5 checks passed
@yordis
yordis deleted the fix-otel-1 branch February 26, 2026 08:58
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