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
17 changes: 17 additions & 0 deletions components-rs/sidecar.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,23 @@ ddog_MaybeError ddog_sidecar_session_set_config(struct ddog_SidecarTransport **t
ddog_MaybeError ddog_sidecar_session_set_process_tags(struct ddog_SidecarTransport **transport,
const struct ddog_Vec_Tag *process_tags);

/**
* Records the tracer's auto-resolved default service name for the session
* (process-bound; sidecar emits `svc.auto:<name>` when `DD_SERVICE` is not
* currently set for the active request). Pass an empty `CharSlice` to clear.
*/
ddog_MaybeError ddog_sidecar_session_set_default_service_name(struct ddog_SidecarTransport **transport,
ddog_CharSlice default_service_name);

/**
* Records whether `DD_SERVICE` is currently set for the session (per-request
* mutable; refresh on each RINIT). When `true` the sidecar emits
* `svc.user:true`; when `false` it falls back to the previously-recorded
* `svc.auto:<name>` (if any).
*/
ddog_MaybeError ddog_sidecar_session_set_user_service_defined(struct ddog_SidecarTransport **transport,
bool is_user_defined);

/**
* Enqueues a telemetry log action to be processed internally.
* Non-blocking. Logs might be dropped if the internal queue is full.
Expand Down
29 changes: 29 additions & 0 deletions ext/sidecar.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,31 @@ void datadog_sidecar_update_process_tags(void) {
}

ddog_sidecar_session_set_process_tags(&DATADOG_G(sidecar), process_tags);

// Session-bound, process-stable: the tracer's auto-resolved default name.
zend_string *default_svc = datadog_default_service_name();
if (default_svc) {
const char *normalized = ddog_normalize_process_tag_value(dd_zend_string_to_CharSlice(default_svc));
if (normalized) {
datadog_ffi_try("Failed updating sidecar default service name",
ddog_sidecar_session_set_default_service_name(&DATADOG_G(sidecar),
(ddog_CharSlice){ .ptr = normalized, .len = strlen(normalized) }));
Comment on lines +158 to +164

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reapply svc.auto state on reconnect

This only sends the new default_service_name from datadog_sidecar_update_process_tags(), which is called from the one-time first-RINIT path and the explicit reload path. Fresh sidecar sessions created later by dd_sidecar_on_reconnect()/datadog_sidecar_ensure_active() run dd_sidecar_post_connect() and resend UST, but never call this setter, so after a sidecar restart or a late worker-thread connection the sidecar has no default service name and its telemetry/runtime-info process tags lose svc.auto:<default> until process tags are manually reloaded.

Useful? React with 👍 / 👎.

ddog_free_normalized_tag_value(normalized);
}
zend_string_release(default_svc);
}

datadog_sidecar_refresh_user_service_defined();
}

void datadog_sidecar_refresh_user_service_defined(void) {
if (!DATADOG_G(sidecar)) {
return;
}
zend_string *dd_service = get_DD_SERVICE();
bool is_defined = dd_service && ZSTR_LEN(dd_service) > 0;
datadog_ffi_try("Failed updating sidecar user-service-defined flag",
ddog_sidecar_session_set_user_service_defined(&DATADOG_G(sidecar), is_defined));
}

static void datadog_sidecar_setup_thread_mode(void);
Expand Down Expand Up @@ -799,6 +824,10 @@ void datadog_sidecar_rinit(void) {
}

ddtrace_sidecar_submit_span_data_direct_defaults(&DATADOG_G(sidecar), NULL);

if (get_global_DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED()) {
datadog_sidecar_refresh_user_service_defined();
Comment thread
Leiyks marked this conversation as resolved.
}
Comment on lines +828 to +830

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Refresh svc source before sidecar emissions

Refreshing the user_service_defined flag after ddtrace_sidecar_submit_span_data_direct_defaults() is too late for the sidecar payloads that function can emit: it sends universal service tags and, when !root, may immediately flush buffered telemetry. In FPM/vhost or remote-config cases where the resolved DD_SERVICE source changes between requests, those first payloads for the new request are tagged using the previous request's svc.user/svc.auto state.

Useful? React with 👍 / 👎.

}

void datadog_sidecar_rshutdown(void) {
Expand Down
1 change: 1 addition & 0 deletions ext/sidecar.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ void datadog_sidecar_handle_fork(void);
bool datadog_sidecar_should_enable(ddog_RemoteConfigFlags *flags);
void datadog_sidecar_ensure_active(void);
void datadog_sidecar_update_process_tags(void);
void datadog_sidecar_refresh_user_service_defined(void);
void datadog_sidecar_finalize(bool clear_id);
void datadog_sidecar_shutdown(void);
void datadog_force_new_instance_id(void);
Expand Down
2 changes: 1 addition & 1 deletion libdatadog
Submodule libdatadog updated 87 files
+1 −1 .gitlab/benchmarks.yml
+4 −2 Cargo.lock
+0 −2 bin_tests/src/bin/crashtracker_bin_test.rs
+3 −0 bin_tests/src/modes/behavior.rs
+1 −0 bin_tests/src/modes/unix/mod.rs
+3 −2 bin_tests/src/modes/unix/test_018_thread_limit.rs
+76 −0 bin_tests/src/modes/unix/test_021_unhandled_exception_multi_thread.rs
+4 −0 bin_tests/src/test_types.rs
+139 −18 bin_tests/tests/crashtracker_bin_test.rs
+1 −1 datadog-ffe/Cargo.toml
+37 −0 datadog-sidecar-ffi/src/lib.rs
+16 −0 datadog-sidecar/src/service/blocking.rs
+3 −0 datadog-sidecar/src/service/runtime_info.rs
+27 −1 datadog-sidecar/src/service/sender.rs
+27 −0 datadog-sidecar/src/service/session_info.rs
+9 −0 datadog-sidecar/src/service/sidecar_interface.rs
+27 −4 datadog-sidecar/src/service/sidecar_server.rs
+1 −1 datadog-sidecar/src/service/telemetry.rs
+4 −0 datadog-sidecar/src/shm_remote_config.rs
+1 −1 libdd-agent-client/Cargo.toml
+1 −1 libdd-capabilities-impl/Cargo.toml
+19 −0 libdd-common/CHANGELOG.md
+1 −1 libdd-common/Cargo.toml
+2 −2 libdd-crashtracker/Cargo.toml
+61 −41 libdd-crashtracker/src/collector/crash_handler.rs
+139 −14 libdd-crashtracker/src/collector/emitters.rs
+0 −3 libdd-crashtracker/src/crash_info/builder.rs
+30 −13 libdd-crashtracker/src/receiver/ptrace_collector.rs
+52 −7 libdd-crashtracker/src/receiver/receive_report.rs
+143 −8 libdd-data-pipeline-ffi/src/trace_exporter.rs
+2 −1 libdd-data-pipeline/Cargo.toml
+3 −3 libdd-data-pipeline/benches/trace_buffer.rs
+3 −3 libdd-data-pipeline/examples/send-traces-with-stats.rs
+7 −7 libdd-data-pipeline/src/agent_info/fetcher.rs
+3 −0 libdd-data-pipeline/src/lib.rs
+106 −8 libdd-data-pipeline/src/otlp/config.rs
+49 −20 libdd-data-pipeline/src/otlp/exporter.rs
+547 −0 libdd-data-pipeline/src/otlp/metrics.rs
+11 −4 libdd-data-pipeline/src/otlp/mod.rs
+15 −15 libdd-data-pipeline/src/telemetry/mod.rs
+20 −10 libdd-data-pipeline/src/trace_buffer/mod.rs
+231 −44 libdd-data-pipeline/src/trace_exporter/builder.rs
+93 −41 libdd-data-pipeline/src/trace_exporter/mod.rs
+8 −5 libdd-data-pipeline/src/trace_exporter/stats.rs
+6 −5 libdd-data-pipeline/tests/test_trace_exporter.rs
+86 −0 libdd-data-pipeline/tests/test_trace_exporter_otlp_protobuf_export.rs
+2 −1 libdd-data-pipeline/tests/test_trace_filters.rs
+37 −0 libdd-ddsketch/src/lib.rs
+1 −1 libdd-dogstatsd-client/Cargo.toml
+1 −1 libdd-http-client/Cargo.toml
+1 −1 libdd-profiling/Cargo.toml
+6 −0 libdd-remote-config/CHANGELOG.md
+2 −2 libdd-remote-config/Cargo.toml
+3 −4 libdd-remote-config/src/lib.rs
+2 −2 libdd-sampling/Cargo.toml
+20 −20 libdd-shared-runtime-ffi/src/shared_runtime.rs
+1 −1 libdd-shared-runtime/Cargo.toml
+30 −6 libdd-shared-runtime/src/lib.rs
+288 −0 libdd-shared-runtime/src/shared_runtime/basic.rs
+424 −0 libdd-shared-runtime/src/shared_runtime/fork_safe.rs
+97 −0 libdd-shared-runtime/src/shared_runtime/local.rs
+70 −568 libdd-shared-runtime/src/shared_runtime/mod.rs
+2 −2 libdd-shared-runtime/src/shared_runtime/pausable_worker.rs
+1 −1 libdd-telemetry/Cargo.toml
+2 −2 libdd-telemetry/src/worker/mod.rs
+1 −1 libdd-trace-obfuscation/Cargo.toml
+23 −2 libdd-trace-protobuf/build.rs
+12 −0 libdd-trace-protobuf/src/_includes.rs
+54 −0 libdd-trace-protobuf/src/opentelemetry.proto.collector.trace.v1.rs
+440 −0 libdd-trace-protobuf/src/opentelemetry.proto.trace.v1.rs
+80 −0 libdd-trace-protobuf/src/pb/opentelemetry/proto/collector/trace/v1/trace_service.proto
+364 −0 libdd-trace-protobuf/src/pb/opentelemetry/proto/trace/v1/trace.proto
+1 −1 libdd-trace-stats/Cargo.toml
+117 −12 libdd-trace-stats/src/span_concentrator/aggregation.rs
+20 −3 libdd-trace-stats/src/span_concentrator/mod.rs
+53 −0 libdd-trace-stats/src/span_concentrator/tests.rs
+3 −3 libdd-trace-stats/src/stats_exporter.rs
+2 −1 libdd-trace-utils/Cargo.toml
+225 −0 libdd-trace-utils/benches/deserialization_v05.rs
+6 −1 libdd-trace-utils/benches/main.rs
+130 −0 libdd-trace-utils/benches/otlp_encoding.rs
+515 −0 libdd-trace-utils/src/otlp_encoder/json_serializer.rs
+0 −174 libdd-trace-utils/src/otlp_encoder/json_types.rs
+799 −426 libdd-trace-utils/src/otlp_encoder/mapper.rs
+114 −2 libdd-trace-utils/src/otlp_encoder/mod.rs
+1 −1 libdd-tracer-flare/Cargo.toml
+11 −11 scripts/semver-level.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace App;

class SetServiceController
{
public function render()
{
ini_set('datadog.service', 'request-svc');
header('Content-type: text/plain; charset=utf-8');
echo 'service set';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

return function(FastRoute\RouteCollector $r) {
$r->addRoute('GET', '/simple', '\App\SimpleController');
$r->addRoute('GET', '/set_service', '\App\SetServiceController');
$r->addRoute('GET', '/simple_view', '\App\SimpleViewController');
$r->addRoute('GET', '/error', '\App\ErrorController');
$r->addRoute('GET', '/telemetry', '\App\TelemetryFlushController');
Expand Down
24 changes: 24 additions & 0 deletions tests/Integrations/Custom/Autoloaded/ProcessTagsWebTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,28 @@ public function testProcessTagsEnabledForWebSapi()
);
$this->assertEquals($tags['entrypoint.type'], 'script');
}

/**
* Proves the per-span svc.* design has no static-state leak between
* requests served by the same FPM worker: request 1 calls
* ini_set('datadog.service', ...) and must report svc.user:true; request 2
* reuses the same worker but does not override the service, and must
* report svc.auto:<default> (not the leaked svc.user from request 1).
*/
public function testSvcTagDoesNotLeakBetweenRequests()
{
$tracesUser = $this->tracesFromWebRequest(function () {
return $this->call(new RequestSpec(__FUNCTION__ . '_user', 'GET', '/set_service', []));
});
$userTags = $tracesUser[0][0]['meta']['_dd.tags.process'];
$this->assertStringContainsString('svc.user:true', $userTags);
$this->assertStringNotContainsString('svc.auto:', $userTags);

$tracesAuto = $this->tracesFromWebRequest(function () {
return $this->call(new RequestSpec(__FUNCTION__ . '_auto', 'GET', '/simple', []));
});
$autoTags = $tracesAuto[0][0]['meta']['_dd.tags.process'];
$this->assertStringNotContainsString('svc.user', $autoTags);
$this->assertStringContainsString('svc.auto:', $autoTags);
}
}
23 changes: 23 additions & 0 deletions tests/ext/svc_auto_tag_cli.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
--TEST--
Process tags include svc.auto:<default> when DD_SERVICE is unset (CLI)
--ENV--
DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED=1
DD_TRACE_GENERATE_ROOT_SPAN=0
DD_TRACE_AUTO_FLUSH_ENABLED=0
--FILE--
<?php
$span = \DDTrace\start_span();
$span->name = 'op';
\DDTrace\close_span();

