Skip to content

Commit 89a8e36

Browse files
authored
Report integration_name and integration_version to telemetry (#82)
1 parent 17098c1 commit 89a8e36

File tree

6 files changed

+87
-16
lines changed

6 files changed

+87
-16
lines changed

src/datadog/tracer.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ Tracer::Tracer(const FinalizedTracerConfig& config,
4343
signature_{runtime_id_, config.defaults.service,
4444
config.defaults.environment},
4545
tracer_telemetry_(std::make_shared<TracerTelemetry>(
46-
config.report_telemetry, config.clock, logger_, signature_)),
46+
config.report_telemetry, config.clock, logger_, signature_,
47+
config.integration_name, config.integration_version)),
4748
span_sampler_(
4849
std::make_shared<SpanSampler>(config.span_sampler, config.clock)),
4950
generator_(generator),

src/datadog/tracer_config.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,8 @@ Expected<FinalizedTracerConfig> finalize_config(const TracerConfig &config,
366366
}
367367

368368
result.runtime_id = config.runtime_id;
369+
result.integration_name = config.integration_name;
370+
result.integration_version = config.integration_version;
369371

370372
return result;
371373
}

src/datadog/tracer_config.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,14 @@ struct TracerConfig {
119119
// such as those in the worker threads/processes of a reverse proxy, might
120120
// specify the same `runtime_id` for all tracer instances in the same run.
121121
Optional<RuntimeID> runtime_id;
122+
123+
// `integration_name` is the name of the product integrating this library.
124+
// Example: "nginx", "envoy" or "istio".
125+
std::string integration_name;
126+
// `integration_version` is the version of the product integrating this
127+
// library.
128+
// Example: "1.2.3", "6c44da20", "2020.02.13"
129+
std::string integration_version;
122130
};
123131

124132
// `FinalizedTracerConfig` contains `Tracer` implementation details derived from
@@ -150,6 +158,8 @@ class FinalizedTracerConfig {
150158
bool report_telemetry;
151159
Optional<RuntimeID> runtime_id;
152160
Clock clock;
161+
std::string integration_name;
162+
std::string integration_version;
153163
};
154164

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

