Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class AppSecContainer<SELF extends AppSecContainer<SELF>> extends GenericContain
withEnv 'DD_TRACE_DEBUG', '1'
withEnv 'DD_AUTOLOAD_NO_COMPILE', 'true' // must be exactly 'true'
withEnv 'DD_TRACE_GIT_METADATA_ENABLED', '0'
withEnv 'DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED', '0'
withEnv 'DD_INSTRUMENTATION_TELEMETRY_ENABLED', '1'
// very verbose:
withEnv '_DD_DEBUG_SIDECAR_LOG_METHOD', 'file:///tmp/logs/sidecar.log'
Expand Down
2 changes: 2 additions & 0 deletions components-rs/ddtrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ ddog_Configurator *ddog_library_configurator_new_dummy(bool debug_logs, ddog_Cha

int posix_spawn_file_actions_addchdir_np(void *file_actions, const char *path);

uint64_t dd_fnv1a_64(const uint8_t *data, uintptr_t len);

const char *ddog_normalize_process_tag_value(ddog_CharSlice tag_value);

void ddog_free_normalized_tag_value(const char *ptr);
Expand Down
18 changes: 18 additions & 0 deletions components-rs/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,24 @@ pub unsafe extern "C" fn posix_spawn_file_actions_addchdir_np(
}

const MAX_TAG_VALUE_LENGTH: usize = 100;
const DD_FNV_PRIME: u64 = 1_099_511_628_211;
const DD_FNV_OFFSET_BASIS: u64 = 14_695_981_039_346_656_037;

#[no_mangle]
pub unsafe extern "C" fn dd_fnv1a_64(data: *const u8, len: usize) -> u64 {
if data.is_null() || len == 0 {
return DD_FNV_OFFSET_BASIS;
}

let bytes = std::slice::from_raw_parts(data, len);
let mut hash = DD_FNV_OFFSET_BASIS;
for byte in bytes {
hash ^= u64::from(*byte);
hash = hash.wrapping_mul(DD_FNV_PRIME);
}

hash
}

#[no_mangle]
pub extern "C" fn ddog_normalize_process_tag_value(
Expand Down
6 changes: 6 additions & 0 deletions components-rs/sidecar.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,12 @@ struct ddog_AgentInfoReader *ddog_get_agent_info_reader(const struct ddog_Endpoi
*/
ddog_CharSlice ddog_get_agent_info_env(struct ddog_AgentInfoReader *reader, bool *changed);

/**
* Gets the container tags hash from agent info (or empty if not existing)
*/
ddog_CharSlice ddog_get_agent_info_container_tags_hash(struct ddog_AgentInfoReader *reader,
bool *changed);

void ddog_send_traces_to_sidecar(ddog_TracesBytes *traces,
struct ddog_SenderParameters *parameters);

Expand Down
16 changes: 16 additions & 0 deletions ext/agent_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "ddtrace.h"
#include "sidecar.h"
#include "configuration.h"
#include "process_tags.h"

ZEND_EXTERN_MODULE_GLOBALS(ddtrace);

Expand All @@ -20,3 +21,18 @@ void ddtrace_agent_info_rinit() {
DDTRACE_G(agent_info_reader) = ddog_get_agent_info_reader(ddtrace_endpoint);
}
}

void ddtrace_get_container_tags_hash(void) {
if (DDTRACE_G(agent_info_reader)) {
bool changed;
ddog_CharSlice hash = ddog_get_agent_info_container_tags_hash(
DDTRACE_G(agent_info_reader),
&changed
);
if (hash.len > 0) {
zend_string *hash_str = zend_string_init(hash.ptr, hash.len, 1);
ddtrace_process_tags_set_container_tags_hash(hash_str);
zend_string_release(hash_str);
}
}
}
4 changes: 4 additions & 0 deletions ext/agent_info.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
#ifndef DD_AGENT_INFO_H
#define DD_AGENT_INFO_H

#include <stddef.h>
#include "Zend/zend_types.h"

void ddtrace_check_agent_info_env(void);
void ddtrace_agent_info_rinit(void);
void ddtrace_get_container_tags_hash(void);

#endif // DD_AGENT_INFO_H
1 change: 1 addition & 0 deletions ext/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ enum ddtrace_sidecar_connection_mode {
CONFIG(STRING, DD_TRACE_AGENT_TEST_SESSION_TOKEN, "", .ini_change = ddtrace_alter_test_session_token) \
CONFIG(BOOL, DD_TRACE_PROPAGATE_USER_ID_DEFAULT, "false") \
CONFIG(CUSTOM(INT), DD_DBM_PROPAGATION_MODE, "disabled", .parser = dd_parse_dbm_mode) \
CONFIG(BOOL, DD_DBM_INJECT_SQL_BASEHASH, "false") \
CONFIG(CUSTOM(INT), DD_TRACE_SIDECAR_CONNECTION_MODE, "auto", .parser = dd_parse_sidecar_connection_mode) \
CONFIG(SET, DD_TRACE_WORDPRESS_ADDITIONAL_ACTIONS, "") \
CONFIG(BOOL, DD_TRACE_WORDPRESS_CALLBACKS, "true") \
Expand Down
27 changes: 27 additions & 0 deletions ext/ddtrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -1720,6 +1720,8 @@ static void dd_initialize_request(void) {

ddtrace_agent_info_rinit();

ddtrace_get_container_tags_hash();

// Reset compile time after request init hook has compiled
ddtrace_compile_time_reset();

Expand Down Expand Up @@ -2583,6 +2585,17 @@ PHP_FUNCTION(DDTrace_System_container_id) {
}
}

PHP_FUNCTION(DDTrace_System_process_tags_base_hash) {
UNUSED(execute_data);

zend_string *base_hash = ddtrace_process_tags_get_base_hash();
if (base_hash) {
RETVAL_STRINGL(ZSTR_VAL(base_hash), ZSTR_LEN(base_hash));
} else {
RETURN_NULL();
}
}

PHP_FUNCTION(DDTrace_Testing_trigger_error) {
ddtrace_string message;
ddtrace_zpplong_t error_type;
Expand Down Expand Up @@ -3028,6 +3041,20 @@ PHP_FUNCTION(dd_trace_internal_fn) {
ddtrace_generate_runtime_id();
ddtrace_force_new_instance_id();
RETURN_TRUE;
} else if (FUNCTION_NAME_MATCHES("reload_process_tags")) {
if (ddtrace_process_tags_enabled()) {
ddtrace_process_tags_reload();
ddtrace_sidecar_update_process_tags();
}
RETVAL_TRUE;
} else if (params_count == 1 && FUNCTION_NAME_MATCHES("set_container_tags_hash")) {
zval *container_tags_hash = ZVAL_VARARG_PARAM(params, 0);
if (Z_TYPE_P(container_tags_hash) == IS_STRING) {
ddtrace_process_tags_set_container_tags_hash(Z_STR_P(container_tags_hash));
RETVAL_TRUE;
} else {
RETVAL_FALSE;
}
} else if (FUNCTION_NAME_MATCHES("synchronous_flush")) {
uint32_t timeout = 100;
if (params_count == 1) {
Expand Down
10 changes: 10 additions & 0 deletions ext/ddtrace.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,16 @@ function add_endpoint(string $path, string $operation_name, string $resource_nam
* @return string|null The container id, or 'null' if no id was found
*/
function container_id(): string|null {}

/**
* Get the process tags base hash
*
* Returns the FNV-1a 64-bit hash of serialized process tags combined with container tags hash.
* This hash is used for Database Monitoring to correlate queries with application processes.
*
* @return string|null The base hash as a binary string (8 bytes), or 'null' if process tags are disabled or not computed
*/
function process_tags_base_hash(): string|null {}
}

namespace DDTrace\Config {
Expand Down
4 changes: 4 additions & 0 deletions ext/ddtrace_arginfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_DDTrace_System_container_id, 0, 0, IS_STRING, 1)
ZEND_END_ARG_INFO()

#define arginfo_DDTrace_System_process_tags_base_hash arginfo_DDTrace_System_container_id

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_DDTrace_Config_integration_analytics_enabled, 0, 1, _IS_BOOL, 0)
ZEND_ARG_TYPE_INFO(0, integrationName, IS_STRING, 0)
ZEND_END_ARG_INFO()
Expand Down Expand Up @@ -390,6 +392,7 @@ ZEND_FUNCTION(DDTrace_resource_weak_get);
ZEND_FUNCTION(DDTrace_are_endpoints_collected);
ZEND_FUNCTION(DDTrace_add_endpoint);
ZEND_FUNCTION(DDTrace_System_container_id);
ZEND_FUNCTION(DDTrace_System_process_tags_base_hash);
ZEND_FUNCTION(DDTrace_Config_integration_analytics_enabled);
ZEND_FUNCTION(DDTrace_Config_integration_analytics_sample_rate);
ZEND_FUNCTION(DDTrace_UserRequest_has_listeners);
Expand Down Expand Up @@ -483,6 +486,7 @@ static const zend_function_entry ext_functions[] = {
ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace", "are_endpoints_collected"), zif_DDTrace_are_endpoints_collected, arginfo_DDTrace_are_endpoints_collected, 0, NULL, NULL)
ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace", "add_endpoint"), zif_DDTrace_add_endpoint, arginfo_DDTrace_add_endpoint, 0, NULL, NULL)
ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace\\System", "container_id"), zif_DDTrace_System_container_id, arginfo_DDTrace_System_container_id, 0, NULL, NULL)
ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace\\System", "process_tags_base_hash"), zif_DDTrace_System_process_tags_base_hash, arginfo_DDTrace_System_process_tags_base_hash, 0, NULL, NULL)
ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace\\Config", "integration_analytics_enabled"), zif_DDTrace_Config_integration_analytics_enabled, arginfo_DDTrace_Config_integration_analytics_enabled, 0, NULL, NULL)
ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace\\Config", "integration_analytics_sample_rate"), zif_DDTrace_Config_integration_analytics_sample_rate, arginfo_DDTrace_Config_integration_analytics_sample_rate, 0, NULL, NULL)
ZEND_RAW_FENTRY(ZEND_NS_NAME("DDTrace\\UserRequest", "has_listeners"), zif_DDTrace_UserRequest_has_listeners, arginfo_DDTrace_UserRequest_has_listeners, 0, NULL, NULL)
Expand Down
127 changes: 100 additions & 27 deletions ext/process_tags.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "php.h"
#include <ctype.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
Expand Down Expand Up @@ -32,11 +33,41 @@ typedef struct {
size_t count;
size_t capacity;
zend_string *serialized;
zend_string *base_hash;
zend_string *container_tags_hash;
ddog_Vec_Tag vec;
} process_tags_t;

static process_tags_t process_tags = {0};

static void clear_process_tags(void) {
for (size_t i = 0; i < process_tags.count; i++) {
ddog_free_normalized_tag_value(process_tags.tag_list[i].value);
}

if (process_tags.tag_list) {
pefree(process_tags.tag_list, 1);
}

if (process_tags.serialized) {
zend_string_release(process_tags.serialized);
}

if (process_tags.vec.ptr) {
ddog_Vec_Tag_drop(process_tags.vec);
}

if (process_tags.base_hash) {
zend_string_release(process_tags.base_hash);
}

if (process_tags.container_tags_hash) {
zend_string_release(process_tags.container_tags_hash);
}

memset(&process_tags, 0, sizeof(process_tags));
}

static inline const char *get_basename(const char *path) {
if (!path || !*path) return NULL;

Expand Down Expand Up @@ -168,6 +199,37 @@ static int cmp_process_tag_by_key(const void *tag1, const void* tag2) {
return strcmp(tag_entry_1->key, tag_entry_2->key);
}

static void recompute_base_hash(void) {
if (!ddtrace_process_tags_enabled() || !process_tags.serialized) {
return;
}

if (process_tags.base_hash) {
zend_string_release(process_tags.base_hash);
process_tags.base_hash = NULL;
}

uint64_t hash_value;
if (process_tags.container_tags_hash) {
size_t total_len = ZSTR_LEN(process_tags.serialized) + ZSTR_LEN(process_tags.container_tags_hash);
unsigned char *combined = emalloc(total_len);

memcpy(combined, ZSTR_VAL(process_tags.serialized), ZSTR_LEN(process_tags.serialized));
memcpy(combined + ZSTR_LEN(process_tags.serialized), ZSTR_VAL(process_tags.container_tags_hash), ZSTR_LEN(process_tags.container_tags_hash));

hash_value = dd_fnv1a_64(combined, total_len);
efree(combined);
} else {
hash_value = dd_fnv1a_64((const uint8_t *)ZSTR_VAL(process_tags.serialized), ZSTR_LEN(process_tags.serialized));
}

smart_str hash_buf = {0};
smart_str_alloc(&hash_buf, 21, 1);
smart_str_append_printf(&hash_buf, "%" PRIu64, hash_value);
smart_str_0(&hash_buf);
process_tags.base_hash = hash_buf.s;
}

static void serialize_process_tags(void) {
if (!ddtrace_process_tags_enabled() || !process_tags.count) {
return;
Expand Down Expand Up @@ -202,6 +264,33 @@ static void serialize_process_tags(void) {
(ddog_CharSlice) {.ptr = value, .len = strlen(value)}
));
}

recompute_base_hash();
}

static void init_process_tags(void) {
process_tags.capacity = 4;
process_tags.tag_list = pemalloc(process_tags.capacity * sizeof(process_tag_entry_t), 1);
if (!process_tags.tag_list) {
process_tags.capacity = 0;
return;
}

collect_process_tags();
serialize_process_tags();
}

void ddtrace_process_tags_set_container_tags_hash(zend_string *container_tags_hash) {
if (!container_tags_hash || !ddtrace_process_tags_enabled()) {
return;
}

if (process_tags.container_tags_hash) {
zend_string_release(process_tags.container_tags_hash);
}
process_tags.container_tags_hash = zend_string_copy(container_tags_hash);

recompute_base_hash();
}

zend_string *ddtrace_process_tags_get_serialized(void) {
Expand All @@ -220,38 +309,22 @@ const ddog_Vec_Tag *ddtrace_process_tags_get_vec(void) {
return &empty_vec;
}

zend_string *ddtrace_process_tags_get_base_hash(void) {
return (ddtrace_process_tags_enabled() && process_tags.base_hash) ? process_tags.base_hash : NULL;
}

bool ddtrace_process_tags_enabled(void){
return get_global_DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED();
return get_DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED();
}

void ddtrace_process_tags_first_rinit(void) {
// process_tags struct initializations
process_tags.count = 0;
process_tags.capacity = 4;
process_tags.tag_list = pemalloc(process_tags.capacity * sizeof(process_tag_entry_t), 1);

if (!process_tags.tag_list) {
process_tags.capacity = 0;
return;
}

collect_process_tags();
serialize_process_tags();
init_process_tags();
}

void ddtrace_process_tags_reload(void) {
clear_process_tags();
init_process_tags();
}
void ddtrace_process_tags_mshutdown(void) {
for (size_t i = 0; i < process_tags.count; i++) {
ddog_free_normalized_tag_value(process_tags.tag_list[i].value);
}
pefree(process_tags.tag_list, 1);

if (process_tags.serialized) {
zend_string_release(process_tags.serialized);
}

if (process_tags.vec.ptr) {
ddog_Vec_Tag_drop(process_tags.vec);
}

memset(&process_tags, 0, sizeof(process_tags));
clear_process_tags();
}
9 changes: 9 additions & 0 deletions ext/process_tags.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

// Called at first RINIT to collect process tags
void ddtrace_process_tags_first_rinit(void);
// Reload process tags in current request
void ddtrace_process_tags_reload(void);

// Called at MSHUTDOWN to free resources
void ddtrace_process_tags_mshutdown(void);
Expand All @@ -24,4 +26,11 @@ DDTRACE_PUBLIC zend_string *ddtrace_process_tags_get_serialized(void);
// Returns a pointer to an empty Vec if disabled or not yet collected
const ddog_Vec_Tag *ddtrace_process_tags_get_vec(void);

// Set the container tags hash
void ddtrace_process_tags_set_container_tags_hash(zend_string *hash);

// Get the base hash which is the hash of container_tags and process_tags
// Returns NULL if disabled or not yet computed
zend_string *ddtrace_process_tags_get_base_hash(void);

#endif // DD_PROCESS_TAGS_H
Loading
Loading