$spans = dd_trace_serialize_closed_spans();
$processTags = $spans[0]['meta']['_dd.tags.process'];

echo "has svc.user: " . (strpos($processTags, 'svc.user') !== false ? 'YES' : 'NO') . "\n";
echo "has svc.auto: " . (strpos($processTags, 'svc.auto:') !== false ? 'YES' : 'NO') . "\n";
echo "auto value matches script: " . (strpos($processTags, 'svc.auto:svc_auto_tag_cli.php') !== false ? 'YES' : 'NO') . "\n";
?>
--EXPECT--
has svc.user: NO
has svc.auto: YES
auto value matches script: YES
24 changes: 24 additions & 0 deletions tests/ext/svc_auto_tag_otel.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
--TEST--
OTEL_SERVICE_NAME counts as user-defined (emits svc.user:true)
--ENV--
DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED=1
OTEL_SERVICE_NAME=otel-app
DD_TRACE_GENERATE_ROOT_SPAN=0
DD_TRACE_AUTO_FLUSH_ENABLED=0
--FILE--
<?php
$span = \DDTrace\start_span();
$span->name = 'op';
\DDTrace\close_span();

$spans = dd_trace_serialize_closed_spans();
$processTags = $spans[0]['meta']['_dd.tags.process'];

echo "DD_SERVICE resolved to: " . ini_get('datadog.service') . "\n";
echo "has svc.user:true: " . (strpos($processTags, 'svc.user:true') !== false ? 'YES' : 'NO') . "\n";
echo "has svc.auto: : " . (strpos($processTags, 'svc.auto:') !== false ? 'YES' : 'NO') . "\n";
?>
--EXPECT--
DD_SERVICE resolved to: otel-app
has svc.user:true: YES
has svc.auto: : NO
37 changes: 37 additions & 0 deletions tests/ext/svc_runtime_change.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
--TEST--
Changing datadog.service at runtime recomputes svc.user/svc.auto process tags per-span
--ENV--
DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED=1
DD_TRACE_GENERATE_ROOT_SPAN=0
DD_TRACE_AUTO_FLUSH_ENABLED=0
--FILE--
<?php
function assert_tags($label) {
$spans = dd_trace_serialize_closed_spans();
$tags = $spans[0]['meta']['_dd.tags.process'];
$hasUser = strpos($tags, 'svc.user:true') !== false;
$hasAuto = strpos($tags, 'svc.auto:') !== false;
echo "$label svc.user=" . ($hasUser ? 'YES' : 'NO') . " svc.auto=" . ($hasAuto ? 'YES' : 'NO') . "\n";
}