src/datadog/tracer_telemetry.cpp

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,16 @@ namespace tracing {
1010

1111
TracerTelemetry::TracerTelemetry(bool enabled, const Clock& clock,
1212
const std::shared_ptr<Logger>& logger,
13-
const TracerSignature& tracer_signature)
13+
const TracerSignature& tracer_signature,
14+
const std::string& integration_name,
15+
const std::string& integration_version)
1416
: enabled_(enabled),
1517
clock_(clock),
1618
logger_(logger),
1719
tracer_signature_(tracer_signature),
18-
hostname_(get_hostname().value_or("hostname-unavailable")) {
20+
hostname_(get_hostname().value_or("hostname-unavailable")),
21+
integration_name_(integration_name),
22+
integration_version_(integration_version) {
1923
if (enabled_) {
2024
// Register all the metrics that we're tracking by adding them to the
2125
// metrics_snapshots_ container. This allows for simpler iteration logic
@@ -80,14 +84,40 @@ nlohmann::json TracerTelemetry::generate_telemetry_body(
8084
}
8185

8286
std::string TracerTelemetry::app_started() {
83-
auto telemetry_body = generate_telemetry_body("app-started");
84-
// TODO: environment variables or finalized config details
85-
telemetry_body["payload"] = nlohmann::json::object({
86-
{"configuration", nlohmann::json::array({})},
87-
87+
// clang-format off
88+
auto app_started_msg = nlohmann::json{
89+
{"request_type", "app-started"},
90+
{"payload", nlohmann::json{
91+
{"configuration", nlohmann::json::array()}
92+
}}
93+
};
94+
95+
auto batch = generate_telemetry_body("message-batch");
96+
batch["payload"] = nlohmann::json::array({
97+
std::move(app_started_msg)
8898
});
89-
auto app_started_payload = telemetry_body.dump();
90-
return app_started_payload;
99+
// clang-format on
100+
101+
if (!integration_name_.empty()) {
102+
// clang-format off
103+
auto integration_msg = nlohmann::json{
104+
{"request_type", "app-integrations-change"},
105+
{"payload", nlohmann::json{
106+
{"integrations", nlohmann::json::array({
107+
nlohmann::json{
108+
{"name", integration_name_},
109+
{"version", integration_version_},
110+
{"enabled", true}
111+
}
112+
})}
113+
}}
114+
};
115+
// clang-format on
116+
117+
batch["payload"].emplace_back(std::move(integration_msg));
118+
}
119+
120+
return batch.dump();
91121
}
92122

93123
void TracerTelemetry::capture_metrics() {

src/datadog/tracer_telemetry.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ class TracerTelemetry {
4646
std::shared_ptr<Logger> logger_;
4747
TracerSignature tracer_signature_;
4848
std::string hostname_;
49+
std::string integration_name_;
50+
std::string integration_version_;
4951
uint64_t seq_id_ = 0;
5052
// This structure contains all the metrics that are exposed by tracer
5153
// telemetry.
@@ -100,7 +102,9 @@ class TracerTelemetry {
100102
public:
101103
TracerTelemetry(bool enabled, const Clock& clock,
102104
const std::shared_ptr<Logger>& logger,
103-
const TracerSignature& tracer_signature);
105+
const TracerSignature& tracer_signature,
106+
const std::string& integration_name,
107+
const std::string& integration_version);
104108
bool enabled() { return enabled_; };
105109
// Provides access to the telemetry metrics for updating the values.
106110
// This value should not be stored.

test/test_tracer_telemetry.cpp

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@
66
#include <datadog/tracer_telemetry.h>
77

88
#include <datadog/json.hpp>
9+
#include <unordered_set>
910

1011
#include "datadog/runtime_id.h"
1112
#include "mocks/loggers.h"
1213
#include "test.h"
1314

1415
using namespace datadog::tracing;
1516

16-
TEST_CASE("Tracer telemetry") {
17+
TEST_CASE("Tracer telemetry", "[telemetry]") {
1718
const std::time_t mock_time = 1672484400;
1819
const Clock clock = []() {
1920
TimePoint result;
@@ -27,12 +28,35 @@ TEST_CASE("Tracer telemetry") {
2728
/* service = */ "testsvc",
2829
/* environment = */ "test"};
2930

30-
TracerTelemetry tracer_telemetry = {true, clock, logger, tracer_signature};
31+
const std::string ignore{""};
32+
33+
TracerTelemetry tracer_telemetry{true, clock, logger, tracer_signature,
34+
ignore, ignore};
3135

3236
SECTION("generates app-started message") {
33-
auto app_started_message = tracer_telemetry.app_started();
34-
auto app_started = nlohmann::json::parse(app_started_message);
35-
REQUIRE(app_started["request_type"] == "app-started");
37+
SECTION("Without a defined integration") {
38+
auto app_started_message = tracer_telemetry.app_started();
39+
auto app_started = nlohmann::json::parse(app_started_message);
40+
REQUIRE(app_started["request_type"] == "message-batch");
41+
REQUIRE(app_started["payload"].size() == 1);
42+
CHECK(app_started["payload"][0]["request_type"] == "app-started");
43+
}
44+
45+
SECTION("With an integration") {
46+
TracerTelemetry tracer_telemetry{
47+
true, clock, logger, tracer_signature, "nginx", "1.25.2"};
48+
auto app_started_message = tracer_telemetry.app_started();
49+
auto app_started = nlohmann::json::parse(app_started_message);
50+
REQUIRE(app_started["request_type"] == "message-batch");
51+
REQUIRE(app_started["payload"].size() == 2);
52+
53+
const std::unordered_set<std::string> expected{"app-started",
54+
"app-integrations-change"};
55+
56+
for (const auto& payload : app_started["payload"]) {
57+
CHECK(expected.find(payload["request_type"]) != expected.cend());
58+
}
59+
}
3660
}
3761

3862
SECTION("generates a heartbeat message") {

0 commit comments

Comments
 (0)