Skip to content

Conversation

zacharycmontoya
Copy link
Contributor

@zacharycmontoya zacharycmontoya commented Sep 1, 2025

Motivation

There are a set of W3C baggage items that the Datadog APM product, RUM product, etc. use to provide a comprehensive observability experience, which includes user.id, account.id, and session.id. To deliver on the APM experience, we must make sure that the values are copied over to our web server spans as span tags.

We also want to provide users the ability to customize this feature or disable if desired.

Changes

Adds new functionality to the Datadog NGINX module to automatically copy W3C baggage items as span tags to the nginx spans, following this RFC.

This is implemented using two new NGINX directives, copied directly from the doc/API.md markdown file since the reference documentation should stand on its own:


datadog_baggage_tags_enabled

  • syntax datadog_baggage_tags_enabled on|off
  • context: http, server, location

If on, enable the datadog_baggage_tags_keys feature in the current configuration context.
If off, disable the datadog_baggage_tags_keys feature in the current configuration context.

datadog_baggage_tags_keys

  • syntax datadog_baggage_tags_keys all | select <key> [<key> ...]
  • default select user.id account.id session.id
  • context: http, server, location

Set span tags for items in the current W3C Baggage header.

To set span tags for baggage items with a matching <key>, use datadog_baggage_tags_keys select <key> [<key> ...].

To set span tags for all baggage items, use datadog_baggage_tags_keys all.

… the entire value. This tells us if the configuration is UNSET (so we apply default values) or if the configuration is disabled with an empty string value
- Change the individual baggage span tags into a list (I think I want to change it back)
- Correctly add a default value at the main conf level
…ual `datadog_baggage_span_tag` directives, which feels more NGINX-y
doc/API.md Outdated
of the current request. `<value>` is a string that may contain
`$`-[variables][2] (including those provided by this module).

### `datadog_baggage_span_tag`
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Offline feedback: See if there is another name we can use for this directive that is more intuitive for users

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I updated doc/API.md with better documentation in 50de5ec. If that looks ok, then I think we should keep the existing directive name so it's similar to other Datadog tracing libraries. WDYT @dmehala ?

…ains all baggage items from the header and creates a corresponding span tag for each.
…e do not need to do a recursive lookup while handling each request.
…an_tags' directive which accepts one or more tags for the list of configured baggage keys to add as span tags, as opposed to multiple 'datadog_baggage_span_tag' directives that each add one baggage key to the list.

The motivation for this approach is that it aligns with the DD_TRACE_BAGGAGE_TAG_KEYS environment variable adopted in other Datadog tracers that accepts one string of comma-separated keys (e.g. 'DD_TRACE_BAGGAGE_TAG_KEYS=user.id,account.id,session.id')
…tives:

- 'datadog_baggage_span_tags'
- 'baggage_span_tags_enabled'
@zacharycmontoya zacharycmontoya marked this pull request as ready for review September 3, 2025 23:04
@zacharycmontoya zacharycmontoya requested a review from a team as a code owner September 3, 2025 23:04
@zacharycmontoya zacharycmontoya requested review from Anilm3 and removed request for a team September 3, 2025 23:04
@codecov-commenter
Copy link

codecov-commenter commented Sep 3, 2025

Codecov Report

❌ Patch coverage is 76.81159% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.69%. Comparing base (6b51d05) to head (b9eee16).
⚠️ Report is 9 commits behind head on master.

Files with missing lines Patch % Lines
src/tracing/directives.cpp 62.96% 8 Missing and 2 partials ⚠️
src/request_tracing.cpp 79.16% 0 Missing and 5 partials ⚠️
src/ngx_http_datadog_module.cpp 92.85% 0 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #246      +/-   ##
==========================================
+ Coverage   68.61%   68.69%   +0.07%     
==========================================
  Files          57       57              
  Lines        7322     7391      +69     
  Branches     1035     1051      +16     
