Skip to content

Commit 0a2ab3e

Browse files
committed
feat: compute process tags
1 parent de34fe8 commit 0a2ab3e

File tree

8 files changed

+76
-9
lines changed

8 files changed

+76
-9
lines changed

include/datadog/tracer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ class Tracer {
106106
std::string config() const;
107107

108108
private:
109-
void store_config();
109+
void store_config(const std::unordered_map<std::string, std::string>&);
110110
};
111111

112112
} // namespace tracing

include/datadog/tracer_config.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,13 @@ struct TracerConfig {
178178
/// Overridden by the `DD_APM_TRACING_ENABLED` environment variable. Defaults
179179
/// to `true`.
180180
Optional<bool> tracing_enabled;
181+
182+
/// A mapping of process-specific tags used to uniquely identify processes.
183+
///
184+
/// The `process_tags` map allows associating arbitrary string-based keys and
185+
/// values with a process. These tags are consumed as fact for identifying
186+
/// processes.
187+
std::unordered_map<std::string, std::string> process_tags;
181188
};
182189

183190
// `FinalizedTracerConfig` contains `Tracer` implementation details derived from
@@ -218,6 +225,7 @@ class FinalizedTracerConfig final {
218225
std::shared_ptr<EventScheduler> event_scheduler;
219226
std::shared_ptr<HTTPClient> http_client;
220227
bool tracing_enabled;
228+
std::unordered_map<std::string, std::string> process_tags;
221229
};
222230

223231
// Return a `FinalizedTracerConfig` from the specified `config` and from any

src/datadog/platform_util.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
// This component provides platform-dependent miscellanea.
44

55
#include <datadog/expected.h>
6+
#include <datadog/optional.h>
67
#include <datadog/string_view.h>
78

9+
#include <filesystem>
810
#include <string>
9-
#include <vector>
1011

1112
// clang-format off
1213
#if defined(__x86_64__) || defined(_M_X64)
@@ -83,6 +84,8 @@ int get_process_id();
8384

8485
std::string get_process_name();
8586

87+
Optional<std::filesystem::path> get_process_path();
88+
8689
int at_fork_in_child(void (*on_fork)());
8790

