Skip to content

Commit 37b816f

Browse files
authored
Revise resource names: (#8)
* Revise resource names: - Add configuration directive `datadog_resource_name` for setting the resource name of the request span. - Add configuration directive `datadog_location_resource_name` for setting the resource name of the location span. - Change the default resource name to be `$request_method $uri` instead of `$request_method $datadog_location`.
1 parent a79ff08 commit 37b816f

22 files changed

+446
-42
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ default tracing behavior to nginx:
4141
- Create one span per request:
4242
- Service name is "nginx".
4343
- Operation name is "nginx.request".
44-
- Resource name is `"$request_method $datadog_location"`, e.g. "GET /api".
44+
- Resource name is `"$request_method $uri"`, e.g. "GET /api/book/0-345-24223-8/title".
4545
- Includes multiple `http.*` [tags][8].
4646

4747
Custom configuration can be specified via the [datadog](doc/API.md#datadog)

doc/API.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,33 @@ those provided by this module).
125125
The location span is a span created in addition to the request span. See
126126
`datadog_trace_locations`.
127127

128+
### `datadog_resource_name`
129+
130+
- **syntax** `datadog_resource_name <variable_pattern>`
131+
- **default**: `$request_method $uri`, e.g. "GET /api/book/0-345-24223-8/title"
132+
- **context**: `http`, `server`, `location`, `if`
133+
134+
Set the request span's "resource name" (sometimes called "endpoint") to the
135+
result of evaluating the specified `<variable_pattern>` in the context of the
136+
current request. `<variable_pattern>` is a string that may contain
137+
`$`-[variables][2] (including those provided by this module).
138+
139+
The request span is the span created while processing a request.
140+
141+
### `datadog_location_resource_name`
142+
143+
- **syntax** `datadog_location_resource_name <variable_pattern>`
144+
- **default**: `$request_method $uri`, e.g. "GET /api/book/0-345-24223-8/title"
145+
- **context**: `http`, `server`, `location`, `if`
146+
147+
Set the location span's "resource name" (sometimes called "endpoint") to the
148+
result of evaluating the specified `<variable_pattern>` in the context of the
149+
current request. `<variable_pattern>` is a string that may contain
150+
`$`-[variables][2] (including those provided by this module).
151+
152+
The location span is a span created in addition to the request span. See
153+
`datadog_trace_locations`.
154+
128155
### `datadog_trust_incoming_span`
129156

130157
- **syntax** `datadog_trust_incoming_span on|off`

example/services/nginx/nginx.conf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ http {
3232
datadog_trace_locations on;
3333
# This tag will be on the location-specific span.
3434
datadog_tag special.tag "The URI is $uri";
35+
# The resource name is customizable for both the request span and
36+
# the location span.
37+
datadog_resource_name "request URI $uri";
38+
datadog_location_resource_name "location URI $uri";
3539
proxy_pass http://http:8080;
3640
}
3741

src/datadog_conf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ struct datadog_loc_conf_t {
7878
ngx_flag_t enable_locations;
7979
NgxScript operation_name_script;
8080
NgxScript loc_operation_name_script;
81+
NgxScript resource_name_script;
82+
NgxScript loc_resource_name_script;
8183
ngx_flag_t trust_incoming_span;
8284
ngx_array_t *tags;
8385
// `response_info_script` is a script that can contain variables that refer

src/datadog_directive.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,17 @@ char *set_datadog_location_operation_name(ngx_conf_t *cf, ngx_command_t *command
487487
return set_script(cf, command, loc_conf->loc_operation_name_script);
488488
}
489489

490+
char *set_datadog_resource_name(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept {
491+
auto loc_conf = static_cast<datadog_loc_conf_t *>(conf);
492+
return set_script(cf, command, loc_conf->resource_name_script);
493+
}
494+
495+
char *set_datadog_location_resource_name(ngx_conf_t *cf, ngx_command_t *command,
496+
void *conf) noexcept {
497+
auto loc_conf = static_cast<datadog_loc_conf_t *>(conf);
498+
return set_script(cf, command, loc_conf->loc_resource_name_script);
499+
}
500+
490501
char *toggle_opentracing(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept {
491502
const auto loc_conf = static_cast<datadog_loc_conf_t *>(conf);
492503
const auto values = static_cast<const ngx_str_t *>(cf->args->elts);

src/datadog_directive.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ char *set_datadog_operation_name(ngx_conf_t *cf, ngx_command_t *command, void *c
3838
char *set_datadog_location_operation_name(ngx_conf_t *cf, ngx_command_t *command,
3939
void *conf) noexcept;
4040

41+
char *set_datadog_resource_name(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept;
42+
43+
char *set_datadog_location_resource_name(ngx_conf_t *cf, ngx_command_t *command,
44+
void *conf) noexcept;
45+
4146
char *toggle_opentracing(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept;
4247

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

src/ngx_http_datadog_module.cpp

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,20 @@ static ngx_command_t datadog_commands[] = {
176176
0,
177177
nullptr),
178178

179+
{ ngx_string("datadog_resource_name"),
180+
anywhere | NGX_CONF_TAKE1,
181+
set_datadog_resource_name,
182+
NGX_HTTP_LOC_CONF_OFFSET,
183+
0,
184+
nullptr},
185+
186+
{ ngx_string("datadog_location_resource_name"),
187+
anywhere | NGX_CONF_TAKE1,
188+
set_datadog_location_resource_name,
189+
NGX_HTTP_LOC_CONF_OFFSET,
190+
0,
191+
nullptr},
192+
179193
DEFINE_COMMAND_WITH_OLD_ALIAS(
180194
"datadog_trust_incoming_span",
181195
"opentracing_trust_incoming_span",
@@ -295,10 +309,13 @@ static ngx_int_t datadog_module_init(ngx_conf_t *cf) noexcept {
295309
if (tags.empty()) return NGX_OK;
296310
main_conf->tags = ngx_array_create(cf->pool, tags.size(), sizeof(datadog_tag_t));
297311
if (!main_conf->tags) return NGX_ERROR;
298-
for (const auto &tag : tags)
312+
for (const auto &tag : tags) {
299313
if (add_datadog_tag(cf, main_conf->tags, to_ngx_str(tag.first), to_ngx_str(tag.second)) !=
300-
NGX_CONF_OK)
314+
NGX_CONF_OK) {
301315
return NGX_ERROR;
316+
}
317+
}
318+
302319
return NGX_OK;
303320
}
304321

@@ -398,13 +415,13 @@ static void *create_datadog_loc_conf(ngx_conf_t *conf) noexcept {
398415

399416
namespace {
400417

401-
// Merge the specified `previous` operation name script into the specified
402-
// `current` operation name script in the context of the specified `conf`. If
403-
// `current` does not have a value and `previous` does, then `previous` will be
404-
// used. If neither has a value, then a hard-coded default will be used.
405-
// Return `NGX_CONF_OK` on success, or another value otherwise.
406-
char *merge_operation_name_script(ngx_conf_t *conf, NgxScript &previous, NgxScript &current,
407-
ot::string_view default_pattern) {
418+
// Merge the specified `previous` script into the specified `current` script in
419+
// the context of the specified `conf`. If `current` does not have a value and
420+
// `previous` does, then `previous` will be used. If neither has a value, then
421+
// the specified `default_pattern` will be used. Return `NGX_CONF_OK` on
422+
// success, or another value otherwise.
423+
char *merge_script(ngx_conf_t *conf, NgxScript &previous, NgxScript &current,
424+
ot::string_view default_pattern) {
408425
if (current.is_valid()) {
409426
return NGX_CONF_OK;
410427
}
@@ -420,28 +437,6 @@ char *merge_operation_name_script(ngx_conf_t *conf, NgxScript &previous, NgxScri
420437
return NGX_CONF_OK;
421438
}
422439

423-
char *merge_response_info_script(ngx_conf_t *conf, NgxScript &previous, NgxScript &current) {
424-
// The response info script is the same for each `datadog_loc_conf_t`. The only
425-
// reason it's a member of `datadog_loc_conf_t` is so that it is available at
426-
// the end of each request, when we might like to inspect e.g. response
427-
// headers.
428-
if (current.is_valid()) {
429-
return NGX_CONF_OK;
430-
}
431-
432-
if (!previous.is_valid()) {
433-
// Response header inspection is not currently used by this module, but I'm
434-
// leaving the boilerplate for future use.
435-
const ngx_int_t rc = previous.compile(conf, ngx_string(""));
436-
if (rc != NGX_OK) {
437-
return (char *)NGX_CONF_ERROR;
438-
}
439-
}
440-
441-
current = previous;
442-
return NGX_CONF_OK;
443-
}
444-
445440
} // namespace
446441

447442
//------------------------------------------------------------------------------
@@ -455,19 +450,26 @@ static char *merge_datadog_loc_conf(ngx_conf_t *cf, void *parent, void *child) n
455450
ngx_conf_merge_value(conf->enable_locations, prev->enable_locations,
456451
TracingLibrary::trace_locations_by_default());
457452

453+
if (const auto rc = merge_script(cf, prev->operation_name_script, conf->operation_name_script,
454+
TracingLibrary::default_request_operation_name_pattern())) {
455+
return rc;
456+
}
458457
if (const auto rc =
459-
merge_operation_name_script(cf, prev->operation_name_script, conf->operation_name_script,
460-
TracingLibrary::default_request_operation_name_pattern())) {
458+
merge_script(cf, prev->loc_operation_name_script, conf->loc_operation_name_script,
459+
TracingLibrary::default_location_operation_name_pattern())) {
461460
return rc;
462461
}
463-
if (const auto rc = merge_operation_name_script(
464-
cf, prev->loc_operation_name_script, conf->loc_operation_name_script,
465-
TracingLibrary::default_location_operation_name_pattern())) {
462+
if (const auto rc = merge_script(cf, prev->resource_name_script, conf->resource_name_script,
463+
TracingLibrary::default_resource_name_pattern())) {
464+
return rc;
465+
}
466+
if (const auto rc =
467+
merge_script(cf, prev->loc_resource_name_script, conf->loc_resource_name_script,
468+
TracingLibrary::default_resource_name_pattern())) {
466469
return rc;
467470
}
468-
469471
if (const auto rc =
470-
merge_response_info_script(cf, prev->response_info_script, conf->response_info_script)) {
472+
merge_script(cf, prev->response_info_script, conf->response_info_script, "")) {
471473
return rc;
472474
}
473475

@@ -510,8 +512,8 @@ static char *merge_datadog_loc_conf(ngx_conf_t *cf, void *parent, void *child) n
510512

511513
*tag = kv.second;
512514
} else {
513-
datadog_tag_t *tag = (datadog_tag_t *)conf->tags->elts;
514-
tag[index] = kv.second;
515+
datadog_tag_t *tags = (datadog_tag_t *)conf->tags->elts;
516+
tags[index] = kv.second;
515517
}
516518

517519
index++;

src/request_tracing.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,24 @@ static std::string get_request_operation_name(ngx_http_request_t *request,
3333
return to_string(core_loc_conf->name);
3434
}
3535

36+
static std::string get_loc_resource_name(ngx_http_request_t *request,
37+
const datadog_loc_conf_t *loc_conf) {
38+
if (loc_conf->loc_resource_name_script.is_valid()) {
39+
return to_string(loc_conf->loc_resource_name_script.run(request));
40+
} else {
41+
return "[invalid_resource_name_pattern]";
42+
}
43+
}
44+
45+
static std::string get_request_resource_name(ngx_http_request_t *request,
46+
const datadog_loc_conf_t *loc_conf) {
47+
if (loc_conf->resource_name_script.is_valid()) {
48+
return to_string(loc_conf->resource_name_script.run(request));
49+
} else {
50+
return "[invalid_resource_name_pattern]";
51+
}
52+
}
53+
3654
static void add_script_tags(ngx_array_t *tags, ngx_http_request_t *request, ot::Span &span) {
3755
if (!tags) return;
3856
auto add_tag = [&](const datadog_tag_t &tag) {
@@ -153,6 +171,7 @@ void RequestTracing::on_exit_block(std::chrono::steady_clock::time_point finish_
153171
//
154172
// See on_log_request below
155173
span_->SetOperationName(get_loc_operation_name(request_, core_loc_conf_, loc_conf_));
174+
span_->SetTag("resource.name", get_loc_resource_name(request_, loc_conf_));
156175

157176
span_->Finish({ot::FinishTimestamp{finish_timestamp}});
158177
} else {
@@ -178,6 +197,7 @@ void RequestTracing::on_log_request() {
178197
auto core_loc_conf = static_cast<ngx_http_core_loc_conf_t *>(
179198
ngx_http_get_module_loc_conf(request_, ngx_http_core_module));
180199
request_span_->SetOperationName(get_request_operation_name(request_, core_loc_conf, loc_conf_));
200+
request_span_->SetTag("resource.name", get_request_resource_name(request_, loc_conf_));
181201

182202
// Note: At this point, we could run an `NginxScript` to interrogate the
183203
// proxied server's response headers, e.g. to retrieve a deferred sampling

src/tracing_library.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,11 @@ std::unordered_map<string_view, string_view> TracingLibrary::default_tags() {
198198
// See
199199
// https://docs.datadoghq.com/logs/log_configuration/attributes_naming_convention/#common-attributes
200200
{"http.useragent", "$http_user_agent"},
201-
{"resource.name", "$request_method $datadog_location"},
202201
{"nginx.location", "$datadog_location"}};
203202
}
204203

204+
string_view TracingLibrary::default_resource_name_pattern() { return "$request_method $uri"; }
205+
205206
bool TracingLibrary::tracing_on_by_default() { return true; }
206207

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

src/tracing_library.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ struct TracingLibrary {
111111
// (realistically this means that it will refer to a string literal).
112112
static string_view default_location_operation_name_pattern();
113113

114+
// Return the pattern of an nginx variable script that will be used for the
115+
// resource name of spans that do not have a resource name configured in the
116+
// nginx configuration. Note that the storage to which the returned value
117+
// refers must outlive any usage of the return value (realistically this
118+
// means that it will refer to a string literal).
119+
static string_view default_resource_name_pattern();
120+
114121
// Return a mapping of tag name to nginx variable script pattern. These
115122
// tags will be defined automatically during configuration as if they
116123
// appeared in the nginx configuration file's http section, e.g.

0 commit comments

Comments
 (0)