Skip to content

Fix #2374: Make getResourceName() consistent with hasResourceName()#3244

Closed
mariusc83 wants to merge 3 commits into
developfrom
mconstantin/2374/span-resource-name-tag-not-used
Closed

Fix #2374: Make getResourceName() consistent with hasResourceName()#3244
mariusc83 wants to merge 3 commits into
developfrom
mconstantin/2374/span-resource-name-tag-not-used

Conversation

@mariusc83

@mariusc83 mariusc83 commented Mar 9, 2026

Copy link
Copy Markdown
Member

Issue

Fixes #2374: Span resource name set with tag is not used

GitHub Issue: #2374

Root Cause Analysis

DDSpanContext.getResourceName() only checked the internal resourceName field, falling back to operationName. Unlike hasResourceName(), it did not check the resource.name tag in unsafeTags. This caused an inconsistency where hasResourceName() returned true but getResourceName() returned the operation name instead of the tag-set resource name — specifically when the resource.name tag was stored directly in the tags map (e.g., when the RESOURCE_NAME rule flag in TagInterceptor is disabled).

A TODO comment at the method explicitly flagged this inconsistency.

Changes

Make getResourceName() check getTag(DDTags.RESOURCE_NAME) as a fallback before returning operationName, matching the logic in hasResourceName(). Remove the TODO comment.

Files Changed

File Change
DDSpanContext.java Fix getResourceName() to check tag fallback
DDSpanContextTest.kt Add 5 tests (2 unit, 2 integration, 1 sampling rule)

Impact Analysis

An architectural impact analysis was performed after the initial fix to evaluate the blast radius:

Caller Map

Caller Module Usage Risk
SamplingRule.TraceSamplingRule.matches() trace-internal Pattern matching for sampling decisions Covered by new test
CoreTracerSpanToSpanEventMapper trace Serializes to SpanEvent.resource Covered by integration test
TraceStructureWriter.Node trace-internal Debug output Low risk
DatadogSpanAdapter trace Public API property Low risk — delegates to DDSpan

All production callers (network instrumentation, OkHttp interceptor) explicitly write to .resourceName before reading, so the fallback path is only hit when no explicit resource name is set.

Thread Safety

The fix adds a getTag() call (which takes synchronized(unsafeTags)) in the fallback path. The old code was lock-free. Risk is low because:

  • getResourceName() is called once per span at serialization time, not in loops
  • Span lifecycle is typically single-threaded
  • The fallback path is only hit when resourceName field is not set

Consistency Scan

Found a latent similar pattern in getServiceName() (only checks internal field, same RuleFlags conditional processing). Not a bug today since no hasServiceName() method exists, but noted for future awareness.

Test Coverage

  • Unit tests: 2 (tag fallback behavior, field-over-tag priority)
  • Integration tests: 2 (builder withTag flow, setTag after start)
  • Impact-driven test: 1 (sampling rule matches resource name from tag fallback)
  • Module test suite: PASS (trace-internal, trace, trace-otel all green)
  • TDD iterations: 1/5

Root cause: DDSpanContext.getResourceName() only checked the internal
resourceName field, falling back to operationName. Unlike hasResourceName(),
it did not check the resource.name tag in unsafeTags.

Changes:
- Make getResourceName() check getTag(DDTags.RESOURCE_NAME) as fallback
- Remove TODO comment that flagged this inconsistency
- Add tests for tag-based resource name resolution

Tests: 2 unit
Performance: SUCCESS
@mariusc83
mariusc83 requested review from a team as code owners March 9, 2026 09:01
Add two integration tests that exercise the full tracer chain
(builder → TagInterceptor → DDSpanContext → getResourceName) to
catch regressions in resource.name tag handling.

Tests:
- Resource name set via builder withTag before start()
- Resource name set via setTag after start()
@mariusc83 mariusc83 self-assigned this Mar 9, 2026
@codecov-commenter

codecov-commenter commented Mar 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 75.00000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.49%. Comparing base (f793454) to head (b9c908b).
⚠️ Report is 90 commits behind head on develop.

Files with missing lines Patch % Lines
...ain/java/com/datadog/trace/core/DDSpanContext.java 75.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #3244      +/-   ##
===========================================
+ Coverage    71.40%   71.49%   +0.09%     
===========================================
  Files          938      938              
  Lines        34667    34674       +7     
  Branches      5874     5877       +3     
===========================================
+ Hits         24752    24788      +36     
+ Misses        8265     8233      -32     
- Partials      1650     1653       +3     
Files with missing lines Coverage Δ
...ain/java/com/datadog/trace/core/DDSpanContext.java 61.23% <75.00%> (+0.27%) ⬆️

... and 36 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@datadog-official

This comment has been minimized.

Impact analysis identified that SamplingRule.TraceSamplingRule.matches()
uses getResourceName() for pattern matching. Without this test, a
regression in the tag fallback could silently change sampling decisions.

The test verifies that a sampling rule targeting a specific resource name
correctly matches when the name comes from the resource.name tag
fallback path (not the internal resourceName field).
@hamorillo

Copy link
Copy Markdown
Contributor

@codex review

// TODO this logic is inconsistent with hasResourceName
public CharSequence getResourceName() {
return isResourceNameSet() ? resourceName : operationName;
if (isResourceNameSet()) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Changing the behavior of existing method can skew existing dashboards/monitors. I'm not sure we should do this for the minor release.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Totally agree and that was my worry too. Actually Claude picked this up also during the fixing session and mentioned it. That's a decision on your end. Choose to keep it as it is or take the risk and merge it. This is a hard one as there's definitely a problem there of inconsistency which can have repercussions later. Either you take the bullet now and fix it or you postpone it and face it later.

@satween satween Mar 11, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Are you sure this change ever needed? According to TagInterceptor logic it would call setResource in case if customer tries to set DDTags.RESOURCE_NAME. So Basically seems like the opposite logic might make more sense - removing hasTag(DDTags.RESOURCE_NAME) from the hasResourceName method. WDYT?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think you have more context than me on this one but from what I see it makes sense what you are saying. But not matter what we decide is going to change the API functionality so it will be some sort of regression. In the same time if we decide to keep it as it is, it means that we acknowledge that there's an issue and we accept it. I let you guys decide and I will apply the changes if needed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

My opinion - is to add TODO comment, with RUM-13454 and link to this PR and close for now. With the next major release - we gonna fix this

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done — I've opened a separate PR (#3252) that updates the TODO comment with RUM-13454 and a link to this PR, deferring the fix to the next major release as suggested. Will close this PR.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@0xnm 0xnm closed this Mar 16, 2026
@0xnm
0xnm deleted the mconstantin/2374/span-resource-name-tag-not-used branch April 2, 2026 10:15
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.

Span resource name set with tag is not used

5 participants