Skip to content

fix(telemetry): strip Elixir. prefix from commanded.application attribute - #93

Merged
yordis merged 1 commit into
mainfrom
yordis/fix-otel-application-prefix
Apr 21, 2026
Merged

yordis merged 1 commit into
mainfrom
yordis/fix-otel-application-prefix

Conversation

@yordis

@yordis yordis commented Apr 21, 2026

Copy link
Copy Markdown
Member
  • OTel convention requires module names without the BEAM-internal Elixir. prefix in attribute values (e.g. Umbrella.CommandRouter not Elixir.Umbrella.CommandRouter)
  • commanded.application was storing the raw module atom which OTel serializes via to_string/1, leaking the Elixir. prefix into APM tools

@cursor

cursor Bot commented Apr 21, 2026 •

Copy link
Copy Markdown

PR Summary

Low Risk
Low risk: changes are limited to telemetry attribute formatting and associated test expectations, with no impact on command/event processing behavior.

Overview
Updates Commanded’s OpenTelemetry instrumentation to emit commanded.application (and messaging.consumer.group.name where used) as a normalized module name string via Helpers.module_name/1 instead of the raw module atom.

Adjusts span attribute assertions across aggregate, application dispatch, event handler, aggregate load/populate/snapshot, and event store tests to expect the new string values (and to use inspect/1 in exception cases where appropriate).

Reviewed by Cursor Bugbot for commit d102a65. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitai Bot commented Apr 21, 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 54 minutes and 23 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 54 minutes and 23 seconds.

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 44e58e22-f4d1-425f-91b2-a8e1c34ea1c2

📥 Commits

Reviewing files that changed from the base of the PR and between 3650d28 and d102a65.

📒 Files selected for processing (12)
  • lib/commanded/opentelemetry/aggregate.ex
  • lib/commanded/opentelemetry/aggregate_populate.ex
  • lib/commanded/opentelemetry/aggregate_snapshot.ex
  • lib/commanded/opentelemetry/application.ex
  • lib/commanded/opentelemetry/event_handler.ex
  • lib/commanded/opentelemetry/event_store.ex
  • test/opentelemetry/aggregate_populate_test.exs
  • test/opentelemetry/aggregate_snapshot_test.exs
  • test/opentelemetry/aggregate_test.exs
  • test/opentelemetry/application_test.exs
  • test/opentelemetry/event_handler_test.exs
  • test/opentelemetry/event_store_test.exs

Walkthrough

This PR normalizes the commanded_application OpenTelemetry span attribute across all telemetry instrumentation modules by applying Helpers.module_name() to convert application module atoms to their string representations, ensuring consistent attribute formatting in traces.

Changes

Cohort / File(s) Summary
OpenTelemetry Instrumentation
lib/commanded/opentelemetry/aggregate.ex, lib/commanded/opentelemetry/aggregate_populate.ex, lib/commanded/opentelemetry/aggregate_snapshot.ex, lib/commanded/opentelemetry/application.ex, lib/commanded/opentelemetry/event_handler.ex, lib/commanded/opentelemetry/event_store.ex
Updated commanded_application span attribute construction to use Helpers.module_name(meta.application) instead of raw meta.application, normalizing application module names to strings across all telemetry span starts.
Telemetry Tests
test/opentelemetry/aggregate_populate_test.exs, test/opentelemetry/aggregate_snapshot_test.exs, test/opentelemetry/aggregate_test.exs, test/opentelemetry/application_test.exs, test/opentelemetry/event_handler_test.exs, test/opentelemetry/event_store_test.exs
Updated expected commanded.application span attribute assertions to match stringified module names (e.g., "MockApp", "Commanded.DefaultApp") instead of atoms, reflecting the normalized representation.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Poem

🐰✨ Module names now strings so bright,
Helpers normalize with all their might,
Traces sparkle clear and true,
Telemetry shines in stringy hue! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(telemetry): strip Elixir. prefix from commanded.application attribute' accurately and concisely describes the main change: normalizing module names in OpenTelemetry span attributes by removing the Elixir. prefix.
Description check ✅ Passed The description clearly explains the problem (OTel convention requires module names without Elixir. prefix, and raw module atoms leak this prefix) and the solution being implemented across the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch yordis/fix-otel-application-prefix

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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
lib/commanded/opentelemetry/aggregate.ex (1)

