From 4d368d702bc0005ab9e578b096eb6043af61f64a Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Fri, 3 Feb 2023 14:42:15 +0100 Subject: [PATCH] Add a DDTrace\generate_distributed_tracing_headers() function It's a direct opposite function to consume_distributed_tracing_headers, thereby trivially enabling users to use it for custom propoagation and later consumption. Also needed for easy testing of parametric tests. Signed-off-by: Bob Weinand --- ext/ddtrace.c | 10 ++++ ext/handlers_curl.c | 2 +- ext/handlers_http.h | 56 +++++++++++-------- .../distributed_trace_generate.phpt | 29 ++++++++++ 4 files changed, 72 insertions(+), 25 deletions(-) create mode 100644 tests/ext/distributed_tracing/distributed_trace_generate.phpt diff --git a/ext/ddtrace.c b/ext/ddtrace.c index b48d8f2c657..e2abc4a5786 100644 --- a/ext/ddtrace.c +++ b/ext/ddtrace.c @@ -39,6 +39,7 @@ #include "dogstatsd_client.h" #include "engine_hooks.h" #include "excluded_modules.h" +#include "handlers_http.h" #include "handlers_internal.h" #include "integrations/integrations.h" #include "ip_extraction.h" @@ -2005,6 +2006,14 @@ static PHP_FUNCTION(consume_distributed_tracing_headers) { RETURN_NULL(); } +/* {{{ proto array generate_distributed_tracing_headers() */ +static PHP_FUNCTION(generate_distributed_tracing_headers) { + UNUSED(execute_data); + + array_init(return_value); + ddtrace_inject_distributed_headers(Z_ARR_P(return_value), true); +} + /* {{{ proto string dd_trace_closed_spans_count() */ static PHP_FUNCTION(dd_trace_closed_spans_count) { UNUSED(execute_data); @@ -2126,6 +2135,7 @@ static const zend_function_entry ddtrace_functions[] = { DDTRACE_NS_FE(current_context, arginfo_ddtrace_void), DDTRACE_NS_FE(set_distributed_tracing_context, arginfo_dd_trace_set_distributed_tracing_context), DDTRACE_NS_FE(consume_distributed_tracing_headers, arginfo_consume_distributed_tracing_headers), + DDTRACE_NS_FE(generate_distributed_tracing_headers, arginfo_ddtrace_void), DDTRACE_FE(dd_trace_reset, arginfo_ddtrace_void), DDTRACE_FE(dd_trace_send_traces_via_thread, arginfo_dd_trace_send_traces_via_thread), DDTRACE_FE(dd_trace_serialize_closed_spans, arginfo_ddtrace_void), diff --git a/ext/handlers_curl.c b/ext/handlers_curl.c index d901256b3d7..8d58b08985e 100644 --- a/ext/handlers_curl.c +++ b/ext/handlers_curl.c @@ -77,7 +77,7 @@ static void dd_inject_distributed_tracing_headers(zend_object *ch) { array_init(&headers); } - ddtrace_inject_distributed_headers(Z_ARR(headers)); + ddtrace_inject_distributed_headers(Z_ARR(headers), false); zend_function *setopt_fn = zend_hash_str_find_ptr(EG(function_table), ZEND_STRL("curl_setopt")); diff --git a/ext/handlers_http.h b/ext/handlers_http.h index f310f2e0b65..0d060971367 100644 --- a/ext/handlers_http.h +++ b/ext/handlers_http.h @@ -7,10 +7,17 @@ ZEND_EXTERN_MODULE_GLOBALS(ddtrace); -static inline void ddtrace_inject_distributed_headers(zend_array *array) { +static inline void ddtrace_inject_distributed_headers(zend_array *array, bool key_value_pairs) { zval headers; ZVAL_ARR(&headers, array); +#define ADD_HEADER(header, ...) \ + if (key_value_pairs) { \ + add_assoc_str_ex(&headers, ZEND_STRL(header), zend_strpprintf(0, __VA_ARGS__)); \ + } else { \ + add_next_index_str(&headers, zend_strpprintf(0, header ": " __VA_ARGS__)); \ + } + zend_array *inject = zai_config_is_modified(DDTRACE_CONFIG_DD_TRACE_PROPAGATION_STYLE) && !zai_config_is_modified(DDTRACE_CONFIG_DD_TRACE_PROPAGATION_STYLE_INJECT) ? get_DD_TRACE_PROPAGATION_STYLE() : get_DD_TRACE_PROPAGATION_STYLE_INJECT(); @@ -23,54 +30,53 @@ static inline void ddtrace_inject_distributed_headers(zend_array *array) { zend_long sampling_priority = ddtrace_fetch_prioritySampling_from_root(); if (sampling_priority != DDTRACE_PRIORITY_SAMPLING_UNKNOWN) { if (send_datadog) { - add_next_index_str(&headers, - zend_strpprintf(0, "x-datadog-sampling-priority: " ZEND_LONG_FMT, sampling_priority)); + ADD_HEADER("x-datadog-sampling-priority", ZEND_LONG_FMT, sampling_priority); } if (send_b3) { if (sampling_priority <= 0) { - add_next_index_string(&headers, "X-B3-Sampled: 0"); + ADD_HEADER("x-b3-sampled", "0"); } else if (sampling_priority == PRIORITY_SAMPLING_USER_KEEP) { - add_next_index_string(&headers, "X-B3-Flags: 1"); + ADD_HEADER("x-b3-flags", "1"); } else { - add_next_index_string(&headers, "X-B3-Sampled: 1"); + ADD_HEADER("x-b3-sampled", "1"); } } } zend_string *propagated_tags = ddtrace_format_propagated_tags(); if (send_datadog || send_b3 || send_b3single) { if (propagated_tags) { - add_next_index_str(&headers, zend_strpprintf(0, "x-datadog-tags: %s", ZSTR_VAL(propagated_tags))); + ADD_HEADER("x-datadog-tags", "%s", ZSTR_VAL(propagated_tags)); } if (DDTRACE_G(dd_origin)) { - add_next_index_str(&headers, zend_strpprintf(0, "x-datadog-origin: %s", ZSTR_VAL(DDTRACE_G(dd_origin)))); + ADD_HEADER("x-datadog-origin", "%s", ZSTR_VAL(DDTRACE_G(dd_origin))); } } ddtrace_trace_id trace_id = ddtrace_peek_trace_id(); uint64_t span_id = ddtrace_peek_span_id(); if (trace_id.low || trace_id.high) { if (send_datadog) { - add_next_index_str(&headers, zend_strpprintf(0, "x-datadog-trace-id: %" PRIu64, trace_id.low)); + ADD_HEADER("x-datadog-trace-id", "%" PRIu64, trace_id.low); } if (send_b3) { if (trace_id.high) { - add_next_index_str(&headers, zend_strpprintf(0, "X-B3-TraceId: %016" PRIx64 "%016" PRIx64, trace_id.high, trace_id.low)); + ADD_HEADER("X-B3-TraceId", "%016" PRIx64 "%016" PRIx64, trace_id.high, trace_id.low); } else { - add_next_index_str(&headers, zend_strpprintf(0, "X-B3-TraceId: %016" PRIx64, trace_id.low)); + ADD_HEADER("X-B3-TraceId", "%016" PRIx64, trace_id.low); } } if (span_id) { if (send_datadog) { - add_next_index_str(&headers, zend_strpprintf(0, "x-datadog-parent-id: %" PRIu64, span_id)); + ADD_HEADER("x-datadog-parent-id", "%" PRIu64, span_id); } if (send_b3) { - add_next_index_str(&headers, zend_strpprintf(0, "X-B3-SpanId: %016" PRIx64, span_id)); + ADD_HEADER("X-B3-SpanId", "%016" PRIx64, span_id); } if (send_tracestate) { - add_next_index_str(&headers, zend_strpprintf(0, "traceparent: 00-%016" PRIx64 "%016" PRIx64 "-%016" PRIx64 "-%02" PRIx8, - trace_id.high, - trace_id.low, - span_id, - sampling_priority > 0)); + ADD_HEADER("traceparent", "00-%016" PRIx64 "%016" PRIx64 "-%016" PRIx64 "-%02" PRIx8, + trace_id.high, + trace_id.low, + span_id, + sampling_priority > 0); smart_str str = {0}; @@ -138,7 +144,7 @@ static inline void ddtrace_inject_distributed_headers(zend_array *array) { } if (str.s) { - add_next_index_str(&headers, zend_strpprintf(0, "tracestate: %s%.*s", hasdd ? "dd=" : "", (int)ZSTR_LEN(str.s), ZSTR_VAL(str.s))); + ADD_HEADER("tracestate", "%s%.*s", hasdd ? "dd=" : "", (int)ZSTR_LEN(str.s), ZSTR_VAL(str.s)); smart_str_free(&str); } } @@ -163,12 +169,12 @@ static inline void ddtrace_inject_distributed_headers(zend_array *array) { } else { sprintf(trace_id_buf, "%016" PRIx64, trace_id.low); } - add_next_index_str(&headers, zend_strpprintf(0, "b3: %s-%016" PRIx64 "%s%s", - trace_id_buf, - span_id, - b3_sampling_decision ? "-" : "", b3_sampling_decision ? b3_sampling_decision : "")); + ADD_HEADER("b3", "%s-%016" PRIx64 "%s%s", + trace_id_buf, + span_id, + b3_sampling_decision ? "-" : "", b3_sampling_decision ? b3_sampling_decision : ""); } else if (b3_sampling_decision) { - add_next_index_str(&headers, zend_strpprintf(0, "b3: %s", b3_sampling_decision)); + ADD_HEADER("b3", "%s", b3_sampling_decision); } } @@ -176,3 +182,5 @@ static inline void ddtrace_inject_distributed_headers(zend_array *array) { zend_string_release(propagated_tags); } } + +#undef ADD_HEADER diff --git a/tests/ext/distributed_tracing/distributed_trace_generate.phpt b/tests/ext/distributed_tracing/distributed_trace_generate.phpt new file mode 100644 index 00000000000..53b70096a2c --- /dev/null +++ b/tests/ext/distributed_tracing/distributed_trace_generate.phpt @@ -0,0 +1,29 @@ +--TEST-- +Test generate_distributed_tracing_headers() +--ENV-- +HTTP_X_DATADOG_TRACE_ID=42 +HTTP_X_DATADOG_PARENT_ID=10 +HTTP_X_DATADOG_ORIGIN=datadog +HTTP_X_DATADOG_SAMPLING_PRIORITY=3 +DD_TRACE_GENERATE_ROOT_SPAN=0 +--FILE-- + +--EXPECT-- +array(6) { + ["x-datadog-sampling-priority"]=> + string(1) "3" + ["x-datadog-origin"]=> + string(7) "datadog" + ["x-datadog-trace-id"]=> + string(2) "42" + ["x-datadog-parent-id"]=> + string(2) "10" + ["traceparent"]=> + string(55) "00-0000000000000000000000000000002a-000000000000000a-01" + ["tracestate"]=> + string(16) "dd=o:datadog;s:3" +}