Skip to content

Commit 1a632bc

Browse files
authored
feat: add telemetry logs (#185)
1 parent f3ebccc commit 1a632bc

File tree

10 files changed

+125
-6
lines changed

10 files changed

+125
-6
lines changed

BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ cc_library(
33
srcs = [
44
"src/datadog/telemetry/configuration.cpp",
55
"src/datadog/telemetry/metrics.cpp",
6+
"src/datadog/telemetry/log.h",
67
"src/datadog/telemetry/telemetry.cpp",
78
"src/datadog/base64.cpp",
89
"src/datadog/cerr_logger.cpp",

include/datadog/environment.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ namespace environment {
5454
MACRO(DD_TELEMETRY_HEARTBEAT_INTERVAL) \
5555
MACRO(DD_TELEMETRY_METRICS_ENABLED) \
5656
MACRO(DD_TELEMETRY_METRICS_INTERVAL_SECONDS) \
57-
MACRO(DD_TELEMETRY_DEBUG)
57+
MACRO(DD_TELEMETRY_DEBUG) \
58+
MACRO(DD_TELEMETRY_LOG_COLLECTION_ENABLED)
5859

5960
#define WITH_COMMA(ARG) ARG,
6061

include/datadog/telemetry/configuration.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,18 @@ struct Configuration {
3333
// library.
3434
// Example: "1.2.3", "6c44da20", "2020.02.13"
3535
tracing::Optional<std::string> integration_version;
36+
// Enable or disable telemetry logs collection.
37+
// Default: enabled.
38+
// Can be overriden by the `DD_TELEMETRY_LOG_COLLECTION_ENABLED` environment
39+
// variable.
40+
tracing::Optional<bool> report_logs;
3641
};
3742

3843
struct FinalizedConfiguration {
3944
bool debug;
4045
bool enabled;
4146
bool report_metrics;
47+
bool report_logs;
4248
std::chrono::steady_clock::duration metrics_interval;
4349
std::chrono::steady_clock::duration heartbeat_interval;
4450
std::string integration_name;

include/datadog/telemetry/telemetry.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,40 @@ class TracerTelemetry;
1616

1717
namespace telemetry {
1818

19-
class Telemetry {
19+
/// The telemetry class is responsible for handling internal telemetry data to
20+
/// track Datadog product usage. It _can_ collect and report logs and metrics.
21+
///
22+
/// IMPORTANT: This is intended for use only by Datadog Engineers.
23+
class Telemetry final {
24+
/// Configuration object containing the validated settings for telemetry
2025
FinalizedConfiguration config_;
26+
/// Shared pointer to the user logger instance.
2127
std::shared_ptr<tracing::Logger> logger_;
22-
28+
/// TODO(@dmehala): Legacy dependency.
2329
std::shared_ptr<tracing::DatadogAgent> datadog_agent_;
2430
std::shared_ptr<tracing::TracerTelemetry> tracer_telemetry_;
2531

2632
public:
33+
/// Constructor for the Telemetry class
34+
///
35+
/// @param configuration The finalized configuration settings.
36+
/// @param logger User logger instance.
37+
/// @param metrics A vector user metrics to report.
2738
Telemetry(FinalizedConfiguration configuration,
2839
std::shared_ptr<tracing::Logger> logger,
2940
std::vector<std::shared_ptr<Metric>> metrics);
3041

3142
~Telemetry() = default;
43+
44+
/// Capture and report internal error message to Datadog.
45+
///
46+
/// @param message The error message.
47+
void log_error(std::string message);
48+
49+
/// capture and report internal warning message to Datadog.
50+
///
51+
/// @param message The warning message to log.
52+
void log_warning(std::string message);
3253
};
3354

3455
} // namespace telemetry

src/datadog/telemetry/configuration.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ tracing::Expected<Configuration> load_telemetry_env_config() {
2424
env_cfg.report_metrics = !falsy(*metrics_enabled);
2525
}
2626

27+
if (auto logs_enabled =
28+
lookup(environment::DD_TELEMETRY_LOG_COLLECTION_ENABLED)) {
29+
env_cfg.report_logs = !falsy(*logs_enabled);
30+
}
31+
2732
if (auto metrics_interval_seconds =
2833
lookup(environment::DD_TELEMETRY_METRICS_INTERVAL_SECONDS)) {
2934
auto maybe_value = parse_double(*metrics_interval_seconds);
@@ -66,10 +71,15 @@ tracing::Expected<FinalizedConfiguration> finalize_config(
6671
// NOTE(@dmehala): if the telemetry module is disabled then report metrics
6772
// is also disabled.
6873
result.report_metrics = false;
74+
result.report_logs = false;
6975
} else {
7076
// report_metrics
7177
std::tie(origin, result.report_metrics) =
7278
pick(env_config->report_metrics, user_config.report_metrics, true);
79+
80+
// report_logs
81+
std::tie(origin, result.report_logs) =
82+
pick(env_config->report_logs, user_config.report_logs, true);
7383
}
7484

7585
// debug

src/datadog/telemetry/log.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <string>
2+
3+
namespace datadog::telemetry {
4+
5+
enum class LogLevel : char { ERROR, WARNING };
6+
7+
struct LogMessage final {
8+
std::string message;
9+
LogLevel level;
10+
};
11+
12+
} // namespace datadog::telemetry

src/datadog/telemetry/telemetry.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,13 @@ Telemetry::Telemetry(FinalizedConfiguration config,
3939
std::vector<std::shared_ptr<remote_config::Listener>>{});
4040
}
4141

42+
void Telemetry::log_error(std::string message) {
43+
tracer_telemetry_->log(std::move(message), LogLevel::ERROR);
44+
}
45+
46+
void Telemetry::log_warning(std::string message) {
47+
tracer_telemetry_->log(std::move(message), LogLevel::WARNING);
48+
}
49+
4250
} // namespace telemetry
4351
} // namespace datadog

src/datadog/tracer_telemetry.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,27 @@ std::string TracerTelemetry::heartbeat_and_telemetry() {
292292
batch_payloads.emplace_back(std::move(generate_metrics));
293293
}
294294

295+
if (!logs_.empty()) {
296+
auto encoded_logs = nlohmann::json::array();
297+
for (const auto& log : logs_) {
298+
auto encoded =
299+
nlohmann::json{{"message", log.message}, {"level", log.level}};
300+
encoded_logs.emplace_back(std::move(encoded));
301+
}
302+
303+
assert(!encoded_logs.empty());
304+
305+
auto logs_payload = nlohmann::json::object({
306+
{"request_type", "logs"},
307+
{"payload",
308+
nlohmann::json{
309+
{"logs", encoded_logs},
310+
}},
311+
});
312+
313+
batch_payloads.emplace_back(std::move(logs_payload));
314+
}
315+
295316
auto telemetry_body = generate_telemetry_body("message-batch");
296317
telemetry_body["payload"] = batch_payloads;
297318
auto message_batch_payload = telemetry_body.dump();
@@ -348,6 +369,27 @@ std::string TracerTelemetry::app_closing() {
348369
batch_payloads.emplace_back(std::move(generate_metrics));
349370
}
350371

372+
if (!logs_.empty()) {
373+
auto encoded_logs = nlohmann::json::array();
374+
for (const auto& log : logs_) {
375+
auto encoded =
376+
nlohmann::json{{"message", log.message}, {"level", log.level}};
377+
encoded_logs.emplace_back(std::move(encoded));
378+
}
379+
380+
assert(!encoded_logs.empty());
381+
382+
auto logs_payload = nlohmann::json::object({
383+
{"request_type", "logs"},
384+
{"payload",
385+
nlohmann::json{
386+
{"logs", encoded_logs},
387+
}},
388+
});
389+
390+
batch_payloads.emplace_back(std::move(logs_payload));
391+
}
392+
351393
auto telemetry_body = generate_telemetry_body("message-batch");
352394
telemetry_body["payload"] = batch_payloads;
353395
auto message_batch_payload = telemetry_body.dump();

src/datadog/tracer_telemetry.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
#include "json.hpp"
4040
#include "platform_util.h"
41+
#include "telemetry/log.h"
4142

4243
namespace datadog {
4344
namespace tracing {
@@ -47,7 +48,7 @@ struct SpanDefaults;
4748

4849
class TracerTelemetry {
4950
bool enabled_ = false;
50-
bool debug_ = false;
51+
bool debug_ = true;
5152
Clock clock_;
5253
std::shared_ptr<Logger> logger_;
5354
HostInfo host_info_;
@@ -120,6 +121,8 @@ class TracerTelemetry {
120121

121122
std::vector<std::shared_ptr<telemetry::Metric>> user_metrics_;
122123

124+
std::vector<telemetry::LogMessage> logs_;
125+
123126
public:
124127
TracerTelemetry(
125128
bool enabled, const Clock& clock, const std::shared_ptr<Logger>& logger,
@@ -151,6 +154,10 @@ class TracerTelemetry {
151154
std::string app_closing();
152155
// Construct an `app-client-configuration-change` message.
153156
Optional<std::string> configuration_change();
157+
158+
inline void log(std::string message, telemetry::LogLevel level) {
159+
logs_.emplace_back(telemetry::LogMessage{std::move(message), level});
160+
}
154161
};
155162

156163
} // namespace tracing

test/telemetry/test_configuration.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
#include <datadog/environment.h>
22
#include <datadog/telemetry/configuration.h>
33

4-
#include <chrono>
5-
64
#include "../common/environment.h"
75
#include "../test.h"
86

@@ -19,6 +17,7 @@ TELEMETRY_CONFIGURATION_TEST("defaults") {
1917
REQUIRE(cfg);
2018
CHECK(cfg->debug == false);
2119
CHECK(cfg->enabled == true);
20+
CHECK(cfg->report_logs == true);
2221
CHECK(cfg->report_metrics == true);
2322
CHECK(cfg->metrics_interval == 60s);
2423
CHECK(cfg->heartbeat_interval == 10s);
@@ -27,6 +26,7 @@ TELEMETRY_CONFIGURATION_TEST("defaults") {
2726
TELEMETRY_CONFIGURATION_TEST("code override") {
2827
telemetry::Configuration cfg;
2928
cfg.enabled = false;
29+
cfg.report_logs = false;
3030
cfg.report_metrics = false;
3131
cfg.metrics_interval_seconds = 1;
3232
cfg.heartbeat_interval_seconds = 2;
@@ -37,6 +37,7 @@ TELEMETRY_CONFIGURATION_TEST("code override") {
3737
REQUIRE(final_cfg);
3838
CHECK(final_cfg->enabled == false);
3939
CHECK(final_cfg->debug == false);
40+
CHECK(final_cfg->report_logs == false);
4041
CHECK(final_cfg->report_metrics == false);
4142
CHECK(final_cfg->metrics_interval == 1s);
4243
CHECK(final_cfg->heartbeat_interval == 2s);
@@ -48,11 +49,13 @@ TELEMETRY_CONFIGURATION_TEST("enabled and report metrics precedence") {
4849
SECTION("enabled takes precedence over metrics enabled") {
4950
telemetry::Configuration cfg;
5051
cfg.enabled = false;
52+
cfg.report_logs = true;
5153
cfg.report_metrics = true;
5254

5355
auto final_cfg = finalize_config(cfg);
5456
REQUIRE(final_cfg);
5557
CHECK(final_cfg->enabled == false);
58+
CHECK(final_cfg->report_logs == false);
5659
CHECK(final_cfg->report_metrics == false);
5760
}
5861
}
@@ -84,6 +87,14 @@ TELEMETRY_CONFIGURATION_TEST("environment environment override") {
8487
CHECK(final_cfg->report_metrics == false);
8588
}
8689

90+
SECTION("Override `report_logs` field") {
91+
cfg.report_logs = true;
92+
ddtest::EnvGuard env("DD_TELEMETRY_LOG_COLLECTION_ENABLED", "false");
93+
auto final_cfg = telemetry::finalize_config(cfg);
94+
REQUIRE(final_cfg);
95+
CHECK(final_cfg->report_logs == false);
96+
}
97+
8798
SECTION("Override metrics interval") {
8899
cfg.metrics_interval_seconds = 88;
89100
ddtest::EnvGuard env("DD_TELEMETRY_METRICS_INTERVAL_SECONDS", "15");

0 commit comments

Comments
 (0)