Skip to content

Commit

Permalink
Report integration_name and integration_version to telemetry (#82)
Browse files Browse the repository at this point in the history
  • Loading branch information
dmehala authored Jan 11, 2024
1 parent 17098c1 commit 89a8e36
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 16 deletions.
3 changes: 2 additions & 1 deletion src/datadog/tracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ Tracer::Tracer(const FinalizedTracerConfig& config,
signature_{runtime_id_, config.defaults.service,
config.defaults.environment},
tracer_telemetry_(std::make_shared<TracerTelemetry>(
config.report_telemetry, config.clock, logger_, signature_)),
config.report_telemetry, config.clock, logger_, signature_,
config.integration_name, config.integration_version)),
span_sampler_(
std::make_shared<SpanSampler>(config.span_sampler, config.clock)),
generator_(generator),
Expand Down
2 changes: 2 additions & 0 deletions src/datadog/tracer_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,8 @@ Expected<FinalizedTracerConfig> finalize_config(const TracerConfig &config,
}

result.runtime_id = config.runtime_id;
result.integration_name = config.integration_name;
result.integration_version = config.integration_version;

return result;
}
Expand Down
10 changes: 10 additions & 0 deletions src/datadog/tracer_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,14 @@ struct TracerConfig {
// such as those in the worker threads/processes of a reverse proxy, might
// specify the same `runtime_id` for all tracer instances in the same run.
Optional<RuntimeID> runtime_id;

// `integration_name` is the name of the product integrating this library.
// Example: "nginx", "envoy" or "istio".
std::string integration_name;
// `integration_version` is the version of the product integrating this
// library.
// Example: "1.2.3", "6c44da20", "2020.02.13"
std::string integration_version;
};

// `FinalizedTracerConfig` contains `Tracer` implementation details derived from
Expand Down Expand Up @@ -150,6 +158,8 @@ class FinalizedTracerConfig {
bool report_telemetry;
Optional<RuntimeID> runtime_id;
Clock clock;
std::string integration_name;
std::string integration_version;
};

// Return a `FinalizedTracerConfig` from the specified `config` and from any
Expand Down
48 changes: 39 additions & 9 deletions src/datadog/tracer_telemetry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@ namespace tracing {

TracerTelemetry::TracerTelemetry(bool enabled, const Clock& clock,
const std::shared_ptr<Logger>& logger,
const TracerSignature& tracer_signature)
const TracerSignature& tracer_signature,
const std::string& integration_name,
const std::string& integration_version)
: enabled_(enabled),
clock_(clock),
logger_(logger),
tracer_signature_(tracer_signature),
hostname_(get_hostname().value_or("hostname-unavailable")) {
hostname_(get_hostname().value_or("hostname-unavailable")),
integration_name_(integration_name),
integration_version_(integration_version) {
if (enabled_) {
// Register all the metrics that we're tracking by adding them to the
// metrics_snapshots_ container. This allows for simpler iteration logic
Expand Down Expand Up @@ -80,14 +84,40 @@ nlohmann::json TracerTelemetry::generate_telemetry_body(
}

std::string TracerTelemetry::app_started() {
auto telemetry_body = generate_telemetry_body("app-started");
// TODO: environment variables or finalized config details
telemetry_body["payload"] = nlohmann::json::object({
{"configuration", nlohmann::json::array({})},

// clang-format off
auto app_started_msg = nlohmann::json{
{"request_type", "app-started"},
{"payload", nlohmann::json{
{"configuration", nlohmann::json::array()}
}}
};

auto batch = generate_telemetry_body("message-batch");
batch["payload"] = nlohmann::json::array({
std::move(app_started_msg)
});
auto app_started_payload = telemetry_body.dump();
return app_started_payload;
// clang-format on

if (!integration_name_.empty()) {
// clang-format off
auto integration_msg = nlohmann::json{
{"request_type", "app-integrations-change"},
{"payload", nlohmann::json{
{"integrations", nlohmann::json::array({
nlohmann::json{
{"name", integration_name_},
{"version", integration_version_},
{"enabled", true}
}
})}
}}
};
// clang-format on

batch["payload"].emplace_back(std::move(integration_msg));
}

return batch.dump();
}

void TracerTelemetry::capture_metrics() {
Expand Down
6 changes: 5 additions & 1 deletion src/datadog/tracer_telemetry.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class TracerTelemetry {
std::shared_ptr<Logger> logger_;
TracerSignature tracer_signature_;
std::string hostname_;
std::string integration_name_;
std::string integration_version_;
uint64_t seq_id_ = 0;
// This structure contains all the metrics that are exposed by tracer
// telemetry.
Expand Down Expand Up @@ -100,7 +102,9 @@ class TracerTelemetry {
public:
TracerTelemetry(bool enabled, const Clock& clock,
const std::shared_ptr<Logger>& logger,
const TracerSignature& tracer_signature);
const TracerSignature& tracer_signature,
const std::string& integration_name,
const std::string& integration_version);
bool enabled() { return enabled_; };
// Provides access to the telemetry metrics for updating the values.
// This value should not be stored.
Expand Down
34 changes: 29 additions & 5 deletions test/test_tracer_telemetry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
#include <datadog/tracer_telemetry.h>

#include <datadog/json.hpp>
#include <unordered_set>

#include "datadog/runtime_id.h"
#include "mocks/loggers.h"
#include "test.h"

using namespace datadog::tracing;

TEST_CASE("Tracer telemetry") {
TEST_CASE("Tracer telemetry", "[telemetry]") {
const std::time_t mock_time = 1672484400;
const Clock clock = []() {
TimePoint result;
Expand All @@ -27,12 +28,35 @@ TEST_CASE("Tracer telemetry") {
/* service = */ "testsvc",
/* environment = */ "test"};

TracerTelemetry tracer_telemetry = {true, clock, logger, tracer_signature};
const std::string ignore{""};

TracerTelemetry tracer_telemetry{true, clock, logger, tracer_signature,
ignore, ignore};

SECTION("generates app-started message") {
auto app_started_message = tracer_telemetry.app_started();
auto app_started = nlohmann::json::parse(app_started_message);
REQUIRE(app_started["request_type"] == "app-started");
SECTION("Without a defined integration") {
auto app_started_message = tracer_telemetry.app_started();
auto app_started = nlohmann::json::parse(app_started_message);
REQUIRE(app_started["request_type"] == "message-batch");
REQUIRE(app_started["payload"].size() == 1);
CHECK(app_started["payload"][0]["request_type"] == "app-started");
}

SECTION("With an integration") {
TracerTelemetry tracer_telemetry{
true, clock, logger, tracer_signature, "nginx", "1.25.2"};
auto app_started_message = tracer_telemetry.app_started();
auto app_started = nlohmann::json::parse(app_started_message);
REQUIRE(app_started["request_type"] == "message-batch");
REQUIRE(app_started["payload"].size() == 2);

const std::unordered_set<std::string> expected{"app-started",
"app-integrations-change"};

for (const auto& payload : app_started["payload"]) {
CHECK(expected.find(payload["request_type"]) != expected.cend());
}
}
}

SECTION("generates a heartbeat message") {
Expand Down

0 comments on commit 89a8e36

Please sign in to comment.