diff --git a/ext/compatibility.h b/ext/compatibility.h index 01530f10987..e50e5d73981 100644 --- a/ext/compatibility.h +++ b/ext/compatibility.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "ext/standard/base64.h" @@ -86,6 +87,13 @@ static inline zend_long zval_get_long(zval *op) { } return _zval_get_long(op); } + +#include +#if defined(DBL_MANT_DIG) && defined(DBL_MIN_EXP) +#define PHP_DOUBLE_MAX_LENGTH (3 + DBL_MANT_DIG - DBL_MIN_EXP) +#else +#define PHP_DOUBLE_MAX_LENGTH 1080 +#endif #endif #if PHP_VERSION_ID < 70200 @@ -110,7 +118,6 @@ static zend_always_inline zend_string *zend_string_init_interned(const char *str typedef void zend_type; -#include static inline void smart_str_append_printf(smart_str *dest, const char *format, ...) { va_list arg; va_start(arg, format); @@ -324,6 +331,19 @@ static zend_always_inline zend_result add_next_index_object(zval *arg, zend_obje return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE; } +#include
+#define zend_gcvt php_gcvt +#define ZEND_DOUBLE_MAX_LENGTH PHP_DOUBLE_MAX_LENGTH +static inline void smart_str_append_double(smart_str *str, double num, int precision, bool zero_fraction) { + char buf[ZEND_DOUBLE_MAX_LENGTH]; + /* Model snprintf precision behavior. */ + zend_gcvt(num, precision ? precision : 1, '.', 'E', buf); + smart_str_appends(str, buf); + if (zero_fraction && zend_finite(num) && !strchr(buf, '.')) { + smart_str_appendl(str, ".0", 2); + } +} + #endif #if PHP_VERSION_ID < 80200 @@ -357,6 +377,8 @@ static inline zend_string *ddtrace_strpprintf(size_t max_len, const char *format #undef zend_strpprintf #define zend_strpprintf ddtrace_strpprintf +#define ZEND_HASH_ELEMENT(ht, idx) (&ht->arData[idx].val) + #if PHP_VERSION_ID >= 80000 #define zend_weakrefs_hash_add zend_weakrefs_hash_add_fallback #define zend_weakrefs_hash_del zend_weakrefs_hash_del_fallback diff --git a/ext/priority_sampling/priority_sampling.c b/ext/priority_sampling/priority_sampling.c index e6685ed86ad..6536818bbba 100644 --- a/ext/priority_sampling/priority_sampling.c +++ b/ext/priority_sampling/priority_sampling.c @@ -12,6 +12,7 @@ #include "ddshared.h" #include "ddtrace.h" #include "span.h" +#include "components/log/log.h" ZEND_EXTERN_MODULE_GLOBALS(ddtrace); @@ -154,6 +155,22 @@ void ddtrace_decide_on_closed_span_sampling(ddtrace_span_data *span) { ddtrace_rule_result result = dd_match_rules(span, &root->span == span && !root->parent_id, root->sampling_rule.rule); if (result.rule != INT32_MAX) { + LOGEV(Debug, { + smart_str buf = {0}; + const char *rule_str = ""; + if (result.rule == -2) { + rule_str = "manual.keep"; + } else if (result.rule == -1) { + rule_str = "manual.drop"; + } else { + zval *rule = ZEND_HASH_ELEMENT(get_DD_TRACE_SAMPLING_RULES(), result.rule); + zai_json_encode(&buf, rule, 0); + smart_str_0(&buf); + rule_str = ZSTR_VAL(buf.s); + } + log("Evaluated sampling rules for span %" PRIu64 " on trace %s. Matched rule %s.", span->span_id, Z_STRVAL(span->root->property_trace_id), rule_str); + smart_str_free(&buf); + }); root->sampling_rule = result; } } @@ -182,8 +199,7 @@ static ddtrace_rule_result dd_decide_on_open_span_sampling(ddtrace_root_span_dat static void dd_decide_on_sampling(ddtrace_root_span_data *span) { int priority; bool is_trace_root = !span->parent_id; - // manual if it's not just inherited, otherwise this value is irrelevant (as sampling priority will be default) - enum dd_sampling_mechanism mechanism = DD_MECHANISM_MANUAL; + enum dd_sampling_mechanism mechanism; ddtrace_rule_result result = dd_decide_on_open_span_sampling(span); double sample_rate = 0; @@ -213,6 +229,13 @@ static void dd_decide_on_sampling(ddtrace_root_span_data *span) { if (!sample_rate_zv) { // Default rate if no service+env pair matches sample_rate_zv = zend_hash_str_find(DDTRACE_G(agent_rate_by_service), ZEND_STRL("service:,env:")); + if (sample_rate_zv) { + LOG(Debug, "Evaluated agent sampling rules for root span for trace %s and applied a default sample_rate of %f", + Z_STRVAL(span->property_trace_id), zval_get_double(sample_rate_zv)); + } + } else { + LOG(Debug, "Evaluated agent sampling rules for root span for trace %s (service: %s, env: %s) and found a sample_rate of %f", + Z_STRVAL(span->property_trace_id), Z_STR_P(service), Z_STR_P(env), zval_get_double(sample_rate_zv)); } if (sample_rate_zv) { sample_rate = zval_get_double(sample_rate_zv); @@ -259,6 +282,7 @@ static void dd_decide_on_sampling(ddtrace_root_span_data *span) { zend_hash_str_del(metrics, ZEND_STRL("_dd.agent_psr")); } else { + // manual if it's not just inherited, otherwise this value is irrelevant (as sampling priority will be default) mechanism = DDTRACE_G(agent_rate_by_service) ? DD_MECHANISM_AGENT_RATE : DD_MECHANISM_DEFAULT; priority = sampling && !limited ? PRIORITY_SAMPLING_AUTO_KEEP : PRIORITY_SAMPLING_AUTO_REJECT; diff --git a/ext/serializer.c b/ext/serializer.c index b982718a98b..aaf1d3f1a3e 100644 --- a/ext/serializer.c +++ b/ext/serializer.c @@ -1669,6 +1669,7 @@ void ddtrace_serialize_span_to_array(ddtrace_span_data *span, zval *array) { } ZEND_HASH_FOREACH_END(); smart_str_0(&metrics_str); } + prop_name = zend_hash_str_find(Z_ARR_P(el), ZEND_STRL("name")); // refetch, array may have been rehashed log("Encoding span %" PRIu64 ": trace_id=%s, name='%s', service='%s', resource: '%s', type '%s' with tags: %s; and metrics: %s", span->span_id, Z_STRVAL(span->root->property_trace_id), Z_TYPE_P(prop_name) == IS_STRING ? Z_STRVAL_P(prop_name) : "", diff --git a/libdatadog b/libdatadog index 2a2dc7fe927..fd298acb7ef 160000 --- a/libdatadog +++ b/libdatadog @@ -1 +1 @@ -Subproject commit 2a2dc7fe927331639a55b2e76555087d6faa3e94 +Subproject commit fd298acb7ef91528f6c91d840c3e0a94e36bf3c6 diff --git a/tests/ext/background-sender/default_unix_domain_socket_agent.phpt b/tests/ext/background-sender/default_unix_domain_socket_agent.phpt index ab5f78a272b..c0a08dd4d7c 100644 --- a/tests/ext/background-sender/default_unix_domain_socket_agent.phpt +++ b/tests/ext/background-sender/default_unix_domain_socket_agent.phpt @@ -15,7 +15,7 @@ if (!file_exists("/var/run/datadog/apm.socket")) { RequestReplayer::launchUnixProxy("/var/run/datadog/apm.socket"); } -$logs = dd_get_startup_logs([], ['DD_TRACE_LOG_LEVEL=info,startup=off']); +$logs = dd_get_startup_logs([], ['DD_TRACE_LOG_LEVEL=error,startup=info']); dd_dump_startup_logs($logs, [ 'agent_error', // should be absent diff --git a/tests/ext/close_spans_until.phpt b/tests/ext/close_spans_until.phpt index 311f0626d7b..33f5209ba1d 100644 --- a/tests/ext/close_spans_until.phpt +++ b/tests/ext/close_spans_until.phpt @@ -25,27 +25,27 @@ var_dump(DDTrace\close_spans_until(null)); ?> --EXPECTF-- -[ddtrace] [span] Creating new root SpanStack: 1, parent_stack: 0 -[ddtrace] [span] Creating new root SpanStack: 3, parent_stack: 1 -[ddtrace] [span] Switching to different SpanStack: 3 -[ddtrace] [span] Starting new root span: trace_id=%s, span_id=%d, parent_id=0, SpanStack=3, parent_SpanStack=1 -[ddtrace] [span] Starting new span: trace_id=%s, span_id=%d, parent_id=%d, SpanStack=3 -[ddtrace] [span] Starting new span: trace_id=%s, span_id=%d, parent_id=%d, SpanStack=3 -[ddtrace] [span] Starting new span: trace_id=%s, span_id=%d, parent_id=%d, SpanStack=3 +[ddtrace] [span] Creating new root SpanStack: %d, parent_stack: 0 +[ddtrace] [span] Creating new root SpanStack: %d, parent_stack: %d +[ddtrace] [span] Switching to different SpanStack: %d +[ddtrace] [span] Starting new root span: trace_id=%s, span_id=%d, parent_id=0, SpanStack=%d, parent_SpanStack=%d +[ddtrace] [span] Starting new span: trace_id=%s, span_id=%d, parent_id=%d, SpanStack=%d +[ddtrace] [span] Starting new span: trace_id=%s, span_id=%d, parent_id=%d, SpanStack=%d +[ddtrace] [span] Starting new span: trace_id=%s, span_id=%d, parent_id=%d, SpanStack=%d bool(false) [ddtrace] [span] Closing span: trace_id=%s, span_id=%d [ddtrace] [span] Closing span: trace_id=%s, span_id=%d int(2) -[ddtrace] [span] Starting new span: trace_id=%s, span_id=%d, parent_id=%d, SpanStack=3 -[ddtrace] [span] Starting new span: trace_id=%s, span_id=%d, parent_id=%d, SpanStack=3 -[ddtrace] [span] Starting new span: trace_id=%s, span_id=%d, parent_id=%d, SpanStack=3 +[ddtrace] [span] Starting new span: trace_id=%s, span_id=%d, parent_id=%d, SpanStack=%d +[ddtrace] [span] Starting new span: trace_id=%s, span_id=%d, parent_id=%d, SpanStack=%d +[ddtrace] [span] Starting new span: trace_id=%s, span_id=%d, parent_id=%d, SpanStack=%d [ddtrace] [span] Closing span: trace_id=%s, span_id=%d [ddtrace] [span] Closing span: trace_id=%s, span_id=%d int(2) [ddtrace] [span] Closing span: trace_id=%s, span_id=%d [ddtrace] [span] Closing span: trace_id=%s, span_id=%d [ddtrace] [span] Closing root span: trace_id=%s, span_id=%d -[ddtrace] [span] Switching to different SpanStack: 1 +[ddtrace] [span] Switching to different SpanStack: %d int(1) int(0) [ddtrace] [span] Encoding span %d: trace_id=%s, name='close_spans_until.php', service='close_spans_until.php', resource: 'close_spans_until.php', type 'cli' with tags: runtime-id='%s', _dd.p.dm='-0', _dd.p.tid='%s'; and metrics: process_id='%d', _dd.agent_psr='1', _sampling_priority_v1='1', php.compilation.total_time_ms='%f'