@@ -22,13 +22,20 @@ namespace tracing {
2222namespace {
2323
2424const StringView traces_api_path = " /v0.4/traces" ;
25+ const StringView telemetry_v2_path = " /telemetry/proxy/api/v2/apmtelemetry" ;
2526
2627HTTPClient::URL traces_endpoint (const HTTPClient::URL& agent_url) {
2728 auto traces_url = agent_url;
2829 append (traces_url.path , traces_api_path);
2930 return traces_url;
3031}
3132
33+ HTTPClient::URL telemetry_endpoint (const HTTPClient::URL& agent_url) {
34+ auto telemetry_v2_url = agent_url;
35+ append (telemetry_v2_url.path , telemetry_v2_path);
36+ return telemetry_v2_url;
37+ }
38+
3239Expected<void > msgpack_encode (
3340 std::string& destination,
3441 const std::vector<DatadogAgent::TraceChunk>& trace_chunks) {
@@ -124,18 +131,30 @@ std::variant<CollectorResponse, std::string> parse_agent_traces_response(
124131
125132} // namespace
126133
127- DatadogAgent::DatadogAgent (const FinalizedDatadogAgentConfig& config,
128- const Clock& clock,
129- const std::shared_ptr<Logger>& logger)
130- : clock_(clock),
134+ DatadogAgent::DatadogAgent (
135+ const FinalizedDatadogAgentConfig& config,
136+ const std::shared_ptr<TracerTelemetry>& tracer_telemetry,
137+ const Clock& clock, const std::shared_ptr<Logger>& logger)
138+ : tracer_telemetry_(tracer_telemetry),
139+ clock_ (clock),
131140 logger_(logger),
132141 traces_endpoint_(traces_endpoint(config.url)),
142+ telemetry_endpoint_(telemetry_endpoint(config.url)),
133143 http_client_(config.http_client),
134144 event_scheduler_(config.event_scheduler),
135145 cancel_scheduled_flush_(event_scheduler_->schedule_recurring_event (
136146 config.flush_interval, [this ]() { flush (); })),
147+ cancel_heartbeat_timer_(event_scheduler_->schedule_recurring_event (
148+ std::chrono::seconds (10 ), [this, n=0]() mutable {
149+ n++;
150+ tracer_telemetry_->captureMetrics ();
151+ if (n%6 == 0 ) {
152+ sendHeartbeatAndTelemetry ();
153+ }
154+ })),
137155 flush_interval_(config.flush_interval) {
138156 assert (logger_);
157+ sendAppStarted ();
139158}
140159
141160DatadogAgent::~DatadogAgent () {
@@ -154,7 +173,6 @@ Expected<void> DatadogAgent::send(
154173}
155174
156175nlohmann::json DatadogAgent::config_json () const {
157- const auto & url = traces_endpoint_; // brevity
158176 const auto flush_interval_milliseconds =
159177 std::chrono::duration_cast<std::chrono::milliseconds>(flush_interval_)
160178 .count ();
@@ -163,7 +181,8 @@ nlohmann::json DatadogAgent::config_json() const {
163181 return nlohmann::json::object ({
164182 {" type" , " datadog::tracing::DatadogAgent" },
165183 {" config" , nlohmann::json::object ({
166- {" url" , (url.scheme + " ://" + url.authority + url.path )},
184+ {" traces_url" , (traces_endpoint_.scheme + " ://" + traces_endpoint_.authority + traces_endpoint_.path )},
185+ {" telemetry_url" , (telemetry_endpoint_.scheme + " ://" + telemetry_endpoint_.authority + telemetry_endpoint_.path )},
167186 {" flush_interval_milliseconds" , flush_interval_milliseconds},
168187 {" http_client" , http_client_->config_json ()},
169188 {" event_scheduler" , event_scheduler_->config_json ()},
@@ -251,10 +270,11 @@ void DatadogAgent::flush() {
251270 // request or retrieving the response. It's invoked
252271 // asynchronously.
253272 auto on_error = [logger = logger_](Error error) {
254- logger->log_error (
255- error. with_prefix ( " Error occurred during HTTP request: " ));
273+ logger->log_error (error. with_prefix (
274+ " Error occurred during HTTP request for submitting traces : " ));
256275 };
257276
277+ tracer_telemetry_->trace_api_requests ().inc ();
258278 auto post_result = http_client_->post (
259279 traces_endpoint_, std::move (set_request_headers), std::move (body),
260280 std::move (on_response), std::move (on_error));
@@ -263,5 +283,87 @@ void DatadogAgent::flush() {
263283 }
264284}
265285
286+ void DatadogAgent::sendAppStarted () {
287+ auto payload = tracer_telemetry_->appStarted ();
288+ auto set_request_headers = [&](DictWriter& headers) {
289+ headers.set (" Content-Type" , " application/json" );
290+ };
291+
292+ // Callback for a successful HTTP request, to examine HTTP status.
293+ auto on_response = [logger = logger_](int response_status,
294+ const DictReader& /* response_headers*/ ,
295+ std::string response_body) {
296+ if (response_status < 200 || response_status >= 300 ) {
297+ logger->log_error ([&](auto & stream) {
298+ stream << " Unexpected telemetry response status " << response_status
299+ << " with body (starts on next line):\n "
300+ << response_body;
301+ });
302+ return ;
303+ } else {
304+ logger->log_error ([&](auto & stream) {
305+ stream << " Successful telemetry submission with response status " << response_status
306+ << " and body (starts on next line):\n "
307+ << response_body;
308+ });
309+ }
310+
311+ };
312+
313+ // Callback for unsuccessful HTTP request.
314+ auto on_error = [logger = logger_](Error error) {
315+ logger->log_error (error.with_prefix (
316+ " Error occurred during HTTP request for telemetry: " ));
317+ };
318+
319+ auto post_result = http_client_->post (
320+ telemetry_endpoint_, std::move (set_request_headers), std::move (payload),
321+ std::move (on_response), std::move (on_error));
322+ if (auto * error = post_result.if_error ()) {
323+ logger_->log_error (*error);
324+ }
325+ }
326+
327+ void DatadogAgent::sendHeartbeatAndTelemetry () {
328+ auto payload = tracer_telemetry_->heartbeatAndTelemetry ();
329+ auto set_request_headers = [&](DictWriter& headers) {
330+ headers.set (" Content-Type" , " application/json" );
331+ };
332+
333+ // Callback for a successful HTTP request, to examine HTTP status.
334+ auto on_response = [logger = logger_](int response_status,
335+ const DictReader& /* response_headers*/ ,
336+ std::string response_body) {
337+ if (response_status < 200 || response_status >= 300 ) {
338+ logger->log_error ([&](auto & stream) {
339+ stream << " Unexpected telemetry response status " << response_status
340+ << " with body (starts on next line):\n "
341+ << response_body;
342+ });
343+ return ;
344+ } else {
345+ logger->log_error ([&](auto & stream) {
346+ stream << " Successful telemetry submission with response status " << response_status
347+ << " and body (starts on next line):\n "
348+ << response_body;
349+ });
350+ }
351+
352+ };
353+
354+ // Callback for unsuccessful HTTP request.
355+ auto on_error = [logger = logger_](Error error) {
356+ logger->log_error (error.with_prefix (
357+ " Error occurred during HTTP request for telemetry: " ));
358+ };
359+
360+ auto post_result = http_client_->post (
361+ telemetry_endpoint_, std::move (set_request_headers), std::move (payload),
362+ std::move (on_response), std::move (on_error));
363+ if (auto * error = post_result.if_error ()) {
364+ logger_->log_error (*error);
365+ }
366+ }
367+
266368} // namespace tracing
267369} // namespace datadog
0 commit comments