Skip to content
Open
88 changes: 50 additions & 38 deletions ext/otel_config.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "otel_config.h"
#include <env/env.h>
#include <zai_string/string.h>
#include "ddtrace.h"
#include <components/log/log.h>
#include "sidecar.h"
Expand All @@ -20,22 +21,33 @@ static void report_otel_cfg_telemetry_invalid(const char *otel_cfg, const char *
}
}

static bool get_otel_value(zai_str str, zai_env_buffer buf, bool pre_rinit) {
if (zai_getenv_ex(str, buf, pre_rinit) == ZAI_ENV_SUCCESS) {
/**
* Borrows the value from the SAPI or the system env vars, or falls back on the
* INI entry, which copies the value into the buffer.
*/
static bool get_otel_value(zai_str str, zai_env_buffer *buf, bool pre_rinit) {
zai_option_str opt = zai_sapi_getenv(str);
if (zai_option_str_is_none(opt)) {
opt = zai_sys_getenv(str);
}
zai_str val;
if (zai_option_str_get(opt, &val)) {
buf->ptr = val.ptr;
buf->len = val.len;
return true;
}

zval *cfg = cfg_get_entry(str.ptr, str.len);
if (cfg) {
if (Z_TYPE_P(cfg) == IS_ARRAY) {
zval *val;
char *off = buf.ptr;
char *off = buf->ptr;
ZEND_HASH_FOREACH_VAL(Z_ARR_P(cfg), val) {
if (Z_TYPE_P(val) == IS_STRING) {
if (off - buf.ptr + Z_STRLEN_P(val) + 2 >= ZAI_ENV_MAX_BUFSIZ) {
if (off - buf->ptr + Z_STRLEN_P(val) + 2 >= ZAI_ENV_MAX_BUFSIZ) {
return false;
}
if (off != buf.ptr) {
if (off != buf->ptr) {
*off++ = ',';
}
memcpy(off, Z_STRVAL_P(val), Z_STRLEN_P(val));
Expand All @@ -46,29 +58,29 @@ static bool get_otel_value(zai_str str, zai_env_buffer buf, bool pre_rinit) {
} else if (Z_STRLEN_P(cfg) == 0 || Z_STRLEN_P(cfg) + 1 >= ZAI_ENV_MAX_BUFSIZ) {
return false;
} else {
memcpy(buf.ptr, Z_STRVAL_P(cfg), Z_STRLEN_P(cfg) + 1);
memcpy(buf->ptr, Z_STRVAL_P(cfg), Z_STRLEN_P(cfg) + 1);
}
return true;
}

return false;
}

static bool ddtrace_conf_otel_resource_attributes_special(const char *tag, int len, zai_env_buffer buf, bool pre_rinit) {
static bool ddtrace_conf_otel_resource_attributes_special(const char *tag, int len, zai_env_buffer *buf, bool pre_rinit) {
if (!get_otel_value((zai_str)ZAI_STRL("OTEL_RESOURCE_ATTRIBUTES"), buf, pre_rinit)) {
return false;
}

for (char *cur = buf.ptr, *key_start = cur; *cur; ++cur) {
for (char *cur = buf->ptr, *key_start = cur; *cur; ++cur) {
if (*cur == '=') {
char *key_end = cur++;
while (*cur && *cur != ',') {
++cur;
}
if (key_end - key_start == len && memcmp(key_start, tag, len) == 0 && key_end[1]) {
size_t vallen = cur - (key_end + 1);
memcpy(buf.ptr, key_end + 1, vallen);
buf.ptr[vallen] = 0;
memcpy(buf->ptr, key_end + 1, vallen);
buf->ptr[vallen] = 0;
return true;
}
key_start = cur-- + 1;
Expand All @@ -78,92 +90,92 @@ static bool ddtrace_conf_otel_resource_attributes_special(const char *tag, int l
return false;
}

bool ddtrace_conf_otel_resource_attributes_env(zai_env_buffer buf, bool pre_rinit) {
bool ddtrace_conf_otel_resource_attributes_env(zai_env_buffer *buf, bool pre_rinit) {
return ddtrace_conf_otel_resource_attributes_special(ZEND_STRL("deployment.environment"), buf, pre_rinit);
}

bool ddtrace_conf_otel_resource_attributes_version(zai_env_buffer buf, bool pre_rinit) {
bool ddtrace_conf_otel_resource_attributes_version(zai_env_buffer *buf, bool pre_rinit) {
return ddtrace_conf_otel_resource_attributes_special(ZEND_STRL("service.version"), buf, pre_rinit);
}

bool ddtrace_conf_otel_service_name(zai_env_buffer buf, bool pre_rinit) {
bool ddtrace_conf_otel_service_name(zai_env_buffer *buf, bool pre_rinit) {
return get_otel_value((zai_str)ZAI_STRL("OTEL_SERVICE_NAME"), buf, pre_rinit)
|| ddtrace_conf_otel_resource_attributes_special(ZEND_STRL("service.name"), buf, pre_rinit);
}

bool ddtrace_conf_otel_log_level(zai_env_buffer buf, bool pre_rinit) {
bool ddtrace_conf_otel_log_level(zai_env_buffer *buf, bool pre_rinit) {
return get_otel_value((zai_str)ZAI_STRL("OTEL_LOG_LEVEL"), buf, pre_rinit);
}

bool ddtrace_conf_otel_propagators(zai_env_buffer buf, bool pre_rinit) {
bool ddtrace_conf_otel_propagators(zai_env_buffer *buf, bool pre_rinit) {
if (!get_otel_value((zai_str)ZAI_STRL("OTEL_PROPAGATORS"), buf, pre_rinit)) {
return false;
}
char *off = (char *)zend_memnstr(buf.ptr, ZEND_STRL("b3"), buf.ptr + strlen(buf.ptr));
if (off && (!off[strlen("b3")] || off[strlen("b3")] == ',') && strlen(buf.ptr) < buf.len - 100) {
memmove(off + strlen("b3 single header"), off + strlen("b3"), buf.ptr + strlen(buf.ptr) - (off + strlen("b3")) + 1);
char *off = (char *)zend_memnstr(buf->ptr, ZEND_STRL("b3"), buf->ptr + strlen(buf->ptr));
if (off && (!off[strlen("b3")] || off[strlen("b3")] == ',') && strlen(buf->ptr) < buf->len - 100) {
memmove(off + strlen("b3 single header"), off + strlen("b3"), buf->ptr + strlen(buf->ptr) - (off + strlen("b3")) + 1);
memcpy(off, "b3 single header", strlen("b3 single header"));
}
return true;
}

bool ddtrace_conf_otel_sample_rate(zai_env_buffer buf, bool pre_rinit) {
bool ddtrace_conf_otel_sample_rate(zai_env_buffer *buf, bool pre_rinit) {
if (!get_otel_value((zai_str)ZAI_STRL("OTEL_TRACES_SAMPLER"), buf, pre_rinit)) {
return false;
}

if (strcmp(buf.ptr, "always_on") == 0 || strcmp(buf.ptr, "parentbased_always_on") == 0) {
memcpy(buf.ptr, ZEND_STRS("1"));
if (strcmp(buf->ptr, "always_on") == 0 || strcmp(buf->ptr, "parentbased_always_on") == 0) {
memcpy(buf->ptr, ZEND_STRS("1"));
return true;
}
if (strcmp(buf.ptr, "always_off") == 0 || strcmp(buf.ptr, "parentbased_always_off") == 0) {
memcpy(buf.ptr, ZEND_STRS("0"));
if (strcmp(buf->ptr, "always_off") == 0 || strcmp(buf->ptr, "parentbased_always_off") == 0) {
memcpy(buf->ptr, ZEND_STRS("0"));
return true;
}
if (strcmp(buf.ptr, "traceidratio") == 0 || strcmp(buf.ptr, "parentbased_traceidratio") == 0) {
if (strcmp(buf->ptr, "traceidratio") == 0 || strcmp(buf->ptr, "parentbased_traceidratio") == 0) {
if (get_otel_value((zai_str)ZAI_STRL("OTEL_TRACES_SAMPLER_ARG"), buf, pre_rinit)) {
return true;
}
LOG_ONCE(WARN, "OTEL_TRACES_SAMPLER is %s, but is missing OTEL_TRACES_SAMPLER_ARG", buf.ptr);
LOG_ONCE(WARN, "OTEL_TRACES_SAMPLER is %s, but is missing OTEL_TRACES_SAMPLER_ARG", buf->ptr);
} else {
LOG_ONCE(WARN, "OTEL_TRACES_SAMPLER has invalid value: %s", buf.ptr);
LOG_ONCE(WARN, "OTEL_TRACES_SAMPLER has invalid value: %s", buf->ptr);
}
report_otel_cfg_telemetry_invalid("otel_traces_sampler", "dd_trace_sample_rate", pre_rinit);
return false;
}

bool ddtrace_conf_otel_traces_exporter(zai_env_buffer buf, bool pre_rinit) {
bool ddtrace_conf_otel_traces_exporter(zai_env_buffer *buf, bool pre_rinit) {
if (get_otel_value((zai_str)ZAI_STRL("OTEL_TRACES_EXPORTER"), buf, pre_rinit)) {
if (strcmp(buf.ptr, "none") == 0) {
memcpy(buf.ptr, ZEND_STRS("0"));
if (strcmp(buf->ptr, "none") == 0) {
memcpy(buf->ptr, ZEND_STRS("0"));
return true;
}
LOG_ONCE(WARN, "OTEL_TRACES_EXPORTER has invalid value: %s", buf.ptr);
LOG_ONCE(WARN, "OTEL_TRACES_EXPORTER has invalid value: %s", buf->ptr);
report_otel_cfg_telemetry_invalid("otel_traces_exporter", "dd_trace_enabled", pre_rinit);
}
return false;
}

bool ddtrace_conf_otel_metrics_exporter(zai_env_buffer buf, bool pre_rinit) {
bool ddtrace_conf_otel_metrics_exporter(zai_env_buffer *buf, bool pre_rinit) {
if (get_otel_value((zai_str)ZAI_STRL("OTEL_METRICS_EXPORTER"), buf, pre_rinit)) {
if (strcmp(buf.ptr, "none") == 0) {
memcpy(buf.ptr, ZEND_STRS("0"));
if (strcmp(buf->ptr, "none") == 0) {
memcpy(buf->ptr, ZEND_STRS("0"));
return true;
}
LOG_ONCE(WARN, "OTEL_METRICS_EXPORTER has invalid value: %s", buf.ptr);
LOG_ONCE(WARN, "OTEL_METRICS_EXPORTER has invalid value: %s", buf->ptr);
report_otel_cfg_telemetry_invalid("otel_metrics_exporter", "dd_integration_metrics_enabled", pre_rinit);
}
return false;
}

bool ddtrace_conf_otel_resource_attributes_tags(zai_env_buffer buf, bool pre_rinit) {
bool ddtrace_conf_otel_resource_attributes_tags(zai_env_buffer *buf, bool pre_rinit) {
if (!get_otel_value((zai_str)ZAI_STRL("OTEL_RESOURCE_ATTRIBUTES"), buf, pre_rinit)) {
return false;
}

char *out = buf.ptr;
char *out = buf->ptr;
int tags = 0;
for (char *cur = buf.ptr, *key_start = cur; *cur; ++cur) {
for (char *cur = buf->ptr, *key_start = cur; *cur; ++cur) {
if (*cur == '=') {
char *key = key_start, *key_end = cur++;
while (*cur && *cur != ',') {
Expand All @@ -190,7 +202,7 @@ bool ddtrace_conf_otel_resource_attributes_tags(zai_env_buffer buf, bool pre_rin
--cur;
}
}
if (out != buf.ptr) {
if (out != buf->ptr) {
--out;
}
*out = 0;
Expand Down
20 changes: 11 additions & 9 deletions ext/otel_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@

#include <env/env.h>

bool ddtrace_conf_otel_resource_attributes_env(zai_env_buffer buf, bool pre_rinit);
bool ddtrace_conf_otel_resource_attributes_version(zai_env_buffer buf, bool pre_rinit);
bool ddtrace_conf_otel_service_name(zai_env_buffer buf, bool pre_rinit);
bool ddtrace_conf_otel_log_level(zai_env_buffer buf, bool pre_rinit);
bool ddtrace_conf_otel_propagators(zai_env_buffer buf, bool pre_rinit);
bool ddtrace_conf_otel_sample_rate(zai_env_buffer buf, bool pre_rinit);
bool ddtrace_conf_otel_traces_exporter(zai_env_buffer buf, bool pre_rinit);
bool ddtrace_conf_otel_metrics_exporter(zai_env_buffer buf, bool pre_rinit);
bool ddtrace_conf_otel_resource_attributes_tags(zai_env_buffer buf, bool pre_rinit);
#include <stdbool.h>

bool ddtrace_conf_otel_resource_attributes_env(zai_env_buffer *buf, bool pre_rinit);
bool ddtrace_conf_otel_resource_attributes_version(zai_env_buffer *buf, bool pre_rinit);
bool ddtrace_conf_otel_service_name(zai_env_buffer *buf, bool pre_rinit);
bool ddtrace_conf_otel_log_level(zai_env_buffer *buf, bool pre_rinit);
bool ddtrace_conf_otel_propagators(zai_env_buffer *buf, bool pre_rinit);
bool ddtrace_conf_otel_sample_rate(zai_env_buffer *buf, bool pre_rinit);
bool ddtrace_conf_otel_traces_exporter(zai_env_buffer *buf, bool pre_rinit);
bool ddtrace_conf_otel_metrics_exporter(zai_env_buffer *buf, bool pre_rinit);
bool ddtrace_conf_otel_resource_attributes_tags(zai_env_buffer *buf, bool pre_rinit);

#endif // DD_OTEL_CONFIG_H
Loading
Loading