Skip to content

feat(telemetry): add aggregate_module to load/populate/snapshot telemetry metadata - #69

Merged
yordis merged 1 commit into
mainfrom
feat/aggregate-module-telemetry-destination
Apr 5, 2026
Merged

yordis merged 1 commit into
mainfrom
feat/aggregate-module-telemetry-destination

Conversation

@yordis

@yordis yordis commented Apr 5, 2026

Copy link
Copy Markdown
Member
  • The aggregate_module field was already present in the %Aggregate{} struct but was omitted from the telemetry metadata emitted by AggregateStateBuilder and do_take_snapshot/1, leaving load, populate, and snapshot spans without a destination
  • With the module available, OTel span names now follow the {operation} {destination} convention (load MyApp.BankAccount, populate MyApp.BankAccount, snapshot MyApp.BankAccount) consistent with how execute, dispatch, and handle spans are already named
  • messaging.destination.name and code.namespace are now surfaced as span attributes for these three operations, matching the attribute coverage already present on execute spans

…etry metadata

Enables OTel span names to follow the {operation} {destination} convention
and surfaces messaging.destination.name + code.namespace attributes.

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

cursor Bot commented Apr 5, 2026 •

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes emitted telemetry metadata and OpenTelemetry span naming/attributes for aggregate load, populate, and snapshot, which may affect downstream dashboards/alerts relying on previous span names or missing attributes.

Overview
Adds aggregate_module to the telemetry metadata emitted during aggregate load, populate, and snapshot operations (including snapshot start/stop/exception).

Updates OpenTelemetry instrumentation for these operations to name spans as "{operation} {AggregateModule}" and to emit messaging.destination.name and code.namespace attributes derived from aggregate_module; tests and telemetry factories are updated accordingly.

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

@coderabbitai

coderabbitai Bot commented Apr 5, 2026 •

Copy link
Copy Markdown

Walkthrough

The PR extends telemetry metadata across aggregate lifecycle events to include aggregate_module, and updates OpenTelemetry span names and attributes to dynamically incorporate derived aggregate module names for improved observability context.

Changes

Cohort / File(s) Summary
Telemetry Metadata Specifications
lib/commanded/aggregates/aggregate.ex, lib/commanded/aggregates/aggregate_state_builder.ex
Added aggregate_module: module() field to telemetry event metadata specs for snapshot (start/stop/exception) and aggregate state builder (load/populate) events. Updated corresponding metadata extraction to include aggregate module from the Aggregate struct.
OpenTelemetry Instrumentation
lib/commanded/opentelemetry/aggregate_populate.ex, lib/commanded/opentelemetry/aggregate_snapshot.ex
Updated telemetry handlers to derive aggregate_module_name from metadata and inject it into span names (e.g., "load MockAggregate") and OpenTelemetry semantic attributes (messaging destination and code namespace).
Test Expectations
test/opentelemetry/aggregate_populate_test.exs, test/opentelemetry/aggregate_snapshot_test.exs, test/support/factory.ex
Updated span name assertions to include module name patterns. Extended attribute assertions to verify new messaging and code namespace fields. Updated test support metadata builders to include and provide defaults for :aggregate_module.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🐰 Hops with glee, the rabbit sees,
Telemetry flowing through the trees,
Module names now dancing bright,
In spans of gold and semantic light!
Observability hops on and on, 🌟

🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding aggregate_module to telemetry metadata for load/populate/snapshot operations, which is the central objective of this changeset.
Description check ✅ Passed The description clearly explains the motivation (aggregate_module field exists but was omitted), the change (adding it to telemetry metadata), and the benefits (consistent span naming and attribute coverage).

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/aggregate-module-telemetry-destination

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 (1)
lib/commanded/opentelemetry/aggregate_populate.ex (1)

33-33: Make aggregate module extraction resilient to missing metadata.

Direct meta.aggregate_module access can raise if metadata is ever partial/malformed. A guarded extraction with fallback avoids handler crashes and avoids blank/ambiguous span names.

♻️ Proposed hardening
-    aggregate_module_name = Helpers.module_name(meta.aggregate_module)
+    aggregate_module_name =
+      meta
+      |> Map.get(:aggregate_module)
+      |> Helpers.module_name()
+      |> Kernel.||("unknown.aggregate")
@@
-      "load #{aggregate_module_name}",
+      "load #{aggregate_module_name}",
@@
-    aggregate_module_name = Helpers.module_name(meta.aggregate_module)
+    aggregate_module_name =
+      meta
+      |> Map.get(:aggregate_module)
+      |> Helpers.module_name()
+      |> Kernel.||("unknown.aggregate")
@@
-      "populate #{aggregate_module_name}",
+      "populate #{aggregate_module_name}",

Also applies to: 49-50, 98-99, 117-118

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

In `@lib/commanded/opentelemetry/aggregate_populate.ex` at line 33, The code
directly accesses meta.aggregate_module which can crash if meta is nil/partial;
update all occurrences (e.g., the assignment creating aggregate_module_name and
the similar uses at the other noted spots) to safely fetch the field (use
Map.get(meta, :aggregate_module) or pattern-match meta to optional keys) and
provide a clear fallback value (e.g., a string like "unknown_aggregate" or
derive from another safe field) before passing into Helpers.module_name so span
names won’t be blank or raise when metadata is malformed; update every instance
referenced (the lines creating aggregate_module_name and the two other similar
blocks) to use the guarded fetch and fallback.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@lib/commanded/opentelemetry/aggregate_populate.ex`:
- Line 33: The code directly accesses meta.aggregate_module which can crash if
meta is nil/partial; update all occurrences (e.g., the assignment creating
aggregate_module_name and the similar uses at the other noted spots) to safely
fetch the field (use Map.get(meta, :aggregate_module) or pattern-match meta to
optional keys) and provide a clear fallback value (e.g., a string like
"unknown_aggregate" or derive from another safe field) before passing into
Helpers.module_name so span names won’t be blank or raise when metadata is
malformed; update every instance referenced (the lines creating
aggregate_module_name and the two other similar blocks) to use the guarded fetch
and fallback.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 78d08e69-d65a-45ad-a3f1-bd63187edd31

📥 Commits

Reviewing files that changed from the base of the PR and between ffaafcf and 295e911.

📒 Files selected for processing (7)
  • lib/commanded/aggregates/aggregate.ex
  • lib/commanded/aggregates/aggregate_state_builder.ex
  • lib/commanded/opentelemetry/aggregate_populate.ex
  • lib/commanded/opentelemetry/aggregate_snapshot.ex
  • test/opentelemetry/aggregate_populate_test.exs
  • test/opentelemetry/aggregate_snapshot_test.exs
  • test/support/factory.ex

@yordis
yordis merged commit 78bcfe7 into main Apr 5, 2026
5 checks passed
@yordis
yordis deleted the feat/aggregate-module-telemetry-destination branch April 5, 2026 18:16
@sht-bot sht-bot mentioned this pull request Apr 5, 2026
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