Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ cc_library(
"src/datadog/telemetry/metrics.cpp",
"src/datadog/telemetry/log.h",
"src/datadog/telemetry/telemetry.cpp",
"src/datadog/telemetry/telemetry_impl.h",
"src/datadog/telemetry/telemetry_impl.cpp",
"src/datadog/baggage.cpp",
"src/datadog/base64.cpp",
"src/datadog/cerr_logger.cpp",
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ target_sources(dd_trace_cpp-objects
src/datadog/telemetry/configuration.cpp
src/datadog/telemetry/metrics.cpp
src/datadog/telemetry/telemetry.cpp
src/datadog/telemetry/telemetry_impl.cpp
src/datadog/baggage.cpp
src/datadog/base64.cpp
src/datadog/cerr_logger.cpp
Expand Down
72 changes: 72 additions & 0 deletions include/datadog/telemetry/metrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,25 @@ class Metric {
Metric(std::string name, std::string type, std::string scope,
std::vector<std::string> tags, bool common);

Metric(Metric&& rhs)
: name_(std::move(rhs.name_)),
type_(std::move(rhs.type_)),
scope_(std::move(rhs.scope_)),
tags_(std::move(rhs.tags_)) {
rhs.value_.store(value_.exchange(rhs.value_));
}

Metric& operator=(Metric&& rhs) {
if (&rhs != this) {
std::swap(name_, rhs.name_);
std::swap(type_, rhs.type_);
std::swap(scope_, rhs.scope_);
std::swap(tags_, rhs.tags_);
rhs.value_.store(value_.exchange(rhs.value_));
}
return *this;
}

public:
// Accessors for name, type, tags, common and capture_and_reset_value are used
// when producing the JSON message for reporting metrics.
Expand Down Expand Up @@ -70,5 +89,58 @@ class GaugeMetric : public Metric {
void sub(uint64_t amount);
};

// This structure contains all the metrics that are exposed by tracer
// telemetry.
struct DefaultMetrics {
struct {
telemetry::CounterMetric spans_created = {
"spans_created", "tracers", {}, true};
telemetry::CounterMetric spans_finished = {
"spans_finished", "tracers", {}, true};

telemetry::CounterMetric trace_segments_created_new = {
"trace_segments_created", "tracers", {"new_continued:new"}, true};
telemetry::CounterMetric trace_segments_created_continued = {
"trace_segments_created", "tracers", {"new_continued:continued"}, true};
telemetry::CounterMetric trace_segments_closed = {
"trace_segments_closed", "tracers", {}, true};
telemetry::CounterMetric baggage_items_exceeded = {
"context_header.truncated",
"tracers",
{{"truncation_reason:baggage_item_count_exceeded"}},
true,
};
telemetry::CounterMetric baggage_bytes_exceeded = {
"context_header.truncated",
"tracers",
{{"truncation_reason:baggage_byte_count_exceeded"}},
true,
};
} tracer;
struct {
telemetry::CounterMetric requests = {
"trace_api.requests", "tracers", {}, true};

telemetry::CounterMetric responses_1xx = {
"trace_api.responses", "tracers", {"status_code:1xx"}, true};
telemetry::CounterMetric responses_2xx = {
"trace_api.responses", "tracers", {"status_code:2xx"}, true};
telemetry::CounterMetric responses_3xx = {
"trace_api.responses", "tracers", {"status_code:3xx"}, true};
telemetry::CounterMetric responses_4xx = {
"trace_api.responses", "tracers", {"status_code:4xx"}, true};
telemetry::CounterMetric responses_5xx = {
"trace_api.responses", "tracers", {"status_code:5xx"}, true};

telemetry::CounterMetric errors_timeout = {
"trace_api.errors", "tracers", {"type:timeout"}, true};
telemetry::CounterMetric errors_network = {
"trace_api.errors", "tracers", {"type:network"}, true};
telemetry::CounterMetric errors_status_code = {
"trace_api.errors", "tracers", {"type:status_code"}, true};

} trace_api;
};

} // namespace telemetry
} // namespace datadog
191 changes: 66 additions & 125 deletions include/datadog/telemetry/telemetry.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,143 +7,84 @@
#include <datadog/logger.h>
#include <datadog/telemetry/configuration.h>
#include <datadog/telemetry/metrics.h>
#include <datadog/tracer_signature.h>

#include <memory>
#include <unordered_map>
#include <vector>

namespace datadog {

namespace tracing {
class TracerTelemetry;
} // namespace tracing

namespace telemetry {

/// The telemetry class is responsible for handling internal telemetry data to
/// Telemetry functions are responsibles for handling internal telemetry data to
/// track Datadog product usage. It _can_ collect and report logs and metrics.
///
/// IMPORTANT: This is intended for use only by Datadog Engineers.
class Telemetry final {
// This structure contains all the metrics that are exposed by tracer
// telemetry.
struct {
struct {
telemetry::CounterMetric spans_created = {
"spans_created", "tracers", {}, true};
telemetry::CounterMetric spans_finished = {
"spans_finished", "tracers", {}, true};

telemetry::CounterMetric trace_segments_created_new = {
"trace_segments_created", "tracers", {"new_continued:new"}, true};
telemetry::CounterMetric trace_segments_created_continued = {
"trace_segments_created",
"tracers",
{"new_continued:continued"},
true};
telemetry::CounterMetric trace_segments_closed = {
"trace_segments_closed", "tracers", {}, true};
telemetry::CounterMetric baggage_items_exceeded = {
"context_header.truncated",
"tracers",
{{"truncation_reason:baggage_item_count_exceeded"}},
true,
};
telemetry::CounterMetric baggage_bytes_exceeded = {
"context_header.truncated",
"tracers",
{{"truncation_reason:baggage_byte_count_exceeded"}},
true,
};
} tracer;
struct {
telemetry::CounterMetric requests = {
"trace_api.requests", "tracers", {}, true};

telemetry::CounterMetric responses_1xx = {
"trace_api.responses", "tracers", {"status_code:1xx"}, true};
telemetry::CounterMetric responses_2xx = {
"trace_api.responses", "tracers", {"status_code:2xx"}, true};
telemetry::CounterMetric responses_3xx = {
"trace_api.responses", "tracers", {"status_code:3xx"}, true};
telemetry::CounterMetric responses_4xx = {
"trace_api.responses", "tracers", {"status_code:4xx"}, true};
telemetry::CounterMetric responses_5xx = {
"trace_api.responses", "tracers", {"status_code:5xx"}, true};

telemetry::CounterMetric errors_timeout = {
"trace_api.errors", "tracers", {"type:timeout"}, true};
telemetry::CounterMetric errors_network = {
"trace_api.errors", "tracers", {"type:network"}, true};
telemetry::CounterMetric errors_status_code = {
"trace_api.errors", "tracers", {"type:status_code"}, true};

} trace_api;
} metrics_;

/// Configuration object containing the validated settings for telemetry
FinalizedConfiguration config_;
/// Shared pointer to the user logger instance.
std::shared_ptr<tracing::Logger> logger_;
std::shared_ptr<tracing::TracerTelemetry> tracer_telemetry_;
std::vector<tracing::EventScheduler::Cancel> tasks_;
tracing::HTTPClient::ResponseHandler telemetry_on_response_;
tracing::HTTPClient::ErrorHandler telemetry_on_error_;
tracing::HTTPClient::URL telemetry_endpoint_;
tracing::TracerSignature tracer_signature_;
std::shared_ptr<tracing::HTTPClient> http_client_;
tracing::Clock clock_;

public:
/// Constructor for the Telemetry class
///
/// @param configuration The finalized configuration settings.
/// @param logger User logger instance.
/// @param metrics A vector user metrics to report.
Telemetry(FinalizedConfiguration configuration,
std::shared_ptr<tracing::Logger> logger,
std::shared_ptr<tracing::HTTPClient> client,
std::vector<std::shared_ptr<Metric>> metrics,
tracing::EventScheduler& scheduler,
tracing::HTTPClient::URL agent_url,
tracing::Clock clock = tracing::default_clock);

/// Destructor
///
/// Send last metrics snapshot and `app-closing` event.
~Telemetry();

// Provides access to the telemetry metrics for updating the values.
// This value should not be stored.
inline auto& metrics() { return metrics_; }

/// Capture and report internal error message to Datadog.
///
/// @param message The error message.
void log_error(std::string message);

/// capture and report internal warning message to Datadog.
///
/// @param message The warning message to log.
void log_warning(std::string message);
namespace datadog::telemetry {

void send_app_started(
const std::unordered_map<tracing::ConfigName, tracing::ConfigMetadata>&
config_metadata);
/// Initialize the telemetry module
/// Once initialized, the telemetry module is running for the entier lifecycle
/// of the application.
///
/// @param configuration The finalized configuration settings.
/// @param logger User logger instance.
/// @param metrics A vector user metrics to report.
///
/// NOTE: Make sure to call `init` before calling any of the other telemetry
/// functions.
void init(FinalizedConfiguration configuration,
std::shared_ptr<tracing::Logger> logger,
std::shared_ptr<tracing::HTTPClient> client,
std::vector<std::shared_ptr<Metric>> metrics,
std::shared_ptr<tracing::EventScheduler> event_scheduler,
tracing::HTTPClient::URL agent_url,
tracing::Clock clock = tracing::default_clock);

/// Sends a notification indicating that the application has started.
///
/// This function is responsible for reporting the application has successfully
/// started. It takes a configuration map as a parameter, which contains various
/// configuration settings helping to understand how our product are used.
///
/// @param conf A map containing configuration names and their corresponding
/// metadata.
///
/// @note This function should be called after the application has completed its
/// initialization process to ensure that all components are aware of the
/// application's startup status.
void send_app_started(const std::unordered_map<tracing::ConfigName,
tracing::ConfigMetadata>& conf);

void send_configuration_change();
/// Sends configuration changes.
///
/// This function is responsible for sending reported configuration changes
/// reported by `capture_configuration_change`.
///
/// @note This function should be called _AFTER_ all configuration changes are
/// captures by `capture_configuration_change`.
void send_configuration_change();

void capture_configuration_change(
const std::vector<tracing::ConfigMetadata>& new_configuration);
/// Captures a change in the application's configuration.
///
/// This function is called to report updates to the application's
/// configuration. It takes a vector of new configuration metadata as a
/// parameter, which contains the updated settings.
///
/// @param new_configuration A vector containing the new configuration metadata.
///
/// @note This function should be invoked whenever there is a change in the
/// configuration.
void capture_configuration_change(
const std::vector<tracing::ConfigMetadata>& new_configuration);

void send_app_closing();
/// Provides access to the telemetry metrics for updating the values.
/// This value should not be stored.
DefaultMetrics& metrics();

private:
void send_telemetry(tracing::StringView request_type, std::string payload);
/// Report internal warning message to Datadog.
///
/// @param message The warning message to log.
void report_warning_log(std::string message);

void send_heartbeat_and_telemetry();
};
/// Report internal error message to Datadog.
///
/// @param message The error message.
void report_error_log(std::string message);

} // namespace telemetry
} // namespace datadog
} // namespace datadog::telemetry
2 changes: 0 additions & 2 deletions include/datadog/trace_segment.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ class TraceSegment {

std::shared_ptr<Logger> logger_;
std::shared_ptr<Collector> collector_;
std::shared_ptr<telemetry::Telemetry> telemetry_;
std::shared_ptr<TraceSampler> trace_sampler_;
std::shared_ptr<SpanSampler> span_sampler_;

Expand All @@ -84,7 +83,6 @@ class TraceSegment {
public:
TraceSegment(const std::shared_ptr<Logger>& logger,
const std::shared_ptr<Collector>& collector,
const std::shared_ptr<telemetry::Telemetry>& telemetry,
const std::shared_ptr<TraceSampler>& trace_sampler,
const std::shared_ptr<SpanSampler>& span_sampler,
const std::shared_ptr<const SpanDefaults>& defaults,
Expand Down
4 changes: 0 additions & 4 deletions include/datadog/tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
// obtained from a `TracerConfig` via the `finalize_config` function. See
// `tracer_config.h`.

#include <datadog/telemetry/telemetry.h>

#include <cstddef>
#include <memory>

Expand All @@ -28,7 +26,6 @@
namespace datadog {
namespace tracing {

class TracerTelemetry;
class ConfigManager;
class DictReader;
struct SpanConfig;
Expand All @@ -41,7 +38,6 @@ class Tracer {
std::shared_ptr<Logger> logger_;
RuntimeID runtime_id_;
TracerSignature signature_;
std::shared_ptr<telemetry::Telemetry> telemetry_;
std::shared_ptr<ConfigManager> config_manager_;
std::shared_ptr<Collector> collector_;
std::shared_ptr<SpanSampler> span_sampler_;
Expand Down
13 changes: 6 additions & 7 deletions src/datadog/config_manager.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "config_manager.h"

#include <datadog/telemetry/telemetry.h>

#include "json_serializer.h"
#include "parse_util.h"
#include "string_util.h"
Expand Down Expand Up @@ -123,17 +125,14 @@ ConfigManager::Update parse_dynamic_config(const nlohmann::json& j) {

namespace rc = datadog::remote_config;

ConfigManager::ConfigManager(
const FinalizedTracerConfig& config,
const std::shared_ptr<telemetry::Telemetry>& telemetry)
ConfigManager::ConfigManager(const FinalizedTracerConfig& config)
: clock_(config.clock),
default_metadata_(config.metadata),
trace_sampler_(
std::make_shared<TraceSampler>(config.trace_sampler, clock_)),
rules_(config.trace_sampler.rules),
span_defaults_(std::make_shared<SpanDefaults>(config.defaults)),
report_traces_(config.report_traces),
telemetry_(telemetry) {}
report_traces_(config.report_traces) {}

rc::Products ConfigManager::get_products() { return rc::product::APM_TRACING; }

Expand All @@ -153,15 +152,15 @@ Optional<std::string> ConfigManager::on_update(const Configuration& config) {
auto config_update = parse_dynamic_config(config_json.at("lib_config"));

auto config_metadata = apply_update(config_update);
telemetry_->capture_configuration_change(config_metadata);
telemetry::capture_configuration_change(config_metadata);

// TODO:
return nullopt;
}

void ConfigManager::on_revert(const Configuration&) {
auto config_metadata = apply_update({});
telemetry_->capture_configuration_change(config_metadata);
telemetry::capture_configuration_change(config_metadata);
}

std::shared_ptr<TraceSampler> ConfigManager::trace_sampler() {
Expand Down
Loading