$span1 = \DDTrace\start_span();
$span1->name = 'before';
\DDTrace\close_span();
assert_tags('BEFORE ');

ini_set('datadog.service', 'changed-svc');
$span2 = \DDTrace\start_span();
$span2->name = 'after_set';
\DDTrace\close_span();
assert_tags('AFTER ');

ini_restore('datadog.service');
$span3 = \DDTrace\start_span();
$span3->name = 'after_restore';
\DDTrace\close_span();
assert_tags('REVERTED');
?>
--EXPECT--
BEFORE svc.user=NO svc.auto=YES
AFTER svc.user=YES svc.auto=NO
REVERTED svc.user=NO svc.auto=YES
22 changes: 22 additions & 0 deletions tests/ext/svc_user_tag.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--TEST--
Process tags include svc.user:true when DD_SERVICE is set
--ENV--
DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED=1
DD_SERVICE=my-app
DD_TRACE_GENERATE_ROOT_SPAN=0
DD_TRACE_AUTO_FLUSH_ENABLED=0
--FILE--
<?php
$span = \DDTrace\start_span();
$span->name = 'op';
\DDTrace\close_span();

$spans = dd_trace_serialize_closed_spans();
$processTags = $spans[0]['meta']['_dd.tags.process'];

echo "has svc.user:true: " . (strpos($processTags, 'svc.user:true') !== false ? 'YES' : 'NO') . "\n";
echo "has svc.auto: : " . (strpos($processTags, 'svc.auto:') !== false ? 'YES' : 'NO') . "\n";
?>
--EXPECT--
has svc.user:true: YES
has svc.auto: : NO
2 changes: 1 addition & 1 deletion tests/ext/telemetry/telemetry_process_tags.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ if ($i == 300) {
?>
--EXPECTF--
Included
string(%d) "entrypoint.basedir:telemetry,entrypoint.name:telemetry_process_tags,entrypoint.type:script,entrypoint.workdir:%s,runtime.sapi:cli"
string(%d) "entrypoint.basedir:telemetry,entrypoint.name:telemetry_process_tags,entrypoint.type:script,entrypoint.workdir:%s,runtime.sapi:cli,svc.auto:telemetry_process_tags.php"
--CLEAN--
<?php

Expand Down
37 changes: 36 additions & 1 deletion tracer/serializer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1575,7 +1575,42 @@ ddog_SpanBytes *ddtrace_serialize_span_to_rust_span(ddtrace_span_data *span, ddo
if (is_first_span) {
zend_string *process_tags = datadog_process_tags_get_serialized();
if (ZSTR_LEN(process_tags)) {
ddog_add_str_span_meta_zstr(rust_span, "_dd.tags.process", process_tags);
const char *svc_tag_appendix = NULL;
const char *normalized_default = NULL;
zend_string *dd_service = get_DD_SERVICE();

if (dd_service && ZSTR_LEN(dd_service)) {
svc_tag_appendix = ",svc.user:true";
} else {
zend_array *root_meta = ddtrace_property_array(&span->root->property_meta);
if (!zend_hash_str_exists(root_meta, ZEND_STRL("_dd.svc_src"))) {
zend_string *root_svc = datadog_convert_to_str(&span->root->property_service);
if (ZSTR_LEN(root_svc)) {
normalized_default = ddog_normalize_process_tag_value(dd_zend_string_to_CharSlice(root_svc));
}
zend_string_release(root_svc);
}
}

if (svc_tag_appendix || normalized_default) {
smart_str combined = {0};
smart_str_append(&combined, process_tags);
if (svc_tag_appendix) {
smart_str_appends(&combined, svc_tag_appendix);
} else {
smart_str_appends(&combined, ",svc.auto:");
smart_str_appends(&combined, normalized_default);
}
smart_str_0(&combined);
ddog_add_str_span_meta_zstr(rust_span, "_dd.tags.process", combined.s);
smart_str_free(&combined);
} else {
ddog_add_str_span_meta_zstr(rust_span, "_dd.tags.process", process_tags);
}

if (normalized_default) {
ddog_free_normalized_tag_value(normalized_default);
}
}
}

Expand Down
Loading