From 1da78e1905307360585c13c21d9d63957867e1c3 Mon Sep 17 00:00:00 2001 From: Damien Mehala Date: Thu, 16 Oct 2025 17:46:05 +0200 Subject: [PATCH 1/5] feat: support process discovery v2 schema --- test/test_tracer.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/test_tracer.cpp b/test/test_tracer.cpp index 26a2b233..b63c2641 100644 --- a/test/test_tracer.cpp +++ b/test/test_tracer.cpp @@ -1851,7 +1851,9 @@ TEST_TRACER("APM tracing disabled") { auto finalized_config = finalize_config(config, clock); REQUIRE(finalized_config); Tracer tracer{*finalized_config}; - { auto root1 = tracer.create_span(); } + { + auto root1 = tracer.create_span(); + } REQUIRE(collector->chunks.size() == 1); REQUIRE(collector->chunks.front().size() == 1); @@ -1930,7 +1932,9 @@ TEST_TRACER("APM tracing disabled") { // When APM Tracing is disabled, we allow one trace per second for service // liveness. To ensure consistency, consume the limiter slot. - { tracer.create_span(); } + { + tracer.create_span(); + } collector->chunks.clear(); // Case 1: extracted context with priority, but no `_dd.p.ts` → depends if From d3ca1e078055bc51d52c3cc9d7c5307c8f00ace7 Mon Sep 17 00:00:00 2001 From: Damien Mehala Date: Thu, 23 Oct 2025 07:22:46 -0400 Subject: [PATCH 2/5] fix: format --- test/test_tracer.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/test/test_tracer.cpp b/test/test_tracer.cpp index b63c2641..26a2b233 100644 --- a/test/test_tracer.cpp +++ b/test/test_tracer.cpp @@ -1851,9 +1851,7 @@ TEST_TRACER("APM tracing disabled") { auto finalized_config = finalize_config(config, clock); REQUIRE(finalized_config); Tracer tracer{*finalized_config}; - { - auto root1 = tracer.create_span(); - } + { auto root1 = tracer.create_span(); } REQUIRE(collector->chunks.size() == 1); REQUIRE(collector->chunks.front().size() == 1); @@ -1932,9 +1930,7 @@ TEST_TRACER("APM tracing disabled") { // When APM Tracing is disabled, we allow one trace per second for service // liveness. To ensure consistency, consume the limiter slot. - { - tracer.create_span(); - } + { tracer.create_span(); } collector->chunks.clear(); // Case 1: extracted context with priority, but no `_dd.p.ts` → depends if From b42999a02d3190f23064bc3f1e7f19157d2f96fa Mon Sep 17 00:00:00 2001 From: Damien Mehala Date: Tue, 28 Oct 2025 19:15:49 -0400 Subject: [PATCH 3/5] chore: split platform code per translation unit --- src/datadog/platform_util_unix.cpp | 10 ++++++++++ src/datadog/platform_util_windows.cpp | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/datadog/platform_util_unix.cpp b/src/datadog/platform_util_unix.cpp index 1797b418..7caa48b4 100644 --- a/src/datadog/platform_util_unix.cpp +++ b/src/datadog/platform_util_unix.cpp @@ -1,3 +1,4 @@ +<<<<<<<< HEAD:src/datadog/platform_util_unix.cpp #include #include #include @@ -276,3 +277,12 @@ Optional get_id() { } // namespace tracing } // namespace datadog +======== +#ifdef _MSC_VER +#include "platform_util_windows.cpp" +#elif defined(__APPLE__) || defined(__FreeBSD__) +#include "platform_util_darwin.cpp" +#else +#include "platform_util_unix.cpp" +#endif +>>>>>>>> de34fe8 (chore: split platform code per translation unit):src/datadog/platform_util.cpp diff --git a/src/datadog/platform_util_windows.cpp b/src/datadog/platform_util_windows.cpp index e4b20311..ef54a8e4 100644 --- a/src/datadog/platform_util_windows.cpp +++ b/src/datadog/platform_util_windows.cpp @@ -21,7 +21,7 @@ std::tuple get_windows_info() { // application manifest, which is the lowest version supported by the // application. Use `RtlGetVersion` to obtain the accurate OS version // regardless of the manifest. - using RtlGetVersion = auto(*)(LPOSVERSIONINFOEXW)->NTSTATUS; + using RtlGetVersion = auto (*)(LPOSVERSIONINFOEXW)->NTSTATUS; RtlGetVersion func = (RtlGetVersion)GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion"); From 6880e32a1f35700d6ac980defd1f95800ee05d4d Mon Sep 17 00:00:00 2001 From: Damien Mehala Date: Tue, 28 Oct 2025 23:23:59 -0400 Subject: [PATCH 4/5] feat: compute process tags --- include/datadog/tracer.h | 2 +- include/datadog/tracer_config.h | 8 +++++++ src/datadog/platform_util.h | 5 ++++- src/datadog/platform_util_darwin.cpp | 12 +++++++++++ src/datadog/platform_util_unix.cpp | 6 ++++++ src/datadog/platform_util_windows.cpp | 30 +++++++++++++++++++++++---- src/datadog/tracer.cpp | 21 ++++++++++++++++--- src/datadog/tracer_config.cpp | 2 ++ 8 files changed, 77 insertions(+), 9 deletions(-) diff --git a/include/datadog/tracer.h b/include/datadog/tracer.h index 1ba99891..6a032a13 100644 --- a/include/datadog/tracer.h +++ b/include/datadog/tracer.h @@ -107,7 +107,7 @@ class Tracer { std::string config() const; private: - void store_config(); + void store_config(const std::unordered_map&); }; } // namespace tracing diff --git a/include/datadog/tracer_config.h b/include/datadog/tracer_config.h index 21b2f687..e1d62597 100644 --- a/include/datadog/tracer_config.h +++ b/include/datadog/tracer_config.h @@ -188,6 +188,13 @@ struct TracerConfig { // present. This is disabled by default. // This option is ignored if `resource_renaming_enabled` is not `true`. Optional resource_renaming_always_simplified_endpoint; + + /// A mapping of process-specific tags used to uniquely identify processes. + /// + /// The `process_tags` map allows associating arbitrary string-based keys and + /// values with a process. These tags are consumed as fact for identifying + /// processes. + std::unordered_map process_tags; }; // `FinalizedTracerConfig` contains `Tracer` implementation details derived from @@ -229,6 +236,7 @@ class FinalizedTracerConfig final { std::shared_ptr http_client; bool tracing_enabled; HttpEndpointCalculationMode resource_renaming_mode; + std::unordered_map process_tags; }; // Return a `FinalizedTracerConfig` from the specified `config` and from any diff --git a/src/datadog/platform_util.h b/src/datadog/platform_util.h index 4ac81ead..85677cf3 100644 --- a/src/datadog/platform_util.h +++ b/src/datadog/platform_util.h @@ -3,10 +3,11 @@ // This component provides platform-dependent miscellanea. #include +#include #include +#include #include -#include // clang-format off #if defined(__x86_64__) || defined(_M_X64) @@ -83,6 +84,8 @@ int get_process_id(); std::string get_process_name(); +Optional get_process_path(); + int at_fork_in_child(void (*on_fork)()); namespace container { diff --git a/src/datadog/platform_util_darwin.cpp b/src/datadog/platform_util_darwin.cpp index 93e1b179..73654333 100644 --- a/src/datadog/platform_util_darwin.cpp +++ b/src/datadog/platform_util_darwin.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -14,6 +15,8 @@ #define DD_SDK_OS "Darwin" #define DD_SDK_KERNEL "Darwin" +namespace fs = std::filesystem; + namespace datadog { namespace tracing { namespace { @@ -56,6 +59,15 @@ std::string get_hostname() { return get_host_info().hostname; } int get_process_id() { return ::getpid(); } +Optional get_process_path() { + char pathbuf[PROC_PIDPATHINFO_MAXSIZE]; + if (!proc_pidpath(::getpid(), pathbuf, sizeof(pathbuf))) { + return nullopt; + } + + return fs::path(pathbuf); +} + std::string get_process_name() { const char* process_name = getprogname(); return (process_name != nullptr) ? process_name : "unknown-service"; diff --git a/src/datadog/platform_util_unix.cpp b/src/datadog/platform_util_unix.cpp index 7caa48b4..e9f8e41d 100644 --- a/src/datadog/platform_util_unix.cpp +++ b/src/datadog/platform_util_unix.cpp @@ -21,6 +21,8 @@ #define DD_SDK_OS "GNU/Linux" #define DD_SDK_KERNEL "Linux" +namespace fs = std::filesystem; + namespace datadog { namespace tracing { namespace { @@ -80,6 +82,10 @@ std::string get_hostname() { return get_host_info().hostname; } int get_process_id() { return ::getpid(); } +Optional get_process_path() { + return fs::path(program_invocation_name); +} + std::string get_process_name() { return program_invocation_short_name; } int at_fork_in_child(void (*on_fork)()) { diff --git a/src/datadog/platform_util_windows.cpp b/src/datadog/platform_util_windows.cpp index ef54a8e4..38295df9 100644 --- a/src/datadog/platform_util_windows.cpp +++ b/src/datadog/platform_util_windows.cpp @@ -11,6 +11,8 @@ #include "platform_util.h" +using namespace std::literals; + namespace datadog { namespace tracing { namespace { @@ -21,7 +23,7 @@ std::tuple get_windows_info() { // application manifest, which is the lowest version supported by the // application. Use `RtlGetVersion` to obtain the accurate OS version // regardless of the manifest. - using RtlGetVersion = auto (*)(LPOSVERSIONINFOEXW)->NTSTATUS; + using RtlGetVersion = auto(*)(LPOSVERSIONINFOEXW)->NTSTATUS; RtlGetVersion func = (RtlGetVersion)GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion"); @@ -100,6 +102,25 @@ std::string get_hostname() { return get_host_info().hostname; } int get_process_id() { return GetCurrentProcessId(); } +Optional get_process_path() { + const char* cmdline = GetCommandLineA(); + if (cmdline == NULL) return nullopt; + + StringView cmdline_sv{cmdline}; + auto end = cmdline_sv.find_first_of(" \t"sv); + if (end == StringView::npos) { + return cmdline; + } + + if (cmdline_sv[end - 1] == '"') { + --end; + } + + size_t beg = cmdline_sv[0] == '"' ? 1 : 0; + + return cmdline_sv.substr(beg, end - beg); +} + std::string get_process_name() { TCHAR exe_name[MAX_PATH]; if (GetModuleFileName(NULL, exe_name, MAX_PATH) <= 0) { @@ -164,11 +185,12 @@ Optional find_container_id(std::istream& source) { source.clear(); source.seekg(0); - // Perform a second pass using a regular expression for matching container IDs - // in a Fargate environment. This two-step approach is used because STL + // Perform a second pass using a regular expression for matching container + // IDs in a Fargate environment. This two-step approach is used because STL // `regex` is relatively slow, so we avoid using it unless necessary. static const std::string uuid_regex_str = - "[0-9a-f]{8}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{12}" + "[0-9a-f]{8}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{" + "12}" "|(?:[0-9a-f]{8}(?:-[0-9a-f]{4}){4}$)"; static const std::string container_regex_str = "[0-9a-f]{64}"; static const std::string task_regex_str = "[0-9a-f]{32}-\\d+"; diff --git a/src/datadog/tracer.cpp b/src/datadog/tracer.cpp index 55174b4e..7603b92b 100644 --- a/src/datadog/tracer.cpp +++ b/src/datadog/tracer.cpp @@ -13,6 +13,7 @@ #include #include +#include #include "config_manager.h" #include "datadog_agent.h" @@ -30,6 +31,8 @@ #include "trace_sampler.h" #include "w3c_propagation.h" +namespace fs = std::filesystem; + namespace datadog { namespace tracing { @@ -100,7 +103,18 @@ Tracer::Tracer(const FinalizedTracerConfig& config, }); } - store_config(); + std::unordered_map process_tags( + config.process_tags); + process_tags.emplace("entrypoint.name", get_process_name()); + process_tags.emplace("entrypoint.type", "executable"); + process_tags.emplace("entrypoint.workdir", + fs::current_path().filename().string()); + if (auto maybe_process_path = get_process_path(); + maybe_process_path.has_value()) { + process_tags.emplace("entrypoint.basedir", + maybe_process_path->parent_path().filename().string()); + } + store_config(process_tags); } std::string Tracer::config() const { @@ -130,7 +144,8 @@ std::string Tracer::config() const { return config.dump(); } -void Tracer::store_config() { +void Tracer::store_config( + const std::unordered_map& process_tags) { auto maybe_file = InMemoryFile::make(std::string("datadog-tracer-info-") + short_uuid()); if (auto error = maybe_file.if_error()) { @@ -163,7 +178,7 @@ void Tracer::store_config() { "service_name", [&](auto& buffer) { return msgpack::pack_string(buffer, defaults->service); }, "service_env", [&](auto& buffer) { return msgpack::pack_string(buffer, defaults->environment); }, "service_version", [&](auto& buffer) { return msgpack::pack_string(buffer, defaults->version); }, - "process_tags", [&](auto& buffer) { return msgpack::pack_string(buffer, ""); }, + "process_tags", [&](auto& buffer) { return msgpack::pack_string(buffer, join_tags(process_tags)); }, "container_id", [&](auto& buffer) { return msgpack::pack_string(buffer, container_id); } ); // clang-format on diff --git a/src/datadog/tracer_config.cpp b/src/datadog/tracer_config.cpp index 852035a5..970367c9 100644 --- a/src/datadog/tracer_config.cpp +++ b/src/datadog/tracer_config.cpp @@ -413,6 +413,8 @@ Expected finalize_config(const TracerConfig &user_config, final_config.runtime_id = user_config.runtime_id; } + final_config.process_tags = user_config.process_tags; + auto agent_finalized = finalize_config(user_config.agent, final_config.logger, clock); if (auto *error = agent_finalized.if_error()) { From 0f8d0e62b516b6b555b917fd2febd51da617a550 Mon Sep 17 00:00:00 2001 From: Damien Mehala Date: Wed, 19 Nov 2025 14:17:22 -0400 Subject: [PATCH 5/5] fix linux compilation --- src/datadog/platform_util_unix.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/datadog/platform_util_unix.cpp b/src/datadog/platform_util_unix.cpp index e9f8e41d..a055610d 100644 --- a/src/datadog/platform_util_unix.cpp +++ b/src/datadog/platform_util_unix.cpp @@ -1,4 +1,3 @@ -<<<<<<<< HEAD:src/datadog/platform_util_unix.cpp #include #include #include @@ -283,12 +282,3 @@ Optional get_id() { } // namespace tracing } // namespace datadog -======== -#ifdef _MSC_VER -#include "platform_util_windows.cpp" -#elif defined(__APPLE__) || defined(__FreeBSD__) -#include "platform_util_darwin.cpp" -#else -#include "platform_util_unix.cpp" -#endif ->>>>>>>> de34fe8 (chore: split platform code per translation unit):src/datadog/platform_util.cpp