Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement extended sampling #2384

Merged
merged 5 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
Comment on lines +9 to +10
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about it, I may have put them in compat_string.[h|c], not to do an additional #include in priority_sampling.c, but this may be irrelevant 🤷

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the will not to do additional includes, but compat_string seems not to be the good placeholder for this. As rule matching as nothing to see with string compatibility.
I could move to a dedicated file if we believe it's not meant in ddshared, but it wouldn't solve the extra incude part of the comment


#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
Loading