Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
de30bb6
TODO: Change the configuration from individual entries to one csv for…
zacharycmontoya Aug 30, 2025
084e7f4
Two changes in one:
zacharycmontoya Aug 31, 2025
9c358a5
Convert the combined `datadog_baggage_span_tags` directive to individ…
zacharycmontoya Aug 31, 2025
3482602
Refactor and format test_baggage_span_tags.py. Also had a general dis…
zacharycmontoya Aug 31, 2025
290cf4a
Small update to example conf
zacharycmontoya Aug 31, 2025
4936a7e
Small code comment update
zacharycmontoya Aug 31, 2025
e07bfa5
Update baggage_span_tags field from an unordered_set to a vector
zacharycmontoya Sep 3, 2025
577d0c3
Fix bug so that specifying one span tag with the wildcard key "*" obt…
zacharycmontoya Sep 3, 2025
82e66e8
Move calculation of baggage span tags to configuration-time so that w…
zacharycmontoya Sep 3, 2025
202fa63
Change the directive again: The user must set the 'datadog_baggage_sp…
zacharycmontoya Sep 3, 2025
50de5ec
Update the API docs with a more complete description of the two direc…
zacharycmontoya Sep 3, 2025
ae00942
Satisfy linter
zacharycmontoya Sep 3, 2025
d02fdaa
Satisfy clang-format-14 formatting
zacharycmontoya Sep 3, 2025
172732c
PR Feedback: Update tests to use tuples instead of lists
zacharycmontoya Sep 10, 2025
7bec512
PR Feedback: Implement changes except for directive name, directive d…
zacharycmontoya Sep 10, 2025
01316b0
PR Feedback: Update the baggage_span_tags field to have the type 'std…
zacharycmontoya Sep 10, 2025
341fdb7
Update docs for the baggage span_tags feature
zacharycmontoya Sep 26, 2025
b9eee16
Update test cases to ensure that if both "datadog_baggage_span_tags …
zacharycmontoya Sep 26, 2025
6a589e6
refactor: Large rename of "datadog_baggage_span_tags" to "datadog_bag…
zacharycmontoya Oct 3, 2025
4ae1f47
refactor: Rename the "datadog_baggage_tags" directive to "datadog_bag…
zacharycmontoya Oct 3, 2025
2672a55
Update the 'datadog_baggage_tags_keys' directive so it's first argume…
zacharycmontoya Oct 3, 2025
c72e391
Run formatter
zacharycmontoya Oct 3, 2025
c0b8928
Address an edge case: Throw a configuration error, when in the same c…
zacharycmontoya Oct 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions doc/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,31 @@ whose value is the result of evaluating the specified `<value>` in the context
of the current request. `<value>` is a string that may contain
`$`-[variables][2] (including those provided by this module).

### `datadog_baggage_span_tags`
- **syntax** `datadog_baggage_span_tags <key> [<key> ...]`
- **default** `user.id account.id session.id`
- **context**: `http`, `server`, `location`

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.

As a convenience, you can capture all baggage items as span tags by setting the directive
`datadog_baggage_span_tags *` rather than specifying each baggage item key.

### `baggage_span_tags_enabled`
- **syntax** `baggage_span_tags_enabled on|off`
- **context**: `http`, `server`, `location`

If `on`, enable the `datadog_baggage_span_tags` feature in the current configuration context.
If `off`, disables the `datadog_baggage_span_tags` feature in the current configuration context.

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

