From 6504e058358d60a7079eda8d685060f0eaacaf2d Mon Sep 17 00:00:00 2001 From: Damien Mehala Date: Wed, 24 Jan 2024 15:25:28 +0100 Subject: [PATCH 1/7] chore: enforce codestyle --- .circleci/config.yml | 14 ++ Makefile | 7 +- bin/format.sh | 7 + bin/lint.sh | 8 + src/datadog_conf.cpp | 3 +- src/datadog_conf.h | 3 +- src/datadog_conf_handler.cpp | 28 ++- src/datadog_context.cpp | 44 ++-- src/datadog_context.h | 16 +- src/datadog_directive.cpp | 357 ++++++++++++++++++----------- src/datadog_directive.h | 79 ++++--- src/datadog_handler.cpp | 9 +- src/datadog_variable.cpp | 81 ++++--- src/defer.h | 3 +- src/log_conf.cpp | 6 +- src/ngx_event_scheduler.cpp | 9 +- src/ngx_event_scheduler.h | 3 +- src/ngx_header_reader.h | 18 +- src/ngx_http_datadog_module.cpp | 94 +++++--- src/ngx_logger.cpp | 4 +- src/ngx_script.cpp | 15 +- src/propagation_header_querier.cpp | 40 ++-- src/propagation_header_querier.h | 3 +- src/request_tracing.cpp | 105 +++++---- src/request_tracing.h | 6 +- src/string_util.h | 21 +- src/tracing_library.cpp | 44 ++-- test/bin/format | 4 - 28 files changed, 655 insertions(+), 376 deletions(-) create mode 100755 bin/format.sh create mode 100755 bin/lint.sh delete mode 100755 test/bin/format diff --git a/.circleci/config.yml b/.circleci/config.yml index a417ba55..83567ae0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -117,6 +117,19 @@ jobs: path: test/logs/test.log destination: test.log + format: + docker: + - image: "datadog/docker-library:dd-trace-cpp-ci" + resource_class: small + steps: + - checkout + - run: git submodule update --init --recursive + - run: + name: Lint + command: | + cp dd-trace-cpp/.clang-format .clang-format + bin/lint.sh + shellcheck: docker: - image: koalaman/shellcheck-alpine:stable @@ -128,6 +141,7 @@ jobs: workflows: build-and-test: jobs: + - format - shellcheck: name: "run shellcheck on shell scripts" filters: diff --git a/Makefile b/Makefile index 1d6b1502..065e1df6 100644 --- a/Makefile +++ b/Makefile @@ -48,9 +48,10 @@ dd-trace-cpp/.clang-format: dd-trace-cpp/.git .PHONY: format format: .clang-format - find src/ -type f \( -name '*.h' -o -name '*.cpp' \) -print0 | xargs -0 clang-format-14 -i --style=file - find bin/ -type f -name '*.py' -print0 | xargs -0 yapf3 -i - test/bin/format + ./bin/format.sh + +lint: .clang-format + ./bin/lint.sh .PHONY: clean clean: diff --git a/bin/format.sh b/bin/format.sh new file mode 100755 index 00000000..9fa87b1e --- /dev/null +++ b/bin/format.sh @@ -0,0 +1,7 @@ +#!/bin/sh +# Format the codebase to follow our codestyle + +find src/ -type f \( -name '*.h' -o -name '*.cpp' \) -print0 | xargs -0 clang-format-14 -i --style=file +find bin/ -type f -name '*.py' -print0 | xargs -0 yapf3 -i + +yapf3 --recursive --in-place "$@" "test/" diff --git a/bin/lint.sh b/bin/lint.sh new file mode 100755 index 00000000..8767ab04 --- /dev/null +++ b/bin/lint.sh @@ -0,0 +1,8 @@ +#!/bin/sh +# Lint the codebase and returns all encountered discrepencies +# with our codestyle + +find src/ -type f \( -name '*.h' -o -name '*.cpp' \) -print0 | xargs -0 clang-format-14 --Werror --dry-run --style=file +find bin/ -type f -name '*.py' -print0 | xargs -0 yapf3 --diff + +yapf3 --recursive --diff "$@" "test/" diff --git a/src/datadog_conf.cpp b/src/datadog_conf.cpp index 00ad3356..96c0605e 100644 --- a/src/datadog_conf.cpp +++ b/src/datadog_conf.cpp @@ -7,7 +7,8 @@ namespace nginx { bool operator==(const conf_directive_source_location_t& left, const conf_directive_source_location_t& right) { - return str(left.file_name) == str(right.file_name) && left.line == right.line && + return str(left.file_name) == str(right.file_name) && + left.line == right.line && str(left.directive_name) == str(right.directive_name); } diff --git a/src/datadog_conf.h b/src/datadog_conf.h index 059ce044..cb68cee0 100644 --- a/src/datadog_conf.h +++ b/src/datadog_conf.h @@ -213,7 +213,8 @@ struct datadog_loc_conf_t { // `allow_sampling_delegation_in_subrequests_directive` is the source location // of the `datadog_allow_sampling_delegation_in_subrequests` directive that // applies this location, if any. - conf_directive_source_location_t allow_sampling_delegation_in_subrequests_directive; + conf_directive_source_location_t + allow_sampling_delegation_in_subrequests_directive; }; } // namespace nginx diff --git a/src/datadog_conf_handler.cpp b/src/datadog_conf_handler.cpp index c732ffd5..0ed30558 100644 --- a/src/datadog_conf_handler.cpp +++ b/src/datadog_conf_handler.cpp @@ -5,9 +5,9 @@ namespace datadog { namespace nginx { /* The eight fixed arguments */ -static ngx_uint_t argument_number[] = {NGX_CONF_NOARGS, NGX_CONF_TAKE1, NGX_CONF_TAKE2, - NGX_CONF_TAKE3, NGX_CONF_TAKE4, NGX_CONF_TAKE5, - NGX_CONF_TAKE6, NGX_CONF_TAKE7}; +static ngx_uint_t argument_number[] = { + NGX_CONF_NOARGS, NGX_CONF_TAKE1, NGX_CONF_TAKE2, NGX_CONF_TAKE3, + NGX_CONF_TAKE4, NGX_CONF_TAKE5, NGX_CONF_TAKE6, NGX_CONF_TAKE7}; ngx_int_t datadog_conf_handler(const DatadogConfHandlerConfig &args) noexcept { ngx_conf_t *const cf = args.conf; @@ -30,7 +30,8 @@ ngx_int_t datadog_conf_handler(const DatadogConfHandlerConfig &args) noexcept { continue; } - if (args.skip_this_module && cf->cycle->modules[i] == &ngx_http_datadog_module) { + if (args.skip_this_module && + cf->cycle->modules[i] == &ngx_http_datadog_module) { continue; } @@ -57,14 +58,15 @@ ngx_int_t datadog_conf_handler(const DatadogConfHandlerConfig &args) noexcept { } if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "directive \"%s\" is not terminated by \";\"", + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "directive \"%s\" is not terminated by \";\"", name->data); return NGX_ERROR; } if ((cmd->type & NGX_CONF_BLOCK) && last != NGX_CONF_BLOCK_START) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "directive \"%s\" has no opening \"{\"", - name->data); + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "directive \"%s\" has no opening \"{\"", name->data); return NGX_ERROR; } @@ -122,25 +124,29 @@ ngx_int_t datadog_conf_handler(const DatadogConfHandlerConfig &args) noexcept { return NGX_ERROR; } - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"%s\" directive %s", name->data, rv); + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"%s\" directive %s", + name->data, rv); return NGX_ERROR; } } if (found) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"%s\" directive is not allowed here", name->data); + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"%s\" directive is not allowed here", name->data); return NGX_ERROR; } - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unknown directive \"%s\"", name->data); + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unknown directive \"%s\"", + name->data); return NGX_ERROR; invalid: - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid number of arguments in \"%s\" directive", + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid number of arguments in \"%s\" directive", name->data); return NGX_ERROR; diff --git a/src/datadog_context.cpp b/src/datadog_context.cpp index 5fd4eceb..16c15544 100644 --- a/src/datadog_context.cpp +++ b/src/datadog_context.cpp @@ -28,19 +28,21 @@ void DatadogContext::on_change_block(ngx_http_request_t *request, // This is a new subrequest, so add a RequestTracing for it. // TODO: Should `active_span` be `request_span` instead? - traces_.emplace_back(request, core_loc_conf, loc_conf, &traces_[0].active_span()); + traces_.emplace_back(request, core_loc_conf, loc_conf, + &traces_[0].active_span()); } void DatadogContext::on_log_request(ngx_http_request_t *request) { auto trace = find_trace(request); if (trace == nullptr) { - throw std::runtime_error{"on_log_request failed: could not find request trace"}; + throw std::runtime_error{ + "on_log_request failed: could not find request trace"}; } trace->on_log_request(); } -ngx_str_t DatadogContext::lookup_propagation_header_variable_value(ngx_http_request_t *request, - std::string_view key) { +ngx_str_t DatadogContext::lookup_propagation_header_variable_value( + ngx_http_request_t *request, std::string_view key) { auto trace = find_trace(request); if (trace == nullptr) { throw std::runtime_error{ @@ -50,11 +52,12 @@ ngx_str_t DatadogContext::lookup_propagation_header_variable_value(ngx_http_requ return trace->lookup_propagation_header_variable_value(key); } -ngx_str_t DatadogContext::lookup_span_variable_value(ngx_http_request_t *request, - std::string_view key) { +ngx_str_t DatadogContext::lookup_span_variable_value( + ngx_http_request_t *request, std::string_view key) { auto trace = find_trace(request); if (trace == nullptr) { - throw std::runtime_error{"lookup_span_variable_value failed: could not find request trace"}; + throw std::runtime_error{ + "lookup_span_variable_value failed: could not find request trace"}; } return trace->lookup_span_variable_value(key); } @@ -64,21 +67,24 @@ ngx_str_t DatadogContext::lookup_sampling_delegation_response_variable_value( auto trace = find_trace(request); if (trace == nullptr) { throw std::runtime_error{ - "lookup_sampling_delegation_response_variable_value failed: could not find request trace"}; + "lookup_sampling_delegation_response_variable_value failed: could not " + "find request trace"}; } return trace->lookup_sampling_delegation_response_variable_value(); } RequestTracing *DatadogContext::find_trace(ngx_http_request_t *request) { - const auto found = std::find_if(traces_.begin(), traces_.end(), - [=](const auto &trace) { return trace.request() == request; }); + const auto found = std::find_if( + traces_.begin(), traces_.end(), + [=](const auto &trace) { return trace.request() == request; }); if (found != traces_.end()) { return &*found; } return nullptr; } -const RequestTracing *DatadogContext::find_trace(ngx_http_request_t *request) const { +const RequestTracing *DatadogContext::find_trace( + ngx_http_request_t *request) const { return const_cast(this)->find_trace(request); } @@ -87,7 +93,8 @@ static void cleanup_datadog_context(void *data) noexcept { } static ngx_pool_cleanup_t *find_datadog_cleanup(ngx_http_request_t *request) { - for (auto cleanup = request->pool->cleanup; cleanup; cleanup = cleanup->next) { + for (auto cleanup = request->pool->cleanup; cleanup; + cleanup = cleanup->next) { if (cleanup->handler == cleanup_datadog_context) { return cleanup; } @@ -96,8 +103,8 @@ static ngx_pool_cleanup_t *find_datadog_cleanup(ngx_http_request_t *request) { } DatadogContext *get_datadog_context(ngx_http_request_t *request) noexcept { - auto context = - static_cast(ngx_http_get_module_ctx(request, ngx_http_datadog_module)); + auto context = static_cast( + ngx_http_get_module_ctx(request, ngx_http_datadog_module)); if (context != nullptr || !request->internal) { return context; } @@ -114,7 +121,8 @@ DatadogContext *get_datadog_context(ngx_http_request_t *request) noexcept { // If we found a context, attach with ngx_http_set_ctx so that we don't have // to loop through the cleanup handlers again. if (context != nullptr) { - ngx_http_set_ctx(request, static_cast(context), ngx_http_datadog_module); + ngx_http_set_ctx(request, static_cast(context), + ngx_http_datadog_module); } return context; @@ -138,7 +146,8 @@ void set_datadog_context(ngx_http_request_t *request, DatadogContext *context) { } cleanup->data = static_cast(context); cleanup->handler = cleanup_datadog_context; - ngx_http_set_ctx(request, static_cast(context), ngx_http_datadog_module); + ngx_http_set_ctx(request, static_cast(context), + ngx_http_datadog_module); } // Supports early destruction of the DatadogContext (in case of an @@ -147,7 +156,8 @@ void destroy_datadog_context(ngx_http_request_t *request) noexcept { auto cleanup = find_datadog_cleanup(request); if (cleanup == nullptr) { ngx_log_error(NGX_LOG_ERR, request->connection->log, 0, - "Unable to find Datadog cleanup handler for request %p", request); + "Unable to find Datadog cleanup handler for request %p", + request); return; } delete static_cast(cleanup->data); diff --git a/src/datadog_context.h b/src/datadog_context.h index ab6a1fd8..648ac1bd 100644 --- a/src/datadog_context.h +++ b/src/datadog_context.h @@ -21,20 +21,24 @@ namespace nginx { class DatadogContext { public: - DatadogContext(ngx_http_request_t* request, ngx_http_core_loc_conf_t* core_loc_conf, + DatadogContext(ngx_http_request_t* request, + ngx_http_core_loc_conf_t* core_loc_conf, datadog_loc_conf_t* loc_conf); - void on_change_block(ngx_http_request_t* request, ngx_http_core_loc_conf_t* core_loc_conf, + void on_change_block(ngx_http_request_t* request, + ngx_http_core_loc_conf_t* core_loc_conf, datadog_loc_conf_t* loc_conf); void on_log_request(ngx_http_request_t* request); - ngx_str_t lookup_propagation_header_variable_value(ngx_http_request_t* request, - std::string_view key); + ngx_str_t lookup_propagation_header_variable_value( + ngx_http_request_t* request, std::string_view key); - ngx_str_t lookup_span_variable_value(ngx_http_request_t* request, std::string_view key); + ngx_str_t lookup_span_variable_value(ngx_http_request_t* request, + std::string_view key); - ngx_str_t lookup_sampling_delegation_response_variable_value(ngx_http_request_t* request); + ngx_str_t lookup_sampling_delegation_response_variable_value( + ngx_http_request_t* request); private: std::vector traces_; diff --git a/src/datadog_directive.cpp b/src/datadog_directive.cpp index 300ba7ed..95da5ccc 100644 --- a/src/datadog_directive.cpp +++ b/src/datadog_directive.cpp @@ -24,10 +24,12 @@ namespace datadog { namespace nginx { namespace { -auto command_source_location(const ngx_command_t *command, const ngx_conf_t *conf) { - return conf_directive_source_location_t{.file_name = conf->conf_file->file.name, - .line = conf->conf_file->line, - .directive_name = command->name}; +auto command_source_location(const ngx_command_t *command, + const ngx_conf_t *conf) { + return conf_directive_source_location_t{ + .file_name = conf->conf_file->file.name, + .line = conf->conf_file->line, + .directive_name = command->name}; } // Dispatch to the "real" handler for the specified `command`, and then invoke @@ -37,12 +39,14 @@ auto command_source_location(const ngx_command_t *command, const ngx_conf_t *con // `proxy_set_header` directives into the current configuration context. // Return the value returned by `inject_propagation_commands`, or return // `NGX_CONF_ERROR` if an error occurs. -char *hijack_pass_directive(char *(*inject_propagation_commands)(ngx_conf_t *cf, - ngx_command_t *cmd, void *conf), - ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept try { +char *hijack_pass_directive(char *(*inject_propagation_commands)( + ngx_conf_t *cf, ngx_command_t *cmd, void *conf), + ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept try { // First, call the handler of the actual command that we're hijacking, e.g. // "proxy_pass". Be sure to skip this module, so we don't call ourself. - const ngx_int_t rcode = datadog_conf_handler({.conf = cf, .skip_this_module = true}); + const ngx_int_t rcode = + datadog_conf_handler({.conf = cf, .skip_this_module = true}); if (rcode != NGX_OK) { return static_cast(NGX_CONF_ERROR); } @@ -57,7 +61,8 @@ char *hijack_pass_directive(char *(*inject_propagation_commands)(ngx_conf_t *cf, // propagation, e.g. `propagate_datadog_context`. return inject_propagation_commands(cf, command, conf); } catch (const std::exception &e) { - ngx_log_error(NGX_LOG_ERR, cf->log, 0, "Datadog-wrapped configuration directive %V failed: %s", + ngx_log_error(NGX_LOG_ERR, cf->log, 0, + "Datadog-wrapped configuration directive %V failed: %s", command->name, e.what()); return static_cast(NGX_CONF_ERROR); } @@ -87,13 +92,14 @@ char *lock_propagation_styles(const ngx_command_t *command, ngx_conf_t *conf) { // We need the propagation HTTP header names, below. But then they cannot be // changed by a subsequent `datadog_propagation_styles` directive. main_conf->are_propagation_styles_locked = true; - main_conf->propagation_styles_source_location = command_source_location(command, conf); + main_conf->propagation_styles_source_location = + command_source_location(command, conf); // In order for span context propagation to work, the names of the HTTP // headers added to requests need to be known ahead of time. NgxLogger logger; - auto maybe_headers = - TracingLibrary::propagation_header_names(main_conf->propagation_styles, logger); + auto maybe_headers = TracingLibrary::propagation_header_names( + main_conf->propagation_styles, logger); if (auto *error = maybe_headers.if_error()) { logger.log_error(*error); return static_cast(NGX_CONF_ERROR); @@ -105,18 +111,21 @@ char *lock_propagation_styles(const ngx_command_t *command, ngx_conf_t *conf) { } // namespace -static char *set_script(ngx_conf_t *cf, ngx_command_t *command, NgxScript &script) noexcept { +static char *set_script(ngx_conf_t *cf, ngx_command_t *command, + NgxScript &script) noexcept { if (script.is_valid()) return const_cast("is duplicate"); auto value = static_cast(cf->args->elts); auto pattern = &value[1]; - if (script.compile(cf, *pattern) != NGX_OK) return static_cast(NGX_CONF_ERROR); + if (script.compile(cf, *pattern) != NGX_OK) + return static_cast(NGX_CONF_ERROR); return static_cast(NGX_CONF_OK); } -static ngx_str_t make_propagation_header_variable(ngx_pool_t *pool, std::string_view key) { +static ngx_str_t make_propagation_header_variable(ngx_pool_t *pool, + std::string_view key) { auto prefix = TracingLibrary::propagation_header_variable_name_prefix(); // result = "$" + prefix + key auto size = 1 + prefix.size() + key.size(); @@ -133,7 +142,8 @@ static ngx_str_t make_propagation_header_variable(ngx_pool_t *pool, std::string_ } // Converts keys to match the naming convention used by CGI parameters. -static ngx_str_t make_fastcgi_span_context_key(ngx_pool_t *pool, std::string_view key) { +static ngx_str_t make_fastcgi_span_context_key(ngx_pool_t *pool, + std::string_view key) { static const std::string_view http_prefix = "HTTP_"; auto size = http_prefix.size() + key.size(); auto data = static_cast(ngx_palloc(pool, size)); @@ -141,23 +151,27 @@ static ngx_str_t make_fastcgi_span_context_key(ngx_pool_t *pool, std::string_vie std::copy_n(http_prefix.data(), http_prefix.size(), data); - std::transform(key.data(), key.data() + key.size(), data + http_prefix.size(), [](char c) { - if (c == '-') return '_'; - return static_cast(std::toupper(c)); - }); + std::transform(key.data(), key.data() + key.size(), data + http_prefix.size(), + [](char c) { + if (c == '-') return '_'; + return static_cast(std::toupper(c)); + }); return {size, reinterpret_cast(data)}; } -char *add_datadog_tag(ngx_conf_t *cf, ngx_array_t *tags, ngx_str_t key, ngx_str_t value) noexcept { +char *add_datadog_tag(ngx_conf_t *cf, ngx_array_t *tags, ngx_str_t key, + ngx_str_t value) noexcept { if (!tags) return static_cast(NGX_CONF_ERROR); auto tag = static_cast(ngx_array_push(tags)); if (!tag) return static_cast(NGX_CONF_ERROR); ngx_memzero(tag, sizeof(datadog_tag_t)); - if (tag->key_script.compile(cf, key) != NGX_OK) return static_cast(NGX_CONF_ERROR); - if (tag->value_script.compile(cf, value) != NGX_OK) return static_cast(NGX_CONF_ERROR); + if (tag->key_script.compile(cf, key) != NGX_OK) + return static_cast(NGX_CONF_ERROR); + if (tag->value_script.compile(cf, value) != NGX_OK) + return static_cast(NGX_CONF_ERROR); return static_cast(NGX_CONF_OK); } @@ -181,7 +195,8 @@ char *add_datadog_tag(ngx_conf_t *cf, ngx_array_t *tags, ngx_str_t key, ngx_str_ // // This approach was discussed here // http://mailman.nginx.org/pipermail/nginx-devel/2018-March/011008.html -char *propagate_datadog_context(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept try { +char *propagate_datadog_context(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept try { auto main_conf = static_cast( ngx_http_conf_get_module_main_conf(cf, ngx_http_datadog_module)); @@ -212,8 +227,8 @@ char *propagate_datadog_context(ngx_conf_t *cf, ngx_command_t *command, void *co const auto guard = defer([&]() { cf->args = old_args; }); for (const std::string_view key : keys) { - args[1] = - ngx_str_t{key.size(), reinterpret_cast(const_cast(key.data()))}; + args[1] = ngx_str_t{key.size(), reinterpret_cast( + const_cast(key.data()))}; args[2] = make_propagation_header_variable(cf->pool, key); auto rcode = datadog_conf_handler({.conf = cf, .skip_this_module = true}); if (rcode != NGX_OK) { @@ -222,15 +237,18 @@ char *propagate_datadog_context(ngx_conf_t *cf, ngx_command_t *command, void *co } return static_cast(NGX_CONF_OK); } catch (const std::exception &e) { - ngx_log_error(NGX_LOG_ERR, cf->log, 0, "datadog_propagate_context failed: %s", e.what()); + ngx_log_error(NGX_LOG_ERR, cf->log, 0, "datadog_propagate_context failed: %s", + e.what()); return static_cast(NGX_CONF_ERROR); } -char *hijack_proxy_pass(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept { +char *hijack_proxy_pass(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept { return hijack_pass_directive(&propagate_datadog_context, cf, command, conf); } -char *delegate_to_datadog_directive_with_warning(ngx_conf_t *cf, ngx_command_t *command, +char *delegate_to_datadog_directive_with_warning(ngx_conf_t *cf, + ngx_command_t *command, void *conf) noexcept { const auto elements = static_cast(cf->args->elts); assert(cf->args->nelts >= 1); @@ -242,7 +260,8 @@ char *delegate_to_datadog_directive_with_warning(ngx_conf_t *cf, ngx_command_t * // valid if we are certain that copies of / references to the `ngx_str_t` will // not outlive this `std::string` (they won't). std::string new_name{"datadog_"}; - const std::string_view suffix = slice(str(elements[0]), deprecated_prefix.size()); + const std::string_view suffix = + slice(str(elements[0]), deprecated_prefix.size()); new_name.append(suffix.data(), suffix.size()); const ngx_str_t new_name_ngx = to_ngx_str(new_name); @@ -250,7 +269,8 @@ char *delegate_to_datadog_directive_with_warning(ngx_conf_t *cf, ngx_command_t * "Backward compatibility with the \"%V\" configuration " "directive is deprecated. " "Please use \"%V\" instead. Occurred at %V:%d", - &elements[0], &new_name_ngx, &cf->conf_file->file.name, cf->conf_file->line); + &elements[0], &new_name_ngx, &cf->conf_file->file.name, + cf->conf_file->line); // Rename the command (opentracing_* → datadog_*) and let // `datadog_conf_handler` dispatch to the appropriate handler. @@ -305,16 +325,19 @@ char *propagate_fastcgi_datadog_context(ngx_conf_t *cf, ngx_command_t *command, } return static_cast(NGX_CONF_OK); } catch (const std::exception &e) { - ngx_log_error(NGX_LOG_ERR, cf->log, 0, "datadog_fastcgi_propagate_context failed: %s", e.what()); + ngx_log_error(NGX_LOG_ERR, cf->log, 0, + "datadog_fastcgi_propagate_context failed: %s", e.what()); return static_cast(NGX_CONF_ERROR); } -char *hijack_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept { - return hijack_pass_directive(&propagate_fastcgi_datadog_context, cf, command, conf); +char *hijack_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept { + return hijack_pass_directive(&propagate_fastcgi_datadog_context, cf, command, + conf); } -char *propagate_grpc_datadog_context(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept - try { +char *propagate_grpc_datadog_context(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept try { auto main_conf = static_cast( ngx_http_conf_get_module_main_conf(cf, ngx_http_datadog_module)); @@ -345,8 +368,8 @@ char *propagate_grpc_datadog_context(ngx_conf_t *cf, ngx_command_t *command, voi const auto guard = defer([&]() { cf->args = old_args; }); for (const std::string_view key : keys) { - args[1] = - ngx_str_t{key.size(), reinterpret_cast(const_cast(key.data()))}; + args[1] = ngx_str_t{key.size(), reinterpret_cast( + const_cast(key.data()))}; args[2] = make_propagation_header_variable(cf->pool, key); auto rcode = datadog_conf_handler({.conf = cf, .skip_this_module = true}); if (rcode != NGX_OK) { @@ -355,12 +378,15 @@ char *propagate_grpc_datadog_context(ngx_conf_t *cf, ngx_command_t *command, voi } return static_cast(NGX_CONF_OK); } catch (const std::exception &e) { - ngx_log_error(NGX_LOG_ERR, cf->log, 0, "datadog_grpc_propagate_context failed: %s", e.what()); + ngx_log_error(NGX_LOG_ERR, cf->log, 0, + "datadog_grpc_propagate_context failed: %s", e.what()); return static_cast(NGX_CONF_ERROR); } -char *hijack_grpc_pass(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept { - return hijack_pass_directive(&propagate_grpc_datadog_context, cf, command, conf); +char *hijack_grpc_pass(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept { + return hijack_pass_directive(&propagate_grpc_datadog_context, cf, command, + conf); } char *propagate_uwsgi_datadog_context(ngx_conf_t *cf, ngx_command_t *command, @@ -407,15 +433,19 @@ char *propagate_uwsgi_datadog_context(ngx_conf_t *cf, ngx_command_t *command, return static_cast(NGX_CONF_OK); } catch (const std::exception &e) { - ngx_log_error(NGX_LOG_ERR, cf->log, 0, "propagate_uwsgi_datadog_context failed: %s", e.what()); + ngx_log_error(NGX_LOG_ERR, cf->log, 0, + "propagate_uwsgi_datadog_context failed: %s", e.what()); return static_cast(NGX_CONF_ERROR); } -char *hijack_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept { - return hijack_pass_directive(&propagate_uwsgi_datadog_context, cf, command, conf); +char *hijack_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept { + return hijack_pass_directive(&propagate_uwsgi_datadog_context, cf, command, + conf); } -char *hijack_access_log(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept try { +char *hijack_access_log(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept try { // In case we need to change the `access_log` command's format to a // Datadog-specific default, first make sure that those formats are defined. ngx_int_t rcode = inject_datadog_log_formats(cf); @@ -469,41 +499,48 @@ char *hijack_access_log(ngx_conf_t *cf, ngx_command_t *command, void *conf) noex } return static_cast(NGX_CONF_OK); } catch (const std::exception &e) { - ngx_log_error(NGX_LOG_ERR, cf->log, 0, "Datadog-wrapped configuration directive %V failed: %s", + ngx_log_error(NGX_LOG_ERR, cf->log, 0, + "Datadog-wrapped configuration directive %V failed: %s", command->name, e.what()); return static_cast(NGX_CONF_ERROR); } -char *set_datadog_tag(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept { +char *set_datadog_tag(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept { auto loc_conf = static_cast(conf); - if (!loc_conf->tags) loc_conf->tags = ngx_array_create(cf->pool, 1, sizeof(datadog_tag_t)); + if (!loc_conf->tags) + loc_conf->tags = ngx_array_create(cf->pool, 1, sizeof(datadog_tag_t)); auto values = static_cast(cf->args->elts); return add_datadog_tag(cf, loc_conf->tags, values[1], values[2]); } -char *json_config_deprecated(ngx_conf_t *cf, ngx_command_t *command, void * /*conf*/) noexcept { +char *json_config_deprecated(ngx_conf_t *cf, ngx_command_t *command, + void * /*conf*/) noexcept { const auto location = command_source_location(command, cf); - ngx_log_error( - NGX_LOG_ERR, cf->log, 0, - "The datadog { ... } block directive is no longer supported. Use the specific datadog_* " - "directives instead, or use DD_TRACE_* environment variables. " - "Error occurred at \"%V\" in %V:%d", - &location.directive_name, &location.file_name, location.line); + ngx_log_error(NGX_LOG_ERR, cf->log, 0, + "The datadog { ... } block directive is no longer supported. " + "Use the specific datadog_* " + "directives instead, or use DD_TRACE_* environment variables. " + "Error occurred at \"%V\" in %V:%d", + &location.directive_name, &location.file_name, location.line); return static_cast(NGX_CONF_ERROR); } -char *set_datadog_operation_name(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept { +char *set_datadog_operation_name(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept { auto loc_conf = static_cast(conf); return set_script(cf, command, loc_conf->operation_name_script); } -char *set_datadog_location_operation_name(ngx_conf_t *cf, ngx_command_t *command, +char *set_datadog_location_operation_name(ngx_conf_t *cf, + ngx_command_t *command, void *conf) noexcept { auto loc_conf = static_cast(conf); return set_script(cf, command, loc_conf->loc_operation_name_script); } -char *set_datadog_resource_name(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept { +char *set_datadog_resource_name(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept { auto loc_conf = static_cast(conf); return set_script(cf, command, loc_conf->resource_name_script); } @@ -514,7 +551,8 @@ char *set_datadog_location_resource_name(ngx_conf_t *cf, ngx_command_t *command, return set_script(cf, command, loc_conf->loc_resource_name_script); } -char *toggle_opentracing(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept { +char *toggle_opentracing(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept { const auto loc_conf = static_cast(conf); const auto values = static_cast(cf->args->elts); assert(cf->args->nelts == 2); @@ -527,47 +565,55 @@ char *toggle_opentracing(ngx_conf_t *cf, ngx_command_t *command, void *conf) noe loc_conf->enable = false; preferred = "datadog_disable"; } else { - ngx_log_error(NGX_LOG_ERR, cf->log, 0, - "Invalid argument \"%V\" to %V directive. Use \"on\" or \"off\". ", &values[1], - &command->name); + ngx_log_error( + NGX_LOG_ERR, cf->log, 0, + "Invalid argument \"%V\" to %V directive. Use \"on\" or \"off\". ", + &values[1], &command->name); return static_cast(NGX_CONF_ERROR); } // Warn the user to prefer the corresponding "datadog_{enable,disable}" // directive. const ngx_str_t preferred_str = to_ngx_str(preferred); - ngx_log_error(NGX_LOG_WARN, cf->log, 0, - "Backward compatibility with the \"%V %V;\" configuration directive is " - "deprecated. Please use \"%V;\" instead.", - &values[0], &values[1], &preferred_str); + ngx_log_error( + NGX_LOG_WARN, cf->log, 0, + "Backward compatibility with the \"%V %V;\" configuration directive is " + "deprecated. Please use \"%V;\" instead.", + &values[0], &values[1], &preferred_str); return static_cast(NGX_CONF_OK); } -char *datadog_enable(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept { +char *datadog_enable(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept { const auto loc_conf = static_cast(conf); loc_conf->enable = true; return static_cast(NGX_CONF_OK); } -char *datadog_disable(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept { +char *datadog_disable(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept { const auto loc_conf = static_cast(conf); loc_conf->enable = false; return static_cast(NGX_CONF_OK); } -char *plugin_loading_deprecated(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept { +char *plugin_loading_deprecated(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept { ngx_log_error(NGX_LOG_ERR, cf->log, 0, - "The \"%V\" directive is no longer necessary. Use the separate datadog_* " + "The \"%V\" directive is no longer necessary. Use the " + "separate datadog_* " "directives to configure tracing.", &command->name); return static_cast(NGX_CONF_ERROR); } -char *set_datadog_sample_rate(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 { const auto loc_conf = static_cast(conf); - conf_directive_source_location_t directive = command_source_location(command, cf); + conf_directive_source_location_t directive = + command_source_location(command, cf); auto values = static_cast(cf->args->elts); // values[0] is the command name, "datadog_sample_rate". @@ -591,27 +637,35 @@ char *set_datadog_sample_rate(ngx_conf_t *cf, ngx_command_t *command, void *conf // `end_index` might not be the end of the input, e.g. if the argument were // "12monkeys". That's an error. if (end_index != rate_str.size()) { - ngx_log_error( - NGX_LOG_ERR, cf->log, 0, - "Invalid argument \"%V\" to %V directive at %V:%d. Expected a real number between 0.0 " - "and 1.0, but the provided argument has unparsed trailing characters.", - &values[1], &directive.directive_name, &directive.file_name, directive.line); + ngx_log_error(NGX_LOG_ERR, cf->log, 0, + "Invalid argument \"%V\" to %V directive at %V:%d. " + "Expected a real number between 0.0 " + "and 1.0, but the provided argument has unparsed trailing " + "characters.", + &values[1], &directive.directive_name, &directive.file_name, + directive.line); return static_cast(NGX_CONF_ERROR); } if (!(rate_float >= 0.0 && rate_float <= 1.0)) { throw std::out_of_range(""); // error message is in the `catch` handler } } catch (const std::invalid_argument &) { - ngx_log_error(NGX_LOG_ERR, cf->log, 0, - "Invalid argument \"%V\" to %V directive at %V:%d. Expected a real number " - "between 0.0 and 1.0, but the provided argument is not a number.", - &values[1], &directive.directive_name, &directive.file_name, directive.line); + ngx_log_error( + NGX_LOG_ERR, cf->log, 0, + "Invalid argument \"%V\" to %V directive at %V:%d. Expected a real " + "number " + "between 0.0 and 1.0, but the provided argument is not a number.", + &values[1], &directive.directive_name, &directive.file_name, + directive.line); return static_cast(NGX_CONF_ERROR); } catch (const std::out_of_range &) { - ngx_log_error(NGX_LOG_ERR, cf->log, 0, - "Invalid argument \"%V\" to %V directive at %V:%d. Expected a real number " - "between 0.0 and 1.0, but the provided argument is out of range.", - &values[1], &directive.directive_name, &directive.file_name, directive.line); + ngx_log_error( + NGX_LOG_ERR, cf->log, 0, + "Invalid argument \"%V\" to %V directive at %V:%d. Expected a real " + "number " + "between 0.0 and 1.0, but the provided argument is out of range.", + &values[1], &directive.directive_name, &directive.file_name, + directive.line); return static_cast(NGX_CONF_ERROR); } @@ -620,10 +674,11 @@ char *set_datadog_sample_rate(ngx_conf_t *cf, ngx_command_t *command, void *conf NgxScript condition_script; if (condition_script.compile(cf, condition_pattern) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, - "Invalid argument \"%V\" to %V directive at %V:%d. Expected an expression that " + "Invalid argument \"%V\" to %V directive at %V:%d. Expected " + "an expression that " "will evaluate to \"on\" or \"off\".", - &condition_pattern, &directive.directive_name, &directive.file_name, - directive.line); + &condition_pattern, &directive.directive_name, + &directive.file_name, directive.line); return static_cast(NGX_CONF_ERROR); } @@ -663,7 +718,8 @@ char *set_datadog_sample_rate(ngx_conf_t *cf, ngx_command_t *command, void *conf return static_cast(NGX_CONF_OK); } -char *set_datadog_propagation_styles(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept { +char *set_datadog_propagation_styles(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept { const auto main_conf = static_cast(conf); // If the propagation styles have already been configured, then either there // are two "datadog_propagation_styles" directives, or, more likely, another @@ -676,13 +732,15 @@ char *set_datadog_propagation_styles(ngx_conf_t *cf, ngx_command_t *command, voi if (str(location.directive_name) != "datadog_propagation_styles") { qualifier = "default-"; } - ngx_log_error( - NGX_LOG_ERR, cf->log, 0, - "Datadog propagation styles are already configured. They were %sconfigured by " - "the call to \"%V\" at " - "%V:%d. Place the datadog_propagation_styles directive in the http block, before any " - "proxy-related directives.", - qualifier, &location.directive_name, &location.file_name, location.line); + ngx_log_error(NGX_LOG_ERR, cf->log, 0, + "Datadog propagation styles are already configured. They " + "were %sconfigured by " + "the call to \"%V\" at " + "%V:%d. Place the datadog_propagation_styles directive in " + "the http block, before any " + "proxy-related directives.", + qualifier, &location.directive_name, &location.file_name, + location.line); return static_cast(NGX_CONF_ERROR); } @@ -699,16 +757,20 @@ char *set_datadog_propagation_styles(ngx_conf_t *cf, ngx_command_t *command, voi if (!maybe_style) { const auto location = command_source_location(command, cf); ngx_log_error(NGX_LOG_ERR, cf->log, 0, - "Invalid propagation style \"%V\". Acceptable values are \"Datadog\", \"B3\", " + "Invalid propagation style \"%V\". Acceptable values are " + "\"Datadog\", \"B3\", " "and \"tracecontext\". Error occurred at \"%V\" in %V:%d", - arg, &location.directive_name, &location.file_name, location.line); + arg, &location.directive_name, &location.file_name, + location.line); return static_cast(NGX_CONF_ERROR); } if (std::find(styles.begin(), styles.end(), *maybe_style) != styles.end()) { const auto location = command_source_location(command, cf); ngx_log_error(NGX_LOG_ERR, cf->log, 0, - "Duplicate propagation style \"%V\". Error occurred at \"%V\" in %V:%d", arg, - &location.directive_name, &location.file_name, location.line); + "Duplicate propagation style \"%V\". Error occurred at " + "\"%V\" in %V:%d", + arg, &location.directive_name, &location.file_name, + location.line); return static_cast(NGX_CONF_ERROR); } styles.push_back(*maybe_style); @@ -721,14 +783,16 @@ template static char *set_configured_value( ngx_conf_t *cf, ngx_command_t *command, void *conf, std::optional datadog_main_conf_t::*conf_member, - SetInDDConfig &&set_in_dd_config, GetFromFinalDDConfig &&get_from_final_dd_config) { + SetInDDConfig &&set_in_dd_config, + GetFromFinalDDConfig &&get_from_final_dd_config) { auto location = command_source_location(command, cf); auto *main_conf = static_cast(conf); auto &field = main_conf->*conf_member; if (field) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, - "Duplicate call to \"%V\". First call was at %V:%d. Duplicate call is at %V:%d.", + "Duplicate call to \"%V\". First call was at %V:%d. " + "Duplicate call is at %V:%d.", &field->location.directive_name, &field->location.file_name, field->location.line, &location.file_name, location.line); return static_cast(NGX_CONF_ERROR); @@ -748,18 +812,20 @@ static char *set_configured_value( set_in_dd_config(minimal_config, arg); auto finalized_config = dd::finalize_config(minimal_config); if (auto *error = finalized_config.if_error()) { - ngx_log_error(NGX_LOG_ERR, cf->log, 0, "Unable to check %V %V; [error code %d]: %s", - &values[0], &values[1], int(error->code), error->message.c_str()); + ngx_log_error(NGX_LOG_ERR, cf->log, 0, + "Unable to check %V %V; [error code %d]: %s", &values[0], + &values[1], int(error->code), error->message.c_str()); return static_cast(NGX_CONF_ERROR); } // Get the resulting configuration property of interest. const std::string &final_value = get_from_final_dd_config(*finalized_config); if (final_value != arg) { - ngx_log_error( - NGX_LOG_ERR, cf->log, 0, - "\"%V %V;\" directive at %V:%d is overriden to \"%s\" by an environment variable", - &values[0], &values[1], &location.file_name, location.line, final_value.c_str()); + ngx_log_error(NGX_LOG_ERR, cf->log, 0, + "\"%V %V;\" directive at %V:%d is overriden to \"%s\" by an " + "environment variable", + &values[0], &values[1], &location.file_name, location.line, + final_value.c_str()); } field.emplace(); @@ -769,38 +835,51 @@ static char *set_configured_value( return NGX_CONF_OK; } -char *set_datadog_service_name(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept { +char *set_datadog_service_name(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept { return set_configured_value( cf, command, conf, &datadog_main_conf_t::service_name, [](dd::TracerConfig &config, std::string_view service_name) { config.defaults.service = service_name; }, - [](const dd::FinalizedTracerConfig &config) { return config.defaults.service; }); + [](const dd::FinalizedTracerConfig &config) { + return config.defaults.service; + }); } -char *set_datadog_environment(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept { +char *set_datadog_environment(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept { return set_configured_value( cf, command, conf, &datadog_main_conf_t::environment, [](dd::TracerConfig &config, std::string_view environment) { - config.report_traces = false; // don't bother with a collector (optimization) + config.report_traces = + false; // don't bother with a collector (optimization) config.defaults.environment = environment; }, - [](const dd::FinalizedTracerConfig &config) { return config.defaults.environment; }); + [](const dd::FinalizedTracerConfig &config) { + return config.defaults.environment; + }); } -char *set_datadog_agent_url(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept { +char *set_datadog_agent_url(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept { return set_configured_value( cf, command, conf, &datadog_main_conf_t::agent_url, - [](dd::TracerConfig &config, std::string_view agent_url) { config.agent.url = agent_url; }, + [](dd::TracerConfig &config, std::string_view agent_url) { + config.agent.url = agent_url; + }, [](const dd::FinalizedTracerConfig &config) { - const auto &url = std::get(config.collector).url; + const auto &url = + std::get(config.collector).url; return url.scheme + "://" + url.authority + url.path; }); } -char *set_datadog_delegate_sampling(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept { +char *set_datadog_delegate_sampling(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept { const auto loc_conf = static_cast(conf); - loc_conf->sampling_delegation_directive = command_source_location(command, cf); + loc_conf->sampling_delegation_directive = + command_source_location(command, cf); auto values = static_cast(cf->args->elts); // values[0] is the command name, "datadog_delegate_sampling". @@ -825,15 +904,16 @@ char *set_datadog_delegate_sampling(ngx_conf_t *cf, ngx_command_t *command, void return NGX_CONF_OK; } -char *set_datadog_allow_sampling_delegation_in_subrequests(ngx_conf_t *cf, ngx_command_t *command, - void *conf) noexcept { +char *set_datadog_allow_sampling_delegation_in_subrequests( + ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept { const auto loc_conf = static_cast(conf); loc_conf->allow_sampling_delegation_in_subrequests_directive = command_source_location(command, cf); auto values = static_cast(cf->args->elts); - // values[0] is the command name, "datadog_allow_sampling_delegation_in_subrequests". - // The other elements are the arguments: either zero or one of them. + // values[0] is the command name, + // "datadog_allow_sampling_delegation_in_subrequests". The other elements are + // the arguments: either zero or one of them. // // datadog_allow_sampling_delegation_in_subrequests [on | off]; @@ -847,17 +927,20 @@ char *set_datadog_allow_sampling_delegation_in_subrequests(ngx_conf_t *cf, ngx_c pattern = values[1]; } - if (loc_conf->allow_sampling_delegation_in_subrequests_script.compile(cf, pattern) != NGX_OK) { + if (loc_conf->allow_sampling_delegation_in_subrequests_script.compile( + cf, pattern) != NGX_OK) { return static_cast(NGX_CONF_ERROR); } return NGX_CONF_OK; } -char *hijack_add_header(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept try { +char *hijack_add_header(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept try { // First, call the handler of the actual command that we're hijacking, i.e. // "add_header". Be sure to skip this module, so we don't call ourself. - ngx_int_t rcode = datadog_conf_handler({.conf = cf, .skip_this_module = true}); + ngx_int_t rcode = + datadog_conf_handler({.conf = cf, .skip_this_module = true}); if (rcode != NGX_OK) { return static_cast(NGX_CONF_ERROR); } @@ -876,14 +959,17 @@ char *hijack_add_header(ngx_conf_t *cf, ngx_command_t *command, void *conf) noex } loc_conf->is_sampling_delegation_response_header_added = true; - const ngx_str_t response_header = ngx_string("X-Datadog-Trace-Sampling-Decision"); + const ngx_str_t response_header = + ngx_string("X-Datadog-Trace-Sampling-Decision"); // Add our own version of the "X-Datadog-Trace-Sampling-Decision" response // header (if it's nonempty): // - // add_header X-Datadog-Trace-Sampling-Decision $datadog_sampling_delegation_response always; + // add_header X-Datadog-Trace-Sampling-Decision + // $datadog_sampling_delegation_response always; ngx_str_t args[] = {ngx_string("add_header"), response_header, - ngx_string("$datadog_sampling_delegation_response"), ngx_string("always")}; + ngx_string("$datadog_sampling_delegation_response"), + ngx_string("always")}; ngx_array_t args_array; args_array.elts = static_cast(&args); args_array.nelts = sizeof args / sizeof args[0]; @@ -898,11 +984,13 @@ char *hijack_add_header(ngx_conf_t *cf, ngx_command_t *command, void *conf) noex } return static_cast(NGX_CONF_OK); } catch (const std::exception &e) { - ngx_log_error(NGX_LOG_ERR, cf->log, 0, "hijack_add_header failed: %s", e.what()); + ngx_log_error(NGX_LOG_ERR, cf->log, 0, "hijack_add_header failed: %s", + e.what()); return static_cast(NGX_CONF_ERROR); } -char *hijack_auth_request(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept try { +char *hijack_auth_request(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept try { // Call the underlying directive handler, and then insert the following: // // auth_request_set $datadog_dummy_variable $datadog_auth_request_hook; @@ -912,12 +1000,14 @@ char *hijack_auth_request(ngx_conf_t *cf, ngx_command_t *command, void *conf) no // must be evaluated within `auth_request_set` so that the // `$upstream_http_...` variables refer to the subrequest's response, as // opposed to the main upstream request's response. - ngx_int_t rcode = datadog_conf_handler({.conf = cf, .skip_this_module = true}); + ngx_int_t rcode = + datadog_conf_handler({.conf = cf, .skip_this_module = true}); if (rcode != NGX_OK) { return static_cast(NGX_CONF_ERROR); } - ngx_str_t args[] = {ngx_string("auth_request_set"), ngx_string("$datadog_dummy_variable"), + ngx_str_t args[] = {ngx_string("auth_request_set"), + ngx_string("$datadog_dummy_variable"), ngx_string("$datadog_auth_request_hook")}; ngx_array_t args_array; args_array.elts = static_cast(&args); @@ -933,7 +1023,8 @@ char *hijack_auth_request(ngx_conf_t *cf, ngx_command_t *command, void *conf) no } return static_cast(NGX_CONF_OK); } catch (const std::exception &e) { - ngx_log_error(NGX_LOG_ERR, cf->log, 0, "hijack_auth_request failed: %s", e.what()); + ngx_log_error(NGX_LOG_ERR, cf->log, 0, "hijack_auth_request failed: %s", + e.what()); return static_cast(NGX_CONF_ERROR); } diff --git a/src/datadog_directive.h b/src/datadog_directive.h index 99b16f09..ddfe61d1 100644 --- a/src/datadog_directive.h +++ b/src/datadog_directive.h @@ -10,68 +10,93 @@ extern "C" { namespace datadog { namespace nginx { -char *propagate_datadog_context(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; +char *propagate_datadog_context(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept; -char *hijack_proxy_pass(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; +char *hijack_proxy_pass(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept; -char *delegate_to_datadog_directive_with_warning(ngx_conf_t *cf, ngx_command_t *command, +char *delegate_to_datadog_directive_with_warning(ngx_conf_t *cf, + ngx_command_t *command, void *conf) noexcept; char *propagate_fastcgi_datadog_context(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; -char *hijack_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; +char *hijack_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept; -char *propagate_grpc_datadog_context(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; +char *propagate_grpc_datadog_context(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept; -char *hijack_grpc_pass(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; +char *hijack_grpc_pass(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept; -char *hijack_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; +char *hijack_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept; -char *hijack_access_log(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; +char *hijack_access_log(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept; -char *add_datadog_tag(ngx_conf_t *cf, ngx_array_t *tags, ngx_str_t key, ngx_str_t value) noexcept; +char *add_datadog_tag(ngx_conf_t *cf, ngx_array_t *tags, ngx_str_t key, + ngx_str_t value) noexcept; -char *set_datadog_tag(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; +char *set_datadog_tag(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept; -char *json_config_deprecated(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; +char *json_config_deprecated(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept; -char *set_datadog_operation_name(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; +char *set_datadog_operation_name(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept; -char *set_datadog_location_operation_name(ngx_conf_t *cf, ngx_command_t *command, +char *set_datadog_location_operation_name(ngx_conf_t *cf, + ngx_command_t *command, void *conf) noexcept; -char *set_datadog_resource_name(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; +char *set_datadog_resource_name(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept; char *set_datadog_location_resource_name(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; -char *toggle_opentracing(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; +char *toggle_opentracing(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept; -char *datadog_enable(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; +char *datadog_enable(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept; -char *datadog_disable(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; +char *datadog_disable(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept; -char *plugin_loading_deprecated(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; +char *plugin_loading_deprecated(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; +char *set_datadog_sample_rate(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept; -char *set_datadog_propagation_styles(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; +char *set_datadog_propagation_styles(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept; -char *set_datadog_service_name(ngx_conf_t *, ngx_command_t *, void *conf) noexcept; +char *set_datadog_service_name(ngx_conf_t *, ngx_command_t *, + void *conf) noexcept; -char *set_datadog_environment(ngx_conf_t *, ngx_command_t *, void *conf) noexcept; +char *set_datadog_environment(ngx_conf_t *, ngx_command_t *, + void *conf) noexcept; char *set_datadog_agent_url(ngx_conf_t *, ngx_command_t *, void *conf) noexcept; -char *set_datadog_delegate_sampling(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; +char *set_datadog_delegate_sampling(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept; -char *set_datadog_allow_sampling_delegation_in_subrequests(ngx_conf_t *cf, ngx_command_t *command, - void *conf) noexcept; +char *set_datadog_allow_sampling_delegation_in_subrequests( + ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; -char *hijack_add_header(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; +char *hijack_add_header(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept; -char *hijack_auth_request(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept; +char *hijack_auth_request(ngx_conf_t *cf, ngx_command_t *command, + void *conf) noexcept; } // namespace nginx } // namespace datadog diff --git a/src/datadog_handler.cpp b/src/datadog_handler.cpp index 2259005b..96dbef6e 100644 --- a/src/datadog_handler.cpp +++ b/src/datadog_handler.cpp @@ -33,7 +33,8 @@ ngx_int_t on_enter_block(ngx_http_request_t *request) noexcept try { ngx_http_get_module_loc_conf(request, ngx_http_core_module)); auto loc_conf = static_cast( ngx_http_get_module_loc_conf(request, ngx_http_datadog_module)); - if (!is_datadog_enabled(request, core_loc_conf, loc_conf)) return NGX_DECLINED; + if (!is_datadog_enabled(request, core_loc_conf, loc_conf)) + return NGX_DECLINED; auto context = get_datadog_context(request); if (context == nullptr) { @@ -52,7 +53,8 @@ ngx_int_t on_enter_block(ngx_http_request_t *request) noexcept try { return NGX_DECLINED; } catch (const std::exception &e) { ngx_log_error(NGX_LOG_ERR, request->connection->log, 0, - "Datadog instrumentation failed for request %p: %s", request, e.what()); + "Datadog instrumentation failed for request %p: %s", request, + e.what()); return NGX_DECLINED; } @@ -63,7 +65,8 @@ ngx_int_t on_log_request(ngx_http_request_t *request) noexcept { context->on_log_request(request); } catch (const std::exception &e) { ngx_log_error(NGX_LOG_ERR, request->connection->log, 0, - "Datadog instrumentation failed for request %p: %s", request, e.what()); + "Datadog instrumentation failed for request %p: %s", request, + e.what()); } return NGX_DECLINED; } diff --git a/src/datadog_variable.cpp b/src/datadog_variable.cpp index 353d3c96..a827df1e 100644 --- a/src/datadog_variable.cpp +++ b/src/datadog_variable.cpp @@ -54,7 +54,8 @@ static ngx_int_t expand_span_variable(ngx_http_request_t* request, return NGX_OK; } - auto span_variable_value = context->lookup_span_variable_value(request, suffix); + auto span_variable_value = + context->lookup_span_variable_value(request, suffix); variable_value->len = span_variable_value.len; variable_value->valid = true; variable_value->no_cacheable = true; @@ -77,11 +78,12 @@ static ngx_int_t expand_span_variable(ngx_http_request_t* request, // string containing the value of the "x-datadog-origin" header as it would be // propagated to a proxied upstream service. Return `NGX_OK` on success or // another value if an error occurs. -static ngx_int_t expand_propagation_header_variable(ngx_http_request_t* request, - ngx_http_variable_value_t* variable_value, - uintptr_t data) noexcept try { +static ngx_int_t expand_propagation_header_variable( + ngx_http_request_t* request, ngx_http_variable_value_t* variable_value, + uintptr_t data) noexcept try { auto variable_name = to_string_view(*reinterpret_cast(data)); - auto prefix_length = TracingLibrary::propagation_header_variable_name_prefix().size(); + auto prefix_length = + TracingLibrary::propagation_header_variable_name_prefix().size(); auto suffix = slice(variable_name, prefix_length); auto context = get_datadog_context(request); @@ -93,7 +95,8 @@ static ngx_int_t expand_propagation_header_variable(ngx_http_request_t* request, return NGX_OK; } - auto value = context->lookup_propagation_header_variable_value(request, suffix); + auto value = + context->lookup_propagation_header_variable_value(request, suffix); variable_value->len = value.len; variable_value->valid = true; variable_value->no_cacheable = true; @@ -118,19 +121,22 @@ static ngx_int_t expand_propagation_header_variable(ngx_http_request_t* request, // only the environment variables listed in // `TracingLibrary::environment_variable_names`. Return `NGX_OK` on success or // another value if an error occurs. -static ngx_int_t expand_environment_variable(ngx_http_request_t* request, - ngx_http_variable_value_t* variable_value, - uintptr_t data) noexcept { +static ngx_int_t expand_environment_variable( + ngx_http_request_t* request, ngx_http_variable_value_t* variable_value, + uintptr_t data) noexcept { auto variable_name = to_string_view(*reinterpret_cast(data)); - auto prefix_length = TracingLibrary::environment_variable_name_prefix().size(); + auto prefix_length = + TracingLibrary::environment_variable_name_prefix().size(); auto suffix = slice(variable_name, prefix_length); std::string env_var_name{suffix.data(), suffix.size()}; - std::transform(env_var_name.begin(), env_var_name.end(), env_var_name.begin(), to_upper); + std::transform(env_var_name.begin(), env_var_name.end(), env_var_name.begin(), + to_upper); const auto allow_list = TracingLibrary::environment_variable_names(); const char* env_value = nullptr; - if (std::find(allow_list.begin(), allow_list.end(), env_var_name) != allow_list.end()) { + if (std::find(allow_list.begin(), allow_list.end(), env_var_name) != + allow_list.end()) { env_value = std::getenv(env_var_name.c_str()); } @@ -159,9 +165,9 @@ static ngx_int_t expand_environment_variable(ngx_http_request_t* request, // `TracingLibrary::configuration_json_variable_name()`. The variable // evaluates to a JSON representation of the tracer configuration. Return // `NGX_OK` on success or another value if an error occurs. -static ngx_int_t expand_configuration_variable(ngx_http_request_t* request, - ngx_http_variable_value_t* variable_value, - uintptr_t /*data*/) noexcept { +static ngx_int_t expand_configuration_variable( + ngx_http_request_t* request, ngx_http_variable_value_t* variable_value, + uintptr_t /*data*/) noexcept { variable_value->valid = true; variable_value->no_cacheable = true; variable_value->not_found = false; @@ -175,7 +181,8 @@ static ngx_int_t expand_configuration_variable(ngx_http_request_t* request, return NGX_OK; } - const ngx_str_t json_str = to_ngx_str(request->pool, tracer->config_json().dump()); + const ngx_str_t json_str = + to_ngx_str(request->pool, tracer->config_json().dump()); variable_value->len = json_str.len; variable_value->data = json_str.data; return NGX_OK; @@ -213,9 +220,9 @@ static ngx_int_t expand_configuration_variable(ngx_http_request_t* request, // `variable_value` a hyphen character ("-"). // // Return `NGX_OK` on success or another value if an error occurs. -static ngx_int_t expand_location_variable(ngx_http_request_t* request, - ngx_http_variable_value_t* variable_value, - uintptr_t /*data*/) noexcept { +static ngx_int_t expand_location_variable( + ngx_http_request_t* request, ngx_http_variable_value_t* variable_value, + uintptr_t /*data*/) noexcept { const auto core_loc_conf = static_cast( ngx_http_get_module_loc_conf(request, ngx_http_core_module)); @@ -245,9 +252,9 @@ static ngx_int_t expand_location_variable(ngx_http_request_t* request, // to the name of the proxy-related configuration directive directly within the // location associated with `request`, or "location" if there is no such // directive. -static ngx_int_t expand_proxy_directive_variable(ngx_http_request_t* request, - ngx_http_variable_value_t* variable_value, - uintptr_t /*data*/) noexcept { +static ngx_int_t expand_proxy_directive_variable( + ngx_http_request_t* request, ngx_http_variable_value_t* variable_value, + uintptr_t /*data*/) noexcept { const auto loc_conf = static_cast( ngx_http_get_module_loc_conf(request, ngx_http_datadog_module)); @@ -289,7 +296,8 @@ static ngx_int_t expand_sampling_delegation_response_variable( return NGX_OK; } - const ngx_str_t value = context->lookup_sampling_delegation_response_variable_value(request); + const ngx_str_t value = + context->lookup_sampling_delegation_response_variable_value(request); variable_value->len = value.len; variable_value->valid = true; variable_value->no_cacheable = true; @@ -299,9 +307,9 @@ static ngx_int_t expand_sampling_delegation_response_variable( return NGX_OK; } -static ngx_int_t expand_auth_request_hook(ngx_http_request_t* request, - ngx_http_variable_value_t* variable_value, - uintptr_t /*data*/) noexcept try { +static ngx_int_t expand_auth_request_hook( + ngx_http_request_t* request, ngx_http_variable_value_t* variable_value, + uintptr_t /*data*/) noexcept try { variable_value->valid = true; variable_value->no_cacheable = true; variable_value->not_found = true; @@ -330,14 +338,17 @@ ngx_int_t add_variables(ngx_conf_t* cf) noexcept { // Register the variable name prefix for span variables. prefix = to_ngx_str(TracingLibrary::span_variables().prefix); variable = ngx_http_add_variable( - cf, &prefix, NGX_HTTP_VAR_NOCACHEABLE | NGX_HTTP_VAR_NOHASH | NGX_HTTP_VAR_PREFIX); + cf, &prefix, + NGX_HTTP_VAR_NOCACHEABLE | NGX_HTTP_VAR_NOHASH | NGX_HTTP_VAR_PREFIX); variable->get_handler = expand_span_variable; variable->data = 0; // Register the variable name prefix for propagation header variables. - prefix = to_ngx_str(TracingLibrary::propagation_header_variable_name_prefix()); + prefix = + to_ngx_str(TracingLibrary::propagation_header_variable_name_prefix()); variable = ngx_http_add_variable( - cf, &prefix, NGX_HTTP_VAR_NOCACHEABLE | NGX_HTTP_VAR_NOHASH | NGX_HTTP_VAR_PREFIX); + cf, &prefix, + NGX_HTTP_VAR_NOCACHEABLE | NGX_HTTP_VAR_NOHASH | NGX_HTTP_VAR_PREFIX); variable->get_handler = expand_propagation_header_variable; variable->data = 0; @@ -345,12 +356,14 @@ ngx_int_t add_variables(ngx_conf_t* cf) noexcept { // variables. prefix = to_ngx_str(TracingLibrary::environment_variable_name_prefix()); variable = ngx_http_add_variable( - cf, &prefix, NGX_HTTP_VAR_NOCACHEABLE | NGX_HTTP_VAR_NOHASH | NGX_HTTP_VAR_PREFIX); + cf, &prefix, + NGX_HTTP_VAR_NOCACHEABLE | NGX_HTTP_VAR_NOHASH | NGX_HTTP_VAR_PREFIX); variable->get_handler = expand_environment_variable; variable->data = 0; // Register the variable name for getting the tracer configuration. - ngx_str_t name = to_ngx_str(TracingLibrary::configuration_json_variable_name()); + ngx_str_t name = + to_ngx_str(TracingLibrary::configuration_json_variable_name()); variable = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_NOHASH); variable->get_handler = expand_configuration_variable; variable->data = 0; @@ -371,7 +384,8 @@ ngx_int_t add_variables(ngx_conf_t* cf) noexcept { // Register the variable name that will be used to send a response header // containing the trace sampling decision whenever sampling delegation is // requested. - name = to_ngx_str(TracingLibrary::sampling_delegation_response_variable_name()); + name = + to_ngx_str(TracingLibrary::sampling_delegation_response_variable_name()); variable = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_NOHASH); variable->get_handler = expand_sampling_delegation_response_variable; variable->data = 0; @@ -385,7 +399,8 @@ ngx_int_t add_variables(ngx_conf_t* cf) noexcept { // sampling delegation to work with auth requests, in the unlikely case that // nginx is configured to allow sampling delegation in subrequests. name = ngx_string("datadog_auth_request_hook"); - variable = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_NOHASH | NGX_HTTP_VAR_CHANGEABLE); + variable = ngx_http_add_variable( + cf, &name, NGX_HTTP_VAR_NOHASH | NGX_HTTP_VAR_CHANGEABLE); variable->get_handler = expand_auth_request_hook; variable->data = 0; diff --git a/src/defer.h b/src/defer.h index 98820942..80a7e45b 100644 --- a/src/defer.h +++ b/src/defer.h @@ -57,7 +57,8 @@ class CleanupFuncGuard { bool active_; // whether to call `on_destroy_` in the destructor public: - explicit CleanupFuncGuard(Func&& func) : on_destroy_(std::move(func)), active_(true) {} + explicit CleanupFuncGuard(Func&& func) + : on_destroy_(std::move(func)), active_(true) {} CleanupFuncGuard(CleanupFuncGuard&& other) : on_destroy_(std::move(other.on_destroy_)), active_(true) { diff --git a/src/log_conf.cpp b/src/log_conf.cpp index a85e0bc6..6b9380ab 100644 --- a/src/log_conf.cpp +++ b/src/log_conf.cpp @@ -32,7 +32,8 @@ ngx_int_t inject_datadog_log_formats(ngx_conf_t *conf) { // execute them. // log_format ; - ngx_str_t args[] = {ngx_string("log_format"), ngx_str_t(), ngx_str_t(), ngx_str_t()}; + ngx_str_t args[] = {ngx_string("log_format"), ngx_str_t(), ngx_str_t(), + ngx_str_t()}; ngx_array_t args_array; args_array.elts = args; args_array.nelts = sizeof args / sizeof args[0]; @@ -55,7 +56,8 @@ ngx_int_t inject_datadog_log_formats(ngx_conf_t *conf) { args[1] = to_ngx_str(std::string_view(format.name)); args[2] = to_ngx_str(std::string_view(format.escaping_style)); args[3] = to_ngx_str(std::string_view(format.format)); - if (auto rcode = datadog_conf_handler({.conf = conf, .skip_this_module = true})) { + if (auto rcode = + datadog_conf_handler({.conf = conf, .skip_this_module = true})) { return rcode; } } diff --git a/src/ngx_event_scheduler.cpp b/src/ngx_event_scheduler.cpp index f62d3466..64de80c8 100644 --- a/src/ngx_event_scheduler.cpp +++ b/src/ngx_event_scheduler.cpp @@ -8,7 +8,8 @@ namespace nginx { namespace { ngx_msec_t to_milliseconds(std::chrono::steady_clock::duration interval) { - return std::chrono::duration_cast(interval).count(); + return std::chrono::duration_cast(interval) + .count(); } extern "C" void handle_event(ngx_event_t *ev) { @@ -31,7 +32,8 @@ NgxEventScheduler::Event::Event(std::function callback, } dd::EventScheduler::Cancel NgxEventScheduler::schedule_recurring_event( - std::chrono::steady_clock::duration interval, std::function callback) { + std::chrono::steady_clock::duration interval, + std::function callback) { auto event = std::make_unique(std::move(callback), interval); events_.insert(event.get()); ngx_add_timer(&event->event, to_milliseconds(event->interval)); @@ -52,7 +54,8 @@ NgxEventScheduler::~NgxEventScheduler() { } nlohmann::json NgxEventScheduler::config_json() const { - return nlohmann::json::object({{"type", "datadog::nginx::NgxEventScheduler"}}); + return nlohmann::json::object( + {{"type", "datadog::nginx::NgxEventScheduler"}}); } } // namespace nginx diff --git a/src/ngx_event_scheduler.h b/src/ngx_event_scheduler.h index 086c36f2..c9517ed3 100644 --- a/src/ngx_event_scheduler.h +++ b/src/ngx_event_scheduler.h @@ -22,7 +22,8 @@ class NgxEventScheduler : public dd::EventScheduler { std::function callback; ngx_event_t event; - Event(std::function callback, std::chrono::steady_clock::duration interval); + Event(std::function callback, + std::chrono::steady_clock::duration interval); Event(const Event&) = delete; Event& operator=(const Event&) = delete; diff --git a/src/ngx_header_reader.h b/src/ngx_header_reader.h index 40c0e522..470f4839 100644 --- a/src/ngx_header_reader.h +++ b/src/ngx_header_reader.h @@ -29,11 +29,14 @@ class NgxHeaderReader : public dd::DictReader { public: explicit NgxHeaderReader(const ngx_http_request_t *request) { - for_each(request->headers_in.headers, [&](const ngx_table_elt_t &header) { - auto key = std::string_view{reinterpret_cast(header.lowcase_key), header.key.len}; - auto value = std::string_view{reinterpret_cast(header.value.data), header.value.len}; - headers_.emplace(key, value); - }); + for_each( + request->headers_in.headers, [&](const ngx_table_elt_t &header) { + auto key = std::string_view{ + reinterpret_cast(header.lowcase_key), header.key.len}; + auto value = std::string_view{ + reinterpret_cast(header.value.data), header.value.len}; + headers_.emplace(key, value); + }); } std::optional lookup(std::string_view key) const override { @@ -47,8 +50,9 @@ class NgxHeaderReader : public dd::DictReader { return std::nullopt; } - void visit(const std::function &visitor) - const override { + void visit( + const std::function + &visitor) const override { for (const auto &[key, value] : headers_) { visitor(key, value); } diff --git a/src/ngx_http_datadog_module.cpp b/src/ngx_http_datadog_module.cpp index 75b3347b..0c651c1b 100644 --- a/src/ngx_http_datadog_module.cpp +++ b/src/ngx_http_datadog_module.cpp @@ -46,10 +46,11 @@ using namespace datadog::nginx; // "datadog_trace_locations". The `ngx_command_t::type` bitmask of the two // versions must match. To ensure this, `DEFINE_COMMAND_WITH_OLD_ALIAS` is a // macro that defines both commands at the same time. -#define DEFINE_COMMAND_WITH_OLD_ALIAS(NAME, OLD_NAME, TYPE, SET, CONF, OFFSET, POST) \ - {ngx_string(NAME), TYPE, SET, CONF, OFFSET, POST}, { \ - ngx_string(OLD_NAME), TYPE, delegate_to_datadog_directive_with_warning, \ - NGX_HTTP_LOC_CONF_OFFSET, 0, nullptr \ +#define DEFINE_COMMAND_WITH_OLD_ALIAS(NAME, OLD_NAME, TYPE, SET, CONF, OFFSET, \ + POST) \ + {ngx_string(NAME), TYPE, SET, CONF, OFFSET, POST}, { \ + ngx_string(OLD_NAME), TYPE, delegate_to_datadog_directive_with_warning, \ + NGX_HTTP_LOC_CONF_OFFSET, 0, nullptr \ } // Part of configuring a command is saying where the command is allowed to @@ -355,7 +356,8 @@ ngx_module_t ngx_http_datadog_module = { // Note that `ngx_set_env` is adapted from the function of the same name in // `nginx.c` within the nginx source code. static void *ngx_set_env(std::string_view entry, ngx_cycle_t *cycle) { - ngx_core_conf_t *ccf = (ngx_core_conf_t *)ngx_get_conf(cycle->conf_ctx, ngx_core_module); + ngx_core_conf_t *ccf = + (ngx_core_conf_t *)ngx_get_conf(cycle->conf_ctx, ngx_core_module); ngx_str_t *value, *var; ngx_uint_t i; @@ -378,9 +380,11 @@ static void *ngx_set_env(std::string_view entry, ngx_cycle_t *cycle) { return NGX_CONF_OK; } -static ngx_int_t datadog_master_process_post_config(ngx_cycle_t *cycle) noexcept { +static ngx_int_t datadog_master_process_post_config( + ngx_cycle_t *cycle) noexcept { // Forward tracer-specific environment variables to worker processes. - for (const auto &env_var_name : TracingLibrary::environment_variable_names()) { + for (const auto &env_var_name : + TracingLibrary::environment_variable_names()) { if (const void *const error = ngx_set_env(env_var_name, cycle)) { return ngx_int_t(error); } @@ -400,7 +404,8 @@ static ngx_int_t datadog_master_process_post_config(ngx_cycle_t *cycle) noexcept // Forward tracer-specific environment variables to worker processes. std::string name; - for (const auto &env_var_name : TracingLibrary::environment_variable_names()) { + for (const auto &env_var_name : + TracingLibrary::environment_variable_names()) { name = env_var_name; if (const char *value = std::getenv(name.c_str())) { main_conf->environment_variables.push_back( @@ -423,8 +428,8 @@ static ngx_int_t datadog_module_init(ngx_conf_t *cf) noexcept { } // Add handlers to create tracing data. - auto handler = static_cast( - ngx_array_push(&core_main_config->phases[NGX_HTTP_REWRITE_PHASE].handlers)); + auto handler = static_cast(ngx_array_push( + &core_main_config->phases[NGX_HTTP_REWRITE_PHASE].handlers)); if (handler == nullptr) return NGX_ERROR; *handler = on_enter_block; @@ -436,11 +441,12 @@ static ngx_int_t datadog_module_init(ngx_conf_t *cf) noexcept { // Add default span tags. const auto tags = TracingLibrary::default_tags(); if (tags.empty()) return NGX_OK; - main_conf->tags = ngx_array_create(cf->pool, tags.size(), sizeof(datadog_tag_t)); + main_conf->tags = + ngx_array_create(cf->pool, tags.size(), sizeof(datadog_tag_t)); if (!main_conf->tags) return NGX_ERROR; for (const auto &tag : tags) { - if (add_datadog_tag(cf, main_conf->tags, to_ngx_str(tag.first), to_ngx_str(tag.second)) != - NGX_CONF_OK) { + if (add_datadog_tag(cf, main_conf->tags, to_ngx_str(tag.first), + to_ngx_str(tag.second)) != NGX_CONF_OK) { return NGX_ERROR; } } @@ -457,7 +463,8 @@ static ngx_int_t datadog_init_worker(ngx_cycle_t *cycle) noexcept try { auto maybe_tracer = TracingLibrary::make_tracer(*main_conf); if (auto *error = maybe_tracer.if_error()) { - ngx_log_error(NGX_LOG_ERR, cycle->log, 0, "Failed to construct tracer: [error code %d] %s", + ngx_log_error(NGX_LOG_ERR, cycle->log, 0, + "Failed to construct tracer: [error code %d] %s", int(error->code), error->message.c_str()); return NGX_ERROR; } @@ -465,7 +472,8 @@ static ngx_int_t datadog_init_worker(ngx_cycle_t *cycle) noexcept try { reset_global_tracer(std::move(*maybe_tracer)); return NGX_OK; } catch (const std::exception &e) { - ngx_log_error(NGX_LOG_ERR, cycle->log, 0, "failed to initialize tracer: %s", e.what()); + ngx_log_error(NGX_LOG_ERR, cycle->log, 0, "failed to initialize tracer: %s", + e.what()); return NGX_ERROR; } @@ -503,7 +511,8 @@ static int register_destructor(ngx_pool_t *pool, Config *config) { // `cf` so that sampling delegation's X-Datadog-Trace-Sampling-Decision response // header can be delivered in response to requests that indicated sampling // delegation, if appropriate. -static char *inject_sampling_delegation_response_header(ngx_conf_t *cf) noexcept try { +static char *inject_sampling_delegation_response_header(ngx_conf_t *cf) noexcept + try { auto main_conf = static_cast( ngx_http_conf_get_module_main_conf(cf, ngx_http_datadog_module)); @@ -520,13 +529,15 @@ static char *inject_sampling_delegation_response_header(ngx_conf_t *cf) noexcept } main_conf->is_sampling_delegation_response_header_added = true; - const ngx_str_t response_header = ngx_string("X-Datadog-Trace-Sampling-Decision"); + const ngx_str_t response_header = + ngx_string("X-Datadog-Trace-Sampling-Decision"); // Prevent an upstream's "X-Datadog-Trace-Sampling-Decision" response header // from leaking to the client: // // proxy_hide_header X-Datadog-Trace-Sampling-Decision; - ngx_str_t args[] = {ngx_string("proxy_hide_header"), response_header, ngx_str_t(), ngx_str_t()}; + ngx_str_t args[] = {ngx_string("proxy_hide_header"), response_header, + ngx_str_t(), ngx_str_t()}; ngx_array_t args_array; args_array.elts = static_cast(&args); args_array.nelts = 2; @@ -543,7 +554,8 @@ static char *inject_sampling_delegation_response_header(ngx_conf_t *cf) noexcept // Add our own version of the "X-Datadog-Trace-Sampling-Decision" response // header (if it's nonempty): // - // add_header X-Datadog-Trace-Sampling-Decision $datadog_sampling_delegation_response always; + // add_header X-Datadog-Trace-Sampling-Decision + // $datadog_sampling_delegation_response always; args[0] = ngx_string("add_header"); args[1] = response_header; args[2] = ngx_string("$datadog_sampling_delegation_response"); @@ -556,7 +568,8 @@ static char *inject_sampling_delegation_response_header(ngx_conf_t *cf) noexcept } return static_cast(NGX_CONF_OK); } catch (const std::exception &e) { - ngx_log_error(NGX_LOG_ERR, cf->log, 0, "inject_sampling_delegation_response_header failed: %s", + ngx_log_error(NGX_LOG_ERR, cf->log, 0, + "inject_sampling_delegation_response_header failed: %s", e.what()); return static_cast(NGX_CONF_ERROR); } @@ -596,7 +609,8 @@ static ngx_str_t block_type(const ngx_conf_t *conf) { if (conf->args == nullptr) { return ngx_string(""); } - return to_ngx_str(conf->pool, str(*static_cast(conf->args->elts))); + return to_ngx_str(conf->pool, + str(*static_cast(conf->args->elts))); } //------------------------------------------------------------------------------ @@ -671,48 +685,54 @@ char *merge_script(ngx_conf_t *conf, NgxScript &previous, NgxScript ¤t, //------------------------------------------------------------------------------ // merge_datadog_loc_conf //------------------------------------------------------------------------------ -static char *merge_datadog_loc_conf(ngx_conf_t *cf, void *parent, void *child) noexcept { +static char *merge_datadog_loc_conf(ngx_conf_t *cf, void *parent, + void *child) noexcept { auto prev = static_cast(parent); auto conf = static_cast(child); conf->parent = prev; conf->depth = prev->depth + 1; - ngx_conf_merge_value(conf->enable, prev->enable, TracingLibrary::tracing_on_by_default()); + ngx_conf_merge_value(conf->enable, prev->enable, + TracingLibrary::tracing_on_by_default()); ngx_conf_merge_value(conf->enable_locations, prev->enable_locations, TracingLibrary::trace_locations_by_default()); - if (const auto rc = merge_script(cf, prev->operation_name_script, conf->operation_name_script, - TracingLibrary::default_request_operation_name_pattern())) { + if (const auto rc = merge_script( + cf, prev->operation_name_script, conf->operation_name_script, + TracingLibrary::default_request_operation_name_pattern())) { return rc; } - if (const auto rc = - merge_script(cf, prev->loc_operation_name_script, conf->loc_operation_name_script, - TracingLibrary::default_location_operation_name_pattern())) { + if (const auto rc = merge_script( + cf, prev->loc_operation_name_script, conf->loc_operation_name_script, + TracingLibrary::default_location_operation_name_pattern())) { return rc; } - if (const auto rc = merge_script(cf, prev->resource_name_script, conf->resource_name_script, - TracingLibrary::default_resource_name_pattern())) { + if (const auto rc = merge_script( + cf, prev->resource_name_script, conf->resource_name_script, + TracingLibrary::default_resource_name_pattern())) { return rc; } - if (const auto rc = - merge_script(cf, prev->loc_resource_name_script, conf->loc_resource_name_script, - TracingLibrary::default_resource_name_pattern())) { + if (const auto rc = merge_script( + cf, prev->loc_resource_name_script, conf->loc_resource_name_script, + TracingLibrary::default_resource_name_pattern())) { return rc; } // $upstream_http_x_datadog_trace_sampling_decision is the value of the // X-Datadog-Trace-Sampling-Decision response header returned by the upstream, // or empty if that response header is not present. - if (const auto rc = merge_script(cf, prev->response_info_script, conf->response_info_script, - "$upstream_http_x_datadog_trace_sampling_decision")) { + if (const auto rc = merge_script( + cf, prev->response_info_script, conf->response_info_script, + "$upstream_http_x_datadog_trace_sampling_decision")) { return rc; } if (const auto rc = merge_script(cf, prev->sampling_delegation_script, conf->sampling_delegation_script, "")) { return rc; } - if (const auto rc = merge_script(cf, prev->allow_sampling_delegation_in_subrequests_script, - conf->allow_sampling_delegation_in_subrequests_script, "off")) { + if (const auto rc = merge_script( + cf, prev->allow_sampling_delegation_in_subrequests_script, + conf->allow_sampling_delegation_in_subrequests_script, "off")) { return rc; } diff --git a/src/ngx_logger.cpp b/src/ngx_logger.cpp index 93ce10d6..fdeef676 100644 --- a/src/ngx_logger.cpp +++ b/src/ngx_logger.cpp @@ -32,8 +32,8 @@ void NgxLogger::log_error(const dd::Error& error) { const ngx_str_t ngx_message = to_ngx_str(error.message); std::lock_guard lock(mutex_); - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "datadog: [error code %d] %V", int(error.code), - &ngx_message); + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "datadog: [error code %d] %V", + int(error.code), &ngx_message); } void NgxLogger::log_error(std::string_view message) { diff --git a/src/ngx_script.cpp b/src/ngx_script.cpp index c81d3c8d..4d69f1e7 100644 --- a/src/ngx_script.cpp +++ b/src/ngx_script.cpp @@ -7,7 +7,8 @@ namespace nginx { //------------------------------------------------------------------------------ // compile //------------------------------------------------------------------------------ -ngx_int_t NgxScript::compile(ngx_conf_t *cf, const ngx_str_t &pattern) noexcept { +ngx_int_t NgxScript::compile(ngx_conf_t *cf, + const ngx_str_t &pattern) noexcept { pattern_ = pattern; lengths_ = nullptr; values_ = nullptr; @@ -34,19 +35,23 @@ ngx_int_t NgxScript::compile(ngx_conf_t *cf, const ngx_str_t &pattern) noexcept //------------------------------------------------------------------------------ ngx_str_t NgxScript::run(ngx_http_request_t *request) const noexcept { if (!is_valid()) { - ngx_log_error(NGX_LOG_ERR, request->connection->log, 0, "Executing invalid Datadog script"); + ngx_log_error(NGX_LOG_ERR, request->connection->log, 0, + "Executing invalid Datadog script"); return {0, nullptr}; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, request->connection->log, 0, - "executing Datadog script \"%V\" for request %p", &pattern_, request); + "executing Datadog script \"%V\" for request %p", &pattern_, + request); // If the script has no variables, we can just return the pattern. if (!lengths_) return pattern_; ngx_str_t result = {0, nullptr}; - if (!ngx_http_script_run(request, &result, lengths_->elts, 0, values_->elts)) { - ngx_log_error(NGX_LOG_ERR, request->connection->log, 0, "failed to run script"); + if (!ngx_http_script_run(request, &result, lengths_->elts, 0, + values_->elts)) { + ngx_log_error(NGX_LOG_ERR, request->connection->log, 0, + "failed to run script"); return {0, nullptr}; } return result; diff --git a/src/propagation_header_querier.cpp b/src/propagation_header_querier.cpp index c042a036..daa68f76 100644 --- a/src/propagation_header_querier.cpp +++ b/src/propagation_header_querier.cpp @@ -22,7 +22,8 @@ extern "C" { namespace datadog { namespace nginx { -ngx_str_t PropagationHeaderQuerier::lookup_value(ngx_http_request_t* request, const dd::Span& span, +ngx_str_t PropagationHeaderQuerier::lookup_value(ngx_http_request_t* request, + const dd::Span& span, std::string_view key) { if (&span != values_span_) { expand_values(request, span); @@ -45,19 +46,22 @@ class SpanContextValueWriter : public dd::DictWriter { public: explicit SpanContextValueWriter( - std::unordered_map& span_context_expansion, std::string& buffer) + std::unordered_map& span_context_expansion, + std::string& buffer) : span_context_expansion_(&span_context_expansion), buffer_(&buffer) {} void set(std::string_view key, std::string_view value) override { buffer_->clear(); - std::transform(key.begin(), key.end(), std::back_inserter(*buffer_), header_transform_char); + std::transform(key.begin(), key.end(), std::back_inserter(*buffer_), + header_transform_char); span_context_expansion_->insert_or_assign(*buffer_, value); } }; } // namespace -void PropagationHeaderQuerier::expand_values(ngx_http_request_t* request, const dd::Span& span) { +void PropagationHeaderQuerier::expand_values(ngx_http_request_t* request, + const dd::Span& span) { dd::InjectionOptions options; auto loc_conf = static_cast( ngx_http_get_module_loc_conf(request, ngx_http_datadog_module)); @@ -76,12 +80,15 @@ void PropagationHeaderQuerier::expand_values(ngx_http_request_t* request, const } else if (str(subrequest_delegation) == "off") { delegation = ngx_string("off"); } else { - const auto& directive = loc_conf->allow_sampling_delegation_in_subrequests_directive; + const auto& directive = + loc_conf->allow_sampling_delegation_in_subrequests_directive; ngx_log_error(NGX_LOG_ERR, request->connection->log, 0, - "Condition expression for %V directive at %V:%d evaluated to unexpected value " - "\"%V\". Expected \"on\" or \"off\". Proceeding as if the value were \"off\".", - &directive.directive_name, &directive.file_name, directive.line, - &subrequest_delegation); + "Condition expression for %V directive at %V:%d evaluated " + "to unexpected value " + "\"%V\". Expected \"on\" or \"off\". Proceeding as if the " + "value were \"off\".", + &directive.directive_name, &directive.file_name, + directive.line, &subrequest_delegation); delegation = ngx_string("off"); } } else { @@ -94,7 +101,8 @@ void PropagationHeaderQuerier::expand_values(ngx_http_request_t* request, const const dd::Optional previous_decision = span.trace_segment().sampling_decision(); const bool already_delegated = - previous_decision && previous_decision->origin == dd::SamplingDecision::Origin::DELEGATED; + previous_decision && + previous_decision->origin == dd::SamplingDecision::Origin::DELEGATED; if (already_delegated) { options.delegate_sampling_decision = false; @@ -107,11 +115,13 @@ void PropagationHeaderQuerier::expand_values(ngx_http_request_t* request, const // configuration will be used instead. } else { const auto& directive = loc_conf->sampling_delegation_directive; - ngx_log_error( - NGX_LOG_ERR, request->connection->log, 0, - "Condition expression for %V directive at %V:%d evaluated to unexpected value " - "\"%V\". Expected \"on\" or \"off\". Proceeding as if the directive were absent.", - &directive.directive_name, &directive.file_name, directive.line, &delegation); + ngx_log_error(NGX_LOG_ERR, request->connection->log, 0, + "Condition expression for %V directive at %V:%d evaluated to " + "unexpected value " + "\"%V\". Expected \"on\" or \"off\". Proceeding as if the " + "directive were absent.", + &directive.directive_name, &directive.file_name, + directive.line, &delegation); } values_span_ = &span; diff --git a/src/propagation_header_querier.h b/src/propagation_header_querier.h index e1d089d1..3a885b08 100644 --- a/src/propagation_header_querier.h +++ b/src/propagation_header_querier.h @@ -24,7 +24,8 @@ class PropagationHeaderQuerier { public: PropagationHeaderQuerier() noexcept {} - ngx_str_t lookup_value(ngx_http_request_t* request, const dd::Span& span, std::string_view key); + ngx_str_t lookup_value(ngx_http_request_t* request, const dd::Span& span, + std::string_view key); private: const dd::Span* values_span_ = nullptr; diff --git a/src/request_tracing.cpp b/src/request_tracing.cpp index 051c1d4d..75de5254 100644 --- a/src/request_tracing.cpp +++ b/src/request_tracing.cpp @@ -24,18 +24,18 @@ namespace datadog { namespace nginx { -static std::string get_loc_operation_name(ngx_http_request_t *request, - const ngx_http_core_loc_conf_t *core_loc_conf, - const datadog_loc_conf_t *loc_conf) { +static std::string get_loc_operation_name( + ngx_http_request_t *request, const ngx_http_core_loc_conf_t *core_loc_conf, + const datadog_loc_conf_t *loc_conf) { if (loc_conf->loc_operation_name_script.is_valid()) return to_string(loc_conf->loc_operation_name_script.run(request)); else return to_string(core_loc_conf->name); } -static std::string get_request_operation_name(ngx_http_request_t *request, - const ngx_http_core_loc_conf_t *core_loc_conf, - const datadog_loc_conf_t *loc_conf) { +static std::string get_request_operation_name( + ngx_http_request_t *request, const ngx_http_core_loc_conf_t *core_loc_conf, + const datadog_loc_conf_t *loc_conf) { if (loc_conf->operation_name_script.is_valid()) return to_string(loc_conf->operation_name_script.run(request)); else @@ -51,8 +51,8 @@ static std::string get_loc_resource_name(ngx_http_request_t *request, } } -static std::string get_request_resource_name(ngx_http_request_t *request, - const datadog_loc_conf_t *loc_conf) { +static std::string get_request_resource_name( + ngx_http_request_t *request, const datadog_loc_conf_t *loc_conf) { if (loc_conf->resource_name_script.is_valid()) { return to_string(loc_conf->resource_name_script.run(request)); } else { @@ -60,7 +60,8 @@ static std::string get_request_resource_name(ngx_http_request_t *request, } } -static void add_script_tags(ngx_array_t *tags, ngx_http_request_t *request, dd::Span &span) { +static void add_script_tags(ngx_array_t *tags, ngx_http_request_t *request, + dd::Span &span) { if (!tags) return; auto add_tag = [&](const datadog_tag_t &tag) { auto key = tag.key_script.run(request); @@ -82,7 +83,8 @@ static void add_status_tags(const ngx_http_request_t *request, dd::Span &span) { } } -static void add_upstream_name(const ngx_http_request_t *request, dd::Span &span) { +static void add_upstream_name(const ngx_http_request_t *request, + dd::Span &span) { if (!request->upstream || !request->upstream->upstream || !request->upstream->upstream->host.data) return; @@ -93,11 +95,12 @@ static void add_upstream_name(const ngx_http_request_t *request, dd::Span &span) // Convert the epoch denoted by epoch_seconds, epoch_milliseconds to an // std::chrono::system_clock::time_point duration from the epoch. -static std::chrono::system_clock::time_point to_system_timestamp(time_t epoch_seconds, - ngx_msec_t epoch_milliseconds) { - auto epoch_duration = - std::chrono::seconds{epoch_seconds} + std::chrono::milliseconds{epoch_milliseconds}; - return std::chrono::system_clock::from_time_t(std::time_t{0}) + epoch_duration; +static std::chrono::system_clock::time_point to_system_timestamp( + time_t epoch_seconds, ngx_msec_t epoch_milliseconds) { + auto epoch_duration = std::chrono::seconds{epoch_seconds} + + std::chrono::milliseconds{epoch_milliseconds}; + return std::chrono::system_clock::from_time_t(std::time_t{0}) + + epoch_duration; } // dd-trace-cpp uses steady time to calculate span duration, but nginx provides @@ -107,7 +110,8 @@ static std::chrono::system_clock::time_point to_system_timestamp(time_t epoch_se // system time. // Return a `dd::TimePoint` containing the specified system (wall) time // (`before`) and the calculated steady (tick) time. -static dd::TimePoint estimate_past_time_point(std::chrono::system_clock::time_point before) { +static dd::TimePoint estimate_past_time_point( + std::chrono::system_clock::time_point before) { dd::TimePoint now = dd::default_clock(); const auto elapsed = now.wall - before; @@ -127,7 +131,8 @@ static dd::TimePoint estimate_past_time_point(std::chrono::system_clock::time_po // `datadog_sample_rate` directive. A sampling rule previously configured in the // tracer will then match on the tag value and apply the sample rate from the // `datadog_sample_rate` directive. -void set_sample_rate_tag(ngx_http_request_t *request, datadog_loc_conf_t *conf, dd::Span &span) { +void set_sample_rate_tag(ngx_http_request_t *request, datadog_loc_conf_t *conf, + dd::Span &span) { do { for (const datadog_sample_rate_condition_t &rate : conf->sample_rates) { const ngx_str_t expression = rate.condition.run(request); @@ -137,9 +142,12 @@ void set_sample_rate_tag(ngx_http_request_t *request, datadog_loc_conf_t *conf, } if (str(expression) != "off") { ngx_log_error(NGX_LOG_ERR, request->connection->log, 0, - "Condition expression for %V directive at %s evaluated to unexpected value " - "\"%V\". Expected \"on\" or \"off\". Proceeding as if it were \"off\".", - &rate.directive.directive_name, rate.tag_value().c_str(), &expression); + "Condition expression for %V directive at %s evaluated " + "to unexpected value " + "\"%V\". Expected \"on\" or \"off\". Proceeding as if it " + "were \"off\".", + &rate.directive.directive_name, rate.tag_value().c_str(), + &expression); } } @@ -167,7 +175,8 @@ RequestTracing::RequestTracing(ngx_http_request_t *request, "starting Datadog request span for %p", request_); dd::SpanConfig config; - auto start_timestamp = to_system_timestamp(request->start_sec, request->start_msec); + auto start_timestamp = + to_system_timestamp(request->start_sec, request->start_msec); config.start = estimate_past_time_point(start_timestamp); config.name = get_request_operation_name(request_, core_loc_conf_, loc_conf_); @@ -190,9 +199,10 @@ RequestTracing::RequestTracing(ngx_http_request_t *request, NgxHeaderReader reader{request}; auto maybe_span = tracer->extract_or_create_span(reader, config); if (auto *error = maybe_span.if_error()) { - ngx_log_error(NGX_LOG_ERR, request->connection->log, 0, - "failed to extract a Datadog span request %p: [error code %d]: %s", request, - error->code, error->message.c_str()); + ngx_log_error( + NGX_LOG_ERR, request->connection->log, 0, + "failed to extract a Datadog span request %p: [error code %d]: %s", + request, error->code, error->message.c_str()); } else { request_span_.emplace(std::move(*maybe_span)); } @@ -207,9 +217,10 @@ RequestTracing::RequestTracing(ngx_http_request_t *request, } if (loc_conf_->enable_locations) { - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, request_->connection->log, 0, - "starting Datadog location span for \"%V\"(%p) in request %p", - &core_loc_conf->name, loc_conf_, request_); + ngx_log_debug3( + NGX_LOG_DEBUG_HTTP, request_->connection->log, 0, + "starting Datadog location span for \"%V\"(%p) in request %p", + &core_loc_conf->name, loc_conf_, request_); dd::SpanConfig config; config.name = get_loc_operation_name(request_, core_loc_conf_, loc_conf_); span_.emplace(request_span_->create_child(config)); @@ -227,9 +238,10 @@ void RequestTracing::on_change_block(ngx_http_core_loc_conf_t *core_loc_conf, loc_conf_ = loc_conf; if (loc_conf->enable_locations) { - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, request_->connection->log, 0, - "starting Datadog location span for \"%V\"(%p) in request %p", - &core_loc_conf->name, loc_conf_, request_); + ngx_log_debug3( + NGX_LOG_DEBUG_HTTP, request_->connection->log, 0, + "starting Datadog location span for \"%V\"(%p) in request %p", + &core_loc_conf->name, loc_conf_, request_); dd::SpanConfig config; config.name = get_loc_operation_name(request_, core_loc_conf, loc_conf); assert(request_span_); // postcondition of our constructor @@ -249,13 +261,15 @@ dd::Span &RequestTracing::active_span() { } } -void RequestTracing::on_exit_block(std::chrono::steady_clock::time_point finish_timestamp) { +void RequestTracing::on_exit_block( + std::chrono::steady_clock::time_point finish_timestamp) { // Set default and custom tags for the block. Many nginx variables won't be // available when a block is first entered, so set tags when the block is // exited instead. if (loc_conf_->enable_locations) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, request_->connection->log, 0, - "finishing Datadog location span for %p in request %p", loc_conf_, request_); + "finishing Datadog location span for %p in request %p", + loc_conf_, request_); add_script_tags(main_conf_->tags, request_, *span_); add_script_tags(loc_conf_->tags, request_, *span_); add_status_tags(request_, *span_); @@ -266,7 +280,8 @@ void RequestTracing::on_exit_block(std::chrono::steady_clock::time_point finish_ // so evaluate them again. // // See on_log_request below - span_->set_name(get_loc_operation_name(request_, core_loc_conf_, loc_conf_)); + span_->set_name( + get_loc_operation_name(request_, core_loc_conf_, loc_conf_)); span_->set_resource_name(get_loc_resource_name(request_, loc_conf_)); span_->set_end_time(finish_timestamp); } else { @@ -295,8 +310,10 @@ void RequestTracing::on_log_request() { // with resource name. auto core_loc_conf = static_cast( ngx_http_get_module_loc_conf(request_, ngx_http_core_module)); - request_span_->set_name(get_request_operation_name(request_, core_loc_conf, loc_conf_)); - request_span_->set_resource_name(get_request_resource_name(request_, loc_conf_)); + request_span_->set_name( + get_request_operation_name(request_, core_loc_conf, loc_conf_)); + request_span_->set_resource_name( + get_request_resource_name(request_, loc_conf_)); request_span_->set_end_time(finish_timestamp); @@ -313,16 +330,19 @@ void RequestTracing::on_log_request() { // once. // // See propagate_datadog_context -ngx_str_t RequestTracing::lookup_propagation_header_variable_value(std::string_view key) { +ngx_str_t RequestTracing::lookup_propagation_header_variable_value( + std::string_view key) { return propagation_header_querier_.lookup_value(request_, active_span(), key); } ngx_str_t RequestTracing::lookup_span_variable_value(std::string_view key) { - return to_ngx_str(request_->pool, TracingLibrary::span_variables().resolve(key, active_span())); + return to_ngx_str(request_->pool, TracingLibrary::span_variables().resolve( + key, active_span())); } ngx_str_t RequestTracing::lookup_sampling_delegation_response_variable_value() { - const ngx_str_t response_header = loc_conf_->response_info_script.run(request_); + const ngx_str_t response_header = + loc_conf_->response_info_script.run(request_); if (response_header.len) { class OneHeaderReader : public dd::DictReader { @@ -338,8 +358,9 @@ ngx_str_t RequestTracing::lookup_sampling_delegation_response_variable_value() { return dd::nullopt; } - void visit(const std::function &visitor) - const override { + void visit( + const std::function + &visitor) const override { visitor("x-datadog-trace-sampling-decision", str(value_)); } } reader{response_header}; @@ -349,7 +370,9 @@ ngx_str_t RequestTracing::lookup_sampling_delegation_response_variable_value() { struct OneHeaderWriter : public dd::DictWriter { std::string value_; - void set(dd::StringView /*key*/, dd::StringView value) override { value_ = value; } + void set(dd::StringView /*key*/, dd::StringView value) override { + value_ = value; + } ~OneHeaderWriter() {} } writer; diff --git a/src/request_tracing.h b/src/request_tracing.h index ca752a0d..ee074520 100644 --- a/src/request_tracing.h +++ b/src/request_tracing.h @@ -22,10 +22,12 @@ namespace nginx { class RequestTracing { public: - RequestTracing(ngx_http_request_t *request, ngx_http_core_loc_conf_t *core_loc_conf, + RequestTracing(ngx_http_request_t *request, + ngx_http_core_loc_conf_t *core_loc_conf, datadog_loc_conf_t *loc_conf, dd::Span *parent = nullptr); - void on_change_block(ngx_http_core_loc_conf_t *core_loc_conf, datadog_loc_conf_t *loc_conf); + void on_change_block(ngx_http_core_loc_conf_t *core_loc_conf, + datadog_loc_conf_t *loc_conf); void on_log_request(); diff --git a/src/string_util.h b/src/string_util.h index 7806fb9e..3d3aadf0 100644 --- a/src/string_util.h +++ b/src/string_util.h @@ -33,9 +33,13 @@ inline ngx_str_t to_ngx_str(std::string_view s) { return result; } -inline char to_upper(unsigned char c) { return static_cast(std::toupper(c)); } +inline char to_upper(unsigned char c) { + return static_cast(std::toupper(c)); +} -inline char to_lower(unsigned char c) { return static_cast(std::tolower(c)); } +inline char to_lower(unsigned char c) { + return static_cast(std::tolower(c)); +} inline char hyphen_to_underscore(char c) { if (c == '-') return '_'; @@ -44,17 +48,22 @@ inline char hyphen_to_underscore(char c) { // Perform the transformations on header characters described by // http://nginx.org/en/docs/http/ngx_http_core_module.html#var_http_ -inline char header_transform_char(char c) { return to_lower(hyphen_to_underscore(c)); } +inline char header_transform_char(char c) { + return to_lower(hyphen_to_underscore(c)); +} -inline bool starts_with(const std::string_view& subject, const std::string_view& prefix) { +inline bool starts_with(const std::string_view& subject, + const std::string_view& prefix) { if (prefix.size() > subject.size()) { return false; } - return std::mismatch(subject.begin(), subject.end(), prefix.begin()).second == prefix.end(); + return std::mismatch(subject.begin(), subject.end(), prefix.begin()).second == + prefix.end(); } -inline std::string_view slice(const std::string_view& text, int begin, int end) { +inline std::string_view slice(const std::string_view& text, int begin, + int end) { if (begin < 0) { begin += text.size(); } diff --git a/src/tracing_library.cpp b/src/tracing_library.cpp index ab1e1010..6fa1d30c 100644 --- a/src/tracing_library.cpp +++ b/src/tracing_library.cpp @@ -35,13 +35,15 @@ std::string_view or_default(std::string_view config_json) { } // namespace -dd::Expected TracingLibrary::make_tracer(const datadog_main_conf_t& nginx_conf) { +dd::Expected TracingLibrary::make_tracer( + const datadog_main_conf_t& nginx_conf) { dd::TracerConfig config; config.logger = std::make_shared(); config.agent.event_scheduler = std::make_shared(); if (!nginx_conf.propagation_styles.empty()) { - config.injection_styles = config.extraction_styles = nginx_conf.propagation_styles; + config.injection_styles = config.extraction_styles = + nginx_conf.propagation_styles; } if (nginx_conf.service_name) { @@ -87,8 +89,10 @@ dd::Expected TracingLibrary::make_tracer(const datadog_main_conf_t& return dd::Tracer(*final_config); } -dd::Expected> TracingLibrary::propagation_header_names( - const std::vector& configured_styles, dd::Logger& logger) { +dd::Expected> +TracingLibrary::propagation_header_names( + const std::vector& configured_styles, + dd::Logger& logger) { std::vector result; // Create a tracer config that contains `configured_styles` (or the default @@ -109,12 +113,16 @@ dd::Expected> TracingLibrary::propagation_header_n return std::move(*error); } - if (!configured_styles.empty() && configured_styles != finalized_config->injection_styles) { + if (!configured_styles.empty() && + configured_styles != finalized_config->injection_styles) { logger.log_error([&](std::ostream& log) { - log << "Actual injection propagation styles differ from that specified in the nginx " - "configuration. The datadog_propagation_styles directive indicated the values " + log << "Actual injection propagation styles differ from that specified " + "in the nginx " + "configuration. The datadog_propagation_styles directive " + "indicated the values " << dd::to_json(configured_styles) - << ", but after applying environment variables, the final values are instead " + << ", but after applying environment variables, the final values are " + "instead " << dd::to_json(finalized_config->injection_styles); }); } @@ -152,13 +160,17 @@ std::string_view TracingLibrary::propagation_header_variable_name_prefix() { return "datadog_propagation_header_"; } -std::string_view TracingLibrary::environment_variable_name_prefix() { return "datadog_env_"; } +std::string_view TracingLibrary::environment_variable_name_prefix() { + return "datadog_env_"; +} std::string_view TracingLibrary::configuration_json_variable_name() { return "datadog_config_json"; } -std::string_view TracingLibrary::location_variable_name() { return "datadog_location"; } +std::string_view TracingLibrary::location_variable_name() { + return "datadog_location"; +} std::string_view TracingLibrary::proxy_directive_variable_name() { return "datadog_proxy_directive"; @@ -205,8 +217,9 @@ NginxVariableFamily TracingLibrary::span_variables() { } std::vector TracingLibrary::environment_variable_names() { - return std::vector{std::begin(dd::environment::variable_names), - std::end(dd::environment::variable_names)}; + return std::vector{ + std::begin(dd::environment::variable_names), + std::end(dd::environment::variable_names)}; } std::string_view TracingLibrary::default_request_operation_name_pattern() { @@ -217,7 +230,8 @@ std::string_view TracingLibrary::default_location_operation_name_pattern() { return "nginx.$datadog_proxy_directive"; } -std::unordered_map TracingLibrary::default_tags() { +std::unordered_map +TracingLibrary::default_tags() { return { // originally defined by nginx-opentracing {"component", "nginx"}, @@ -234,7 +248,9 @@ std::unordered_map TracingLibrary::default_t {"nginx.location", "$datadog_location"}}; } -std::string_view TracingLibrary::default_resource_name_pattern() { return "$request_method $uri"; } +std::string_view TracingLibrary::default_resource_name_pattern() { + return "$request_method $uri"; +} bool TracingLibrary::tracing_on_by_default() { return true; } diff --git a/test/bin/format b/test/bin/format deleted file mode 100755 index 08711c72..00000000 --- a/test/bin/format +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -test_dir=$(dirname "$(dirname "$0")") -yapf3 --recursive --in-place "$@" "$test_dir" From 75b1eb347d2153d5e9ec232ea12224c0bc4d2c3d Mon Sep 17 00:00:00 2001 From: David Goffredo Date: Wed, 24 Jan 2024 15:16:20 -0500 Subject: [PATCH 2/7] lint.sh: error status on bad formatting, but run all of them --- bin/lint.sh | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/bin/lint.sh b/bin/lint.sh index 8767ab04..039f46e3 100755 --- a/bin/lint.sh +++ b/bin/lint.sh @@ -1,8 +1,28 @@ #!/bin/sh -# Lint the codebase and returns all encountered discrepencies -# with our codestyle +# Print any discrepancies between the formatting of the code and the expected +# style. + +error_messages='' find src/ -type f \( -name '*.h' -o -name '*.cpp' \) -print0 | xargs -0 clang-format-14 --Werror --dry-run --style=file +rc=$? +if [ "$rc" -ne 0 ]; then + error_messages=$(printf '%s\nC++ formatter reported formatting differences in src/ and returned error status %d.\n' "$error_messages" "$rc") +fi + find bin/ -type f -name '*.py' -print0 | xargs -0 yapf3 --diff +rc=$? +if [ "$rc" -ne 0 ]; then + error_messages=$(printf '%s\nPython formatter reported formatting differences in bin/ and returned error status %d.\n' "$error_messages" "$rc") +fi yapf3 --recursive --diff "$@" "test/" +rc=$? +if [ "$rc" -ne 0 ]; then + error_messages=$(printf '%s\nPython formatter reported formatting differences in test/ and returned error status %d.\n' "$error_messages" "$rc") +fi + +if [ -n "$error_messages" ]; then + >&2 echo "$error_messages" + exit 1 +fi From be60e907ef43f88946f399e7c286ae662b8c3cfc Mon Sep 17 00:00:00 2001 From: David Goffredo Date: Wed, 24 Jan 2024 15:56:55 -0500 Subject: [PATCH 3/7] use a symlink for .clang-format --- .clang-format | 1 + .gitignore | 3 --- Makefile | 6 +++--- bin/format.sh | 7 ++++++- bin/lint.sh | 5 +++++ 5 files changed, 15 insertions(+), 7 deletions(-) create mode 120000 .clang-format diff --git a/.clang-format b/.clang-format new file mode 120000 index 00000000..18dd1664 --- /dev/null +++ b/.clang-format @@ -0,0 +1 @@ +dd-trace-cpp/.clang-format \ No newline at end of file diff --git a/.gitignore b/.gitignore index 16117da4..7e174ca1 100644 --- a/.gitignore +++ b/.gitignore @@ -10,9 +10,6 @@ .*.sw? .vscode/ -# clang-format config copied from dd-opentracing-cpp (see `make format`) -/.clang-format - # file used as part of the build configuration /nginx-version-info diff --git a/Makefile b/Makefile index 065e1df6..de506ef2 100644 --- a/Makefile +++ b/Makefile @@ -44,14 +44,14 @@ nginx-version-info: dd-trace-cpp/.clang-format: dd-trace-cpp/.git .clang-format: dd-trace-cpp/.clang-format - cp $< $@ .PHONY: format format: .clang-format - ./bin/format.sh + bin/format.sh +.PHONY: lint lint: .clang-format - ./bin/lint.sh + bin/lint.sh .PHONY: clean clean: diff --git a/bin/format.sh b/bin/format.sh index 9fa87b1e..e6694dbc 100755 --- a/bin/format.sh +++ b/bin/format.sh @@ -1,5 +1,10 @@ #!/bin/sh -# Format the codebase to follow our codestyle +# Format the codebase to follow this project's style. + +if ! [ -e .clang-format ]; then + >&2 echo '.clang-format file is missing. Run "make format".' + exit 1 +fi find src/ -type f \( -name '*.h' -o -name '*.cpp' \) -print0 | xargs -0 clang-format-14 -i --style=file find bin/ -type f -name '*.py' -print0 | xargs -0 yapf3 -i diff --git a/bin/lint.sh b/bin/lint.sh index 039f46e3..74cfbaf9 100755 --- a/bin/lint.sh +++ b/bin/lint.sh @@ -2,6 +2,11 @@ # Print any discrepancies between the formatting of the code and the expected # style. +if ! [ -e .clang-format ]; then + >&2 echo '.clang-format file is missing. Run "make lint".' + exit 1 +fi + error_messages='' find src/ -type f \( -name '*.h' -o -name '*.cpp' \) -print0 | xargs -0 clang-format-14 --Werror --dry-run --style=file From ee1943cde8d770a7ca0b1d5f6ca800bb0811dae4 Mon Sep 17 00:00:00 2001 From: David Goffredo Date: Wed, 24 Jan 2024 15:57:33 -0500 Subject: [PATCH 4/7] run `make format` --- src/tracing_library.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/tracing_library.cpp b/src/tracing_library.cpp index 0ea6145e..5a8eb111 100644 --- a/src/tracing_library.cpp +++ b/src/tracing_library.cpp @@ -35,7 +35,8 @@ std::string_view or_default(std::string_view config_json) { } // namespace -dd::Expected TracingLibrary::make_tracer(const datadog_main_conf_t &nginx_conf) { +dd::Expected TracingLibrary::make_tracer( + const datadog_main_conf_t &nginx_conf) { dd::TracerConfig config; config.logger = std::make_shared(); config.agent.event_scheduler = std::make_shared(); @@ -90,8 +91,10 @@ dd::Expected TracingLibrary::make_tracer(const datadog_main_conf_t & return dd::Tracer(*final_config); } -dd::Expected> TracingLibrary::propagation_header_names( - const std::vector &configured_styles, dd::Logger &logger) { +dd::Expected> +TracingLibrary::propagation_header_names( + const std::vector &configured_styles, + dd::Logger &logger) { std::vector result; // Create a tracer config that contains `configured_styles` (or the default @@ -112,7 +115,8 @@ dd::Expected> TracingLibrary::propagation_header_n return std::move(*error); } - if (!configured_styles.empty() && configured_styles != finalized_config->injection_styles) { + if (!configured_styles.empty() && + configured_styles != finalized_config->injection_styles) { logger.log_error([&](std::ostream &log) { log << "Actual injection propagation styles differ from that specified " "in the nginx " From 6fef4c2365d4f4325dbd8f214de4c556a9b114e9 Mon Sep 17 00:00:00 2001 From: David Goffredo Date: Wed, 24 Jan 2024 17:30:18 -0500 Subject: [PATCH 5/7] CI: combine submodule update and lint, via make --- .circleci/config.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 83567ae0..e218c0e1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -123,12 +123,9 @@ jobs: resource_class: small steps: - checkout - - run: git submodule update --init --recursive - run: name: Lint - command: | - cp dd-trace-cpp/.clang-format .clang-format - bin/lint.sh + command: make lint shellcheck: docker: From 55c7d8e18003217c16520b888ec74bca96650cb9 Mon Sep 17 00:00:00 2001 From: Damien Mehala Date: Thu, 25 Jan 2024 12:43:25 +0100 Subject: [PATCH 6/7] install yapf dep --- .circleci/config.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e218c0e1..3931119b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -124,8 +124,11 @@ jobs: steps: - checkout - run: - name: Lint - command: make lint + name: Install Python dependencies + command: | + pip install yapf + update-alternatives --install /usr/local/bin/yapf3 yapf3 /usr/local/bin/yapf 100 + - run: make lint shellcheck: docker: From fb828bbd9208ee856e7d336fcac926f1151f87bc Mon Sep 17 00:00:00 2001 From: Damien Mehala Date: Thu, 25 Jan 2024 12:46:32 +0100 Subject: [PATCH 7/7] set useless variable because Makefile --- .circleci/config.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3931119b..203c20e0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -128,7 +128,11 @@ jobs: command: | pip install yapf update-alternatives --install /usr/local/bin/yapf3 yapf3 /usr/local/bin/yapf 100 - - run: make lint + - run: + name: Lint + command: | + touch nginx-version-info + make lint shellcheck: docker: