Skip to content
Open
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
4 changes: 2 additions & 2 deletions .gitlab/compile_extension.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
set -eo pipefail
set -xeo pipefail

SWITCH_PHP_VERSION=${SWITCH_PHP_VERSION:-}
WITH_ASAN=${WITH_ASAN:-}
Expand All @@ -20,7 +20,7 @@ if [ "${WITH_ASAN}" -eq "1" ]; then
export COMPILE_ASAN=1
fi
# Compile Rust and PHP in parallel
./compile_rust.sh &
SHARED=1 ./compile_rust.sh &
make -j static &
wait

Expand Down
2 changes: 1 addition & 1 deletion .gitlab/generate-tracer.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ function before_script_steps($with_docker_auth = false) {
ARCH: *arch_targets
variables:
host_os: linux-gnu
SHARED: "1"
WITH_ASAN: "0"
CARGO_HOME: "/rust/cargo/"
SWITCH_PHP_VERSION: "debug"
Expand Down Expand Up @@ -204,6 +203,7 @@ function before_script_steps($with_docker_auth = false) {
DATADOG_HAVE_DEV_ENV: 1
HTTPBIN_HOSTNAME: httpbin-integration
HTTPBIN_PORT: 8080
RUST_BACKTRACE: 1
<?php sidecar_logs(); ?>
before_script:
<?php before_script_steps(true) ?>
Expand Down
8 changes: 0 additions & 8 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ inherits = "release"
# components-rs. There may be a better way to fix this, but I'm alreday two
# tasks removed from what I'm trying to do, so pushing forward.
[workspace.dependencies]
arc-swap = "1.7.1"
hyper = { version = "1.6", features = [
"http1",
"client",
Expand Down
8 changes: 8 additions & 0 deletions components-rs/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fn main() {
// On Linux, set ddog_sidecar_direct_entry as the ELF entry point for the
// cdylib build (libddtrace_php.so in SSI deployments). This allows ld.so
// to exec the library directly without a trampoline binary.
if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("linux") {
println!("cargo:rustc-cdylib-link-arg=-Wl,-e,ddog_sidecar_direct_entry");
}
}
2 changes: 0 additions & 2 deletions components-rs/php_sidecar_mockgen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ name = "php_sidecar_mockgen"
version = "0.1.0"

[dependencies]
cc_utils = { path = "../../libdatadog/tools/cc_utils" }
current_platform = "0.2.0"
sidecar_mockgen = { path = "../../libdatadog/tools/sidecar_mockgen" }

[[bin]]
Expand Down
88 changes: 13 additions & 75 deletions components-rs/php_sidecar_mockgen/src/bin/php_sidecar_mockgen.rs
Original file line number Diff line number Diff line change
@@ -1,89 +1,27 @@
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021-Present Datadog, Inc.

pub use cc_utils::cc;
pub use sidecar_mockgen::generate_mock_symbols;
pub use sidecar_mockgen::weaken_object_symbols;
use std::path::Path;
use std::{env, fs, process};
use std::{env, process};

fn main() {
// This script is necessary to avoid the linker puking when the sidecar tries to load our ddtrace.so
// As php itself is not available within the sidecar, it needs to make sure that all symbols ddtrace.so depends on, are available.
// The mock_generator takes care of generating these symbols.
let args: Vec<_> = env::args_os().collect();
if args.len() < 3 {
eprintln!(
"Needs at least 3 args: the output file, the shared object file followed by at least one object file"
);
process::exit(1);
}

let output_path = Path::new(&args[1]);
let binary_path = Path::new(&args[2]);
let object_paths: Vec<_> = args.iter().skip(3).map(Path::new).collect();
let mock_symbols = match generate_mock_symbols(binary_path, object_paths.as_slice()) {
Ok(symbols) => symbols,
Err(err) => {
eprintln!("Failed generating mock_php_syms.c: {}", err);
process::exit(1);
}
};

if fs::read("mock_php_syms.c")
.ok()
.map(|contents| contents == mock_symbols.as_str().as_bytes())
!= Some(true)
{
if let Err(err) = fs::write("mock_php_syms.c", mock_symbols) {
eprintln!("Failed generating mock_php_syms.c: {}", err);
process::exit(1);
}
if args.get(1).and_then(|a| a.to_str()) != Some("weaken-dynsym") || args.len() < 4 {
eprintln!("Usage: php_sidecar_mockgen weaken-dynsym <target.o ...> <php_binary>");
process::exit(1);
}

let source_modified = fs::metadata("mock_php_syms.c").unwrap().modified().unwrap();
if fs::metadata("mock_php.shared_lib").map_or(true, |m| m.modified().unwrap() < source_modified) {
env::set_var("OPT_LEVEL", "2");

let mut cc_build = cc::Build::new();

// The 'host' and 'target' options are required to compile.
// They can be provided using the HOST and TARGET environment variables.
// On Linux, these environment variables can be empty strings, but it's not the case on macOS.
let host = std::env::var("HOST").unwrap_or("".to_string());
if host == "" {
cc_build.host(current_platform::CURRENT_PLATFORM);
}
let target = std::env::var("TARGET").unwrap_or("".to_string());
if target == "" {
cc_build.target(current_platform::CURRENT_PLATFORM);
}

cc_utils::ImprovedBuild::new()
.set_cc_builder(cc_build)
.file("mock_php_syms.c")
.link_dynamically("dl")
.warnings(true)
.warnings_into_errors(true)
.emit_rerun_if_env_changed(false)
.try_compile_shared_lib("mock_php.shared_lib")
.unwrap();

let bin = match fs::read("mock_php.shared_lib") {
Ok(bin) => bin,
Err(err) => {
eprintln!("Failed opening generated mock_php.shared_lib: {}", err);
process::exit(1);
}
};

let comma_separated = bin.iter().map(|byte| format!("{byte:#X}")).collect::<Vec<String>>().join(",");
let out = format!(r#"
const unsigned char DDTRACE_MOCK_PHP[] = {{{comma_separated}}};
const void *DDTRACE_MOCK_PHP_SIZE = (void *) sizeof(DDTRACE_MOCK_PHP);
"#);
let php_binary = Path::new(args.last().unwrap());
let targets: Vec<_> = args[2..args.len() - 1]
.iter()
.map(|a| Path::new(a.as_os_str()))
.collect();

if let Err(err) = fs::write(output_path, out) {
eprintln!("Failed generating {:?}: {}", output_path, err);
for target in targets {
if let Err(e) = weaken_object_symbols(target, php_binary) {
eprintln!("Warning: weaken-dynsym {}: {e}", target.display());
process::exit(1);
}
}
Expand Down
19 changes: 5 additions & 14 deletions components-rs/sidecar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,17 @@ use libdd_common::Endpoint;
use libdd_common_ffi::slice::AsBytes;
use libdd_common_ffi::{CharSlice, self as ffi, MaybeError};
use libdd_telemetry_ffi::try_c;
#[cfg(any(windows, php_shared_build))]
#[cfg(windows)]
use spawn_worker::LibDependency;
#[cfg(windows)]
use spawn_worker::get_trampoline_target_data;


#[cfg(php_shared_build)]
extern "C" {
#[linkage="extern_weak"]
static DDTRACE_MOCK_PHP: *mut u8;
#[linkage="extern_weak"]
static DDTRACE_MOCK_PHP_SIZE: *mut usize;
}

#[cfg(php_shared_build)]
fn run_sidecar(mut cfg: config::Config) -> anyhow::Result<SidecarTransport> {
if !unsafe { DDTRACE_MOCK_PHP_SIZE }.is_null() {
let mock = unsafe { std::slice::from_raw_parts(DDTRACE_MOCK_PHP, *DDTRACE_MOCK_PHP_SIZE) };
cfg.library_dependencies
.push(LibDependency::Binary(mock));
#[cfg(target_os = "linux")]
if std::env::var_os("DD_SIDECAR_DISABLE_DIRECT_EXEC").map(|s| s.is_empty()).unwrap_or(true)
&& std::env::var_os("DD_SPAWN_WORKER_USE_EXEC").map(|s| s.is_empty()).unwrap_or(true) {
cfg.spawn_without_trampoline = true;
}
datadog_sidecar::start_or_connect_to_sidecar(cfg)
}
Expand Down
49 changes: 30 additions & 19 deletions config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ PHP_ARG_ENABLE(ddtrace-sanitize, whether to enable AddressSanitizer for ddtrace,
PHP_ARG_WITH(ddtrace-rust-library, the rust library is located; i.e. to compile without cargo,
[ --with-ddtrace-rust-library Location to rust library for linking against], -, will be compiled)

PHP_ARG_WITH(ddtrace-sidecar-mockgen, binary to generate mock_php.c,
PHP_ARG_WITH(ddtrace-sidecar-mockgen, binary to weaken PHP symbols in object files,
[ --with-ddtrace-sidecar-library Location to cargo binary produced by components-rs/php_sidecar_mockgen], -, will be compiled)

PHP_ARG_WITH(ddtrace-cargo, where cargo is located for rust code compilation,
Expand Down Expand Up @@ -281,6 +281,14 @@ if test "$PHP_DDTRACE" != "no"; then
EXTRA_CFLAGS="$EXTRA_CFLAGS -fvisibility=hidden"
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -export-symbols $ext_srcdir/ddtrace.sym -flto -fuse-linker-plugin"

dnl On Linux: set the ELF entry point so ddtrace.so can be exec'd directly by ld.so
dnl for sidecar spawning (no trampoline binary, no memfd, no temp files).
case $host_os in
linux*)
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-e,ddog_sidecar_direct_entry"
;;
esac

PHP_SUBST(EXTRA_CFLAGS)
PHP_SUBST(EXTRA_LDFLAGS)
PHP_SUBST(DDTRACE_SHARED_LIBADD)
Expand Down Expand Up @@ -365,6 +373,17 @@ EOT
$(LIBTOOL) --mode=link $(CC) -static $(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) $(LDFLAGS) -o $@ -avoid-version -prefer-pic -module $(shared_objects_ddtrace)
EOT

if test "$ext_shared" = "yes"; then
all_object_files=$(for src in $DD_TRACE_PHP_SOURCES $ZAI_SOURCES; do printf ' %s' "${src%?}lo"; done)
all_object_files_absolute=$(for src in $DD_TRACE_PHP_SOURCES $ZAI_SOURCES; do printf ' $(builddir)/%s' "$(dirname "$src")/$objdir/$(basename "${src%?}o")"; done)
php_binary=$("$PHP_CONFIG" --php-binary)
if test "$PHP_DDTRACE_SIDECAR_MOCKGEN" != "-"; then
ddtrace_mockgen_invocation="HOST= TARGET= $PHP_DDTRACE_SIDECAR_MOCKGEN"
else
ddtrace_mockgen_invocation="cd \"$ext_srcdir/components-rs/php_sidecar_mockgen\"; HOST= TARGET= CARGO_TARGET_DIR=\$(builddir)/target_mockgen/ \$(DDTRACE_CARGO) run"
fi
fi

if test "$PHP_DDTRACE_RUST_LIBRARY_SPLIT" != "no"; then
ddtrace_rust_lib=""
elif test "$PHP_DDTRACE_RUST_LIBRARY" != "-"; then
Expand All @@ -380,25 +399,17 @@ $ddtrace_rust_lib: $( (find "$ext_srcdir/components-rs" -name "*.rs" -o -name "C
EOT
fi

dnl Weaken PHP-origin symbols in all .o files before the link step so that
dnl the resulting .so/.a naturally has weak references.
if test "$ext_shared" = "yes"; then
all_object_files=$(for src in $DD_TRACE_PHP_SOURCES $ZAI_SOURCES; do printf ' %s' "${src%?}lo"; done)
all_object_files_absolute=$(for src in $DD_TRACE_PHP_SOURCES $ZAI_SOURCES; do printf ' $(builddir)/%s' "$(dirname "$src")/$objdir/$(basename "${src%?}o")"; done)
php_binary=$("$PHP_CONFIG" --php-binary)
if test "$PHP_DDTRACE_SIDECAR_MOCKGEN" != "-"; then
ddtrace_mockgen_invocation="HOST= TARGET= $PHP_DDTRACE_SIDECAR_MOCKGEN"
else
ddtrace_mockgen_invocation="cd \"$ext_srcdir/components-rs/php_sidecar_mockgen\"; HOST= TARGET= CARGO_TARGET_DIR=\$(builddir)/target_mockgen/ \$(DDTRACE_CARGO) run"
fi
cat <<EOT >> Makefile.fragments

/\$(builddir)/components-rs/mock_php.c: $all_object_files
($ddtrace_mockgen_invocation \$(builddir)/components-rs/mock_php.c $php_binary $all_object_files_absolute)

# avoid cargo running simultaneously for libddtrace_php and php_sidecar_mockgen
/\$(builddir)/components-rs/mock_php.c: | \$(filter-out \$(builddir)/components-rs/mock_php.lo,\$(shared_objects_ddtrace))
EOT

PHP_ADD_SOURCES_X("/$ext_dir", "\$(builddir)/components-rs/mock_php.c", $ac_extra, shared_objects_ddtrace, yes)
_ddtrace_weaken_tmp=$(mktemp)
cat > "$_ddtrace_weaken_tmp" << WEAKEN
($ddtrace_mockgen_invocation weaken-dynsym $all_object_files_absolute $php_binary)
WEAKEN
sed -i $({ sed --version 2>&1 || echo ''; } | grep GNU >/dev/null || echo "''") -e "/\/ddtrace\.la:\ \\$/r $_ddtrace_weaken_tmp" Makefile.objects
dnl run weaken only once, create a dependency on .la for .a
echo "./modules/ddtrace.a: | ./ddtrace.la" >> Makefile.fragments
rm -f "$_ddtrace_weaken_tmp"
fi

if test "$ext_shared" = "shared" || test "$ext_shared" = "yes"; then
Expand Down
1 change: 0 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ x-aliases:
- PHP_IDE_CONFIG=serverName=docker
- DD_TRACE_DOCKER_DEBUG
- DATADOG_HAVE_DEV_ENV=1
- DD_SPAWN_WORKER_USE_EXEC=1
cap_add:
- SYS_PTRACE
security_opt:
Expand Down
2 changes: 1 addition & 1 deletion libdatadog
Submodule libdatadog updated 68 files
+2 −2 .github/chainguard/self.read.members.sts.yaml
+2 −2 .github/chainguard/self.write.pr.sts.yaml
+4 −2 .github/workflows/rustfmt-auto.yml
+2 −1 CONTRIBUTING.md
+9 −0 Cargo.lock
+1 −0 Cargo.toml
+4 −2 datadog-ffe/src/rules_based/sharder.rs
+1 −1 datadog-ffe/src/rules_based/ufc/compiled_flag_config.rs
+2 −2 datadog-ffe/src/rules_based/ufc/models.rs
+3 −1 datadog-sidecar/Cargo.toml
+4 −0 datadog-sidecar/src/config.rs
+7 −0 datadog-sidecar/src/entry.rs
+2 −2 datadog-sidecar/src/service/agent_info.rs
+9 −1 datadog-sidecar/src/service/stats_flusher.rs
+4 −5 datadog-sidecar/src/service/tracing/trace_flusher.rs
+35 −19 datadog-sidecar/src/unix.rs
+1 −0 libdd-capabilities-impl/Cargo.toml
+5 −2 libdd-capabilities-impl/README.md
+13 −9 libdd-capabilities-impl/src/http.rs
+60 −43 libdd-capabilities-impl/src/lib.rs
+23 −0 libdd-capabilities-impl/src/sleep.rs
+4 −4 libdd-capabilities/README.md
+1 −1 libdd-capabilities/src/http.rs
+5 −1 libdd-capabilities/src/lib.rs
+24 −0 libdd-capabilities/src/sleep.rs
+29 −0 libdd-capabilities/src/spawn.rs
+43 −36 libdd-crashtracker/src/crash_info/errors_intake.rs
+0 −7 libdd-crashtracker/src/crash_info/mod.rs
+5 −5 libdd-crashtracker/src/crash_info/telemetry.rs
+3 −3 libdd-crashtracker/src/receiver/ptrace_collector.rs
+10 −2 libdd-data-pipeline/Cargo.toml
+1 −1 libdd-data-pipeline/benches/trace_buffer.rs
+46 −34 libdd-data-pipeline/src/agent_info/fetcher.rs
+10 −4 libdd-data-pipeline/src/agent_info/schema.rs
+1 −0 libdd-data-pipeline/src/lib.rs
+4 −4 libdd-data-pipeline/src/otlp/exporter.rs
+1 −0 libdd-data-pipeline/src/telemetry/mod.rs
+13 −8 libdd-data-pipeline/src/trace_buffer/mod.rs
+183 −215 libdd-data-pipeline/src/trace_exporter/builder.rs
+149 −18 libdd-data-pipeline/src/trace_exporter/mod.rs
+132 −34 libdd-data-pipeline/src/trace_exporter/stats.rs
+8 −0 libdd-shared-runtime/Cargo.toml
+282 −194 libdd-shared-runtime/src/shared_runtime/mod.rs
+61 −25 libdd-shared-runtime/src/shared_runtime/pausable_worker.rs
+4 −3 libdd-telemetry/Cargo.toml
+96 −0 libdd-telemetry/src/worker/mod.rs
+80 −2 libdd-trace-obfuscation/src/obfuscate.rs
+7 −1 libdd-trace-obfuscation/src/obfuscation_config.rs
+2 −1 libdd-trace-obfuscation/src/sql.rs
+5 −3 libdd-trace-stats/Cargo.toml
+2 −0 libdd-trace-stats/benches/span_concentrator_bench.rs
+1 −0 libdd-trace-stats/src/lib.rs
+15 −2 libdd-trace-stats/src/span_concentrator/aggregation.rs
+77 −25 libdd-trace-stats/src/span_concentrator/mod.rs
+48 −8 libdd-trace-stats/src/span_concentrator/tests.rs
+104 −20 libdd-trace-stats/src/stats_exporter.rs
+26 −23 libdd-trace-utils/src/send_data/mod.rs
+23 −24 libdd-trace-utils/src/send_with_retry/mod.rs
+33 −55 libdd-trace-utils/src/send_with_retry/retry_strategy.rs
+2 −2 libdd-trace-utils/src/stats_utils.rs
+1 −1 libdd-trace-utils/src/test_utils/datadog_test_agent.rs
+1 −1 libdd-trace-utils/tests/test_send_data.rs
+35 −6 spawn_worker/build.rs
+6 −0 spawn_worker/src/check_execinfo.c
+263 −0 spawn_worker/src/direct_entry.c
+47 −0 spawn_worker/src/unix/mod.rs
+106 −52 spawn_worker/src/unix/spawn.rs
+182 −12 tools/sidecar_mockgen/src/lib.rs
19 changes: 18 additions & 1 deletion loader/tests/functional/test_configuration_telemetry.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,37 @@

$telemetryLogPath = tempnam(sys_get_temp_dir(), 'test_loader_');

$sidecarLogPath = tempnam(sys_get_temp_dir(), 'sidecar_loader_');
$output = runCLI('-r "echo \'foo\'; dd_trace_internal_fn(\'finalize_telemetry\');"', true, [
'DD_TRACE_AGENT_URL=file://'.$telemetryLogPath,
'DD_TRACE_LOG_LEVEL=debug,startup',
'DD_INJECT_FORCE=true',
'DD_INJECTION_ENABLED=tracer', // Normally set by the injector
'DD_SERVICE=loader',
'_DD_DEBUG_SIDECAR_LOG_LEVEL=trace',
'_DD_DEBUG_SIDECAR_LOG_METHOD=file://'.$sidecarLogPath,
]);

assertMatchesFormat($output, '%A"loaded_by_ssi":true%s%A');

// Let time to write the telemetry log
usleep(10000);
usleep(300000);

$content = file_get_contents($telemetryLogPath);

// On failure: dump diagnostic info so CI logs show what happened
if (strpos($content, '"instrumentation_source"') === false) {
fwrite(STDERR, "\n=== Sidecar log (" . $sidecarLogPath . ") ===\n");
fwrite(STDERR, file_get_contents($sidecarLogPath) ?: "(empty)\n");
// Dump any crash files left by direct_entry.c crash_handler
foreach (glob('/tmp/ddog_sidecar_crash_*') ?: [] as $f) {
fwrite(STDERR, "\n=== Crash file: $f ===\n");
fwrite(STDERR, file_get_contents($f) ?: "(empty)\n");
}
fwrite(STDERR, "\n=== Telemetry file (" . $telemetryLogPath . ", " . strlen($content) . " bytes) ===\n");
fwrite(STDERR, substr($content, 0, 1024) ?: "(empty)\n");
}

assertContains($content, '{"name":"instrumentation_source","value":"ssi","origin":"default","config_id":null,"seq_id":null}');
assertContains($content, '{"name":"ssi_injection_enabled","value":"tracer","origin":"env_var","config_id":null,"seq_id":null}');
assertContains($content, '{"name":"ssi_forced_injection_enabled","value":"True","origin":"env_var","config_id":null,"seq_id":null}');
Loading