Skip to content

Commit 434d817

Browse files
dubloomPROFeNoMbwoebi
authored
Adds process_tags to the first span of each tracing payload (#3566)
* init process tags for APM Co-Authored-By: PROFeNoM <[email protected]> * feat(process_tags): add process_tags to tracing payloads * small auto review and fix test * bwoebi review * fix test * Move process tags assign Signed-off-by: Bob Weinand <[email protected]> --------- Signed-off-by: Bob Weinand <[email protected]> Co-authored-by: PROFeNoM <[email protected]> Co-authored-by: Bob Weinand <[email protected]>
1 parent 1316514 commit 434d817

File tree

14 files changed

+620
-18
lines changed

14 files changed

+620
-18
lines changed

components-rs/ddtrace.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,4 +239,8 @@ void ddog_add_zstr_span_meta_struct_CharSlice(ddog_SpanBytes *ptr,
239239
struct _zend_string *key,
240240
ddog_CharSlice val);
241241

242+
const char *ddog_normalize_process_tag_value(ddog_CharSlice val);
243+
244+
void ddog_free_normalized_tag_value(const char* normalized_val);
245+
242246
#endif /* DDTRACE_PHP_H */

components-rs/lib.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,54 @@ pub unsafe extern "C" fn posix_spawn_file_actions_addchdir_np(
132132
-libc::ENOSYS
133133
}
134134
}
135+
136+
const MAX_TAG_VALUE_LENGTH: usize = 100;
137+
138+
#[no_mangle]
139+
pub extern "C" fn ddog_normalize_process_tag_value(
140+
tag_value: CharSlice,
141+
) -> *const c_char {
142+
let value = tag_value.to_utf8_lossy();
143+
144+
let mut out = String::new();
145+
let mut prev_underscore = false;
146+
let mut started = false;
147+
for c in value.chars().take(MAX_TAG_VALUE_LENGTH) {
148+
if c.is_alphanumeric() || matches!(c, '/' | '.' | '-') {
149+
for lc in c.to_lowercase() {
150+
out.push(lc);
151+
}
152+
started = true;
153+
prev_underscore = false;
154+
} else {
155+
if started && !prev_underscore {
156+
out.push('_');
157+
prev_underscore = true;
158+
}
159+
}
160+
}
161+
162+
// trim trailing underscores
163+
if out.ends_with('_') {
164+
out.pop();
165+
}
166+
167+
match std::ffi::CString::new(out) {
168+
Ok(c_string) => {
169+
let out_ptr = c_string.as_ptr();
170+
std::mem::forget(c_string);
171+
out_ptr
172+
}
173+
Err(_) => std::ptr::null(),
174+
}
175+
}
176+
177+
#[no_mangle]
178+
pub extern "C" fn ddog_free_normalized_tag_value(ptr: *const c_char) {
179+
if ptr.is_null() {
180+
return;
181+
}
182+
unsafe {
183+
drop(std::ffi::CString::from_raw(ptr as *mut c_char));
184+
}
185+
}

config.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ if test "$PHP_DDTRACE" != "no"; then
203203
ext/memory_limit.c \
204204
ext/otel_config.c \
205205
ext/priority_sampling/priority_sampling.c \
206+
ext/process_tags.c \
206207
ext/profiling.c \
207208
ext/random.c \
208209
ext/remote_config.c \

