Skip to content

Conversation

@philprime
Copy link
Member

@philprime philprime commented Feb 11, 2026

Description

Add documentation comments to TelemetryScopeApplier clarifying how trace_id and span_id are set for logs (and other telemetry items), with links to the official SDK telemetry docs. No behavior change; this PR is for discussion and to capture what we discovered while investigating #7415

This PR serves as common grounds as we need to discuss if either our develop docs are wrong.

Motivation and Context

Closes #7415

The issue asks to ensure span_id is only set when there is an active span, and that a propagated span_id is not considered an active span.

We cross-checked the implementation against develop.sentry.dev and the codebase and concluded the following.

Docs (develop.sentry.dev):

The trace id should be grabbed from the current propagation context in the SDK.

  • span_id: "The span id of the span that was active when the log was collected."

The span id should be grabbed from the current active span in the SDK.

If a log is recorded during an active span, the SDK should set the span_id property of the log to the span id of the span that was active when the log was collected.

A non-existing spanId will be propagated along with the trace" and that propagated span_id must not be used for logs.

Current implementation (TelemetryScopeApplier.swift):

  • trace_id: item.traceId = span?.traceId ?? propagationContextTraceId. When a span is active we use its traceId; otherwise propagation context. When span is active, scope has been set with that span so the two sources match.
  • span_id: Only set inside addDefaultAttributes when self.span is non-nil: if let span = self.span { attributes["span_id"] = .string(span.spanId.sentrySpanIdString) }. So span_id is only set when scope.span exists.

Why no code change is required:

  • scope.span in Sentry Cocoa is only set when a transaction/tracer is started (SentryHub.m setSpan when starting a tracer). It is never set from propagation context. So scope.span always represents an active span we created.
  • TelemetryScopeApplier only receives propagationContextTraceId from the scope, not the propagation context's span_id. So we never have access to a "propagated span_id" in this path and cannot accidentally use it. The only span we see is scope.span, which is the active span.
  • Therefore we already only set span_id when an active span exists. The comments we added document this and link to the docs so future readers and other SDKs can align.

Possible follow-ups (not in this PR):

  • The docs describe span_id as a top-level field in the log envelope payload. We currently put span_id in the attributes dict. Moving it to a top-level field on the log payload might require SentryLog/encoding changes and could be a separate change.

How did you test it?

No behavior change. make build-macos and make test-ios ONLY_TESTING=TelemetryScopeApplierTests were run; existing tests pass.

Checklist

  • I added tests to verify the changes. (N/A: documentation only; tests could be added in follow-up)
  • No new PII added or SDK only sends newly added PII if sendDefaultPii is enabled.
  • I updated the docs if needed. (Only inline comments with doc links.)
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

#skip-changelog

Add comments with links to develop.sentry.dev telemetry logs docs.
span_id is only set for active span; trace_id from propagation context.
No behavior change. For discussion (COCOA-1263 / #7415).
@github-actions
Copy link
Contributor

github-actions bot commented Feb 11, 2026

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


This PR will not appear in the changelog.


🤖 This preview updates automatically when you update the PR.

@philprime philprime self-assigned this Feb 11, 2026
@philprime philprime marked this pull request as ready for review February 11, 2026 15:38
@codecov
Copy link

codecov bot commented Feb 11, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.041%. Comparing base (70fb69e) to head (1e5cc87).
⚠️ Report is 6 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files

Impacted file tree graph

@@              Coverage Diff              @@
##              main     #7439       +/-   ##
=============================================
- Coverage   85.318%   85.041%   -0.278%     
=============================================
  Files          480       480               
  Lines        28622     28625        +3     
  Branches     12384     12370       -14     
=============================================
- Hits         24420     24343       -77     
- Misses        4155      4232       +77     
- Partials        47        50        +3     
Files with missing lines Coverage Δ
.../TelemetryScopeApplier/TelemetryScopeApplier.swift 100.000% <100.000%> (ø)

... and 13 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 70fb69e...1e5cc87. Read the comment docs.

Copy link
Contributor

@itaybre itaybre left a comment

Choose a reason for hiding this comment

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

LGTM

@philprime philprime marked this pull request as draft February 12, 2026 14:32
@philprime
Copy link
Member Author

Update: span_id moved from attributes to top-level field

We identified that the SDK was incorrectly placing span_id inside the log item's attributes dictionary, but according to the develop docs and the Python SDK reference implementation, span_id should be a top-level field on the log item payload (alongside trace_id, timestamp, level, body, etc.).

Changes made in this branch:

  • TelemetryItem protocol: Added var spanId: SpanId? { get set } as a top-level property
  • SentryLog: Added spanId as a top-level property with Encodable support ("span_id" key)
  • SentryMetric: Added spanId stub for TelemetryItem conformance (metrics don't use span_id)
  • TelemetryScopeApplier: Sets item.spanId = span?.spanId directly instead of adding "span_id" to attributesDict
  • Tests: Updated all assertions to check item.spanId instead of item.attributesDict["span_id"]

Still investigating: logs not appearing in trace explorer

Logs are being sent successfully (HTTP 200) and contain the correct trace_id, but they are not showing up in the Sentry trace explorer. For example: https://sentry-sdks.sentry.io/explore/traces/trace/b295c61cc5e74068b5d7e6aedce2e816

We also confirmed that the transaction was being dropped due to sample_rate (visible in the client_report in the envelope), which has been fixed by setting tracesSampleRate = 1 in the sample app. However, even with logs sent and associated with a valid trace_id, they don't appear in the trace view. This may be a project configuration issue (e.g., the ourlogs feature flag) or a Relay/ingestion issue on the sentry-sdks org.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Revisit TelemetryScopeApplier span_id assignment for logs

2 participants