50-56: ⚠️ Potential issue | 🟡 Minor

Normalize the adjacent consumer group application value too.

Line 56 fixes commanded.application using Helpers.module_name(meta.application), but line 50 still passes the raw meta.application atom to messaging_consumer_group_name(). When OpenTelemetry exporters stringify atoms, this will still surface Elixir.MockApp instead of just MockApp.

Apply the same normalization:

Proposed fix
-      {MessagingAttributes.messaging_consumer_group_name(), meta.application},
+      {MessagingAttributes.messaging_consumer_group_name(), Helpers.module_name(meta.application)},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/commanded/opentelemetry/aggregate.ex` around lines 50 - 56, The messaging
consumer group attribute currently uses the raw atom meta.application which
yields "Elixir.MockApp" when exported; update the tuple
{MessagingAttributes.messaging_consumer_group_name(), meta.application} to use
the same normalization as commanded_application by calling
Helpers.module_name(meta.application) so it becomes
{MessagingAttributes.messaging_consumer_group_name(),
Helpers.module_name(meta.application)}; this mirrors the change already made for
CommandedAttributes.commanded_application and ensures consistent,
non-Elixir-prefixed names in OpenTelemetry.
lib/commanded/opentelemetry/event_handler.ex (1)

84-90: ⚠️ Potential issue | 🟡 Minor

Normalize consumer group names alongside commanded.application in event and aggregate handlers.

Lines 84/187 in event_handler.ex and line 50 in aggregate.ex emit the raw application module for messaging.consumer.group.name, but the corresponding commanded.application attributes normalize it with Helpers.module_name(). This leaves the Elixir. prefix visible on event and aggregate handler spans.

Apply the fix across all three locations:

Proposed fixes

lib/commanded/opentelemetry/event_handler.ex (line 84):

-      {MessagingAttributes.messaging_consumer_group_name(), meta.application},
+      {MessagingAttributes.messaging_consumer_group_name(), Helpers.module_name(meta.application)},

lib/commanded/opentelemetry/event_handler.ex (line 187):

-      {MessagingAttributes.messaging_consumer_group_name(), meta.application},
+      {MessagingAttributes.messaging_consumer_group_name(), Helpers.module_name(meta.application)},

lib/commanded/opentelemetry/aggregate.ex (line 50):

-      {MessagingAttributes.messaging_consumer_group_name(), meta.application},
+      {MessagingAttributes.messaging_consumer_group_name(), Helpers.module_name(meta.application)},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/commanded/opentelemetry/event_handler.ex` around lines 84 - 90, The
Messaging consumer group attribute is emitting the raw application module
(showing the Elixir. prefix); update all places that set
{MessagingAttributes.messaging_consumer_group_name(), meta.application} to
normalize the module name using Helpers.module_name(meta.application).
Specifically, replace the tuple value for
MessagingAttributes.messaging_consumer_group_name() in the event handler (both
where attributes are assembled in handle spans and the other attribute block)
and in the aggregate handler so they use Helpers.module_name(meta.application)
instead of meta.application; leave the corresponding
CommandedAttributes.commanded_application() usage unchanged.
🧹 Nitpick comments (1)
test/opentelemetry/application_test.exs (1)

101-101: LGTM — mixed literal/inspect strategy is consistent with module-atom behavior.

Using inspect(meta.application) at lines 372/417 for dynamic cases and string literals elsewhere both produce the same output as Helpers.module_name/1 for module atoms (e.g., inspect(MockApp) == "MockApp"). This is safe here because meta.application is always a module atom in these factory-built metas.

One small consideration: if Helpers.module_name/1 ever diverges from inspect/1 for non-module inputs (e.g., handles nil or non-atoms specially), these tests would silently go out of sync with the implementation. For long-term robustness you could assert against a shared helper call rather than re-deriving with inspect/1, but it's optional given the factory guarantees.

Also applies to: 229-229, 372-372, 417-417

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