8891
namespace container {

src/datadog/platform_util_darwin.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <libproc.h>
12
#include <pthread.h>
23
#include <sys/sysctl.h>
34
#include <sys/types.h>
@@ -14,6 +15,8 @@
1415
#define DD_SDK_OS "Darwin"
1516
#define DD_SDK_KERNEL "Darwin"
1617

18+
namespace fs = std::filesystem;
19+
1720
namespace datadog {
1821
namespace tracing {
1922
namespace {
@@ -56,6 +59,15 @@ std::string get_hostname() { return get_host_info().hostname; }
5659

5760
int get_process_id() { return ::getpid(); }
5861

62+
Optional<std::filesystem::path> get_process_path() {
63+
char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
64+
if (!proc_pidpath(::getpid(), pathbuf, sizeof(pathbuf))) {
65+
return nullopt;
66+
}
67+
68+
return fs::path(pathbuf);
69+
}
70+
5971
std::string get_process_name() {
6072
const char* process_name = getprogname();
6173
return (process_name != nullptr) ? process_name : "unknown-service";

src/datadog/platform_util_unix.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#define DD_SDK_OS "GNU/Linux"
2121
#define DD_SDK_KERNEL "Linux"
2222

23+
namespace fs = std::filesystem;
24+
2325
namespace datadog {
2426
namespace tracing {
2527
namespace {
@@ -79,6 +81,10 @@ std::string get_hostname() { return get_host_info().hostname; }
7981

8082
int get_process_id() { return ::getpid(); }
8183

84+
Optional<std::filesystem::path> get_process_path() {
85+
return fs::path(program_invocation_name);
86+
}
87+
8288
std::string get_process_name() { return program_invocation_short_name; }
8389

8490
int at_fork_in_child(void (*on_fork)()) {

src/datadog/platform_util_windows.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
#include "platform_util.h"
1111

12+
using namespace std::literals;
13+
1214
namespace datadog {
1315
namespace tracing {
1416
namespace {
@@ -19,7 +21,7 @@ std::tuple<std::string, std::string> get_windows_info() {
1921
// application manifest, which is the lowest version supported by the
2022
// application. Use `RtlGetVersion` to obtain the accurate OS version
2123
// regardless of the manifest.
22-
using RtlGetVersion = auto (*)(LPOSVERSIONINFOEXW)->NTSTATUS;
24+
using RtlGetVersion = auto(*)(LPOSVERSIONINFOEXW)->NTSTATUS;
2325

2426
RtlGetVersion func =
2527
(RtlGetVersion)GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");
@@ -98,6 +100,25 @@ std::string get_hostname() { return get_host_info().hostname; }
98100

99101
int get_process_id() { return GetCurrentProcessId(); }
100102

103+
Optional<std::filesystem::path> get_process_path() {
104+
const char* cmdline = GetCommandLineA();
105+
if (cmdline == NULL) return nullopt;
106+
107+
StringView cmdline_sv{cmdline};
108+
auto end = cmdline_sv.find_first_of(" \t"sv);
109+
if (end == cmdline_sv::npos) {
110+
return cmdline;
111+
}
112+
113+
if (cmdline_sv[end - 1] == '"') {
114+
--end;
115+
}
116+
117+
size_t beg = cmdline_sv[0] == '"' ? 1 : 0;
118+
119+
return cmdline_sv.substr(beg, end - beg);
120+
}
121+
101122
std::string get_process_name() {
102123
TCHAR exe_name[MAX_PATH];
103124
if (GetModuleFileName(NULL, exe_name, MAX_PATH) <= 0) {
@@ -161,11 +182,12 @@ Optional<std::string> find_container_id(std::istream& source) {
161182
source.clear();
162183
source.seekg(0);
163184

164-
// Perform a second pass using a regular expression for matching container IDs
165-
// in a Fargate environment. This two-step approach is used because STL
185+
// Perform a second pass using a regular expression for matching container
186+
// IDs in a Fargate environment. This two-step approach is used because STL
166187
// `regex` is relatively slow, so we avoid using it unless necessary.
167188
static const std::string uuid_regex_str =
168-
"[0-9a-f]{8}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{12}"
189+
"[0-9a-f]{8}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{"
190+
"12}"
169191
"|(?:[0-9a-f]{8}(?:-[0-9a-f]{4}){4}$)";
170192
static const std::string container_regex_str = "[0-9a-f]{64}";
171193
static const std::string task_regex_str = "[0-9a-f]{32}-\\d+";

src/datadog/tracer.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include <algorithm>
1515
#include <cassert>
16+
#include <filesystem>
1617

1718
#include "config_manager.h"
1819
#include "datadog_agent.h"
@@ -30,6 +31,8 @@
3031
#include "trace_sampler.h"
3132
#include "w3c_propagation.h"
3233

34+
namespace fs = std::filesystem;
35+
3336
namespace datadog {
3437
namespace tracing {
3538

@@ -99,7 +102,17 @@ Tracer::Tracer(const FinalizedTracerConfig& config,
99102
});
100103
}
101104

102-
store_config();
105+
std::unordered_map<std::string, std::string> process_tags(
106+
config.process_tags);
107+
process_tags.emplace("entrypoint.name", get_process_name());
108+
process_tags.emplace("entrypoint.type", "executable");
109+
process_tags.emplace("entrypoint.workdir", fs::current_path().filename());
110+
if (auto maybe_process_path = get_process_path();
111+
maybe_process_path.has_value()) {
112+
process_tags.emplace("entrypoint.basedir",
113+
maybe_process_path->parent_path().filename());
114+
}
115+
store_config(process_tags);
103116
}
104117

105118
std::string Tracer::config() const {
@@ -129,7 +142,8 @@ std::string Tracer::config() const {
129142
return config.dump();
130143
}
131144

132-
void Tracer::store_config() {
145+
void Tracer::store_config(
146+
const std::unordered_map<std::string, std::string>& process_tags) {
133147
auto maybe_file =
134148
InMemoryFile::make(std::string("datadog-tracer-info-") + short_uuid());
135149
if (auto error = maybe_file.if_error()) {
@@ -162,7 +176,7 @@ void Tracer::store_config() {
162176
"service_name", [&](auto& buffer) { return msgpack::pack_string(buffer, defaults->service); },
163177
"service_env", [&](auto& buffer) { return msgpack::pack_string(buffer, defaults->environment); },
164178
"service_version", [&](auto& buffer) { return msgpack::pack_string(buffer, defaults->version); },
165-
"process_tags", [&](auto& buffer) { return msgpack::pack_string(buffer, ""); },
179+
"process_tags", [&](auto& buffer) { return msgpack::pack_string(buffer, join_tags(process_tags)); },
166180
"container_id", [&](auto& buffer) { return msgpack::pack_string(buffer, container_id); }
167181
);
168182
// clang-format on

src/datadog/tracer_config.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,8 @@ Expected<FinalizedTracerConfig> finalize_config(const TracerConfig &user_config,
403403
final_config.runtime_id = user_config.runtime_id;
404404
}
405405

406+
final_config.process_tags = user_config.process_tags;
407+
406408
auto agent_finalized =
407409
finalize_config(user_config.agent, final_config.logger, clock);
408410
if (auto *error = agent_finalized.if_error()) {

0 commit comments

Comments
 (0)