==========================================
+ Hits         5024     5077      +53     
- Misses       1796     1804       +8     
- Partials      502      510       +8     
Files with missing lines Coverage Δ
src/tracing_library.cpp 81.20% <100.00%> (+0.51%) ⬆️
src/ngx_http_datadog_module.cpp 66.06% <92.85%> (+1.42%) ⬆️
src/request_tracing.cpp 76.92% <79.16%> (+0.27%) ⬆️
src/tracing/directives.cpp 57.75% <62.96%> (+0.87%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@dmehala dmehala left a comment

Choose a reason for hiding this comment

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

I’ve added a few comments, in particular, I believe the wildcard case needs some rework. Additionally, I noticed a couple of scenarios that are not yet covered by tests:

  • datadog_baggage_span_tags user.id; and datadog_baggage_span off; should not set span tags.
  • datadog_baggage_span_tags user.id * fancy.tag;, ensure that in this case all baggage is captured.

doc/API.md Outdated
Comment on lines 187 to 192
On the currently active span, if the current W3C baggage header has a baggage item
whose key matches the specified `<key>`, automatically set a tag whose name is
`baggage.<key>` and whose value is the value of the key-value pair.

This overrides any `baggage_span_tags_enabled` directives at higher levels,
and may be overriden by `baggage_span_tags_enabled` directives at lower levels.
Copy link
Contributor

Choose a reason for hiding this comment

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

The current wording makes the directive harder to understand. I recommend simplifying it to convey the purpose as clearly and directly as possible.

Suggested change
On the currently active span, if the current W3C baggage header has a baggage item
whose key matches the specified `<key>`, automatically set a tag whose name is
`baggage.<key>` and whose value is the value of the key-value pair.
This overrides any `baggage_span_tags_enabled` directives at higher levels,
and may be overriden by `baggage_span_tags_enabled` directives at lower levels.
Set span tags for all baggage items matching `<key>` from the current W3C Baggage header.

I also believe baggage_span_tags_enabled should always take precedence over this directive. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes if the configuration is baggage_span_tags_enabled off that should disable this. I believe I had a copy/paste issue here, sorry about that!

In commit 341fdb7 I've reworded this highlighted portion to say the following, which is essentially what you suggested. WDYT?

Set span tags for all items from the current W3C Baggage header with a matching `<key>`.

…::variant<std::vector<std::string>, bool>'. This distinguishes between the first type containing baggage keys to set vs the second type indicating that the wildcard key '*' was specified so all baggage keys should be set.
…key>" and "datadog_baggage_span_tags_enabled off" are set, then no baggage span tags are set
@zacharycmontoya
Copy link
Contributor Author

I’ve added a few comments, in particular, I believe the wildcard case needs some rework. Additionally, I noticed a couple of scenarios that are not yet covered by tests:

  • datadog_baggage_span_tags user.id; and datadog_baggage_span off; should not set span tags.

In b9eee16 I've added a test case to cover this scenario.

  • datadog_baggage_span_tags user.id * fancy.tag;, ensure that in this case all baggage is captured.

For this scenario, I'm getting clarification in the RFC but my reading is that this does not invoke the wildcard behavior. This appears to only be activated when the configuration is exactly datadog_baggage_span_tags *; (only one item with the value "*")

@zacharycmontoya
Copy link
Contributor Author

zacharycmontoya commented Sep 29, 2025

  • datadog_baggage_span_tags user.id * fancy.tag;, ensure that in this case all baggage is captured.

For this scenario, I'm getting clarification in the RFC but my reading is that this does not invoke the wildcard behavior. This appears to only be activated when the configuration is exactly datadog_baggage_span_tags *; (only one item with the value "*")

I confirmed with the RFC author that only the configuration datadog_baggage_span_tags *; should be a wildcard. If there are multiple items such as datadog_baggage_span_tags tag1 tag2 *; then there's no wildcard behavior and the * is treated as a named header, since that character is allowed in HTTP headers. So my current implementation is up-to-date with that specification

@dmehala
Copy link
Contributor

dmehala commented Oct 1, 2025

then there's no wildcard behavior and the * is treated as a named header, since that character is allowed in HTTP headers

That means, for the same directive,* has two meanings:

  • everything when its by itself.
  • the * character when there's multiple items.

That's error-prone, WDYT?

@zacharycmontoya
Copy link
Contributor Author

then there's no wildcard behavior and the * is treated as a named header, since that character is allowed in HTTP headers

That means, for the same directive,* has two meanings:

  • everything when its by itself.
  • the * character when there's multiple items.

That's error-prone, WDYT?

As discussed offline, to eliminate the * character having two meanings, the keys directive must now be specified as datadog_baggage_tags_keys all to invoke the wildcard behavior or datadog_baggage_tags_keys select <key> [<key> ...] to select keys. So now * no longer has any special meanings.

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.

3 participants