In `@test/opentelemetry/application_test.exs` at line 101, Replace uses of
inspect(meta.application) in the tests with a call to the shared helper
Helpers.module_name/1 so the expectation follows the real implementation; locate
the assertions that currently derive the application name via
inspect(meta.application) and change them to assert
Helpers.module_name(meta.application) (keeping the rest of the assertion text
intact) to avoid future divergence between inspect/1 and Helpers.module_name/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/event_handler_test.exs`:
- Line 109: Wrap the raw meta.application atoms with Helpers.module_name/1 when
building the messaging.consumer.group.name attribute so it emits the normalized
string (e.g., "MyApp.CommandedApp") instead of Elixir-prefixed atoms;
specifically update the attribute builders that set
"messaging.consumer.group.name" (see messaging_consumer_group_name / attribute
builder usage in EventHandler - functions where meta.application is used around
lines referenced and in Aggregate where meta.application is used) to call
Helpers.module_name(meta.application) before converting/assigning the attribute.
Ensure the same change is applied in both EventHandler and Aggregate attribute
builders to keep OTel name formatting consistent.

---

Outside diff comments:
In `@lib/commanded/opentelemetry/aggregate.ex`:
- Around line 50-56: The messaging consumer group attribute currently uses the
raw atom meta.application which yields "Elixir.MockApp" when exported; update
the tuple {MessagingAttributes.messaging_consumer_group_name(),
meta.application} to use the same normalization as commanded_application by
calling Helpers.module_name(meta.application) so it becomes
{MessagingAttributes.messaging_consumer_group_name(),
Helpers.module_name(meta.application)}; this mirrors the change already made for
CommandedAttributes.commanded_application and ensures consistent,
non-Elixir-prefixed names in OpenTelemetry.

In `@lib/commanded/opentelemetry/event_handler.ex`:
- Around line 84-90: The Messaging consumer group attribute is emitting the raw
application module (showing the Elixir. prefix); update all places that set
{MessagingAttributes.messaging_consumer_group_name(), meta.application} to
normalize the module name using Helpers.module_name(meta.application).
Specifically, replace the tuple value for
MessagingAttributes.messaging_consumer_group_name() in the event handler (both
where attributes are assembled in handle spans and the other attribute block)
and in the aggregate handler so they use Helpers.module_name(meta.application)
instead of meta.application; leave the corresponding
CommandedAttributes.commanded_application() usage unchanged.

---

Nitpick comments:
In `@test/opentelemetry/application_test.exs`:
- Line 101: Replace uses of inspect(meta.application) in the tests with a call
to the shared helper Helpers.module_name/1 so the expectation follows the real
implementation; locate the assertions that currently derive the application name
via inspect(meta.application) and change them to assert
Helpers.module_name(meta.application) (keeping the rest of the assertion text
intact) to avoid future divergence between inspect/1 and Helpers.module_name/1.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8e75c79e-0762-485b-956b-962d25ca2d83

📥 Commits

Reviewing files that changed from the base of the PR and between 0d0763a and 3650d28.

📒 Files selected for processing (12)
  • lib/commanded/opentelemetry/aggregate.ex
  • lib/commanded/opentelemetry/aggregate_populate.ex
  • lib/commanded/opentelemetry/aggregate_snapshot.ex
  • lib/commanded/opentelemetry/application.ex
  • lib/commanded/opentelemetry/event_handler.ex
  • lib/commanded/opentelemetry/event_store.ex
  • test/opentelemetry/aggregate_populate_test.exs
  • test/opentelemetry/aggregate_snapshot_test.exs
  • test/opentelemetry/aggregate_test.exs
  • test/opentelemetry/application_test.exs
  • test/opentelemetry/event_handler_test.exs
  • test/opentelemetry/event_store_test.exs

Comment thread test/opentelemetry/event_handler_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.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 3650d28. Configure here.

Comment thread lib/commanded/opentelemetry/aggregate.ex
…bute

- OTel convention requires module names without the BEAM-internal Elixir.
  prefix in attribute values

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
@yordis
yordis force-pushed the yordis/fix-otel-application-prefix branch from 3650d28 to d102a65 Compare April 21, 2026 03:12
@yordis
yordis merged commit 909c484 into main Apr 21, 2026
3 checks passed
@yordis
yordis deleted the yordis/fix-otel-application-prefix branch April 21, 2026 03:17
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