### `datadog_tracing`
- **syntax** `datadog_tracing on|off`
- **default** `on`
Expand Down
9 changes: 9 additions & 0 deletions example/tracing/services/nginx/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ http {
location /http {
# Add a custom tag. Tag values can contain nginx variables.
datadog_tag special.tag "The URI is $uri";
# Add baggage span tags. If a baggage item has a matching key, the key-value is set a span tag.
datadog_baggage_span_tag user.id

proxy_pass http://http:8080;
}

Expand All @@ -33,6 +36,12 @@ http {
datadog_trace_locations on;
# This tag will be on the location-specific span.
datadog_tag special.tag "The URI is $uri";
# Do not configure additional baggage span tags. When unspecified, this is the same as specifiying the following:
# datadog_baggage_span_tag user.id
# datadog_baggage_span_tag session.id
# datadog_baggage_span_tag account.id
# To disable baggage span tags on this location, set 'datadog_baggage_span_tags_enabled off'

# The resource name is customizable for both the request span and
# the location span.
datadog_resource_name "request URI $uri";
Expand Down
2 changes: 2 additions & 0 deletions src/datadog_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,8 @@ struct datadog_loc_conf_t {
// `service_version` is set by the `datadog_version` directive.
ngx_http_complex_value_t *service_version = DD_NGX_CONF_COMPLEX_UNSET;
std::unordered_map<std::string, ngx_http_complex_value_t *> tags;
ngx_flag_t baggage_span_tags_enabled = NGX_CONF_UNSET;
std::vector<std::string> baggage_span_tags;
// `parent` is the parent context (e.g. the `server` to this `location`), or
// `nullptr` if this context has no parent.
datadog_loc_conf_t *parent;
Expand Down
14 changes: 14 additions & 0 deletions src/ngx_http_datadog_module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,9 @@ static char *merge_datadog_loc_conf(ngx_conf_t *cf, void *parent,
TracingLibrary::tracing_on_by_default());
ngx_conf_merge_value(conf->enable_locations, prev->enable_locations,
TracingLibrary::trace_locations_by_default());
ngx_conf_merge_value(conf->baggage_span_tags_enabled,
prev->baggage_span_tags_enabled,
TracingLibrary::bagage_span_tags_by_default());
ngx_conf_merge_ptr_value(conf->service_name, prev->service_name, nullptr);
ngx_conf_merge_ptr_value(conf->service_env, prev->service_env, nullptr);
ngx_conf_merge_ptr_value(conf->service_version, prev->service_version,
Expand Down Expand Up @@ -497,6 +500,17 @@ static char *merge_datadog_loc_conf(ngx_conf_t *cf, void *parent,
conf->tags.merge(parent_tags);
}

// Merge baggage span tags, but only if this conf has no specified baggage
// span tags.
if (!prev->baggage_span_tags.empty() && conf->baggage_span_tags.empty()) {
conf->baggage_span_tags = prev->baggage_span_tags;
} else if (conf->baggage_span_tags.empty()) {
const auto baggage_span_tags = TracingLibrary::default_baggage_span_tags();
for (const auto &tag_name : baggage_span_tags) {
conf->baggage_span_tags.emplace_back(std::string(tag_name));
}
}

#ifdef WITH_WAF
if (conf->waf_pool == nullptr) {
conf->waf_pool = prev->waf_pool;
Expand Down
37 changes: 37 additions & 0 deletions src/request_tracing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <sstream>
#include <stdexcept>
#include <string>
#include <unordered_set>
#include <utility>

#include "array_util.h"
Expand Down Expand Up @@ -74,6 +75,35 @@ static void add_status_tags(const ngx_http_request_t *request, dd::Span &span) {
}
}

// Iterate through the configured baggage_span_tags and create span tags for the
// configured baggage keys. The one special case is if baggage_span_tags=["*"].
// In this case, create a corresponding span tag for all baggage items.
//
// Precondition: The local conf has the directive
// `datadog_baggage_span_tags_enabled` set.
void add_baggage_span_tags(datadog_loc_conf_t *conf, tracing::Baggage &baggage,
dd::Span &span) {
if (baggage.empty()) return;

static const std::string baggage_prefix = "baggage.";

if (!conf->baggage_span_tags.empty()) {
if (conf->baggage_span_tags.size() == 1 &&
conf->baggage_span_tags.front() == "*") {
baggage.visit([&span](std::string_view key, std::string_view value) {
span.set_tag(baggage_prefix + std::string(key), value);
});
} else {
for (const auto &tag_name : conf->baggage_span_tags) {
if (baggage.contains(tag_name)) {
span.set_tag(baggage_prefix + tag_name,
baggage.get(tag_name).value());
}
}
}
}
}

static void add_upstream_name(const ngx_http_request_t *request,
dd::Span &span) {
if (!request->upstream || !request->upstream->upstream ||
Expand Down Expand Up @@ -212,6 +242,13 @@ RequestTracing::RequestTracing(ngx_http_request_t *request,
} else {
request_span_.emplace(std::move(*maybe_span));
}

if (loc_conf_->baggage_span_tags_enabled) {
auto maybe_baggage = tracer->extract_baggage(reader);
if (maybe_baggage && request_span_) {
add_baggage_span_tags(loc_conf, *maybe_baggage, *request_span_);
}
}
}

if (!request_span_) {
Expand Down
25 changes: 25 additions & 0 deletions src/tracing/directives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,31 @@ char *set_datadog_tag(ngx_conf_t *cf, ngx_command_t *command,
return NGX_CONF_OK;
}

char *set_datadog_baggage_span_tags(ngx_conf_t *cf, ngx_command_t *command,
void *conf) noexcept {
auto loc_conf = static_cast<datadog_loc_conf_t *>(conf);
const auto values = static_cast<ngx_str_t *>(cf->args->elts);
assert(cf->args->nelts >= 1);

const auto args = values + 1;
const auto nargs = cf->args->nelts - 1;

for (const ngx_str_t *arg = args; arg != args + nargs; ++arg) {
const auto baggage_key = to_string_view(*arg);
if (baggage_key.empty()) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
"Invalid argument \"%V\" to %V directive. Expected a "
"non-empty string.",
arg, &command->name);
return static_cast<char *>(NGX_CONF_ERROR);
}

loc_conf->baggage_span_tags.emplace_back(std::string(baggage_key));
}

return NGX_CONF_OK;
}

char *set_datadog_sample_rate(ngx_conf_t *cf, ngx_command_t *command,
void *conf) noexcept {
const auto loc_conf = static_cast<datadog_loc_conf_t *>(conf);
Expand Down
21 changes: 21 additions & 0 deletions src/tracing/directives.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ constexpr ngx_uint_t anywhere =
char *set_datadog_tag(ngx_conf_t *cf, ngx_command_t *command,
void *conf) noexcept;

char *set_datadog_baggage_span_tags(ngx_conf_t *cf, ngx_command_t *command,
void *conf) noexcept;

char *set_datadog_sample_rate(ngx_conf_t *cf, ngx_command_t *command,
void *conf) noexcept;

Expand Down Expand Up @@ -124,6 +127,15 @@ constexpr datadog::nginx::directive tracing_directives[] = {
nullptr,
},

{
"datadog_baggage_span_tags",
anywhere | NGX_CONF_1MORE,
set_datadog_baggage_span_tags,
NGX_HTTP_LOC_CONF_OFFSET,
0,
nullptr,
},

{
"datadog_sample_rate",
// NGX_CONF_TAKE12 means "take 1 or 2 args," not "take 12 args."
Expand All @@ -144,6 +156,15 @@ constexpr datadog::nginx::directive tracing_directives[] = {
nullptr,
},

{
"datadog_baggage_span_tags_enabled",
anywhere | NGX_CONF_TAKE1,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(datadog_loc_conf_t, baggage_span_tags_enabled),
nullptr,
},

// aliases opentracing (legacy)
ALIAS_COMMAND("datadog_tracing", "opentracing", anywhere | NGX_CONF_TAKE1),
ALIAS_COMMAND("datadog_operation_name", "opentracing_operation_name",
Expand Down
8 changes: 8 additions & 0 deletions src/tracing_library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,12 @@ TracingLibrary::default_tags() {
return tags;
}

std::vector<std::string_view> TracingLibrary::default_baggage_span_tags() {
static const std::vector<std::string_view> baggage_span_tags{
"user.id", "session.id", "account.id"};
return baggage_span_tags;
}

std::string_view TracingLibrary::default_resource_name_pattern() {
return "$request_method $uri";
}
Expand All @@ -240,5 +246,7 @@ bool TracingLibrary::tracing_on_by_default() { return true; }

bool TracingLibrary::trace_locations_by_default() { return false; }

bool TracingLibrary::bagage_span_tags_by_default() { return true; }

} // namespace nginx
} // namespace datadog
18 changes: 18 additions & 0 deletions src/tracing_library.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,31 @@ struct TracingLibrary {
// that they will refer to string literals).
static std::unordered_map<std::string_view, std::string_view> default_tags();

// Return the default baggage span tags. These tags will be defined
// automatically during configuration as if they appeared in the nginx
// configuration file's http section, e.g.
//
// http {
// datadog_baggage_span_tags user.id session.id account.id;
// ...
// }
//
// Note that the storage to which each returned `std::string_view` refers
// must outlive any usage of the return value (realistically this means
// that they will refer to string literals).
static std::vector<std::string_view> default_baggage_span_tags();

// Return the default setting for whether tracing is enabled in nginx.
static bool tracing_on_by_default();

// Return the default setting for whether HTTP locations generate a trace.
// An HTTP location is an endpoint as configured using a "location" block
// in the nginx configuration.
static bool trace_locations_by_default();

// Return the default setting for whether baggage span tags will be added
// to the current span.
static bool bagage_span_tags_by_default();
};

} // namespace nginx
Expand Down
6 changes: 6 additions & 0 deletions test/cases/baggage_span_tags/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
This test verifies that the expected baggage span tags are added to spans produced by
the nginx module.

Some tags are defined by default (see `TracingLibrary::default_baggage_span_tags` in the
module source), while others can be defined by the user via the `datadog_baggage_span_tag`
configuration directive.
Empty file.
21 changes: 21 additions & 0 deletions test/cases/baggage_span_tags/conf/builtins.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# "/datadog-tests" is a directory created by the docker build
# of the nginx test image. It contains the module, the
# nginx config, and "index.html".
load_module /datadog-tests/ngx_http_datadog_module.so;

events {
worker_connections 1024;
}

http {
datadog_agent_url http://agent:8126;

server {
listen 80;
server_name localhost;

location /http {
proxy_pass http://http:8080;
}
}
}
22 changes: 22 additions & 0 deletions test/cases/baggage_span_tags/conf/custom_in_http.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# "/datadog-tests" is a directory created by the docker build
# of the nginx test image. It contains the module, the
# nginx config, and "index.html".
load_module /datadog-tests/ngx_http_datadog_module.so;

events {
worker_connections 1024;
}

http {
datadog_agent_url http://agent:8126;
datadog_baggage_span_tags snazzy.tag fancy.tag;

server {
listen 80;
server_name localhost;

location /http {
proxy_pass http://http:8080;
}
}
}
22 changes: 22 additions & 0 deletions test/cases/baggage_span_tags/conf/custom_in_location.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# "/datadog-tests" is a directory created by the docker build
# of the nginx test image. It contains the module, the
# nginx config, and "index.html".
load_module /datadog-tests/ngx_http_datadog_module.so;

events {
worker_connections 1024;
}

http {
datadog_agent_url http://agent:8126;

server {
listen 80;
server_name localhost;

location /http {
datadog_baggage_span_tags snazzy.tag fancy.tag;
proxy_pass http://http:8080;
}
}
}
23 changes: 23 additions & 0 deletions test/cases/baggage_span_tags/conf/custom_in_server.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# "/datadog-tests" is a directory created by the docker build
# of the nginx test image. It contains the module, the
# nginx config, and "index.html".
load_module /datadog-tests/ngx_http_datadog_module.so;

events {
worker_connections 1024;
}

http {
datadog_agent_url http://agent:8126;

server {
listen 80;
server_name localhost;

datadog_baggage_span_tags snazzy.tag fancy.tag;

location /http {
proxy_pass http://http:8080;
}
}
}
22 changes: 22 additions & 0 deletions test/cases/baggage_span_tags/conf/disabled.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# "/datadog-tests" is a directory created by the docker build
# of the nginx test image. It contains the module, the
# nginx config, and "index.html".
load_module /datadog-tests/ngx_http_datadog_module.so;

events {
worker_connections 1024;
}

http {
datadog_agent_url http://agent:8126;
datadog_baggage_span_tags_enabled off;

server {
listen 80;
server_name localhost;

location /http {
proxy_pass http://http:8080;
}
}
}
Loading