config.w32

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ if (PHP_DDTRACE != 'no') {
4949
DDTRACE_EXT_SOURCES += " logging.c";
5050
DDTRACE_EXT_SOURCES += " memory_limit.c";
5151
DDTRACE_EXT_SOURCES += " otel_config.c";
52+
DDTRACE_EXT_SOURCES += " process_tags.c";
5253
DDTRACE_EXT_SOURCES += " profiling.c";
5354
DDTRACE_EXT_SOURCES += " random.c";
5455
DDTRACE_EXT_SOURCES += " remote_config.c";

ext/configuration.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ enum ddtrace_sampling_rules_format {
263263
CONFIG(INT, DD_CODE_ORIGIN_MAX_USER_FRAMES, "8") \
264264
CONFIG(BOOL, DD_TRACE_RESOURCE_RENAMING_ENABLED, "false") \
265265
CONFIG(BOOL, DD_TRACE_RESOURCE_RENAMING_ALWAYS_SIMPLIFIED_ENDPOINT, "false") \
266+
CONFIG(BOOL, DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED, "false") \
266267
DD_INTEGRATIONS
267268

268269
#ifndef _WIN32

ext/ddtrace.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
#include "limiter/limiter.h"
6969
#include "standalone_limiter.h"
7070
#include "priority_sampling/priority_sampling.h"
71+
#include "process_tags.h"
7172
#include "random.h"
7273
#include "autoload_php_files.h"
7374
#include "remote_config.h"
@@ -1615,6 +1616,7 @@ static PHP_MSHUTDOWN_FUNCTION(ddtrace) {
16151616
ddtrace_sidecar_shutdown();
16161617

16171618
ddtrace_live_debugger_mshutdown();
1619+
ddtrace_process_tags_mshutdown();
16181620

16191621
#if PHP_VERSION_ID >= 80000 && PHP_VERSION_ID < 80100
16201622
// See dd_register_span_data_ce for explanation
@@ -1637,6 +1639,11 @@ static void dd_rinit_once(void) {
16371639
*/
16381640
ddtrace_startup_logging_first_rinit();
16391641

1642+
// Collect process tags now that script path is available
1643+
if (get_global_DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED()) {
1644+
ddtrace_process_tags_first_rinit();
1645+
}
1646+
16401647
// Uses config, cannot run earlier
16411648
#ifndef _WIN32
16421649
ddtrace_signals_first_rinit();
@@ -2610,6 +2617,26 @@ PHP_FUNCTION(DDTrace_Testing_trigger_error) {
26102617
}
26112618
}
26122619

2620+
PHP_FUNCTION(DDTrace_Testing_normalize_tag_value) {
2621+
ddtrace_string value;
2622+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &value.ptr, &value.len) != SUCCESS) {
2623+
RETURN_EMPTY_STRING();
2624+
}
2625+
2626+
const char* normalized = ddog_normalize_process_tag_value((ddog_CharSlice){
2627+
.ptr = value.ptr,
2628+
.len = value.len
2629+
});
2630+
2631+
if (normalized) {
2632+
zend_string *result = zend_string_init(normalized, strlen(normalized), 0);
2633+
ddog_free_normalized_tag_value(normalized);
2634+
RETURN_STR(result);
2635+
} else {
2636+
RETURN_EMPTY_STRING();
2637+
}
2638+
}
2639+
26132640
PHP_FUNCTION(DDTrace_Internal_add_span_flag) {
26142641
zend_object *span;
26152642
zend_long flag;

ext/ddtrace.stub.php

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,13 @@ function trigger_error(string $message, int $errorType): void {}
904904
* Emits an asm event
905905
*/
906906
function emit_asm_event(): void {}
907+
/**
908+
* Normalizes a process tag value
909+
*
910+
* @param string $value The tag value to normalize
911+
* @return string The normalized tag value
912+
*/
913+
function normalize_tag_value(string $value): string {}
907914
}
908915

909916
namespace DDTrace\Internal {
@@ -939,24 +946,24 @@ function handle_fork(): void {}
939946

940947
namespace datadog\appsec\v2 {
941948
/**
942-
* Track a user login success event.
943-
*
944-
* @param string $login is the data used by the user to authenticate
945-
* @param string|array $user when string, it represents the user id. When array it represents the user information.
946-
* The array should at least contain the following keys:
947-
* - id: string, Unique identifier of the user. Should be the same id and format used on set_user
948-
* @param array $metadata User metadata added to the root span
949-
*/
950-
function track_user_login_success(string $login, string|array|null $user = null, array $metadata = []): void {}
951-
952-
/**
953-
* Track a user login failure event.
954-
*
955-
* @param string $login is the data used by the user to authenticate
956-
* @param bool $exists Whether the user exists in the system
957-
* @param array $metadata User metadata added to the root span
958-
*/
959-
function track_user_login_failure(string $login, bool $exists, array $metadata = []): void {}
949+
* Track a user login success event.
950+
*
951+
* @param string $login is the data used by the user to authenticate
952+
* @param string|array $user when string, it represents the user id. When array it represents the user information.
953+
* The array should at least contain the following keys:
954+
* - id: string, Unique identifier of the user. Should be the same id and format used on set_user
955+
* @param array $metadata User metadata added to the root span
956+
*/
957+
function track_user_login_success(string $login, string|array|null $user = null, array $metadata = []): void {}
958+
959+
/**
960+
* Track a user login failure event.
961+
*
962+
* @param string $login is the data used by the user to authenticate
963+
* @param bool $exists Whether the user exists in the system
964+
* @param array $metadata User metadata added to the root span
965+
*/
966+
function track_user_login_failure(string $login, bool $exists, array $metadata = []): void {}
960967
}
961968

962969
namespace {

ext/ddtrace_arginfo.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,10 @@ ZEND_END_ARG_INFO()
203203

204204
#define arginfo_DDTrace_Testing_emit_asm_event arginfo_DDTrace_flush
205205

206+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_DDTrace_Testing_normalize_tag_value, 0, 1, IS_STRING, 0)
207+
ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0)
208+
ZEND_END_ARG_INFO()
209+
206210
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_DDTrace_Internal_add_span_flag, 0, 2, IS_VOID, 0)
207211
ZEND_ARG_OBJ_INFO(0, span, DDTrace\\SpanData, 0)
208212
ZEND_ARG_TYPE_INFO(0, flag, IS_LONG, 0)
@@ -383,6 +387,7 @@ ZEND_FUNCTION(DDTrace_UserRequest_notify_commit);
383387
ZEND_FUNCTION(DDTrace_UserRequest_set_blocking_function);
384388
ZEND_FUNCTION(DDTrace_Testing_trigger_error);
385389
ZEND_FUNCTION(DDTrace_Testing_emit_asm_event);
390+
ZEND_FUNCTION(DDTrace_Testing_normalize_tag_value);
386391
ZEND_FUNCTION(DDTrace_Internal_add_span_flag);
387392
ZEND_FUNCTION(DDTrace_Internal_handle_fork);
388393
ZEND_FUNCTION(datadog_appsec_v2_track_user_login_success);
@@ -473,6 +478,7 @@ static const zend_function_entry ext_functions[] = {
473478
ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace\\UserRequest", "set_blocking_function"), zif_DDTrace_UserRequest_set_blocking_function, arginfo_DDTrace_UserRequest_set_blocking_function, 0, NULL, NULL)
474479
ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace\\Testing", "trigger_error"), zif_DDTrace_Testing_trigger_error, arginfo_DDTrace_Testing_trigger_error, 0, NULL, NULL)
475480
ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace\\Testing", "emit_asm_event"), zif_DDTrace_Testing_emit_asm_event, arginfo_DDTrace_Testing_emit_asm_event, 0, NULL, NULL)
481+
ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace\\Testing", "normalize_tag_value"), zif_DDTrace_Testing_normalize_tag_value, arginfo_DDTrace_Testing_normalize_tag_value, 0, NULL, NULL)
476482
ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace\\Internal", "add_span_flag"), zif_DDTrace_Internal_add_span_flag, arginfo_DDTrace_Internal_add_span_flag, 0, NULL, NULL)
477483
ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace\\Internal", "handle_fork"), zif_DDTrace_Internal_handle_fork, arginfo_DDTrace_Internal_handle_fork, 0, NULL, NULL)
478484
ZEND_RAW_FENTRY(ZEND_NS_NAME("datadog\\appsec\\v2", "track_user_login_success"), zif_datadog_appsec_v2_track_user_login_success, arginfo_datadog_appsec_v2_track_user_login_success, 0, NULL, NULL)

0 commit comments

Comments
 (0)