Skip to content

Commit

Permalink
Merge pull request #2384 from DataDog/bob/extended-sampling
Browse files Browse the repository at this point in the history
Implement extended sampling
  • Loading branch information
pierotibou authored Dec 12, 2023
2 parents e33deef + ef2686c commit b7a55c5
Show file tree
Hide file tree
Showing 40 changed files with 784 additions and 200 deletions.
9 changes: 9 additions & 0 deletions ext/compatibility.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,15 @@ static inline zval *ddtrace_assign_variable(zval *variable_ptr, zval *value) {
#define MAY_BE_ARRAY 0

#define Z_EXTRA_P(z) Z_NEXT_P(z)

#undef zval_get_long
#define zval_get_long ddtrace_zval_get_long
static inline zend_long zval_get_long(zval *op) {
if (Z_ISUNDEF_P(op)) {
return 0;
}
return _zval_get_long(op);
}
#endif

#if PHP_VERSION_ID < 70200
Expand Down
13 changes: 13 additions & 0 deletions ext/configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,19 @@ static bool dd_parse_dbm_mode(zai_str value, zval *decoded_value, bool persisten
return true;
}

static bool dd_parse_sampling_rules_format(zai_str value, zval *decoded_value, bool persistent) {
UNUSED(persistent);
if (zai_str_eq_ci_cstr(value, "regex")) {
ZVAL_LONG(decoded_value, DD_TRACE_SAMPLING_RULES_FORMAT_REGEX);
} else if (zai_str_eq_ci_cstr(value, "glob")) {
ZVAL_LONG(decoded_value, DD_TRACE_SAMPLING_RULES_FORMAT_GLOB);
} else {
return false;
}

return true;
}

// Allow for partially defined struct initialization here
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"

Expand Down
7 changes: 7 additions & 0 deletions ext/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ enum ddtrace_dbm_propagation_mode {
DD_TRACE_DBM_PROPAGATION_FULL,
};

// To remove in 1.0
enum ddtrace_sampling_rules_format {
DD_TRACE_SAMPLING_RULES_FORMAT_REGEX,
DD_TRACE_SAMPLING_RULES_FORMAT_GLOB
};

/* From the curl docs on CONNECT_TIMEOUT_MS:
* If libcurl is built to use the standard system name resolver, that
* portion of the transfer will still use full-second resolution for
Expand Down Expand Up @@ -116,6 +122,7 @@ enum ddtrace_dbm_propagation_mode {
CONFIG(INT, DD_TRACE_RATE_LIMIT, "0", .ini_change = zai_config_system_ini_change) \
CALIAS(DOUBLE, DD_TRACE_SAMPLE_RATE, "-1", CALIASES("DD_SAMPLING_RATE")) \
CONFIG(JSON, DD_TRACE_SAMPLING_RULES, "[]") \
CONFIG(CUSTOM(INT), DD_TRACE_SAMPLING_RULES_FORMAT, "regex", .parser = dd_parse_sampling_rules_format) \
CONFIG(JSON, DD_SPAN_SAMPLING_RULES, "[]") \
CONFIG(STRING, DD_SPAN_SAMPLING_RULES_FILE, "", .ini_change = ddtrace_alter_sampling_rules_file_config) \
CONFIG(SET_LOWERCASE, DD_TRACE_HEADER_TAGS, "") \
Expand Down
83 changes: 82 additions & 1 deletion ext/ddshared.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#include <components-rs/ddtrace.h>
#include <Zend/zend_API.h>
#include <components/log/log.h>

#include "ddshared.h"
#include "configuration.h"
#include "ddtrace.h"
#include <components/log/log.h>
#include "uri_normalization.h"

ZEND_EXTERN_MODULE_GLOBALS(ddtrace);

Expand All @@ -14,3 +16,82 @@ void ddshared_minit(void) {

ddtrace_php_version = Z_STR_P(zend_get_constant_str(ZEND_STRL("PHP_VERSION")));
}

bool dd_rule_matches(zval *pattern, zval *prop, int rulesFormat) {
if (Z_TYPE_P(pattern) != IS_STRING) {
return false;
}
if (Z_TYPE_P(prop) != IS_STRING) {
return true; // default case unset or null must be true, everything else is too then...
}

if (rulesFormat == DD_TRACE_SAMPLING_RULES_FORMAT_GLOB) {
return dd_glob_rule_matches(pattern, Z_STR_P(prop));
}
else {
return zai_match_regex(Z_STR_P(pattern), Z_STR_P(prop));
}
}

bool dd_glob_rule_matches(zval *pattern, zend_string* value) {
if (Z_TYPE_P(pattern) != IS_STRING) {
return false;
}

char *p = Z_STRVAL_P(pattern);
char *s = ZSTR_VAL(value);

int wildcards = 0;
int patternLength = 0;
int stringLength = ZSTR_LEN(value);
while (*p) {
if (*(p++) == '*') {
++wildcards;
}
patternLength++;
}

// If there are no wildcards, no need to go through the whole string if pattern is shorter than the input string
// Indeed wildcards (ie '*') can replace multiple characters while '?' canonly replace one
if (wildcards == 0 && patternLength < stringLength) {
return false;
}

p = Z_STRVAL_P(pattern);

ALLOCA_FLAG(use_heap)
char **backtrack_points = do_alloca(wildcards * 2 * sizeof(char *), use_heap);
int backtrack_idx = 0;

while (*p) {
if (!*s) {
while (*p == '*') {
++p;
}
free_alloca(backtrack_points, use_heap);
return !*p;
}
if (*s == *p || *p == '?') {
++s, ++p;
} else if (*p == '*') {
backtrack_points[backtrack_idx++] = ++p;
backtrack_points[backtrack_idx++] = s;
} else {
do {
if (backtrack_idx > 0) {
backtrack_idx -= 2;
p = backtrack_points[backtrack_idx];
s = ++backtrack_points[backtrack_idx + 1];
} else {
free_alloca(backtrack_points, use_heap);
return false;
}
} while (!*s);
backtrack_idx += 2;
}
}

free_alloca(backtrack_points, use_heap);

return true;
}
2 changes: 2 additions & 0 deletions ext/ddshared.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@
extern zend_string *ddtrace_php_version;

void ddshared_minit(void);
bool dd_rule_matches(zval *pattern, zval *prop, int rulesFormat);
bool dd_glob_rule_matches(zval *pattern, zend_string* value);

#endif // DD_TRACE_SHARED_H
4 changes: 3 additions & 1 deletion ext/ddtrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -632,14 +632,16 @@ static zval *ddtrace_root_span_data_write(zend_object *object, zend_string *memb
}
}
} else if (zend_string_equals_literal(prop_name, "traceId")) {
span->trace_id = Z_TYPE_P(value) == IS_STRING ? ddtrace_parse_userland_trace_id(Z_STR_P(value)) : (ddtrace_trace_id){ 0 };
span->trace_id = Z_TYPE_P(value) == IS_STRING ? ddtrace_parse_hex_trace_id(Z_STRVAL_P(value), Z_STRLEN_P(value)) : (ddtrace_trace_id){ 0 };
if (!span->trace_id.low && !span->trace_id.high) {
span->trace_id = (ddtrace_trace_id) {
.low = span->span_id,
.time = get_DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED() ? span->start / UINT64_C(1000000000) : 0,
};
value = &span->property_id;
}
} else if (zend_string_equals_literal(prop_name, "samplingPriority")) {
span->explicit_sampling_priority = zval_get_long(value) != DDTRACE_PRIORITY_SAMPLING_UNKNOWN;
}

#if PHP_VERSION_ID >= 70400
Expand Down
21 changes: 5 additions & 16 deletions ext/distributed_tracing_headers.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,6 @@

ZEND_EXTERN_MODULE_GLOBALS(ddtrace);

static ddtrace_trace_id dd_parse_b3_trace_id(char *trace_id, ssize_t trace_id_len) {
return (ddtrace_trace_id){
.high = trace_id_len > 16 ? ddtrace_parse_hex_span_id_str(trace_id, MIN(16, trace_id_len - 16)) : 0,
.low = ddtrace_parse_hex_span_id_str(trace_id + MAX(0, trace_id_len - 16), MIN(16, trace_id_len)),
};
}

static inline bool dd_is_hex_char(char chr) {
return (chr >= '0' && chr <= '9') || (chr >= 'a' && chr <= 'f');
}
Expand Down Expand Up @@ -99,7 +92,7 @@ static ddtrace_distributed_tracing_result ddtrace_read_distributed_tracing_ids_b
++b3_ptr;
}

result.trace_id = dd_parse_b3_trace_id(b3_traceid, b3_ptr - b3_traceid);
result.trace_id = ddtrace_parse_hex_trace_id(b3_traceid, b3_ptr - b3_traceid);

char *b3_spanid = ++b3_ptr;
while (b3_ptr < b3_end && *b3_ptr != '-') {
Expand Down Expand Up @@ -137,7 +130,7 @@ static ddtrace_distributed_tracing_result ddtrace_read_distributed_tracing_ids_b
ddtrace_distributed_tracing_result result = dd_init_empty_result();

if (read_header(ZAI_STRL("X_B3_TRACEID"), "x-b3-traceid", &trace_id_str, data)) {
result.trace_id = dd_parse_b3_trace_id(ZSTR_VAL(trace_id_str), ZSTR_LEN(trace_id_str));
result.trace_id = ddtrace_parse_hex_trace_id(ZSTR_VAL(trace_id_str), ZSTR_LEN(trace_id_str));
zend_string_release(trace_id_str);
}

Expand Down Expand Up @@ -482,14 +475,10 @@ void ddtrace_apply_distributed_tracing_result(ddtrace_distributed_tracing_result
if (!span) {
DDTRACE_G(propagated_priority_sampling) = DDTRACE_G(default_priority_sampling) = result->priority_sampling;
} else {
ddtrace_set_priority_sampling_on_span(span, result->priority_sampling, DD_MECHANISM_DEFAULT);

if (result->priority_sampling == DDTRACE_PRIORITY_SAMPLING_UNSET) {
ZVAL_UNDEF(&zv);
} else {
ZVAL_LONG(&zv, result->priority_sampling);
}
ZVAL_LONG(&zv, result->priority_sampling);
ddtrace_assign_variable(&span->property_propagated_sampling_priority, &zv);

ddtrace_set_priority_sampling_on_span(span, result->priority_sampling, DD_MECHANISM_DEFAULT);
}
}
}
Expand Down
Loading

0 comments on commit b7a55c5

Please sign in to comment.