Skip to content

Commit e2e42fa

Browse files
authored
feat: compute process tags (#256)
1 parent fad6060 commit e2e42fa

File tree

8 files changed

+76
-8
lines changed

8 files changed

+76
-8
lines changed

include/datadog/tracer.h

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

109109
private:
110-
void store_config();
110+
void store_config(const std::unordered_map<std::string, std::string>&);
111111
};
112112

113113
} // namespace tracing

include/datadog/tracer_config.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,13 @@ struct TracerConfig {
188188
// present. This is disabled by default.
189189
// This option is ignored if `resource_renaming_enabled` is not `true`.
190190
Optional<bool> resource_renaming_always_simplified_endpoint;
191+
192+
/// A mapping of process-specific tags used to uniquely identify processes.
193+
///
194+
/// The `process_tags` map allows associating arbitrary string-based keys and
195+
/// values with a process. These tags are consumed as fact for identifying
196+
/// processes.
197+
std::unordered_map<std::string, std::string> process_tags;
191198
};
192199

193200
// `FinalizedTracerConfig` contains `Tracer` implementation details derived from
@@ -229,6 +236,7 @@ class FinalizedTracerConfig final {
229236
std::shared_ptr<HTTPClient> http_client;
230237
bool tracing_enabled;
231238
HttpEndpointCalculationMode resource_renaming_mode;
239+
std::unordered_map<std::string, std::string> process_tags;
232240
};
233241

234242
// 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: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
#include "platform_util.h"
1313

14+
using namespace std::literals;
15+
1416
namespace datadog {
1517
namespace tracing {
1618
namespace {
@@ -100,6 +102,25 @@ std::string get_hostname() { return get_host_info().hostname; }
100102

101103
int get_process_id() { return GetCurrentProcessId(); }
102104

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

167-
// Perform a second pass using a regular expression for matching container IDs
168-
// in a Fargate environment. This two-step approach is used because STL
188+
// Perform a second pass using a regular expression for matching container
189+
// IDs in a Fargate environment. This two-step approach is used because STL
169190
// `regex` is relatively slow, so we avoid using it unless necessary.
170191
static const std::string uuid_regex_str =
171-
"[0-9a-f]{8}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{12}"
192+
"[0-9a-f]{8}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{"
193+
"12}"
172194
"|(?:[0-9a-f]{8}(?:-[0-9a-f]{4}){4}$)";
173195
static const std::string container_regex_str = "[0-9a-f]{64}";
174196
static const std::string task_regex_str = "[0-9a-f]{32}-\\d+";

src/datadog/tracer.cpp

Lines changed: 18 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

@@ -100,7 +103,18 @@ Tracer::Tracer(const FinalizedTracerConfig& config,
100103
});
101104
}
102105

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

106120
std::string Tracer::config() const {
@@ -130,7 +144,8 @@ std::string Tracer::config() const {
130144
return config.dump();
131145
}
132146

133-
void Tracer::store_config() {
147+
void Tracer::store_config(
148+
const std::unordered_map<std::string, std::string>& process_tags) {
134149
auto maybe_file =
135150
InMemoryFile::make(std::string("datadog-tracer-info-") + short_uuid());
136151
if (auto error = maybe_file.if_error()) {
@@ -163,7 +178,7 @@ void Tracer::store_config() {
163178
"service_name", [&](auto& buffer) { return msgpack::pack_string(buffer, defaults->service); },
164179
"service_env", [&](auto& buffer) { return msgpack::pack_string(buffer, defaults->environment); },
165180
"service_version", [&](auto& buffer) { return msgpack::pack_string(buffer, defaults->version); },
166-
"process_tags", [&](auto& buffer) { return msgpack::pack_string(buffer, ""); },
181+
"process_tags", [&](auto& buffer) { return msgpack::pack_string(buffer, join_tags(process_tags)); },
167182
"container_id", [&](auto& buffer) { return msgpack::pack_string(buffer, container_id); }
168183
);
169184
// clang-format on

src/datadog/tracer_config.cpp

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

416+
final_config.process_tags = user_config.process_tags;
417+
416418
auto agent_finalized =
417419
finalize_config(user_config.agent, final_config.logger, clock);
418420
if (auto *error = agent_finalized.if_error()) {

0 commit comments

Comments
 (0)