Skip to content
Draft
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
18 changes: 18 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 7 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ RUN_TESTS_CMD := DD_SERVICE= DD_ENV= REPORT_EXIT_STATUS=1 TEST_PHP_SRCDIR=$(PROJ

C_FILES = $(shell find components components-rs ext src/dogstatsd tracer zend_abstract_interface -name '*.c' -o -name '*.h' | awk '{ printf "$(BUILD_DIR)/%s\n", $$1 }' )
TEST_FILES = $(shell find tests/ext -name '*.php*' -o -name '*.inc' -o -name '*.json' -o -name '*.yaml' -o -name 'CONFLICTS' | awk '{ printf "$(BUILD_DIR)/%s\n", $$1 }' )
RUST_FILES = $(BUILD_DIR)/Cargo.toml $(BUILD_DIR)/Cargo.lock $(shell find components-rs -name '*.c' -o -name '*.rs' -o -name 'Cargo.toml' | awk '{ printf "$(BUILD_DIR)/%s\n", $$1 }' ) $(shell find libdatadog/{build-common,datadog-ffe,datadog-ipc,datadog-ipc-macros,datadog-live-debugger,datadog-live-debugger-ffi,datadog-remote-config,datadog-sidecar,datadog-sidecar-ffi,datadog-sidecar-macros,libdd-alloc,libdd-capabilities,libdd-capabilities-impl,libdd-common,libdd-common-ffi,libdd-crashtracker,libdd-crashtracker-ffi,libdd-data-pipeline,libdd-ddsketch,libdd-dogstatsd-client,libdd-library-config,libdd-library-config-ffi,libdd-log,libdd-shared-runtime,libdd-telemetry,libdd-telemetry-ffi,libdd-tinybytes,libdd-trace-*,spawn_worker,tools/{cc_utils,sidecar_mockgen},libdd-trace-*,Cargo.toml} \( -type l -o -type f \) \( -path "*/src*" -o -path "*/examples*" -o -path "*Cargo.toml" -o -path "*/build.rs" -o -path "*/tests/dataservice.rs" -o -path "*/tests/service_functional.rs" \) -not -path "*/datadog-ipc/build.rs" -not -path "*/datadog-sidecar-ffi/build.rs")
RUST_FILES = $(BUILD_DIR)/Cargo.toml $(BUILD_DIR)/Cargo.lock $(shell find components-rs -name '*.c' -o -name '*.rs' -o -name 'Cargo.toml' | awk '{ printf "$(BUILD_DIR)/%s\n", $$1 }' ) $(shell find libdatadog/{build-common,datadog-ffe,datadog-ipc,datadog-ipc-macros,datadog-live-debugger,datadog-live-debugger-ffi,datadog-remote-config,datadog-sidecar,datadog-sidecar-ffi,datadog-sidecar-macros,libdd-alloc,libdd-capabilities,libdd-capabilities-impl,libdd-common,libdd-common-ffi,libdd-crashtracker,libdd-crashtracker-ffi,libdd-data-pipeline,libdd-ddsketch,libdd-dogstatsd-client,libdd-library-config,libdd-library-config-ffi,libdd-log,libdd-otel-thread-ctx*,libdd-shared-runtime,libdd-telemetry,libdd-telemetry-ffi,libdd-tinybytes,libdd-trace-*,spawn_worker,tools/{cc_utils,sidecar_mockgen},libdd-trace-*,Cargo.toml} \( -type l -o -type f \) \( -path "*/src*" -o -path "*/examples*" -o -path "*Cargo.toml" -o -path "*/build.rs" -o -path "*/tests/dataservice.rs" -o -path "*/tests/service_functional.rs" \) -not -path "*/datadog-ipc/build.rs" -not -path "*/datadog-sidecar-ffi/build.rs")
ALL_OBJECT_FILES = $(C_FILES) $(RUST_FILES) $(BUILD_DIR)/Makefile
TEST_OPCACHE_FILES = $(shell find tests/opcache -name '*.php*' -o -name '.gitkeep' | awk '{ printf "$(BUILD_DIR)/%s\n", $$1 }' )
TEST_STUB_FILES = $(shell find tests/ext -type d -name 'stubs' -exec find '{}' -type f \; | awk '{ printf "$(BUILD_DIR)/%s\n", $$1 }' )
Expand Down Expand Up @@ -423,9 +423,9 @@ clang_format_fix:
cbindgen: remove_cbindgen generate_cbindgen

remove_cbindgen:
rm -f components-rs/datadog.h components-rs/live-debugger.h components-rs/telemetry.h components-rs/sidecar.h components-rs/common.h components-rs/crashtracker.h components-rs/library-config.h
rm -f components-rs/datadog.h components-rs/live-debugger.h components-rs/telemetry.h components-rs/sidecar.h components-rs/common.h components-rs/crashtracker.h components-rs/library-config.h components-rs/otel-thread-ctx.h

generate_cbindgen: cbindgen_binary # Regenerate components-rs/datadog.h components-rs/live-debugger.h components-rs/telemetry.h components-rs/sidecar.h components-rs/common.h components-rs/crashtracker.h components-rs/library-config.h
generate_cbindgen: cbindgen_binary # Regenerate components-rs/datadog.h components-rs/live-debugger.h components-rs/telemetry.h components-rs/sidecar.h components-rs/common.h components-rs/crashtracker.h components-rs/library-config.h components-rs/otel-thread-ctx.h
( \
$(command rustup && echo run nightly --) cbindgen --crate datadog-php \
--config cbindgen.toml \
Expand All @@ -449,11 +449,14 @@ generate_cbindgen: cbindgen_binary # Regenerate components-rs/datadog.h componen
$(command rustup && echo run nightly --) cbindgen --crate libdd-library-config-ffi \
--config libdd-library-config-ffi/cbindgen.toml \
--output $(PROJECT_ROOT)/components-rs/library-config.h; \
$(command rustup && echo run nightly --) cbindgen --crate libdd-otel-thread-ctx-ffi \
--config libdd-otel-thread-ctx-ffi/cbindgen.toml \
--output $(PROJECT_ROOT)/components-rs/otel-thread-ctx.h; \
if test -d $(PROJECT_ROOT)/tmp; then \
mkdir -pv "$(BUILD_DIR)"; \
export CARGO_TARGET_DIR="$(BUILD_DIR)/target"; \
fi; \
cargo run -p tools --bin dedup_headers -- $(PROJECT_ROOT)/components-rs/common.h $(PROJECT_ROOT)/components-rs/datadog.h $(PROJECT_ROOT)/components-rs/live-debugger.h $(PROJECT_ROOT)/components-rs/telemetry.h $(PROJECT_ROOT)/components-rs/sidecar.h $(PROJECT_ROOT)/components-rs/crashtracker.h $(PROJECT_ROOT)/components-rs/library-config.h \
cargo run -p tools --bin dedup_headers -- $(PROJECT_ROOT)/components-rs/common.h $(PROJECT_ROOT)/components-rs/datadog.h $(PROJECT_ROOT)/components-rs/live-debugger.h $(PROJECT_ROOT)/components-rs/telemetry.h $(PROJECT_ROOT)/components-rs/sidecar.h $(PROJECT_ROOT)/components-rs/crashtracker.h $(PROJECT_ROOT)/components-rs/library-config.h $(PROJECT_ROOT)/components-rs/otel-thread-ctx.h \
)

cbindgen_binary:
Expand Down
3 changes: 3 additions & 0 deletions components-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ libc = "0.2"
bincode = { version = "1.3.3" }
hashbrown = "0.15"

[target.'cfg(target_os = "linux")'.dependencies]
libdd-otel-thread-ctx-ffi = { path = "../libdatadog/libdd-otel-thread-ctx-ffi", default-features = false }

[build-dependencies]
cbindgen = "0.27"

Expand Down
24 changes: 14 additions & 10 deletions components-rs/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,29 @@ pub mod telemetry;
pub mod trace_filter;
pub mod bytes;

use libdd_common::entity_id::{get_container_id, set_cgroup_file};
pub use datadog_sidecar_ffi::*;
pub use libdd_crashtracker_ffi::*;
pub use libdd_common_ffi::*;
pub use libdd_library_config_ffi::*;
pub use libdd_telemetry_ffi::*;

use http::uri::{PathAndQuery, Scheme};
use http::Uri;
use libdd_common::entity_id::{get_container_id, set_cgroup_file};
use libdd_common::{parse_uri, Endpoint};
use libdd_common_ffi::slice::AsBytes;
use std::borrow::Cow;
use std::ffi::{c_char, OsStr};
#[cfg(unix)]
use std::path::Path;
use std::ptr::null_mut;
use uuid::Uuid;

pub use libdd_crashtracker_ffi::*;
pub use libdd_library_config_ffi::*;
pub use datadog_sidecar_ffi::*;
use libdd_common::{parse_uri, Endpoint};
#[cfg(unix)]
use libdd_common::connector::uds::socket_path_to_uri;
use libdd_common_ffi::slice::AsBytes;
pub use libdd_common_ffi::*;
pub use libdd_telemetry_ffi::*;
#[cfg(unix)]
use std::path::Path;

#[cfg(target_os = "linux")]
pub use libdd_otel_thread_ctx_ffi::*;

#[no_mangle]
#[allow(non_upper_case_globals)]
Expand Down
35 changes: 35 additions & 0 deletions components-rs/otel-thread-ctx.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2026-Present Datadog, Inc. https://www.datadoghq.com/
// SPDX-License-Identifier: Apache-2.0

#ifndef DDOG_OTEL_THREAD_CTX_H
#define DDOG_OTEL_THREAD_CTX_H

#pragma once

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#ifdef __linux__

#define ddog_MAX_ATTRS_DATA_SIZE 612

typedef struct ddog_ThreadContextHandle ddog_ThreadContextHandle;

struct ddog_ThreadContextHandle *ddog_otel_thread_ctx_new(const uint8_t (*trace_id)[16],
const uint8_t (*span_id)[8],
const uint8_t (*local_root_span_id)[8]);

void ddog_otel_thread_ctx_free(struct ddog_ThreadContextHandle *ctx);

struct ddog_ThreadContextHandle *ddog_otel_thread_ctx_attach(struct ddog_ThreadContextHandle *ctx);

struct ddog_ThreadContextHandle *ddog_otel_thread_ctx_detach(void);

void ddog_otel_thread_ctx_update(const uint8_t (*trace_id)[16],
const uint8_t (*span_id)[8],
const uint8_t (*local_root_span_id)[8]);

#endif

#endif /* DDOG_OTEL_THREAD_CTX_H */
2 changes: 2 additions & 0 deletions datadog.sym
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
ddtrace_close_all_spans_and_flush
datadog_get_formatted_session_id
ddtrace_get_profiling_context
ddtrace_get_profiling_otel_context
otel_thread_ctx_v1
ddtrace_get_root_span
datadog_process_tags_get_serialized
datadog_get_sidecar_queue_id
Expand Down
1 change: 1 addition & 0 deletions profiling/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ fn generate_bindings(php_config_includes: &str, fibers: bool, zend_error_observe
.raw_line("pub type zend_vm_opcode_handler_func_t = *const ::std::ffi::c_void;")
// Block a few of functions that we'll provide defs for manually
.blocklist_item("datadog_php_profiling_vm_interrupt_addr")
.blocklist_item("datadog_php_profiling_context_api_name")
// I had to block these for some reason *shrug*
.blocklist_item("FP_INFINITE")
.blocklist_item("FP_INT_DOWNWARD")
Expand Down
3 changes: 3 additions & 0 deletions profiling/src/bindings/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@ extern "C" {
/// Must be called from a PHP thread during a request.
pub fn datadog_php_profiling_vm_interrupt_addr() -> *const AtomicBool;

/// Returns the ddtrace profiling context API selected during startup.
pub fn datadog_php_profiling_context_api_name() -> ZaiStr<'static>;

/// Registers the extension. Note that it's kept in a zend_llist and gets
/// pemalloc'd + memcpy'd into place. The engine says this is a mutable
/// pointer, but in practice it's const.
Expand Down
7 changes: 7 additions & 0 deletions profiling/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,13 @@ extern "C" fn rinit(_type: c_int, _module_number: c_int) -> ZendResult {
let once = unsafe { &*ptr::addr_of!(RINIT_ONCE) };
once.call_once(|| {
if system_settings.profiling_enabled {
// SAFETY: this returns a view of a static string owned by php_ffi.c.
let context_api = unsafe { bindings::datadog_php_profiling_context_api_name() };
info!(
"Profiling context API selected: {}.",
context_api.to_string_lossy()
);

// SAFETY: sapi_module is initialized by rinit and shouldn't be
// modified at this point (safe to read values).
let sapi_module = unsafe { &*ptr::addr_of!(zend::sapi_module) };
Expand Down
20 changes: 20 additions & 0 deletions profiling/src/php_ffi.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,31 @@ const char *datadog_extension_build_id(void) { return ZEND_EXTENSION_BUILD_ID; }
const char *datadog_module_build_id(void) { return ZEND_MODULE_BUILD_ID; }

uint8_t *datadog_runtime_id = NULL;
static const zai_str datadog_php_profiling_context_api_none = ZAI_STRL("none");
static const zai_str datadog_php_profiling_context_api_otel = ZAI_STRL("ddtrace_get_profiling_otel_context");
static const zai_str datadog_php_profiling_context_api_legacy = ZAI_STRL("ddtrace_get_profiling_context");
static zai_str datadog_php_profiling_context_api = ZAI_STRL("none");

static void locate_datadog_runtime_id(const zend_extension *extension) {
datadog_runtime_id = DL_FETCH_SYMBOL(extension->handle, "datadog_runtime_id");
}

static void locate_ddtrace_get_profiling_context(const zend_extension *extension) {
#ifdef __linux__
ddtrace_profiling_context (*get_profiling_otel)(void) =
DL_FETCH_SYMBOL(extension->handle, "ddtrace_get_profiling_otel_context");
if (EXPECTED(get_profiling_otel)) {
datadog_php_profiling_get_profiling_context = get_profiling_otel;
datadog_php_profiling_context_api = datadog_php_profiling_context_api_otel;
return;
}
#endif

ddtrace_profiling_context (*get_profiling)(void) =
DL_FETCH_SYMBOL(extension->handle, "ddtrace_get_profiling_context");
if (EXPECTED(get_profiling)) {
datadog_php_profiling_get_profiling_context = get_profiling;
datadog_php_profiling_context_api = datadog_php_profiling_context_api_legacy;
}
}

Expand Down Expand Up @@ -153,6 +168,7 @@ void datadog_php_profiling_startup(zend_extension *extension) {

datadog_php_profiling_get_profiling_context = noop_get_profiling_context;
datadog_php_profiling_get_process_tags_serialized = noop_get_process_tags_serialized;
datadog_php_profiling_context_api = datadog_php_profiling_context_api_none;

/* Due to the optional dependency on ddtrace, the profiling module will be
* loaded after ddtrace if it's present, so ddtrace should always be found
Expand All @@ -177,6 +193,10 @@ void datadog_php_profiling_startup(zend_extension *extension) {
#endif
}

zai_str datadog_php_profiling_context_api_name(void) {
return datadog_php_profiling_context_api;
}

void *datadog_php_profiling_vm_interrupt_addr(void) { return &EG(vm_interrupt); }

zend_module_entry *datadog_get_module_entry(const char *str, uintptr_t len) {
Expand Down
11 changes: 9 additions & 2 deletions profiling/src/php_ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,9 @@ typedef struct ddtrace_profiling_context_s {
} ddtrace_profiling_context;

/**
* A pointer to the tracer's ddtrace_get_profiling_context function if it was
* found, otherwise points to a function which just returns {0, 0}.
* A pointer to the tracer's profiling-context function if it was found,
* otherwise points to a function which just returns {0, 0}. On Linux this
* prefers ddtrace_get_profiling_otel_context when available.
*/
extern ddtrace_profiling_context (*datadog_php_profiling_get_profiling_context)(void);

Expand All @@ -101,6 +102,12 @@ extern zend_string *(*datadog_php_profiling_get_process_tags_serialized)(void);
*/
void datadog_php_profiling_startup(zend_extension *extension);

/**
* Returns the ddtrace profiling context API selected during zend_extension
* startup, or "none" when no provider was found.
*/
zai_str datadog_php_profiling_context_api_name(void);

/**
* Used to hold information for overwriting the internal function handler
* pointer in the Zend Engine.
Expand Down
3 changes: 3 additions & 0 deletions tracer/ddtrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#include "live_debugger.h"
#include "standalone_limiter.h"
#include "priority_sampling/priority_sampling.h"
#include "profiling.h"
#include "random.h"
#include "autoload_php_files.h"
#include "serializer.h"
Expand Down Expand Up @@ -608,6 +609,7 @@ void ddtrace_rshutdown(bool fast_shutdown) {
OBJ_RELEASE(&DDTRACE_G(active_stack)->std);
}
DDTRACE_G(active_stack) = NULL;
ddtrace_detach_otel_thread_context();
}

ddtrace_ffe_flush_exposures();
Expand Down Expand Up @@ -656,6 +658,7 @@ bool datadog_alter_dd_trace_disabled_config(zval *old_value, zval *new_value, ze
} else if (!datadog_disable) { // if this is true, the request has not been initialized at all
ddtrace_close_all_open_spans(false); // All remaining userland spans (and root span)
dd_clean_globals();
ddtrace_detach_otel_thread_context();
}

return true;
Expand Down
2 changes: 2 additions & 0 deletions tracer/handlers_fiber.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "ddtrace.h"
#include "configuration.h"
#include "handlers_fiber.h"
#include "profiling.h"
#include "span.h"
#include <Zend/zend_extensions.h>
#include <Zend/zend_observer.h>
Expand Down Expand Up @@ -130,6 +131,7 @@ static void dd_observe_fiber_switch(zend_fiber_context *from, zend_fiber_context

from->reserved[dd_resource_handle] = DDTRACE_G(active_stack);
DDTRACE_G(active_stack) = to_stack;
ddtrace_update_otel_thread_context();
}

static void dd_observe_fiber_init(zend_fiber_context *context) {
Expand Down
Loading
Loading