Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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