Skip to content

feat: support disablement of APM Tracing (the product) #224

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ cc_library(
"src/datadog/string_util.cpp",
"src/datadog/tag_propagation.cpp",
"src/datadog/tags.cpp",
"src/datadog/trace_source.cpp",
"src/datadog/telemetry_metrics.cpp",
"src/datadog/threaded_event_scheduler.cpp",
"src/datadog/tracer_config.cpp",
Expand Down Expand Up @@ -117,6 +118,7 @@ cc_library(
"include/datadog/tracer_config.h",
"include/datadog/tracer_signature.h",
"include/datadog/trace_id.h",
"include/datadog/trace_source.h",
"include/datadog/trace_sampler_config.h",
"include/datadog/trace_segment.h",
"include/datadog/version.h",
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ target_sources(dd_trace_cpp-objects
src/datadog/trace_sampler_config.cpp
src/datadog/trace_sampler.cpp
src/datadog/trace_segment.cpp
src/datadog/trace_source.cpp
src/datadog/telemetry_metrics.cpp
src/datadog/version.cpp
src/datadog/w3c_propagation.cpp
Expand Down
1 change: 1 addition & 0 deletions include/datadog/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ enum class ConfigName : char {
SPAN_SAMPLING_RULES,
TRACE_BAGGAGE_MAX_BYTES,
TRACE_BAGGAGE_MAX_ITEMS,
APM_TRACING_ENABLED,
};

// Represents metadata for configuration parameters
Expand Down
6 changes: 5 additions & 1 deletion include/datadog/datadog_agent_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#include "expected.h"
#include "http_client.h"
#include "remote_config/listener.h"
#include "string_view.h"

namespace datadog {
namespace tracing {
Expand Down Expand Up @@ -90,6 +89,11 @@ class FinalizedDatadogAgentConfig {

// Origin detection
Optional<std::string> admission_controller_uid;

// Indicate if stats computation should be delegated to the Agent.
// This feature is not supported yet, however, we need to inform the Agent to
// not compute stats when APM Tracing `DD_APM_TRACING_ENABLED` is disabled.
bool stats_computation_enabled;
};

Expected<FinalizedDatadogAgentConfig> finalize_config(
Expand Down
3 changes: 3 additions & 0 deletions include/datadog/dict_writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ class DictWriter {
// implementation may, but is not required to, overwrite any previous value at
// `key`.
virtual void set(StringView key, StringView value) = 0;

// Removes the entry associated with the given key.
virtual void erase(StringView){};
};

} // namespace tracing
Expand Down
1 change: 1 addition & 0 deletions include/datadog/environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ namespace environment {
MACRO(DD_INSTRUMENTATION_INSTALL_ID) \
MACRO(DD_INSTRUMENTATION_INSTALL_TYPE) \
MACRO(DD_INSTRUMENTATION_INSTALL_TIME) \
MACRO(DD_APM_TRACING_ENABLED) \
MACRO(DD_EXTERNAL_ENV)

#define WITH_COMMA(ARG) ARG,
Expand Down
2 changes: 1 addition & 1 deletion include/datadog/sampling_mechanism.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ enum class SamplingMechanism {
// The sampling decision was made explicitly by the user, who set a sampling
// priority.
MANUAL = 4,
// Reserved for future use.
// Trace was kept because of AppSec event.
APP_SEC = 5,
// Reserved for future use.
REMOTE_RATE_USER_DEFINED = 6,
Expand Down
3 changes: 3 additions & 0 deletions include/datadog/span.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "optional.h"
#include "string_view.h"
#include "trace_id.h"
#include "trace_source.h"

namespace datadog {
namespace tracing {
Expand Down Expand Up @@ -162,6 +163,8 @@ class Span {
// Set end time of this span. Doing so will override the default behavior of
// using the current time in the destructor.
void set_end_time(std::chrono::steady_clock::time_point);
// Specifies the product (AppSec, DBM) that created this span.
void set_source(Source);

// Write information about this span and its trace into the specified `writer`
// using all of the configured injection propagation styles.
Expand Down
5 changes: 5 additions & 0 deletions include/datadog/trace_sampler_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct TraceSamplerRule final {
Rate rate;
SpanMatcher matcher;
SamplingMechanism mechanism;
bool bypass_limiter = false;
};

struct TraceSamplerConfig {
Expand All @@ -50,6 +51,10 @@ class FinalizedTraceSamplerConfig {
double max_per_second;
std::vector<TraceSamplerRule> rules;
std::unordered_map<ConfigName, ConfigMetadata> metadata;

public:
/// Returns the trace sampler configuration when APM Tracing is disabled.
static FinalizedTraceSamplerConfig apm_tracing_disabled_config();
};

Expected<FinalizedTraceSamplerConfig> finalize_config(
Expand Down
11 changes: 8 additions & 3 deletions include/datadog/trace_segment.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
#include <utility>
#include <vector>

#include "expected.h"
#include "optional.h"
#include "propagation_style.h"
#include "runtime_id.h"
Expand Down Expand Up @@ -80,6 +79,8 @@ class TraceSegment {

std::shared_ptr<ConfigManager> config_manager_;

bool tracing_enabled_;

public:
TraceSegment(const std::shared_ptr<Logger>& logger,
const std::shared_ptr<Collector>& collector,
Expand All @@ -95,7 +96,8 @@ class TraceSegment {
Optional<SamplingDecision> sampling_decision,
Optional<std::string> additional_w3c_tracestate,
Optional<std::string> additional_datadog_w3c_tracestate,
std::unique_ptr<SpanData> local_root);
std::unique_ptr<SpanData> local_root,
bool tracing_enabled = true);

const SpanDefaults& defaults() const;
const Optional<std::string>& hostname() const;
Expand All @@ -118,10 +120,13 @@ class TraceSegment {
void span_finished();

// Set the sampling decision to be a local, manual decision with the specified
// sampling `priority`. Overwrite any previous sampling decision.
// sampling `priority`. Overwrite any previous sampling decision.
void override_sampling_priority(int priority);
void override_sampling_priority(SamplingPriority priority);

// Retrieves the local root span.
SpanData& local_root() const;

private:
// If `sampling_decision_` is null, use `trace_sampler_` to make a
// sampling decision and assign it to `sampling_decision_`.
Expand Down
53 changes: 53 additions & 0 deletions include/datadog/trace_source.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#pragma once

#include <datadog/string_view.h>

namespace datadog {
namespace tracing {

/// Enumerates the possible trace sources that can generate a span.
///
/// This enum class identifies the different products that can create a span.
/// Each source is represented by a distinct bit flag, allowing for bitwise
/// operations.
enum class Source : char {
apm = 0x01,
appsec = 0x02,
datastream_monitoring = 0x04,
datajob_monitoring = 0x08,
database_monitoring = 0x10,
};

/// Validates if a given string corresponds to a valid trace source.
///
/// This function checks whether the provided string matches any of the
/// predefined trace sources specified in the Source enum. It is useful for
/// ensuring that a source string obtained from an external input is valid
/// before further processing.
///
/// @param source_str A string view representing the trace source to validate.
///
/// @return true if the source string is valid and corresponds to a known trace
/// source, false otherwise.
bool validate_trace_source(StringView source_str);

/// Converts a Source enum value to its corresponding string representation
inline constexpr StringView to_tag(Source source) {
switch (source) {
case Source::apm:
return "01";
case Source::appsec:
return "02";
case Source::database_monitoring:
return "04";
case Source::datajob_monitoring:
return "08";
case Source::datastream_monitoring:
return "10";
}

return "";
}

} // namespace tracing
} // namespace datadog
1 change: 1 addition & 0 deletions include/datadog/tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class Tracer {
Baggage::Options baggage_opts_;
bool baggage_injection_enabled_;
bool baggage_extraction_enabled_;
bool tracing_enabled_;

public:
// Create a tracer configured using the specified `config`, and optionally:
Expand Down
11 changes: 11 additions & 0 deletions include/datadog/tracer_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,16 @@ struct TracerConfig {
/// By default, it uses `ThreadedEventScheduler`, which runs tasks on a
/// separate thread.
std::shared_ptr<EventScheduler> event_scheduler;

/// `tracing_enabled` indicates whether APM traces and APM trace metrics
/// are enabled. If `false`, APM-specific traces are and metrics are dropped
/// This allows other products to operate independently (for example, AppSec).
/// This is distinct from `report_traces`, which controls whether any traces
/// are sent at all.
///
/// Overridden by the `DD_APM_TRACING_ENABLED` environment variable. Defaults
/// to `true`.
Optional<bool> tracing_enabled;
};

// `FinalizedTracerConfig` contains `Tracer` implementation details derived from
Expand Down Expand Up @@ -207,6 +217,7 @@ class FinalizedTracerConfig final {
HTTPClient::URL agent_url;
std::shared_ptr<EventScheduler> event_scheduler;
std::shared_ptr<HTTPClient> http_client;
bool tracing_enabled;
};

// Return a `FinalizedTracerConfig` from the specified `config` and from any
Expand Down
3 changes: 3 additions & 0 deletions src/datadog/datadog_agent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ DatadogAgent::DatadogAgent(
tracer_signature.library_language_version);
headers_.emplace("Datadog-Meta-Tracer-Version",
tracer_signature.library_version);
if (config.stats_computation_enabled) {
headers_.emplace("Datadog-Client-Computed-Stats", "yes");
}

// Origin Detection headers are not necessary when Unix Domain Socket (UDS)
// is used to communicate with the Datadog Agent.
Expand Down
8 changes: 6 additions & 2 deletions src/datadog/datadog_agent_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,16 @@ Expected<FinalizedDatadogAgentConfig> finalize_config(
result.metadata[ConfigName::AGENT_URL] =
ConfigMetadata(ConfigName::AGENT_URL, url, origin);

/// Starting Agent X, the admission controller inject a unique identifier
/// through `DD_EXTERNAL_ENV`. This uid is used for origin detection.
// Starting Datadog Agent 7.62.0, the admission controller inject a unique
// identifier through `DD_EXTERNAL_ENV`. This uid is used for origin
// detection.
if (auto external_env = lookup(environment::DD_EXTERNAL_ENV)) {
result.admission_controller_uid = std::string(*external_env);
}

// Not supported yet but required for APM tracing disablement.
result.stats_computation_enabled = false;

return result;
}

Expand Down
4 changes: 3 additions & 1 deletion src/datadog/extraction_util.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#include "extraction_util.h"

#include <datadog/logger.h>
#include <datadog/trace_source.h>

#include <algorithm>
#include <cstdint>
#include <sstream>
#include <string>
Expand Down Expand Up @@ -51,6 +51,8 @@ void handle_trace_tags(StringView trace_tags, ExtractedData& result,
// been extracted (i.e. we look for X-Datadog-Trace-ID first).
result.trace_id->high = *high;
}
} else if (key == tags::internal::trace_source) {
if (!validate_trace_source(value)) continue;
}

result.trace_tags.emplace_back(std::move(key), std::move(value));
Expand Down
5 changes: 5 additions & 0 deletions src/datadog/span.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ void Span::set_end_time(std::chrono::steady_clock::time_point end_time) {
end_time_ = end_time;
}

void Span::set_source(Source source) {
trace_segment_->local_root().tags.emplace(tags::internal::trace_source,
to_tag(source));
}

TraceSegment& Span::trace_segment() { return *trace_segment_; }

const TraceSegment& Span::trace_segment() const { return *trace_segment_; }
Expand Down
2 changes: 2 additions & 0 deletions src/datadog/tags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ const std::string language = "language";
const std::string runtime_id = "runtime-id";
const std::string sampling_decider = "_dd.is_sampling_decider";
const std::string w3c_parent_id = "_dd.parent_id";
const std::string trace_source = "_dd.p.ts";
const std::string apm_enabled = "_dd.apm.enabled";

} // namespace internal

Expand Down
3 changes: 3 additions & 0 deletions src/datadog/tags.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ extern const std::string language;
extern const std::string runtime_id;
extern const std::string sampling_decider;
extern const std::string w3c_parent_id;
extern const std::string trace_source; // _dd.p.ts
extern const std::string apm_enabled; // _dd.apm.enabled

} // namespace internal

// Return whether the specified `tag_name` is reserved for use internal to this
Expand Down
2 changes: 2 additions & 0 deletions src/datadog/telemetry/telemetry_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ std::string to_string(datadog::tracing::ConfigName name) {
return "trace_baggage_max_bytes";
case ConfigName::TRACE_BAGGAGE_MAX_ITEMS:
return "trace_baggage_max_items";
case ConfigName::APM_TRACING_ENABLED:
return "apm_tracing_enabled";
}

std::abort();
Expand Down
6 changes: 5 additions & 1 deletion src/datadog/trace_sampler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <limits>

#include "collector_response.h"
#include "json_serializer.h"
Expand Down Expand Up @@ -56,6 +55,11 @@ SamplingDecision TraceSampler::decide(const SpanData& span) {
decision.configured_rate = rule.rate;
const std::uint64_t threshold = max_id_from_rate(rule.rate);
if (knuth_hash(span.trace_id.low) <= threshold) {
if (rule.bypass_limiter) {
decision.priority = int(SamplingPriority::USER_KEEP);
return decision;
}

const auto result = limiter_.allow();
if (result.allowed) {
decision.priority = int(SamplingPriority::USER_KEEP);
Expand Down
Loading