diff --git a/BUILD.bazel b/BUILD.bazel index 9fecbd67..af291d9a 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -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", diff --git a/CMakeLists.txt b/CMakeLists.txt index 92ef08c2..a8a2cae7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/include/datadog/telemetry/metrics.h b/include/datadog/telemetry/metrics.h index c2943759..45beb464 100644 --- a/include/datadog/telemetry/metrics.h +++ b/include/datadog/telemetry/metrics.h @@ -34,6 +34,25 @@ class Metric { Metric(std::string name, std::string type, std::string scope, std::vector 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. @@ -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 diff --git a/include/datadog/telemetry/telemetry.h b/include/datadog/telemetry/telemetry.h index 89a83216..852d75f9 100644 --- a/include/datadog/telemetry/telemetry.h +++ b/include/datadog/telemetry/telemetry.h @@ -7,143 +7,84 @@ #include #include #include -#include #include #include #include -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 logger_; - std::shared_ptr tracer_telemetry_; - std::vector 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 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 logger, - std::shared_ptr client, - std::vector> 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& - 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 logger, + std::shared_ptr client, + std::vector> metrics, + std::shared_ptr 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& 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& 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& 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 diff --git a/include/datadog/trace_segment.h b/include/datadog/trace_segment.h index 0622f49f..4db61f85 100644 --- a/include/datadog/trace_segment.h +++ b/include/datadog/trace_segment.h @@ -61,7 +61,6 @@ class TraceSegment { std::shared_ptr logger_; std::shared_ptr collector_; - std::shared_ptr telemetry_; std::shared_ptr trace_sampler_; std::shared_ptr span_sampler_; @@ -84,7 +83,6 @@ class TraceSegment { public: TraceSegment(const std::shared_ptr& logger, const std::shared_ptr& collector, - const std::shared_ptr& telemetry, const std::shared_ptr& trace_sampler, const std::shared_ptr& span_sampler, const std::shared_ptr& defaults, diff --git a/include/datadog/tracer.h b/include/datadog/tracer.h index 581521e9..5c183795 100644 --- a/include/datadog/tracer.h +++ b/include/datadog/tracer.h @@ -10,8 +10,6 @@ // obtained from a `TracerConfig` via the `finalize_config` function. See // `tracer_config.h`. -#include - #include #include @@ -28,7 +26,6 @@ namespace datadog { namespace tracing { -class TracerTelemetry; class ConfigManager; class DictReader; struct SpanConfig; @@ -41,7 +38,6 @@ class Tracer { std::shared_ptr logger_; RuntimeID runtime_id_; TracerSignature signature_; - std::shared_ptr telemetry_; std::shared_ptr config_manager_; std::shared_ptr collector_; std::shared_ptr span_sampler_; diff --git a/src/datadog/config_manager.cpp b/src/datadog/config_manager.cpp index e5697e55..36b054e5 100644 --- a/src/datadog/config_manager.cpp +++ b/src/datadog/config_manager.cpp @@ -1,5 +1,7 @@ #include "config_manager.h" +#include + #include "json_serializer.h" #include "parse_util.h" #include "string_util.h" @@ -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) +ConfigManager::ConfigManager(const FinalizedTracerConfig& config) : clock_(config.clock), default_metadata_(config.metadata), trace_sampler_( std::make_shared(config.trace_sampler, clock_)), rules_(config.trace_sampler.rules), span_defaults_(std::make_shared(config.defaults)), - report_traces_(config.report_traces), - telemetry_(telemetry) {} + report_traces_(config.report_traces) {} rc::Products ConfigManager::get_products() { return rc::product::APM_TRACING; } @@ -153,7 +152,7 @@ Optional 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; @@ -161,7 +160,7 @@ Optional ConfigManager::on_update(const Configuration& config) { 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 ConfigManager::trace_sampler() { diff --git a/src/datadog/config_manager.h b/src/datadog/config_manager.h index 0125a9ac..a19824a4 100644 --- a/src/datadog/config_manager.h +++ b/src/datadog/config_manager.h @@ -9,7 +9,6 @@ #include #include #include -#include #include #include @@ -76,16 +75,13 @@ class ConfigManager : public remote_config::Listener { DynamicConfig> span_defaults_; DynamicConfig report_traces_; - std::shared_ptr telemetry_; - private: template void reset_config(ConfigName name, T& conf, std::vector& metadata); public: - ConfigManager(const FinalizedTracerConfig& config, - const std::shared_ptr& telemetry); + ConfigManager(const FinalizedTracerConfig& config); ~ConfigManager() override{}; remote_config::Products get_products() override; diff --git a/src/datadog/datadog_agent.cpp b/src/datadog/datadog_agent.cpp index bea4a868..af925797 100644 --- a/src/datadog/datadog_agent.cpp +++ b/src/datadog/datadog_agent.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -18,7 +19,6 @@ #include "msgpack.h" #include "span_data.h" #include "trace_sampler.h" -#include "tracer_telemetry.h" namespace datadog { namespace tracing { @@ -143,12 +143,10 @@ namespace rc = datadog::remote_config; DatadogAgent::DatadogAgent( const FinalizedDatadogAgentConfig& config, - const std::shared_ptr& telemetry, const std::shared_ptr& logger, const TracerSignature& tracer_signature, const std::vector>& rc_listeners) - : telemetry_(telemetry), - clock_(config.clock), + : clock_(config.clock), logger_(logger), traces_endpoint_(traces_endpoint(config.url)), remote_configuration_endpoint_(remote_configuration_endpoint(config.url)), @@ -160,7 +158,6 @@ DatadogAgent::DatadogAgent( remote_config_(tracer_signature, rc_listeners, logger), tracer_signature_(tracer_signature) { assert(logger_); - assert(telemetry_); tasks_.emplace_back(event_scheduler_->schedule_recurring_event( config.flush_interval, [this]() { flush(); })); @@ -250,21 +247,20 @@ void DatadogAgent::flush() { // This is the callback for the HTTP response. It's invoked // asynchronously. - auto on_response = [telemetry = telemetry_, - samplers = std::move(response_handlers), + auto on_response = [samplers = std::move(response_handlers), logger = logger_](int response_status, const DictReader& /*response_headers*/, std::string response_body) { if (response_status >= 500) { - telemetry->metrics().trace_api.responses_5xx.inc(); + telemetry::metrics().trace_api.responses_5xx.inc(); } else if (response_status >= 400) { - telemetry->metrics().trace_api.responses_4xx.inc(); + telemetry::metrics().trace_api.responses_4xx.inc(); } else if (response_status >= 300) { - telemetry->metrics().trace_api.responses_3xx.inc(); + telemetry::metrics().trace_api.responses_3xx.inc(); } else if (response_status >= 200) { - telemetry->metrics().trace_api.responses_2xx.inc(); + telemetry::metrics().trace_api.responses_2xx.inc(); } else if (response_status >= 100) { - telemetry->metrics().trace_api.responses_1xx.inc(); + telemetry::metrics().trace_api.responses_1xx.inc(); } if (response_status != 200) { logger->log_error([&](auto& stream) { @@ -301,13 +297,13 @@ void DatadogAgent::flush() { // This is the callback for if something goes wrong sending the // request or retrieving the response. It's invoked // asynchronously. - auto on_error = [telemetry = telemetry_, logger = logger_](Error error) { - telemetry->metrics().trace_api.errors_network.inc(); + auto on_error = [logger = logger_](Error error) { + telemetry::metrics().trace_api.errors_network.inc(); logger->log_error(error.with_prefix( "Error occurred during HTTP request for submitting traces: ")); }; - telemetry_->metrics().trace_api.requests.inc(); + telemetry::metrics().trace_api.requests.inc(); auto post_result = http_client_->post(traces_endpoint_, std::move(set_request_headers), std::move(body), std::move(on_response), @@ -361,7 +357,7 @@ void DatadogAgent::get_and_apply_remote_configuration_updates() { // and not the agent pulling from telemetry. That way telemetry will // be more flexible and could support env var to customize how often // it captures metrics. - telemetry_->send_configuration_change(); + telemetry::send_configuration_change(); } }; diff --git a/src/datadog/datadog_agent.h b/src/datadog/datadog_agent.h index 36391647..16e48da1 100644 --- a/src/datadog/datadog_agent.h +++ b/src/datadog/datadog_agent.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -20,9 +19,6 @@ #include "remote_config/remote_config.h" namespace datadog { -namespace telemetry { -class Telemetry; -} namespace tracing { class FinalizedDatadogAgentConfig; @@ -40,7 +36,6 @@ class DatadogAgent : public Collector { private: std::mutex mutex_; - std::shared_ptr telemetry_; Clock clock_; std::shared_ptr logger_; std::vector trace_chunks_; @@ -60,7 +55,6 @@ class DatadogAgent : public Collector { public: DatadogAgent(const FinalizedDatadogAgentConfig&, - const std::shared_ptr&, const std::shared_ptr&, const TracerSignature& id, const std::vector>& rc_listeners); diff --git a/src/datadog/telemetry/telemetry.cpp b/src/datadog/telemetry/telemetry.cpp index 775bbe0e..bcbc4afd 100644 --- a/src/datadog/telemetry/telemetry.cpp +++ b/src/datadog/telemetry/telemetry.cpp @@ -1,176 +1,119 @@ -#include -#include -#include -#include -#include +#include #include -#include +#include "telemetry_impl.h" -#include "datadog_agent.h" -#include "platform_util.h" -#include "tracer_telemetry.h" +namespace datadog::telemetry { +namespace details { -using namespace datadog::tracing; -using namespace std::chrono_literals; +/// NOTE(@dmehala): Generic overload function (P0051R3) like implementation. +template +struct Overload : Ts... { + using Ts::operator()...; +}; -namespace datadog { -namespace telemetry { -namespace { +/// NOTE(@dmehala): Guide required for C++17. Remove once we switch to C++20. +template +Overload(Ts...) -> Overload; -HTTPClient::URL make_telemetry_endpoint(HTTPClient::URL url) { - append(url.path, "/telemetry/proxy/api/v2/apmtelemetry"); - return url; -} +} // namespace details -} // namespace -Telemetry::Telemetry(FinalizedConfiguration config, - std::shared_ptr logger, - std::shared_ptr client, - std::vector> metrics, - tracing::EventScheduler& event_scheduler, - HTTPClient::URL agent_url, Clock clock) - : config_(std::move(config)), - logger_(std::move(logger)), - telemetry_endpoint_(make_telemetry_endpoint(agent_url)), - tracer_signature_(tracing::RuntimeID::generate(), - tracing::get_process_name(), ""), - http_client_(client), - clock_(std::move(clock)) { - tracer_telemetry_ = std::make_shared( - config_.enabled, clock_, logger_, tracer_signature_, - config_.integration_name, config_.integration_version, - std::vector>{ - {metrics_.tracer.spans_created}, - {metrics_.tracer.spans_finished}, - {metrics_.tracer.trace_segments_created_new}, - {metrics_.tracer.trace_segments_created_continued}, - {metrics_.tracer.trace_segments_closed}, - {metrics_.trace_api.requests}, - {metrics_.trace_api.responses_1xx}, - {metrics_.trace_api.responses_2xx}, - {metrics_.trace_api.responses_3xx}, - {metrics_.trace_api.responses_4xx}, - {metrics_.trace_api.responses_5xx}, - {metrics_.trace_api.errors_timeout}, - {metrics_.trace_api.errors_network}, - {metrics_.trace_api.errors_status_code}, - }, - metrics); +using NoopTelemetry = std::monostate; - if (!config_.enabled) { - return; - } +/// `TelemetryProxy` holds either the real implementation or a no-op +/// implementation. +using TelemetryProxy = std::variant; - // Callback for successful telemetry HTTP requests, to examine HTTP - // status. - telemetry_on_response_ = [logger = logger_]( - int response_status, - const DictReader& /*response_headers*/, - std::string response_body) { - if (response_status < 200 || response_status >= 300) { - logger->log_error([&](auto& stream) { - stream << "Unexpected telemetry response status " << response_status - << " with body (if any, starts on next line):\n" - << response_body; - }); - } - }; - - // Callback for unsuccessful telemetry HTTP requests. - telemetry_on_error_ = [logger = logger_](Error error) { - logger->log_error(error.with_prefix( - "Error occurred during HTTP request for telemetry: ")); - }; - - // Only schedule this if telemetry is enabled. - // Every 10 seconds, have the tracer telemetry capture the metrics - // values. Every 60 seconds, also report those values to the datadog - // agent. - tasks_.emplace_back(event_scheduler.schedule_recurring_event( - std::chrono::seconds(10), [this, n = 0]() mutable { - n++; - tracer_telemetry_->capture_metrics(); - if (n % 6 == 0) { - send_heartbeat_and_telemetry(); - } - })); -} +// NOTE(@dmehala): until metrics handling is improved. +static DefaultMetrics noop_metrics; -Telemetry::~Telemetry() { - if (!config_.enabled) return; - tracer_telemetry_->capture_metrics(); - // The app-closing message is bundled with a message containing the - // final metric values. - send_app_closing(); - http_client_->drain(clock_().tick + 1s); -} +/// NOTE(@dmehala): Here to facilitate Meyer's singleton construction. +struct Ctor_param final { + FinalizedConfiguration configuration; + std::shared_ptr logger; + std::shared_ptr client; + std::vector> metrics; + std::shared_ptr scheduler; + tracing::HTTPClient::URL agent_url; + tracing::Clock clock = tracing::default_clock; +}; -void Telemetry::log_error(std::string message) { - tracer_telemetry_->log(std::move(message), LogLevel::ERROR); +TelemetryProxy make_telemetry(const Ctor_param& init) { + if (!init.configuration.enabled) return NoopTelemetry{}; + return Telemetry{init.configuration, init.logger, init.client, + init.metrics, init.scheduler, init.agent_url, + init.clock}; } -void Telemetry::log_warning(std::string message) { - tracer_telemetry_->log(std::move(message), LogLevel::WARNING); +TelemetryProxy& instance( + const tracing::Optional& init = tracing::nullopt) { + static TelemetryProxy telemetry(make_telemetry(*init)); + return telemetry; } -void Telemetry::send_telemetry(StringView request_type, std::string payload) { - if (!config_.enabled) return; - auto set_telemetry_headers = [request_type, payload_size = payload.size(), - debug_enabled = tracer_telemetry_->debug(), - tracer_signature = - &tracer_signature_](DictWriter& headers) { - /* - TODO: - Datadog-Container-ID - */ - headers.set("Content-Type", "application/json"); - headers.set("Content-Length", std::to_string(payload_size)); - headers.set("DD-Telemetry-API-Version", "v2"); - headers.set("DD-Client-Library-Language", "cpp"); - headers.set("DD-Client-Library-Version", tracer_signature->library_version); - headers.set("DD-Telemetry-Request-Type", request_type); - - if (debug_enabled) { - headers.set("DD-Telemetry-Debug-Enabled", "true"); - } - }; - - // TODO(@dmehala): make `clock::instance()` a singleton - auto post_result = http_client_->post( - telemetry_endpoint_, set_telemetry_headers, std::move(payload), - telemetry_on_response_, telemetry_on_error_, - tracing::default_clock().tick + 5s); - if (auto* error = post_result.if_error()) { - logger_->log_error( - error->with_prefix("Unexpected error submitting telemetry event: ")); - } +void init(FinalizedConfiguration configuration, + std::shared_ptr logger, + std::shared_ptr client, + std::vector> metrics, + std::shared_ptr event_scheduler, + tracing::HTTPClient::URL agent_url, tracing::Clock clock) { + instance(Ctor_param{configuration, logger, client, metrics, event_scheduler, + agent_url, clock}); } -void Telemetry::send_app_started( - const std::unordered_map& config_metadata) { - send_telemetry("app-started", - tracer_telemetry_->app_started(config_metadata)); +void send_app_started(const std::unordered_map& conf) { + std::visit( + details::Overload{ + [&](Telemetry& telemetry) { telemetry.send_app_started(conf); }, + [](NoopTelemetry) {}, + }, + instance()); } -void Telemetry::send_app_closing() { - send_telemetry("app-closing", tracer_telemetry_->app_closing()); +void send_configuration_change() { + std::visit( + details::Overload{ + [&](Telemetry& telemetry) { telemetry.send_configuration_change(); }, + [](NoopTelemetry) {}, + }, + instance()); } -void Telemetry::send_heartbeat_and_telemetry() { - send_telemetry("app-heartbeat", tracer_telemetry_->heartbeat_and_telemetry()); +void capture_configuration_change( + const std::vector& new_configuration) { + std::visit(details::Overload{ + [&](Telemetry& telemetry) { + telemetry.capture_configuration_change(new_configuration); + }, + [](NoopTelemetry) {}, + }, + instance()); } -void Telemetry::send_configuration_change() { - if (auto payload = tracer_telemetry_->configuration_change()) { - send_telemetry("app-client-configuration-change", *payload); +DefaultMetrics& metrics() { + auto& proxy = instance(); + if (std::holds_alternative(proxy)) { + return noop_metrics; + } else { + return std::get(proxy).metrics(); } } -void Telemetry::capture_configuration_change( - const std::vector& new_configuration) { - return tracer_telemetry_->capture_configuration_change(new_configuration); +void report_warning_log(std::string message) { + std::visit(details::Overload{ + [&](Telemetry& telemetry) { telemetry.log_warning(message); }, + [](NoopTelemetry) {}, + }, + instance()); +} + +void report_error_log(std::string message) { + std::visit(details::Overload{ + [&](Telemetry& telemetry) { telemetry.log_error(message); }, + [](NoopTelemetry) {}, + }, + instance()); } -} // namespace telemetry -} // namespace datadog +} // namespace datadog::telemetry diff --git a/src/datadog/telemetry/telemetry_impl.cpp b/src/datadog/telemetry/telemetry_impl.cpp new file mode 100644 index 00000000..9e9cef8d --- /dev/null +++ b/src/datadog/telemetry/telemetry_impl.cpp @@ -0,0 +1,266 @@ +#include "telemetry_impl.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "datadog_agent.h" +#include "platform_util.h" +#include "tracer_telemetry.h" + +using namespace datadog::tracing; +using namespace std::chrono_literals; + +namespace datadog::telemetry { +namespace { + +HTTPClient::URL make_telemetry_endpoint(HTTPClient::URL url) { + append(url.path, "/telemetry/proxy/api/v2/apmtelemetry"); + return url; +} + +void cancel_tasks(std::vector& tasks) { + for (auto& cancel_task : tasks) { + cancel_task(); + } + tasks.clear(); +} + +} // namespace + +Telemetry::Telemetry(FinalizedConfiguration config, + std::shared_ptr logger, + std::shared_ptr client, + std::vector> metrics, + std::shared_ptr event_scheduler, + HTTPClient::URL agent_url, Clock clock) + : config_(std::move(config)), + logger_(std::move(logger)), + telemetry_endpoint_(make_telemetry_endpoint(agent_url)), + tracer_signature_(tracing::RuntimeID::generate(), + tracing::get_process_name(), ""), + http_client_(client), + clock_(std::move(clock)), + scheduler_(event_scheduler) { + tracer_telemetry_ = std::make_shared( + config_.enabled, clock_, logger_, tracer_signature_, + config_.integration_name, config_.integration_version, + std::vector>{ + {metrics_.tracer.spans_created}, + {metrics_.tracer.spans_finished}, + {metrics_.tracer.trace_segments_created_new}, + {metrics_.tracer.trace_segments_created_continued}, + {metrics_.tracer.trace_segments_closed}, + {metrics_.trace_api.requests}, + {metrics_.trace_api.responses_1xx}, + {metrics_.trace_api.responses_2xx}, + {metrics_.trace_api.responses_3xx}, + {metrics_.trace_api.responses_4xx}, + {metrics_.trace_api.responses_5xx}, + {metrics_.trace_api.errors_timeout}, + {metrics_.trace_api.errors_network}, + {metrics_.trace_api.errors_status_code}, + }, + metrics); + + // Callback for successful telemetry HTTP requests, to examine HTTP + // status. + telemetry_on_response_ = [logger = logger_]( + int response_status, + const DictReader& /*response_headers*/, + std::string response_body) { + if (response_status < 200 || response_status >= 300) { + logger->log_error([&](auto& stream) { + stream << "Unexpected telemetry response status " << response_status + << " with body (if any, starts on next line):\n" + << response_body; + }); + } + }; + + // Callback for unsuccessful telemetry HTTP requests. + telemetry_on_error_ = [logger = logger_](Error error) { + logger->log_error(error.with_prefix( + "Error occurred during HTTP request for telemetry: ")); + }; + + schedule_tasks(); +} + +void Telemetry::schedule_tasks() { + // Only schedule this if telemetry is enabled. + // Every 10 seconds, have the tracer telemetry capture the metrics + // values. Every 60 seconds, also report those values to the datadog + // agent. + tasks_.emplace_back(scheduler_->schedule_recurring_event( + std::chrono::seconds(10), [this, n = 0]() mutable { + n++; + tracer_telemetry_->capture_metrics(); + if (n % 6 == 0) { + send_heartbeat_and_telemetry(); + } + })); +} + +Telemetry::~Telemetry() { + if (!tasks_.empty()) { + cancel_tasks(tasks_); + tracer_telemetry_->capture_metrics(); + // The app-closing message is bundled with a message containing the + // final metric values. + send_app_closing(); + http_client_->drain(clock_().tick + 1s); + } +} + +Telemetry::Telemetry(Telemetry&& rhs) + : metrics_(std::move(rhs.metrics_)), + config_(std::move(rhs.config_)), + logger_(std::move(rhs.logger_)), + // tracer_telemetry_(std::move(rhs.tracer_telemetry_)), + telemetry_on_response_(std::move(rhs.telemetry_on_response_)), + telemetry_on_error_(std::move(rhs.telemetry_on_error_)), + telemetry_endpoint_(std::move(rhs.telemetry_endpoint_)), + tracer_signature_(std::move(rhs.tracer_signature_)), + http_client_(rhs.http_client_), + clock_(std::move(rhs.clock_)), + scheduler_(std::move(rhs.scheduler_)) { + cancel_tasks(rhs.tasks_); + + tracer_telemetry_ = std::make_shared( + config_.enabled, clock_, logger_, tracer_signature_, + config_.integration_name, config_.integration_version, + std::vector>{ + {metrics_.tracer.spans_created}, + {metrics_.tracer.spans_finished}, + {metrics_.tracer.trace_segments_created_new}, + {metrics_.tracer.trace_segments_created_continued}, + {metrics_.tracer.trace_segments_closed}, + {metrics_.trace_api.requests}, + {metrics_.trace_api.responses_1xx}, + {metrics_.trace_api.responses_2xx}, + {metrics_.trace_api.responses_3xx}, + {metrics_.trace_api.responses_4xx}, + {metrics_.trace_api.responses_5xx}, + {metrics_.trace_api.errors_timeout}, + {metrics_.trace_api.errors_network}, + {metrics_.trace_api.errors_status_code}, + }, + std::vector>{}); + schedule_tasks(); +} + +Telemetry& Telemetry::operator=(Telemetry&& rhs) { + if (&rhs != this) { + std::swap(metrics_, rhs.metrics_); + std::swap(config_, rhs.config_); + std::swap(logger_, rhs.logger_); + std::swap(tracer_telemetry_, rhs.tracer_telemetry_); + std::swap(telemetry_on_response_, rhs.telemetry_on_response_); + std::swap(telemetry_on_error_, rhs.telemetry_on_error_); + std::swap(telemetry_endpoint_, rhs.telemetry_endpoint_); + std::swap(http_client_, rhs.http_client_); + std::swap(tracer_signature_, rhs.tracer_signature_); + std::swap(http_client_, rhs.http_client_); + std::swap(clock_, rhs.clock_); + + cancel_tasks(rhs.tasks_); + + tracer_telemetry_ = std::make_shared( + config_.enabled, clock_, logger_, tracer_signature_, + config_.integration_name, config_.integration_version, + std::vector>{ + {metrics_.tracer.spans_created}, + {metrics_.tracer.spans_finished}, + {metrics_.tracer.trace_segments_created_new}, + {metrics_.tracer.trace_segments_created_continued}, + {metrics_.tracer.trace_segments_closed}, + {metrics_.trace_api.requests}, + {metrics_.trace_api.responses_1xx}, + {metrics_.trace_api.responses_2xx}, + {metrics_.trace_api.responses_3xx}, + {metrics_.trace_api.responses_4xx}, + {metrics_.trace_api.responses_5xx}, + {metrics_.trace_api.errors_timeout}, + {metrics_.trace_api.errors_network}, + {metrics_.trace_api.errors_status_code}, + }, + std::vector>{}); + schedule_tasks(); + } + return *this; +} + +void Telemetry::log_error(std::string message) { + tracer_telemetry_->log(std::move(message), LogLevel::ERROR); +} + +void Telemetry::log_warning(std::string message) { + tracer_telemetry_->log(std::move(message), LogLevel::WARNING); +} + +void Telemetry::send_telemetry(StringView request_type, std::string payload) { + auto set_telemetry_headers = [request_type, payload_size = payload.size(), + debug_enabled = tracer_telemetry_->debug(), + tracer_signature = + &tracer_signature_](DictWriter& headers) { + /* + TODO: + Datadog-Container-ID + */ + headers.set("Content-Type", "application/json"); + headers.set("Content-Length", std::to_string(payload_size)); + headers.set("DD-Telemetry-API-Version", "v2"); + headers.set("DD-Client-Library-Language", "cpp"); + headers.set("DD-Client-Library-Version", tracer_signature->library_version); + headers.set("DD-Telemetry-Request-Type", request_type); + + if (debug_enabled) { + headers.set("DD-Telemetry-Debug-Enabled", "true"); + } + }; + + // TODO(@dmehala): make `clock::instance()` a singleton + auto post_result = http_client_->post( + telemetry_endpoint_, set_telemetry_headers, std::move(payload), + telemetry_on_response_, telemetry_on_error_, + tracing::default_clock().tick + 5s); + if (auto* error = post_result.if_error()) { + logger_->log_error( + error->with_prefix("Unexpected error submitting telemetry event: ")); + } +} + +void Telemetry::send_app_started( + const std::unordered_map& + config_metadata) { + send_telemetry("app-started", + tracer_telemetry_->app_started(config_metadata)); +} + +void Telemetry::send_app_closing() { + send_telemetry("app-closing", tracer_telemetry_->app_closing()); +} + +void Telemetry::send_heartbeat_and_telemetry() { + send_telemetry("app-heartbeat", tracer_telemetry_->heartbeat_and_telemetry()); +} + +void Telemetry::send_configuration_change() { + if (auto payload = tracer_telemetry_->configuration_change()) { + send_telemetry("app-client-configuration-change", *payload); + } +} + +void Telemetry::capture_configuration_change( + const std::vector& new_configuration) { + return tracer_telemetry_->capture_configuration_change(new_configuration); +} + +} // namespace datadog::telemetry diff --git a/src/datadog/telemetry/telemetry_impl.h b/src/datadog/telemetry/telemetry_impl.h new file mode 100644 index 00000000..097cce0b --- /dev/null +++ b/src/datadog/telemetry/telemetry_impl.h @@ -0,0 +1,85 @@ +#pragma once + +#include +#include +#include +#include + +#include "tracer_telemetry.h" + +namespace datadog::telemetry { + +/// The telemetry class is responsible for handling internal telemetry data to +/// track Datadog product usage. It _can_ collect and report logs and metrics. +class Telemetry final { + DefaultMetrics metrics_; + /// Configuration object containing the validated settings for telemetry + FinalizedConfiguration config_; + /// Shared pointer to the user logger instance. + std::shared_ptr logger_; + std::shared_ptr tracer_telemetry_; + std::vector 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 http_client_; + tracing::Clock clock_; + std::shared_ptr scheduler_; + + 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 logger, + std::shared_ptr client, + std::vector> metrics, + std::shared_ptr event_scheduler, + tracing::HTTPClient::URL agent_url, + tracing::Clock clock = tracing::default_clock); + + /// Destructor + /// + /// Send last metrics snapshot and `app-closing` event. + ~Telemetry(); + + /// Move semantics. + Telemetry(Telemetry&& rhs); + Telemetry& operator=(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); + + void send_app_started( + const std::unordered_map& + config_metadata); + + void send_configuration_change(); + + void capture_configuration_change( + const std::vector& new_configuration); + + void send_app_closing(); + + private: + void send_telemetry(tracing::StringView request_type, std::string payload); + + void send_heartbeat_and_telemetry(); + void schedule_tasks(); +}; + +} // namespace datadog::telemetry diff --git a/src/datadog/trace_segment.cpp b/src/datadog/trace_segment.cpp index 29104a80..fcdcc060 100644 --- a/src/datadog/trace_segment.cpp +++ b/src/datadog/trace_segment.cpp @@ -27,7 +27,6 @@ #include "tag_propagation.h" #include "tags.h" #include "trace_sampler.h" -#include "tracer_telemetry.h" #include "w3c_propagation.h" namespace datadog { @@ -86,7 +85,6 @@ void inject_trace_tags( TraceSegment::TraceSegment( const std::shared_ptr& logger, const std::shared_ptr& collector, - const std::shared_ptr& tracer_telemetry, const std::shared_ptr& trace_sampler, const std::shared_ptr& span_sampler, const std::shared_ptr& defaults, @@ -102,7 +100,6 @@ TraceSegment::TraceSegment( std::unique_ptr local_root) : logger_(logger), collector_(collector), - telemetry_(tracer_telemetry), trace_sampler_(trace_sampler), span_sampler_(span_sampler), defaults_(defaults), @@ -120,7 +117,6 @@ TraceSegment::TraceSegment( config_manager_(config_manager) { assert(logger_); assert(collector_); - assert(telemetry_); assert(trace_sampler_); assert(span_sampler_); assert(defaults_); @@ -146,7 +142,7 @@ Optional TraceSegment::sampling_decision() const { Logger& TraceSegment::logger() const { return *logger_; } void TraceSegment::register_span(std::unique_ptr span) { - telemetry_->metrics().tracer.spans_created.inc(); + telemetry::metrics().tracer.spans_created.inc(); std::lock_guard lock(mutex_); assert(spans_.empty() || num_finished_spans_ < spans_.size()); @@ -155,7 +151,7 @@ void TraceSegment::register_span(std::unique_ptr span) { void TraceSegment::span_finished() { { - telemetry_->metrics().tracer.spans_finished.inc(); + telemetry::metrics().tracer.spans_finished.inc(); std::lock_guard lock(mutex_); ++num_finished_spans_; assert(num_finished_spans_ <= spans_.size()); @@ -246,7 +242,7 @@ void TraceSegment::span_finished() { } } - telemetry_->metrics().tracer.trace_segments_closed.inc(); + telemetry::metrics().tracer.trace_segments_closed.inc(); } void TraceSegment::override_sampling_priority(SamplingPriority priority) { diff --git a/src/datadog/tracer.cpp b/src/datadog/tracer.cpp index a4d590b4..6023924b 100644 --- a/src/datadog/tracer.cpp +++ b/src/datadog/tracer.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -26,7 +27,6 @@ #include "span_sampler.h" #include "tags.h" #include "trace_sampler.h" -#include "tracer_telemetry.h" #include "w3c_propagation.h" namespace datadog { @@ -46,11 +46,7 @@ Tracer::Tracer(const FinalizedTracerConfig& config, : RuntimeID::generate()), signature_{runtime_id_, config.defaults.service, config.defaults.environment}, - telemetry_{std::make_shared( - config.telemetry, logger_, config.http_client, - std::vector>{}, - *config.event_scheduler, config.agent_url)}, - config_manager_(std::make_shared(config, telemetry_)), + config_manager_(std::make_shared(config)), collector_(/* see constructor body */), span_sampler_( std::make_shared(config.span_sampler, config.clock)), @@ -62,6 +58,9 @@ Tracer::Tracer(const FinalizedTracerConfig& config, baggage_opts_(config.baggage_opts), baggage_injection_enabled_(false), baggage_extraction_enabled_(false) { + telemetry::init(config.telemetry, logger_, config.http_client, + std::vector>{}, + config.event_scheduler, config.agent_url); if (config.report_hostname) { hostname_ = get_hostname(); } @@ -74,11 +73,11 @@ Tracer::Tracer(const FinalizedTracerConfig& config, auto rc_listeners = agent_config.remote_configuration_listeners; rc_listeners.emplace_back(config_manager_); - auto agent = std::make_shared( - agent_config, telemetry_, config.logger, signature_, rc_listeners); + auto agent = std::make_shared(agent_config, config.logger, + signature_, rc_listeners); collector_ = agent; - telemetry_->send_app_started(config.metadata); + telemetry::send_app_started(config.metadata); } for (const auto style : extraction_styles_) { @@ -184,13 +183,12 @@ Span Tracer::create_span(const SpanConfig& config) { } const auto span_data_ptr = span_data.get(); - telemetry_->metrics().tracer.trace_segments_created_new.inc(); + telemetry::metrics().tracer.trace_segments_created_new.inc(); const auto segment = std::make_shared( - logger_, collector_, telemetry_, config_manager_->trace_sampler(), - span_sampler_, defaults, config_manager_, runtime_id_, injection_styles_, - hostname_, nullopt /* origin */, tags_header_max_size_, - std::move(trace_tags), nullopt /* sampling_decision */, - nullopt /* additional_w3c_tracestate */, + logger_, collector_, config_manager_->trace_sampler(), span_sampler_, + defaults, config_manager_, runtime_id_, injection_styles_, hostname_, + nullopt /* origin */, tags_header_max_size_, std::move(trace_tags), + nullopt /* sampling_decision */, nullopt /* additional_w3c_tracestate */, nullopt /* additional_datadog_w3c_tracestate*/, std::move(span_data)); Span span{span_data_ptr, segment, [generator = generator_]() { return generator->span_id(); }, @@ -384,13 +382,13 @@ Expected Tracer::extract_span(const DictReader& reader, } const auto span_data_ptr = span_data.get(); - telemetry_->metrics().tracer.trace_segments_created_continued.inc(); + telemetry::metrics().tracer.trace_segments_created_continued.inc(); const auto segment = std::make_shared( - logger_, collector_, telemetry_, config_manager_->trace_sampler(), - span_sampler_, config_manager_->span_defaults(), config_manager_, - runtime_id_, injection_styles_, hostname_, - std::move(merged_context.origin), tags_header_max_size_, - std::move(merged_context.trace_tags), std::move(sampling_decision), + logger_, collector_, config_manager_->trace_sampler(), span_sampler_, + config_manager_->span_defaults(), config_manager_, runtime_id_, + injection_styles_, hostname_, std::move(merged_context.origin), + tags_header_max_size_, std::move(merged_context.trace_tags), + std::move(sampling_decision), std::move(merged_context.additional_w3c_tracestate), std::move(merged_context.additional_datadog_w3c_tracestate), std::move(span_data)); @@ -445,9 +443,9 @@ Expected Tracer::inject(const Baggage& baggage, DictWriter& writer) { err->with_prefix("failed to serialize all baggage items: ")); if (err->code == Error::Code::BAGGAGE_MAXIMUM_BYTES_REACHED) { - telemetry_->metrics().tracer.baggage_bytes_exceeded.inc(); + telemetry::metrics().tracer.baggage_bytes_exceeded.inc(); } else if (err->code == Error::Code::BAGGAGE_MAXIMUM_ITEMS_REACHED) { - telemetry_->metrics().tracer.baggage_items_exceeded.inc(); + telemetry::metrics().tracer.baggage_items_exceeded.inc(); } } diff --git a/test/telemetry/test_telemetry.cpp b/test/telemetry/test_telemetry.cpp index 0067b5bc..3a8846c6 100644 --- a/test/telemetry/test_telemetry.cpp +++ b/test/telemetry/test_telemetry.cpp @@ -4,12 +4,12 @@ #include #include -#include #include #include #include "datadog/runtime_id.h" +#include "datadog/telemetry/telemetry_impl.h" #include "mocks/event_schedulers.h" #include "mocks/http_clients.h" #include "mocks/loggers.h" @@ -69,7 +69,7 @@ TEST_CASE("Tracer telemetry", "[telemetry]") { logger, client, std::vector>{}, - *scheduler, + scheduler, *url, clock}; @@ -98,7 +98,7 @@ TEST_CASE("Tracer telemetry", "[telemetry]") { logger, client, std::vector>{}, - *scheduler, + scheduler, *url}; client->clear(); diff --git a/test/test_config_manager.cpp b/test/test_config_manager.cpp index f68cfcbb..c3e6bbb5 100644 --- a/test/test_config_manager.cpp +++ b/test/test_config_manager.cpp @@ -1,7 +1,6 @@ #include "catch.hpp" #include "datadog/config_manager.h" #include "datadog/remote_config/listener.h" -#include "datadog/telemetry/telemetry.h" #include "datadog/trace_sampler.h" #include "mocks/http_clients.h" @@ -21,11 +20,6 @@ nlohmann::json load_json(std::string_view sv) { } CONFIG_MANAGER_TEST("remote configuration handling") { - const TracerSignature tracer_signature{ - /* runtime_id = */ RuntimeID::generate(), - /* service = */ "testsvc", - /* environment = */ "test"}; - TracerConfig config; config.service = "testsvc"; config.environment = "test"; @@ -33,12 +27,9 @@ CONFIG_MANAGER_TEST("remote configuration handling") { auto final_cfg = *finalize_config(config); auto http_client = std::make_shared(); - auto tracer_telemetry = std::make_shared( - *telemetry::finalize_config(), final_cfg.logger, http_client, - std::vector>{}, - *final_cfg.event_scheduler, final_cfg.agent_url); - ConfigManager config_manager(final_cfg, tracer_telemetry); + // TODO: set mock telemetry + ConfigManager config_manager(final_cfg); rc::Listener::Configuration config_update{/* id = */ "id", /* path = */ "", diff --git a/test/test_datadog_agent.cpp b/test/test_datadog_agent.cpp index 762432a3..3a9bfc7f 100644 --- a/test/test_datadog_agent.cpp +++ b/test/test_datadog_agent.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -198,16 +199,12 @@ TEST_CASE("Remote Configuration", "[datadog_agent]") { const TracerSignature signature(RuntimeID::generate(), "testsvc", "test"); - auto telemetry = std::make_shared( - *telemetry::finalize_config(), finalized->logger, http_client, - std::vector>{}, - *finalized->event_scheduler, finalized->agent_url); - - auto config_manager = std::make_shared(*finalized, telemetry); + // TODO: set telemetry mock + auto config_manager = std::make_shared(*finalized); const auto& agent_config = std::get(finalized->collector); - DatadogAgent agent(agent_config, telemetry, config.logger, signature, {}); + DatadogAgent agent(agent_config, config.logger, signature, {}); SECTION("404 do not log an error") { http_client->response_status = 404;