diff --git a/include/datadog/datadog_agent_config.h b/include/datadog/datadog_agent_config.h index b5859132..0c05d643 100644 --- a/include/datadog/datadog_agent_config.h +++ b/include/datadog/datadog_agent_config.h @@ -66,8 +66,6 @@ struct DatadogAgentConfig { // How often, in seconds, to query the Datadog Agent for remote configuration // updates. Optional remote_configuration_poll_interval_seconds; - - static Expected parse(StringView); }; class FinalizedDatadogAgentConfig { diff --git a/include/datadog/telemetry/telemetry.h b/include/datadog/telemetry/telemetry.h index c2f9a9ac..89a83216 100644 --- a/include/datadog/telemetry/telemetry.h +++ b/include/datadog/telemetry/telemetry.h @@ -1,16 +1,21 @@ #pragma once +#include +#include +#include +#include #include #include #include +#include #include +#include #include namespace datadog { namespace tracing { -class DatadogAgent; class TracerTelemetry; } // namespace tracing @@ -21,13 +26,74 @@ namespace telemetry { /// /// 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_; - /// TODO(@dmehala): Legacy dependency. - std::shared_ptr datadog_agent_; 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 @@ -37,9 +103,20 @@ class Telemetry final { /// @param metrics A vector user metrics to report. Telemetry(FinalizedConfiguration configuration, std::shared_ptr logger, - std::vector> metrics); + 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(); - ~Telemetry() = default; + // 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. /// @@ -50,6 +127,22 @@ class Telemetry final { /// /// @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(); }; } // namespace telemetry diff --git a/include/datadog/trace_segment.h b/include/datadog/trace_segment.h index f2e28e79..0622f49f 100644 --- a/include/datadog/trace_segment.h +++ b/include/datadog/trace_segment.h @@ -40,6 +40,9 @@ #include "sampling_priority.h" namespace datadog { +namespace telemetry { +class Telemetry; +} namespace tracing { class Collector; @@ -52,14 +55,13 @@ struct SpanDefaults; class SpanSampler; class TraceSampler; class ConfigManager; -class TracerTelemetry; class TraceSegment { mutable std::mutex mutex_; std::shared_ptr logger_; std::shared_ptr collector_; - std::shared_ptr tracer_telemetry_; + std::shared_ptr telemetry_; std::shared_ptr trace_sampler_; std::shared_ptr span_sampler_; @@ -82,7 +84,7 @@ class TraceSegment { public: TraceSegment(const std::shared_ptr& logger, const std::shared_ptr& collector, - const std::shared_ptr& tracer_telemetry, + 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 d7d85286..581521e9 100644 --- a/include/datadog/tracer.h +++ b/include/datadog/tracer.h @@ -10,6 +10,8 @@ // obtained from a `TracerConfig` via the `finalize_config` function. See // `tracer_config.h`. +#include + #include #include @@ -39,7 +41,7 @@ class Tracer { std::shared_ptr logger_; RuntimeID runtime_id_; TracerSignature signature_; - std::shared_ptr tracer_telemetry_; + std::shared_ptr telemetry_; std::shared_ptr config_manager_; std::shared_ptr collector_; std::shared_ptr span_sampler_; diff --git a/include/datadog/tracer_config.h b/include/datadog/tracer_config.h index db8376a5..ab8608d0 100644 --- a/include/datadog/tracer_config.h +++ b/include/datadog/tracer_config.h @@ -156,11 +156,18 @@ struct TracerConfig { // programmatic value in Datadog's Active Configuration, whereas it is // actually the default value for the integration. Optional report_service_as_default; + /// The maximum number of baggage items that can be stored or propagated. Optional baggage_max_items; + /// The maximum amount of bytes allowed to be written during tracing context /// injection. Optional baggage_max_bytes; + + /// The event scheduler used for scheduling recurring tasks. + /// By default, it uses `ThreadedEventScheduler`, which runs tasks on a + /// separate thread. + std::shared_ptr event_scheduler; }; // `FinalizedTracerConfig` contains `Tracer` implementation details derived from @@ -197,6 +204,9 @@ class FinalizedTracerConfig final { bool report_traces; std::unordered_map metadata; Baggage::Options baggage_opts; + HTTPClient::URL agent_url; + std::shared_ptr event_scheduler; + std::shared_ptr http_client; }; // Return a `FinalizedTracerConfig` from the specified `config` and from any diff --git a/src/datadog/config_manager.cpp b/src/datadog/config_manager.cpp index df4a7896..e5697e55 100644 --- a/src/datadog/config_manager.cpp +++ b/src/datadog/config_manager.cpp @@ -123,8 +123,9 @@ 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, + const std::shared_ptr& telemetry) : clock_(config.clock), default_metadata_(config.metadata), trace_sampler_( diff --git a/src/datadog/config_manager.h b/src/datadog/config_manager.h index 280fb971..0125a9ac 100644 --- a/src/datadog/config_manager.h +++ b/src/datadog/config_manager.h @@ -9,12 +9,12 @@ #include #include #include +#include #include #include #include "json.hpp" -#include "tracer_telemetry.h" namespace datadog { namespace tracing { @@ -76,7 +76,7 @@ class ConfigManager : public remote_config::Listener { DynamicConfig> span_defaults_; DynamicConfig report_traces_; - std::shared_ptr telemetry_; + std::shared_ptr telemetry_; private: template @@ -85,7 +85,7 @@ class ConfigManager : public remote_config::Listener { public: ConfigManager(const FinalizedTracerConfig& config, - const std::shared_ptr& telemetry); + const std::shared_ptr& telemetry); ~ConfigManager() override{}; remote_config::Products get_products() override; diff --git a/src/datadog/datadog_agent.cpp b/src/datadog/datadog_agent.cpp index 21e4e6c8..bea4a868 100644 --- a/src/datadog/datadog_agent.cpp +++ b/src/datadog/datadog_agent.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -19,13 +18,13 @@ #include "msgpack.h" #include "span_data.h" #include "trace_sampler.h" +#include "tracer_telemetry.h" namespace datadog { namespace tracing { namespace { constexpr StringView traces_api_path = "/v0.4/traces"; -constexpr StringView telemetry_v2_path = "/telemetry/proxy/api/v2/apmtelemetry"; constexpr StringView remote_configuration_path = "/v0.7/config"; void set_content_type_json(DictWriter& headers) { @@ -38,12 +37,6 @@ HTTPClient::URL traces_endpoint(const HTTPClient::URL& agent_url) { return traces_url; } -HTTPClient::URL telemetry_endpoint(const HTTPClient::URL& agent_url) { - auto telemetry_v2_url = agent_url; - append(telemetry_v2_url.path, telemetry_v2_path); - return telemetry_v2_url; -} - HTTPClient::URL remote_configuration_endpoint( const HTTPClient::URL& agent_url) { auto remote_configuration = agent_url; @@ -150,15 +143,14 @@ namespace rc = datadog::remote_config; DatadogAgent::DatadogAgent( const FinalizedDatadogAgentConfig& config, - const std::shared_ptr& tracer_telemetry, + const std::shared_ptr& telemetry, const std::shared_ptr& logger, const TracerSignature& tracer_signature, const std::vector>& rc_listeners) - : tracer_telemetry_(tracer_telemetry), + : telemetry_(telemetry), clock_(config.clock), logger_(logger), traces_endpoint_(traces_endpoint(config.url)), - telemetry_endpoint_(telemetry_endpoint(config.url)), remote_configuration_endpoint_(remote_configuration_endpoint(config.url)), http_client_(config.http_client), event_scheduler_(config.event_scheduler), @@ -168,47 +160,11 @@ DatadogAgent::DatadogAgent( remote_config_(tracer_signature, rc_listeners, logger), tracer_signature_(tracer_signature) { assert(logger_); - assert(tracer_telemetry_); + assert(telemetry_); tasks_.emplace_back(event_scheduler_->schedule_recurring_event( config.flush_interval, [this]() { flush(); })); - if (tracer_telemetry_->enabled()) { - // 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(); - } - })); - } - if (config.remote_configuration_enabled) { tasks_.emplace_back(event_scheduler_->schedule_recurring_event( config.remote_configuration_poll_interval, @@ -225,13 +181,6 @@ DatadogAgent::~DatadogAgent() { flush(); - if (tracer_telemetry_->enabled()) { - tracer_telemetry_->capture_metrics(); - // The app-closing message is bundled with a message containing the - // final metric values. - send_app_closing(); - } - http_client_->drain(deadline); } @@ -249,7 +198,6 @@ std::string DatadogAgent::config() const { {"type", "datadog::tracing::DatadogAgent"}, {"config", nlohmann::json::object({ {"traces_url", (traces_endpoint_.scheme + "://" + traces_endpoint_.authority + traces_endpoint_.path)}, - {"telemetry_url", (telemetry_endpoint_.scheme + "://" + telemetry_endpoint_.authority + telemetry_endpoint_.path)}, {"remote_configuration_url", (remote_configuration_endpoint_.scheme + "://" + remote_configuration_endpoint_.authority + remote_configuration_endpoint_.path)}, {"flush_interval_milliseconds", std::chrono::duration_cast(flush_interval_).count() }, {"request_timeout_milliseconds", std::chrono::duration_cast(request_timeout_).count() }, @@ -302,7 +250,7 @@ void DatadogAgent::flush() { // This is the callback for the HTTP response. It's invoked // asynchronously. - auto on_response = [telemetry = tracer_telemetry_, + auto on_response = [telemetry = telemetry_, samplers = std::move(response_handlers), logger = logger_](int response_status, const DictReader& /*response_headers*/, @@ -353,14 +301,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 = tracer_telemetry_, - logger = logger_](Error error) { + auto on_error = [telemetry = telemetry_, 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: ")); }; - tracer_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), @@ -371,58 +318,6 @@ void DatadogAgent::flush() { } } -void DatadogAgent::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"); - } - }; - - auto post_result = - http_client_->post(telemetry_endpoint_, set_telemetry_headers, - std::move(payload), telemetry_on_response_, - telemetry_on_error_, clock_().tick + request_timeout_); - if (auto* error = post_result.if_error()) { - logger_->log_error( - error->with_prefix("Unexpected error submitting telemetry event: ")); - } -} - -void DatadogAgent::send_app_started( - const std::unordered_map& config_metadata) { - send_telemetry("app-started", - tracer_telemetry_->app_started(config_metadata)); -} - -void DatadogAgent::send_heartbeat_and_telemetry() { - send_telemetry("app-heartbeat", tracer_telemetry_->heartbeat_and_telemetry()); -} - -void DatadogAgent::send_configuration_change() { - if (auto payload = tracer_telemetry_->configuration_change()) { - send_telemetry("app-client-configuration-change", *payload); - } -} - -void DatadogAgent::send_app_closing() { - send_telemetry("app-closing", tracer_telemetry_->app_closing()); -} - void DatadogAgent::get_and_apply_remote_configuration_updates() { auto remote_configuration_on_response = [this](int response_status, const DictReader& /*response_headers*/, @@ -466,7 +361,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. - send_configuration_change(); + telemetry_->send_configuration_change(); } }; diff --git a/src/datadog/datadog_agent.h b/src/datadog/datadog_agent.h index 40e712ba..36391647 100644 --- a/src/datadog/datadog_agent.h +++ b/src/datadog/datadog_agent.h @@ -17,11 +17,12 @@ #include #include -#include "config_manager.h" #include "remote_config/remote_config.h" -#include "tracer_telemetry.h" namespace datadog { +namespace telemetry { +class Telemetry; +} namespace tracing { class FinalizedDatadogAgentConfig; @@ -39,20 +40,16 @@ class DatadogAgent : public Collector { private: std::mutex mutex_; - std::shared_ptr tracer_telemetry_; + std::shared_ptr telemetry_; Clock clock_; std::shared_ptr logger_; std::vector trace_chunks_; HTTPClient::URL traces_endpoint_; - HTTPClient::URL telemetry_endpoint_; HTTPClient::URL remote_configuration_endpoint_; std::shared_ptr http_client_; std::shared_ptr event_scheduler_; std::vector tasks_; std::chrono::steady_clock::duration flush_interval_; - // Callbacks for submitting telemetry data - HTTPClient::ResponseHandler telemetry_on_response_; - HTTPClient::ErrorHandler telemetry_on_error_; std::chrono::steady_clock::duration request_timeout_; std::chrono::steady_clock::duration shutdown_timeout_; @@ -60,13 +57,10 @@ class DatadogAgent : public Collector { TracerSignature tracer_signature_; void flush(); - void send_telemetry(StringView, std::string); - void send_heartbeat_and_telemetry(); - void send_app_closing(); public: DatadogAgent(const FinalizedDatadogAgentConfig&, - const std::shared_ptr&, + const std::shared_ptr&, const std::shared_ptr&, const TracerSignature& id, const std::vector>& rc_listeners); @@ -76,11 +70,6 @@ class DatadogAgent : public Collector { std::vector>&& spans, const std::shared_ptr& response_handler) override; - void send_app_started( - const std::unordered_map& config_metadata); - - void send_configuration_change(); - void get_and_apply_remote_configuration_updates(); std::string config() const override; diff --git a/src/datadog/telemetry/telemetry.cpp b/src/datadog/telemetry/telemetry.cpp index 9e06f007..775bbe0e 100644 --- a/src/datadog/telemetry/telemetry.cpp +++ b/src/datadog/telemetry/telemetry.cpp @@ -1,42 +1,109 @@ #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 { namespace telemetry { +namespace { + +HTTPClient::URL make_telemetry_endpoint(HTTPClient::URL url) { + append(url.path, "/telemetry/proxy/api/v2/apmtelemetry"); + return url; +} +} // namespace Telemetry::Telemetry(FinalizedConfiguration config, std::shared_ptr logger, - std::vector> metrics) - : config_(std::move(config)), logger_(std::move(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); + if (!config_.enabled) { return; } - tracing::TracerSignature tracer_signature(tracing::RuntimeID::generate(), - tracing::get_process_name(), ""); - - tracer_telemetry_ = std::make_shared( - config_.enabled, tracing::default_clock, logger_, tracer_signature, - config_.integration_name, config_.integration_version, 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; + }); + } + }; - tracing::DatadogAgentConfig dd_config; - dd_config.remote_configuration_enabled = false; + // 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: ")); + }; - auto final_cfg = - tracing::finalize_config(dd_config, logger_, tracing::default_clock); - if (!final_cfg) { - return; - } + // 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(); + } + })); +} - datadog_agent_ = std::make_shared( - *final_cfg, tracer_telemetry_, logger_, tracer_signature, - std::vector>{}); +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); } void Telemetry::log_error(std::string message) { @@ -47,5 +114,63 @@ 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) { + 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 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 telemetry } // namespace datadog diff --git a/src/datadog/trace_segment.cpp b/src/datadog/trace_segment.cpp index 46444716..29104a80 100644 --- a/src/datadog/trace_segment.cpp +++ b/src/datadog/trace_segment.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -85,7 +86,7 @@ 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& tracer_telemetry, const std::shared_ptr& trace_sampler, const std::shared_ptr& span_sampler, const std::shared_ptr& defaults, @@ -101,7 +102,7 @@ TraceSegment::TraceSegment( std::unique_ptr local_root) : logger_(logger), collector_(collector), - tracer_telemetry_(tracer_telemetry), + telemetry_(tracer_telemetry), trace_sampler_(trace_sampler), span_sampler_(span_sampler), defaults_(defaults), @@ -119,7 +120,7 @@ TraceSegment::TraceSegment( config_manager_(config_manager) { assert(logger_); assert(collector_); - assert(tracer_telemetry_); + assert(telemetry_); assert(trace_sampler_); assert(span_sampler_); assert(defaults_); @@ -145,7 +146,7 @@ Optional TraceSegment::sampling_decision() const { Logger& TraceSegment::logger() const { return *logger_; } void TraceSegment::register_span(std::unique_ptr span) { - tracer_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()); @@ -154,7 +155,7 @@ void TraceSegment::register_span(std::unique_ptr span) { void TraceSegment::span_finished() { { - tracer_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()); @@ -245,7 +246,7 @@ void TraceSegment::span_finished() { } } - tracer_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 d52814e8..a4d590b4 100644 --- a/src/datadog/tracer.cpp +++ b/src/datadog/tracer.cpp @@ -46,11 +46,11 @@ Tracer::Tracer(const FinalizedTracerConfig& config, : RuntimeID::generate()), signature_{runtime_id_, config.defaults.service, config.defaults.environment}, - tracer_telemetry_(std::make_shared( - config.telemetry.enabled, config.clock, logger_, signature_, - config.integration_name, config.integration_version)), - config_manager_( - std::make_shared(config, tracer_telemetry_)), + 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_)), collector_(/* see constructor body */), span_sampler_( std::make_shared(config.span_sampler, config.clock)), @@ -74,14 +74,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, tracer_telemetry_, - config.logger, signature_, rc_listeners); + auto agent = std::make_shared( + agent_config, telemetry_, config.logger, signature_, rc_listeners); collector_ = agent; - if (tracer_telemetry_->enabled()) { - agent->send_app_started(config.metadata); - } + telemetry_->send_app_started(config.metadata); } for (const auto style : extraction_styles_) { @@ -187,9 +184,9 @@ Span Tracer::create_span(const SpanConfig& config) { } const auto span_data_ptr = span_data.get(); - tracer_telemetry_->metrics().tracer.trace_segments_created_new.inc(); + telemetry_->metrics().tracer.trace_segments_created_new.inc(); const auto segment = std::make_shared( - logger_, collector_, tracer_telemetry_, config_manager_->trace_sampler(), + 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 */, @@ -387,9 +384,9 @@ Expected Tracer::extract_span(const DictReader& reader, } const auto span_data_ptr = span_data.get(); - tracer_telemetry_->metrics().tracer.trace_segments_created_continued.inc(); + telemetry_->metrics().tracer.trace_segments_created_continued.inc(); const auto segment = std::make_shared( - logger_, collector_, tracer_telemetry_, config_manager_->trace_sampler(), + 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_, @@ -448,9 +445,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) { - tracer_telemetry_->metrics().tracer.baggage_bytes_exceeded.inc(); + telemetry_->metrics().tracer.baggage_bytes_exceeded.inc(); } else if (err->code == Error::Code::BAGGAGE_MAXIMUM_ITEMS_REACHED) { - tracer_telemetry_->metrics().tracer.baggage_items_exceeded.inc(); + telemetry_->metrics().tracer.baggage_items_exceeded.inc(); } } diff --git a/src/datadog/tracer_config.cpp b/src/datadog/tracer_config.cpp index 06983ff9..9b145004 100644 --- a/src/datadog/tracer_config.cpp +++ b/src/datadog/tracer_config.cpp @@ -14,6 +14,7 @@ #include "parse_util.h" #include "platform_util.h" #include "string_util.h" +#include "threaded_event_scheduler.h" namespace datadog { namespace tracing { @@ -397,14 +398,14 @@ Expected finalize_config(const TracerConfig &user_config, final_config.runtime_id = user_config.runtime_id; } + auto agent_finalized = + finalize_config(user_config.agent, final_config.logger, clock); + if (auto *error = agent_finalized.if_error()) { + return std::move(*error); + } if (!user_config.collector) { - auto finalized = - finalize_config(user_config.agent, final_config.logger, clock); - if (auto *error = finalized.if_error()) { - return std::move(*error); - } - final_config.collector = *finalized; - final_config.metadata.merge(finalized->metadata); + final_config.collector = *agent_finalized; + final_config.metadata.merge(agent_finalized->metadata); } else { final_config.collector = user_config.collector; } @@ -431,6 +432,17 @@ Expected finalize_config(const TracerConfig &user_config, return std::move(telemetry_final_config.error()); } + // agent url + final_config.agent_url = agent_finalized->url; + + if (user_config.event_scheduler == nullptr) { + final_config.event_scheduler = std::make_shared(); + } else { + final_config.event_scheduler = user_config.event_scheduler; + } + + final_config.http_client = agent_finalized->http_client; + return final_config; } diff --git a/src/datadog/tracer_telemetry.cpp b/src/datadog/tracer_telemetry.cpp index 7aed7da1..ed7910b7 100644 --- a/src/datadog/tracer_telemetry.cpp +++ b/src/datadog/tracer_telemetry.cpp @@ -61,6 +61,8 @@ TracerTelemetry::TracerTelemetry( bool enabled, const Clock& clock, const std::shared_ptr& logger, const TracerSignature& tracer_signature, const std::string& integration_name, const std::string& integration_version, + const std::vector>& + internal_metrics, const std::vector>& user_metrics) : enabled_(enabled), clock_(clock), @@ -74,35 +76,9 @@ TracerTelemetry::TracerTelemetry( // Register all the metrics that we're tracking by adding them to the // metrics_snapshots_ container. This allows for simpler iteration logic // when using the values in `generate-metrics` messages. - metrics_snapshots_.emplace_back(metrics_.tracer.spans_created, - MetricSnapshot{}); - metrics_snapshots_.emplace_back(metrics_.tracer.spans_finished, - MetricSnapshot{}); - metrics_snapshots_.emplace_back(metrics_.tracer.trace_segments_created_new, - MetricSnapshot{}); - metrics_snapshots_.emplace_back( - metrics_.tracer.trace_segments_created_continued, MetricSnapshot{}); - metrics_snapshots_.emplace_back(metrics_.tracer.trace_segments_closed, - MetricSnapshot{}); - metrics_snapshots_.emplace_back(metrics_.trace_api.requests, - MetricSnapshot{}); - metrics_snapshots_.emplace_back(metrics_.trace_api.responses_1xx, - MetricSnapshot{}); - metrics_snapshots_.emplace_back(metrics_.trace_api.responses_2xx, - MetricSnapshot{}); - metrics_snapshots_.emplace_back(metrics_.trace_api.responses_3xx, - MetricSnapshot{}); - metrics_snapshots_.emplace_back(metrics_.trace_api.responses_4xx, - MetricSnapshot{}); - metrics_snapshots_.emplace_back(metrics_.trace_api.responses_5xx, - MetricSnapshot{}); - metrics_snapshots_.emplace_back(metrics_.trace_api.errors_timeout, - MetricSnapshot{}); - metrics_snapshots_.emplace_back(metrics_.trace_api.errors_network, - MetricSnapshot{}); - metrics_snapshots_.emplace_back(metrics_.trace_api.errors_status_code, - MetricSnapshot{}); - + for (auto& m : internal_metrics) { + metrics_snapshots_.emplace_back(m, MetricSnapshot{}); + } for (auto& m : user_metrics_) { metrics_snapshots_.emplace_back(*m, MetricSnapshot{}); } diff --git a/src/datadog/tracer_telemetry.h b/src/datadog/tracer_telemetry.h index fc1649bc..ddd3d32e 100644 --- a/src/datadog/tracer_telemetry.h +++ b/src/datadog/tracer_telemetry.h @@ -59,61 +59,6 @@ class TracerTelemetry { uint64_t seq_id_ = 0; // Track sequence id per configuration field std::unordered_map config_seq_ids; - // 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_; // Each metric has an associated MetricSnapshot that contains the data points, // represented as a timestamp and the value of that metric. using MetricSnapshot = std::vector>; @@ -141,13 +86,12 @@ class TracerTelemetry { const TracerSignature& tracer_signature, const std::string& integration_name, const std::string& integration_version, + const std::vector>& + internal_metrics, const std::vector>& user_metrics = std::vector>{}); inline bool enabled() { return enabled_; } inline bool debug() { return debug_; } - // Provides access to the telemetry metrics for updating the values. - // This value should not be stored. - auto& metrics() { return metrics_; } // Constructs an `app-started` message using information provided when // constructed and the tracer_config value passed in. std::string app_started( diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e9273d3e..ab4f084b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -19,6 +19,7 @@ add_executable(tests # telemetry test cases telemetry/test_configuration.cpp telemetry/test_metrics.cpp + telemetry/test_telemetry.cpp # test cases test_baggage.cpp @@ -37,7 +38,6 @@ add_executable(tests test_trace_id.cpp test_trace_segment.cpp test_tracer_config.cpp - test_tracer_telemetry.cpp test_tracer.cpp test_trace_sampler.cpp diff --git a/test/mocks/http_clients.h b/test/mocks/http_clients.h index e6f0f6c0..e369b299 100644 --- a/test/mocks/http_clients.h +++ b/test/mocks/http_clients.h @@ -39,12 +39,16 @@ struct MockHTTPClient : public HTTPClient { std::mutex mutex_; ResponseHandler on_response_; ErrorHandler on_error_; + std::string request_body; + + void clear() { request_body = ""; } Expected post( - const URL&, HeadersSetter set_headers, std::string /*body*/, + const URL&, HeadersSetter set_headers, std::string body, ResponseHandler on_response, ErrorHandler on_error, std::chrono::steady_clock::time_point /*deadline*/) override { std::lock_guard lock{mutex_}; + request_body = body; if (!post_error) { on_response_ = on_response; on_error_ = on_error; diff --git a/test/test_tracer_telemetry.cpp b/test/telemetry/test_telemetry.cpp similarity index 68% rename from test/test_tracer_telemetry.cpp rename to test/telemetry/test_telemetry.cpp index 33bc7e38..0067b5bc 100644 --- a/test/test_tracer_telemetry.cpp +++ b/test/telemetry/test_telemetry.cpp @@ -2,17 +2,21 @@ // activity in other parts of the tracer implementation, and construct messages // that are sent to the datadog agent. +#include #include -#include +#include #include #include #include "datadog/runtime_id.h" +#include "mocks/event_schedulers.h" +#include "mocks/http_clients.h" #include "mocks/loggers.h" #include "test.h" using namespace datadog::tracing; +using namespace datadog::telemetry; namespace { bool is_valid_telemetry_payload(const nlohmann::json& json) { @@ -31,12 +35,27 @@ bool is_valid_telemetry_payload(const nlohmann::json& json) { TEST_CASE("Tracer telemetry", "[telemetry]") { const std::time_t mock_time = 1672484400; - const Clock clock = [mock_time]() { + const Clock clock = [&mock_time]() { TimePoint result; result.wall = std::chrono::system_clock::from_time_t(mock_time); return result; }; + auto logger = std::make_shared(); + auto client = std::make_shared(); + auto scheduler = std::make_shared(); + + auto trigger_heartbeat = [&]() { + // White box testing. The current implementation send a heartbeat every 60s + // and the task is executed every 10s. + // TODO(@dmehala): should depends on the config + scheduler->event_callback(); + scheduler->event_callback(); + scheduler->event_callback(); + scheduler->event_callback(); + scheduler->event_callback(); + scheduler->event_callback(); + }; const TracerSignature tracer_signature{ /* runtime_id = */ RuntimeID::generate(), @@ -45,16 +64,26 @@ TEST_CASE("Tracer telemetry", "[telemetry]") { const std::string ignore{""}; - TracerTelemetry tracer_telemetry{true, clock, logger, tracer_signature, - ignore, ignore}; + auto url = HTTPClient::URL::parse("http://localhost:8000"); + Telemetry telemetry{*finalize_config(), + logger, + client, + std::vector>{}, + *scheduler, + *url, + clock}; SECTION("generates app-started message") { SECTION("Without a defined integration") { - auto app_started_message = tracer_telemetry.app_started({}); - auto app_started = nlohmann::json::parse(app_started_message); + /// By default the integration is `datadog` with the tracer version. + /// TODO: remove the default because these datadog are already part of the + /// request header. + telemetry.send_app_started({}); + + auto app_started = nlohmann::json::parse(client->request_body); REQUIRE(is_valid_telemetry_payload(app_started) == true); REQUIRE(app_started["request_type"] == "message-batch"); - REQUIRE(app_started["payload"].size() == 1); + REQUIRE(app_started["payload"].size() == 2); auto& app_started_payload = app_started["payload"][0]; CHECK(app_started_payload["request_type"] == "app-started"); @@ -62,10 +91,20 @@ TEST_CASE("Tracer telemetry", "[telemetry]") { } SECTION("With an integration") { - TracerTelemetry tracer_telemetry2{ - true, clock, logger, tracer_signature, "nginx", "1.25.2"}; - auto app_started_message = tracer_telemetry2.app_started({}); - auto app_started = nlohmann::json::parse(app_started_message); + Configuration cfg; + cfg.integration_name = "nginx"; + cfg.integration_version = "1.25.2"; + Telemetry telemetry2{*finalize_config(cfg), + logger, + client, + std::vector>{}, + *scheduler, + *url}; + + client->clear(); + telemetry2.send_app_started({}); + + auto app_started = nlohmann::json::parse(client->request_body); REQUIRE(is_valid_telemetry_payload(app_started) == true); REQUIRE(app_started["request_type"] == "message-batch"); REQUIRE(app_started["payload"].size() == 2); @@ -84,12 +123,14 @@ TEST_CASE("Tracer telemetry", "[telemetry]") { ConfigMetadata(ConfigName::SERVICE_NAME, "foo", ConfigMetadata::Origin::CODE)}}; - auto app_started_message = tracer_telemetry.app_started(configuration); - auto app_started = nlohmann::json::parse(app_started_message); + client->clear(); + telemetry.send_app_started(configuration); + + auto app_started = nlohmann::json::parse(client->request_body); REQUIRE(is_valid_telemetry_payload(app_started) == true); REQUIRE(app_started["request_type"] == "message-batch"); REQUIRE(app_started["payload"].is_array()); - REQUIRE(app_started["payload"].size() == 1); + REQUIRE(app_started["payload"].size() == 2); auto& app_started_payload = app_started["payload"][0]; CHECK(app_started_payload["request_type"] == "app-started"); @@ -111,8 +152,10 @@ TEST_CASE("Tracer telemetry", "[telemetry]") { SECTION("generates a configuration change event") { SECTION("empty configuration do not generate a valid payload") { - auto config_update = tracer_telemetry.configuration_change(); - CHECK(!config_update); + client->clear(); + telemetry.send_configuration_change(); + + CHECK(client->request_body.empty()); } SECTION("valid configurations update") { @@ -122,11 +165,14 @@ TEST_CASE("Tracer telemetry", "[telemetry]") { {ConfigName::REPORT_TRACES, "", ConfigMetadata::Origin::DEFAULT, Error{Error::Code::OTHER, "empty field"}}}; - tracer_telemetry.capture_configuration_change(new_config); - auto updates = tracer_telemetry.configuration_change(); - REQUIRE(updates); + client->clear(); + telemetry.capture_configuration_change(new_config); + telemetry.send_configuration_change(); + + auto updates = client->request_body; + REQUIRE(!updates.empty()); auto config_change_message = - nlohmann::json::parse(*updates, nullptr, false); + nlohmann::json::parse(updates, nullptr, false); REQUIRE(config_change_message.is_discarded() == false); REQUIRE(is_valid_telemetry_payload(config_change_message) == true); @@ -171,14 +217,19 @@ TEST_CASE("Tracer telemetry", "[telemetry]") { } // No update -> no configuration update - CHECK(tracer_telemetry.configuration_change() == nullopt); + client->clear(); + telemetry.send_configuration_change(); + CHECK(client->request_body.empty()); } } } } SECTION("generates a heartbeat message") { - auto heartbeat_message = tracer_telemetry.heartbeat_and_telemetry(); + client->clear(); + trigger_heartbeat(); + + auto heartbeat_message = client->request_body; auto message_batch = nlohmann::json::parse(heartbeat_message); REQUIRE(is_valid_telemetry_payload(message_batch) == true); REQUIRE(message_batch["payload"].size() == 1); @@ -187,16 +238,13 @@ TEST_CASE("Tracer telemetry", "[telemetry]") { } SECTION("captures metrics and sends generate-metrics payload") { - tracer_telemetry.metrics().tracer.trace_segments_created_new.inc(); - REQUIRE( - tracer_telemetry.metrics().tracer.trace_segments_created_new.value() == - 1); - tracer_telemetry.capture_metrics(); - REQUIRE( - tracer_telemetry.metrics().tracer.trace_segments_created_new.value() == - 0); - auto heartbeat_and_telemetry_message = - tracer_telemetry.heartbeat_and_telemetry(); + telemetry.metrics().tracer.trace_segments_created_new.inc(); + REQUIRE(telemetry.metrics().tracer.trace_segments_created_new.value() == 1); + trigger_heartbeat(); + + REQUIRE(telemetry.metrics().tracer.trace_segments_created_new.value() == 0); + + auto heartbeat_and_telemetry_message = client->request_body; auto message_batch = nlohmann::json::parse(heartbeat_and_telemetry_message); REQUIRE(is_valid_telemetry_payload(message_batch) == true); REQUIRE(message_batch["payload"].size() == 2); @@ -217,8 +265,10 @@ TEST_CASE("Tracer telemetry", "[telemetry]") { } SECTION("generates an app-closing event") { - auto app_closing_message = tracer_telemetry.app_closing(); - auto message_batch = nlohmann::json::parse(app_closing_message); + client->clear(); + telemetry.send_app_closing(); + + auto message_batch = nlohmann::json::parse(client->request_body); REQUIRE(is_valid_telemetry_payload(message_batch) == true); REQUIRE(message_batch["payload"].size() == 1); auto heartbeat = message_batch["payload"][0]; diff --git a/test/test_config_manager.cpp b/test/test_config_manager.cpp index aa2f9f5c..f68cfcbb 100644 --- a/test/test_config_manager.cpp +++ b/test/test_config_manager.cpp @@ -1,9 +1,13 @@ #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" namespace rc = datadog::remote_config; + +using namespace datadog; using namespace datadog::tracing; #define CONFIG_MANAGER_TEST(x) TEST_CASE(x, "[config_manager]") @@ -26,10 +30,15 @@ CONFIG_MANAGER_TEST("remote configuration handling") { config.service = "testsvc"; config.environment = "test"; - auto tracer_telemetry = std::make_shared( - false, default_clock, nullptr, tracer_signature, "", ""); + 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(*finalize_config(config), tracer_telemetry); + ConfigManager config_manager(final_cfg, tracer_telemetry); rc::Listener::Configuration config_update{/* id = */ "id", /* path = */ "", diff --git a/test/test_datadog_agent.cpp b/test/test_datadog_agent.cpp index 532c088f..762432a3 100644 --- a/test/test_datadog_agent.cpp +++ b/test/test_datadog_agent.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -12,6 +13,7 @@ #include "mocks/loggers.h" #include "test.h" +using namespace datadog; using namespace datadog::tracing; using namespace std::chrono_literals; @@ -196,9 +198,10 @@ TEST_CASE("Remote Configuration", "[datadog_agent]") { const TracerSignature signature(RuntimeID::generate(), "testsvc", "test"); - auto telemetry = std::make_shared( - finalized->telemetry.enabled, finalized->clock, finalized->logger, - signature, "", ""); + 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);