diff --git a/datadog-opentelemetry/src/core/configuration/configuration.rs b/datadog-opentelemetry/src/core/configuration/configuration.rs index 57ed6bbc..1cd39cfc 100644 --- a/datadog-opentelemetry/src/core/configuration/configuration.rs +++ b/datadog-opentelemetry/src/core/configuration/configuration.rs @@ -13,16 +13,17 @@ use std::{borrow::Cow, sync::OnceLock}; #[cfg(target_os = "linux")] use libdd_library_config::tracer_metadata::TracerMetadata; -use rustc_version_runtime::version; - use crate::core::configuration::sampling_rule_config::{ParsedSamplingRules, SamplingRuleConfig}; use crate::core::configuration::sources::{ CompositeConfigSourceResult, CompositeSource, ConfigKey, ConfigSourceOrigin, }; -use crate::core::configuration::supported_configurations::SupportedConfigurations; +#[path = "supported_configurations.rs"] +mod supported_configurations; use crate::core::log::LevelFilter; use crate::core::telemetry; use crate::{dd_error, dd_warn}; +pub use supported_configurations::Config; +pub(crate) use supported_configurations::{is_alias_deprecated, SupportedConfigurations}; /// Different types of remote configuration updates that can trigger callbacks #[derive(Debug, Clone)] @@ -620,8 +621,6 @@ macro_rules! impl_config_value_provider { }; } -type SamplingRulesConfigItem = ConfigItemWithOverride; - /// Manages extra services discovered at runtime /// This is used to track services beyond the main service for remote configuration #[derive(Debug, Clone)] @@ -860,187 +859,21 @@ impl ConfigurationValueProvider for Option, bool, u32, usize, i32, f64, ServiceName, LevelFilter, ParsedSamplingRules); impl_config_value_provider!(option: String); -#[derive(Clone)] -/// Configuration for the Datadog Tracer -/// -/// # Usage -/// -/// ``` -/// use datadog_opentelemetry::configuration::Config; -/// -/// let config = Config::builder() // This pulls configuration from the environment and other sources -/// .set_service("my-service".to_string()) // Override service name -/// .set_version("1.0.0".to_string()) // Override version -/// .build(); -/// ``` -pub struct Config { - // # Global - runtime_id: &'static str, - - // # Tracer - tracer_version: &'static str, - language_version: String, - language: &'static str, - - // # Service tagging - service: ConfigItemWithOverride, - env: ConfigItem>, - version: ConfigItem>, - - // # Agent - /// A list of default tags to be added to every span - /// If DD_ENV or DD_VERSION is used, it overrides any env or version tag defined in DD_TAGS - global_tags: ConfigItem>, - /// OTEL resource attributes parsed from OTEL_RESOURCE_ATTRIBUTES env var - otel_resource_attributes: ConfigItem>, - /// OTEL metrics exporter type - otel_metrics_exporter: ConfigItem>, - /// OTEL metrics temporality preference - otel_metrics_temporality_preference: - ConfigItem>, - /// host of the trace agent - agent_host: ConfigItem>, - /// port of the trace agent - trace_agent_port: ConfigItem, - /// url of the trace agent - trace_agent_url: ConfigItemWithOverride>, - /// host of the dogstatsd agent - dogstatsd_agent_host: ConfigItem>, - /// port of the dogstatsd agent - dogstatsd_agent_port: ConfigItem, - /// url of the dogstatsd agent - dogstatsd_agent_url: ConfigItemWithOverride>, - - // # Sampling - /// A list of sampling rules. Each rule is matched against the root span of a trace - /// If a rule matches, the trace is sampled with the associated sample rate. - trace_sampling_rules: SamplingRulesConfigItem, - - /// Maximum number of spans to sample per second - /// Only applied if trace_sampling_rules are matched - trace_rate_limit: ConfigItem, - - /// Disables the library if this is false - enabled: ConfigItem, - /// The log level filter for the tracer - log_level_filter: ConfigItem, - - /// Whether to enable stats computation for the tracer - /// Results in dropped spans not being sent to the agent - trace_stats_computation_enabled: ConfigItem, - - /// Whether we wait for trace chunk to have been flushed to the agent before returning to - /// the critical path of the app - trace_writer_synchronous_write: bool, - /// How long we wait for the synchronous export to be done - trace_writer_synchronous_timeout: Duration, - /// The max amount of time a span stays in the writer buffer before we trigger a flush - trace_writer_max_flush_interval: Duration, - - /// Configurations for testing. Not exposed to customer - #[cfg(feature = "test-utils")] - wait_agent_info_ready: bool, - - // # Telemetry configuration - /// Disables telemetry if false - telemetry_enabled: ConfigItem, - /// Disables telemetry log collection if false. - telemetry_log_collection_enabled: ConfigItem, - /// Interval by which telemetry events are flushed (seconds) - telemetry_heartbeat_interval: ConfigItem, - - /// Partial flush - trace_partial_flush_enabled: ConfigItem, - trace_partial_flush_min_spans: ConfigItem, - - /// Trace propagation configuration - trace_propagation_style: ConfigItem>>, - trace_propagation_style_extract: ConfigItem>>, - trace_propagation_style_inject: ConfigItem>>, - trace_propagation_extract_first: ConfigItem, - - /// Whether remote configuration is enabled - remote_config_enabled: ConfigItem, - - /// Interval by with remote configuration is polled (seconds) - /// 5 seconds is the highest interval allowed by the spec - remote_config_poll_interval: ConfigItem, - - /// Tracks extra services discovered at runtime - /// Used for remote configuration to report all services - extra_services_tracker: ExtraServicesTracker, - - /// General callbacks to be called when configuration is updated from remote configuration - /// Allows components like the DatadogSampler to be updated without circular imports - remote_config_callbacks: Arc>, - - /// Max length of x-datadog-tags header. It only accepts values between 0 and 512. - /// The default value is 512 and x-datadog-tags header is not injected if value is 0. - datadog_tags_max_length: ConfigItem, - - // # OpenTelemetry Metrics - /// Enables OpenTelemetry metrics export - metrics_otel_enabled: ConfigItem, - /// OTLP metrics endpoint - otlp_metrics_endpoint: ConfigItem>, - /// OTLP general endpoint - otlp_endpoint: ConfigItem>, - /// OTLP general headers - otlp_headers: ConfigItem>, - /// OTLP metrics protocol (grpc, http/protobuf, http/json) - otlp_metrics_protocol: ConfigItem>, - /// OTLP metrics headers - otlp_metrics_headers: ConfigItem>, - /// OTLP general protocol (fallback for metrics protocol) - otlp_protocol: ConfigItem>, - /// OTLP metrics timeout in milliseconds - otlp_metrics_timeout: ConfigItem, - /// OTLP general timeout - otlp_timeout: ConfigItem, - /// Metric export interval in milliseconds - metric_export_interval: ConfigItem, - /// Metric export timeout in milliseconds - metric_export_timeout: ConfigItem, - - // # OpenTelemetry Logs - /// Enables OpenTelemetry logs export - logs_otel_enabled: ConfigItem, - /// OTEL logs exporter type - otel_logs_exporter: ConfigItem>, - /// OTLP logs endpoint - otlp_logs_endpoint: ConfigItem>, - /// OTLP logs headers - otlp_logs_headers: ConfigItem>, - /// OTLP logs protocol (grpc, http/protobuf, http/json) - otlp_logs_protocol: ConfigItem>, - /// OTLP logs timeout in milliseconds - otlp_logs_timeout: ConfigItem, -} - impl Config { fn from_sources(sources: &CompositeSource) -> Self { - let default = default_config(); + use SupportedConfigurations as S; - /// Wrapper to parse "," separated string to vector struct DdTags(Vec); - impl FromStr for DdTags { type Err = &'static str; - fn from_str(s: &str) -> Result { - Ok(DdTags( - s.split(',').map(|s| s.to_string()).collect::>(), - )) + Ok(DdTags(s.split(',').map(|s| s.to_string()).collect())) } } - /// Wrapper to parse "," separated key:value tags to vector<(key, value)> - /// discarding tags without ":" delimiter struct DdKeyValueTags(Vec<(String, String)>); - impl FromStr for DdKeyValueTags { type Err = &'static str; - fn from_str(s: &str) -> Result { Ok(DdKeyValueTags( s.split(',') @@ -1054,10 +887,8 @@ impl Config { } struct OtelResourceAttributes(Vec<(String, String)>); - impl FromStr for OtelResourceAttributes { type Err = &'static str; - fn from_str(s: &str) -> Result { Ok(OtelResourceAttributes( s.split(',') @@ -1070,19 +901,17 @@ impl Config { } } - let parsed_sampling_rules_config = sources - .get_parse::(SupportedConfigurations::DD_TRACE_SAMPLING_RULES); - + let parsed_sampling_rules_config = + sources.get_parse::(S::DD_TRACE_SAMPLING_RULES); let mut sampling_rules_item = ConfigItemWithOverride::new_rc( parsed_sampling_rules_config.name, - ParsedSamplingRules::default(), // default is empty rules + ParsedSamplingRules::default(), ); - - // Set env value if it was parsed from environment if let Some(rules) = parsed_sampling_rules_config.value { sampling_rules_item.set_value_source(rules.value, rules.origin); } + let default = default_config(); let cisu = ConfigItemSourceUpdater { sources }; Self { @@ -1093,41 +922,19 @@ impl Config { service: cisu.update_non_empty_string(default.service, ServiceName::Configured), env: cisu.update_string(default.env, Some), version: cisu.update_string(default.version, Some), - // TODO(paullgdc): tags should be merged, not replaced global_tags: cisu .update_parsed_with_transform(default.global_tags, |DdKeyValueTags(tags)| tags), otel_resource_attributes: cisu.update_parsed_with_transform( default.otel_resource_attributes, |OtelResourceAttributes(attrs)| attrs, ), - otel_metrics_exporter: cisu.update_string(default.otel_metrics_exporter, Cow::Owned), otel_metrics_temporality_preference: cisu.update_string( default.otel_metrics_temporality_preference, parse_temporality, ), - agent_host: cisu.update_string(default.agent_host, Cow::Owned), - trace_agent_port: cisu.update_parsed(default.trace_agent_port), - trace_agent_url: cisu.update_non_empty_string(default.trace_agent_url, Cow::Owned), - dogstatsd_agent_host: cisu.update_string(default.dogstatsd_agent_host, Cow::Owned), - dogstatsd_agent_port: cisu.update_parsed(default.dogstatsd_agent_port), - dogstatsd_agent_url: cisu - .update_non_empty_string(default.dogstatsd_agent_url, Cow::Owned), - - trace_partial_flush_enabled: cisu.update_parsed(default.trace_partial_flush_enabled), - trace_partial_flush_min_spans: cisu - .update_parsed(default.trace_partial_flush_min_spans), - - // Use the initialized ConfigItem trace_sampling_rules: sampling_rules_item, trace_rate_limit: cisu.update_parsed(default.trace_rate_limit), - - enabled: cisu.update_parsed(default.enabled), log_level_filter: cisu.update_parsed(default.log_level_filter), - trace_stats_computation_enabled: cisu - .update_parsed(default.trace_stats_computation_enabled), - telemetry_enabled: cisu.update_parsed(default.telemetry_enabled), - telemetry_log_collection_enabled: cisu - .update_parsed(default.telemetry_log_collection_enabled), telemetry_heartbeat_interval: cisu.update_parsed_with_transform( default.telemetry_heartbeat_interval, |interval: f64| interval.abs(), @@ -1144,15 +951,14 @@ impl Config { default.trace_propagation_style_inject, |DdTags(tags)| TracePropagationStyle::from_tags(Some(tags)), ), - trace_propagation_extract_first: cisu - .update_parsed(default.trace_propagation_extract_first), + trace_partial_flush_min_spans: cisu + .update_parsed(default.trace_partial_flush_min_spans), trace_writer_synchronous_write: default.trace_writer_synchronous_write, trace_writer_synchronous_timeout: default.trace_writer_synchronous_timeout, trace_writer_max_flush_interval: default.trace_writer_max_flush_interval, #[cfg(feature = "test-utils")] wait_agent_info_ready: default.wait_agent_info_ready, extra_services_tracker: ExtraServicesTracker::new(), - remote_config_enabled: cisu.update_parsed(default.remote_config_enabled), remote_config_poll_interval: cisu.update_parsed_with_transform( default.remote_config_poll_interval, |interval: f64| interval.abs().min(RC_DEFAULT_POLL_INTERVAL), @@ -1162,16 +968,34 @@ impl Config { .update_parsed_with_transform(default.datadog_tags_max_length, |max: usize| { max.min(DATADOG_TAGS_MAX_LENGTH) }), - metrics_otel_enabled: cisu.update_parsed(default.metrics_otel_enabled), - otlp_metrics_endpoint: cisu.update_string(default.otlp_metrics_endpoint, Cow::Owned), - otlp_endpoint: cisu.update_string(default.otlp_endpoint, Cow::Owned), - otlp_headers: cisu.update_string(default.otlp_headers, Cow::Owned), otlp_metrics_protocol: cisu .update_string(default.otlp_metrics_protocol, OtlpProtocol::parse_optional), + dogstatsd_agent_url: cisu + .update_non_empty_string(default.dogstatsd_agent_url, Cow::Owned), + otlp_headers: cisu.update_string(default.otlp_headers, Cow::Owned), otlp_metrics_headers: cisu.update_string(default.otlp_metrics_headers, Cow::Owned), otlp_protocol: cisu.update_string(default.otlp_protocol, OtlpProtocol::parse_optional), + agent_host: cisu.update_string(default.agent_host, Cow::Owned), + dogstatsd_agent_host: cisu.update_string(default.dogstatsd_agent_host, Cow::Owned), + dogstatsd_agent_port: cisu.update_parsed(default.dogstatsd_agent_port), + telemetry_enabled: cisu.update_parsed(default.telemetry_enabled), + metrics_otel_enabled: cisu.update_parsed(default.metrics_otel_enabled), + remote_config_enabled: cisu.update_parsed(default.remote_config_enabled), + telemetry_log_collection_enabled: cisu + .update_parsed(default.telemetry_log_collection_enabled), + trace_agent_port: cisu.update_parsed(default.trace_agent_port), + trace_agent_url: cisu.update_non_empty_string(default.trace_agent_url, Cow::Owned), + enabled: cisu.update_parsed(default.enabled), + trace_partial_flush_enabled: cisu.update_parsed(default.trace_partial_flush_enabled), + trace_propagation_extract_first: cisu + .update_parsed(default.trace_propagation_extract_first), + trace_stats_computation_enabled: cisu + .update_parsed(default.trace_stats_computation_enabled), + otlp_endpoint: cisu.update_string(default.otlp_endpoint, Cow::Owned), + otlp_metrics_endpoint: cisu.update_string(default.otlp_metrics_endpoint, Cow::Owned), otlp_metrics_timeout: cisu.update_parsed(default.otlp_metrics_timeout), otlp_timeout: cisu.update_parsed(default.otlp_timeout), + otel_metrics_exporter: cisu.update_string(default.otel_metrics_exporter, Cow::Owned), metric_export_interval: cisu.update_parsed(default.metric_export_interval), metric_export_timeout: cisu.update_parsed(default.metric_export_timeout), logs_otel_enabled: cisu.update_parsed(default.logs_otel_enabled), @@ -1195,54 +1019,6 @@ impl Config { Self::builder_with_sources(&CompositeSource::default_sources()) } - pub(crate) fn get_telemetry_configuration(&self) -> Vec<&dyn ConfigurationProvider> { - vec![ - &self.service, - &self.env, - &self.version, - &self.global_tags, - &self.agent_host, - &self.trace_agent_port, - &self.trace_agent_url, - &self.dogstatsd_agent_host, - &self.dogstatsd_agent_port, - &self.dogstatsd_agent_url, - &self.trace_sampling_rules, - &self.trace_rate_limit, - &self.enabled, - &self.log_level_filter, - &self.trace_stats_computation_enabled, - &self.telemetry_enabled, - &self.telemetry_log_collection_enabled, - &self.telemetry_heartbeat_interval, - &self.trace_partial_flush_enabled, - &self.trace_partial_flush_min_spans, - &self.trace_propagation_style, - &self.trace_propagation_style_extract, - &self.trace_propagation_style_inject, - &self.trace_propagation_extract_first, - &self.remote_config_enabled, - &self.remote_config_poll_interval, - &self.datadog_tags_max_length, - &self.otlp_endpoint, - &self.otlp_timeout, - &self.otlp_headers, - &self.otlp_protocol, - &self.otlp_metrics_endpoint, - &self.otlp_metrics_timeout, - &self.otlp_metrics_headers, - &self.otlp_metrics_protocol, - &self.metric_export_interval, - &self.metric_export_timeout, - &self.logs_otel_enabled, - &self.otel_logs_exporter, - &self.otlp_logs_endpoint, - &self.otlp_logs_headers, - &self.otlp_logs_protocol, - &self.otlp_logs_timeout, - ] - } - /// Returns the unique runtime identifier for this process. pub fn runtime_id(&self) -> &str { self.runtime_id @@ -1302,11 +1078,6 @@ impl Config { .map(|attr| (attr.0.as_str(), attr.1.as_str())) } - /// Returns the OpenTelemetry metrics exporter type. - pub fn otel_metrics_exporter(&self) -> &str { - self.otel_metrics_exporter.value().as_ref() - } - /// Returns the OpenTelemetry metrics temporality preference (Delta or Cumulative). pub fn otel_metrics_temporality_preference( &self, @@ -1314,21 +1085,6 @@ impl Config { *self.otel_metrics_temporality_preference.value() } - /// Returns the URL of the Datadog trace agent. - pub fn trace_agent_url(&self) -> impl Deref + use<'_> { - self.trace_agent_url.value() - } - - /// Returns the host of the DogStatsD agent. - pub fn dogstatsd_agent_host(&self) -> &Cow<'static, str> { - self.dogstatsd_agent_host.value() - } - - /// Returns the port of the DogStatsD agent. - pub fn dogstatsd_agent_port(&self) -> &u32 { - self.dogstatsd_agent_port.value() - } - /// Returns the full URL of the DogStatsD agent. pub fn dogstatsd_agent_url(&self) -> impl Deref + use<'_> { self.dogstatsd_agent_url.value() @@ -1344,21 +1100,11 @@ impl Config { *self.trace_rate_limit.value() } - /// Returns whether tracing is enabled. - pub fn enabled(&self) -> bool { - *self.enabled.value() - } - /// Returns the configured log level filter. pub fn log_level_filter(&self) -> &LevelFilter { self.log_level_filter.value() } - /// Returns whether client-side trace stats computation is enabled. - pub fn trace_stats_computation_enabled(&self) -> bool { - *self.trace_stats_computation_enabled.value() - } - pub(crate) fn trace_writer_synchronous_write(&self) -> bool { self.trace_writer_synchronous_write } @@ -1383,36 +1129,11 @@ impl Config { RUNTIME_ID.get_or_init(|| uuid::Uuid::new_v4().to_string()) } - /// Returns whether telemetry collection is enabled. - pub fn telemetry_enabled(&self) -> bool { - *self.telemetry_enabled.value() - } - - /// Returns whether telemetry log collection is enabled. - pub fn telemetry_log_collection_enabled(&self) -> bool { - *self.telemetry_log_collection_enabled.value() - } - /// Returns the telemetry heartbeat interval in seconds. pub fn telemetry_heartbeat_interval(&self) -> f64 { *self.telemetry_heartbeat_interval.value() } - /// Returns whether OpenTelemetry metrics export is enabled. - pub fn metrics_otel_enabled(&self) -> bool { - *self.metrics_otel_enabled.value() - } - - /// Returns the OTLP metrics endpoint URL. - pub fn otlp_metrics_endpoint(&self) -> &str { - self.otlp_metrics_endpoint.value().as_ref() - } - - /// Returns the OTLP endpoint URL (fallback for metrics if metrics endpoint is not set). - pub fn otlp_endpoint(&self) -> &str { - self.otlp_endpoint.value().as_ref() - } - /// Returns the OTLP headers (fallback for metrics if metrics headers are not set). pub fn otlp_headers(&self) -> &str { self.otlp_headers.value().as_ref() @@ -1433,62 +1154,11 @@ impl Config { *self.otlp_protocol.value() } - /// Returns the OTLP metrics timeout in milliseconds. - pub fn otlp_metrics_timeout(&self) -> u32 { - *self.otlp_metrics_timeout.value() - } - - /// Returns the OTLP timeout in milliseconds (fallback for metrics if metrics timeout is not - /// set). - pub fn otlp_timeout(&self) -> u32 { - *self.otlp_timeout.value() - } - - /// Returns the metric export interval in milliseconds. - pub fn metric_export_interval(&self) -> u32 { - *self.metric_export_interval.value() - } - - /// Returns the metric export timeout in milliseconds. - pub fn metric_export_timeout(&self) -> u32 { - *self.metric_export_timeout.value() - } - - /// Returns whether OpenTelemetry logs export is enabled. - pub fn logs_otel_enabled(&self) -> bool { - *self.logs_otel_enabled.value() - } - - /// Returns the OpenTelemetry logs exporter type. - pub fn otel_logs_exporter(&self) -> &str { - self.otel_logs_exporter.value().as_ref() - } - - /// Returns the OTLP logs endpoint URL. - pub fn otlp_logs_endpoint(&self) -> &str { - self.otlp_logs_endpoint.value().as_ref() - } - - /// Returns the OTLP logs headers. - pub fn otlp_logs_headers(&self) -> &str { - self.otlp_logs_headers.value().as_ref() - } - /// Returns the OTLP logs protocol. pub fn otlp_logs_protocol(&self) -> Option { *self.otlp_logs_protocol.value() } - /// Returns the OTLP logs timeout in milliseconds. - pub fn otlp_logs_timeout(&self) -> u32 { - *self.otlp_logs_timeout.value() - } - - /// Returns whether partial trace flushing is enabled. - pub fn trace_partial_flush_enabled(&self) -> bool { - *self.trace_partial_flush_enabled.value() - } - /// Returns the minimum number of spans required to trigger a partial flush. pub fn trace_partial_flush_min_spans(&self) -> usize { *self.trace_partial_flush_min_spans.value() @@ -1509,11 +1179,6 @@ impl Config { self.trace_propagation_style_inject.value().as_deref() } - /// Returns whether to stop extraction after the first successful propagator. - pub fn trace_propagation_extract_first(&self) -> bool { - *self.trace_propagation_extract_first.value() - } - pub(crate) fn update_sampling_rules_from_remote( &self, rules_json: &str, @@ -1616,11 +1281,6 @@ impl Config { self.extra_services_tracker.get_extra_services() } - /// Check if remote configuration is enabled - pub fn remote_config_enabled(&self) -> bool { - *self.remote_config_enabled.value() - } - /// Get RC poll interval (seconds) pub fn remote_config_poll_interval(&self) -> f64 { *self.remote_config_poll_interval.value() @@ -1670,231 +1330,8 @@ impl Config { } } -impl std::fmt::Debug for Config { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("Config") - .field("runtime_id", &self.runtime_id) - .field("tracer_version", &self.tracer_version) - .field("language_version", &self.language_version) - .field("service", &self.service) - .field("env", &self.env) - .field("version", &self.version) - .field("global_tags", &self.global_tags) - .field("trace_agent_url", &self.trace_agent_url) - .field("dogstatsd_agent_url", &self.dogstatsd_agent_url) - .field("trace_sampling_rules", &self.trace_sampling_rules) - .field("trace_rate_limit", &self.trace_rate_limit) - .field("enabled", &self.enabled) - .field("log_level_filter", &self.log_level_filter) - .field( - "trace_stats_computation_enabled", - &self.trace_stats_computation_enabled, - ) - .field("trace_propagation_style", &self.trace_propagation_style) - .field( - "trace_propagation_style_extract", - &self.trace_propagation_style_extract, - ) - .field( - "trace_propagation_style_inject", - &self.trace_propagation_style_inject, - ) - .field( - "trace_propagation_extract_first", - &self.trace_propagation_extract_first, - ) - .field("extra_services_tracker", &self.extra_services_tracker) - .field("remote_config_enabled", &self.remote_config_enabled) - .field( - "remote_config_poll_interval", - &self.remote_config_poll_interval, - ) - .field("remote_config_callbacks", &self.remote_config_callbacks) - .finish() - } -} - fn default_config() -> Config { - Config { - runtime_id: Config::process_runtime_id(), - env: ConfigItem::new(SupportedConfigurations::DD_ENV, None), - // TODO(paullgdc): Default service naming detection, probably from arg0 - service: ConfigItemWithOverride::new_calculated( - SupportedConfigurations::DD_SERVICE, - ServiceName::Default, - ), - version: ConfigItem::new(SupportedConfigurations::DD_VERSION, None), - global_tags: ConfigItem::new(SupportedConfigurations::DD_TAGS, Vec::new()), - otel_resource_attributes: ConfigItem::new( - SupportedConfigurations::OTEL_RESOURCE_ATTRIBUTES, - Vec::new(), - ), - otel_metrics_exporter: ConfigItem::new( - SupportedConfigurations::OTEL_METRICS_EXPORTER, - Cow::Borrowed("otlp"), - ), - otel_metrics_temporality_preference: ConfigItem::new( - SupportedConfigurations::OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE, - Some(opentelemetry_sdk::metrics::Temporality::Delta), - ), - - agent_host: ConfigItem::new( - SupportedConfigurations::DD_AGENT_HOST, - Cow::Borrowed("localhost"), - ), - trace_agent_port: ConfigItem::new(SupportedConfigurations::DD_TRACE_AGENT_PORT, 8126), - trace_agent_url: ConfigItemWithOverride::new_calculated( - SupportedConfigurations::DD_TRACE_AGENT_URL, - Cow::Borrowed(""), - ), - dogstatsd_agent_host: ConfigItem::new( - SupportedConfigurations::DD_DOGSTATSD_HOST, - Cow::Borrowed("localhost"), - ), - dogstatsd_agent_port: ConfigItem::new(SupportedConfigurations::DD_DOGSTATSD_PORT, 8125), - dogstatsd_agent_url: ConfigItemWithOverride::new_calculated( - SupportedConfigurations::DD_DOGSTATSD_URL, - Cow::Borrowed(""), - ), - trace_sampling_rules: ConfigItemWithOverride::new_rc( - SupportedConfigurations::DD_TRACE_SAMPLING_RULES, - ParsedSamplingRules::default(), // Empty rules by default - ), - trace_rate_limit: ConfigItem::new(SupportedConfigurations::DD_TRACE_RATE_LIMIT, 100), - enabled: ConfigItem::new(SupportedConfigurations::DD_TRACE_ENABLED, true), - log_level_filter: ConfigItem::new( - SupportedConfigurations::DD_LOG_LEVEL, - LevelFilter::default(), - ), - tracer_version: TRACER_VERSION, - language: "rust", - language_version: version().to_string(), - trace_stats_computation_enabled: ConfigItem::new( - SupportedConfigurations::DD_TRACE_STATS_COMPUTATION_ENABLED, - true, - ), - trace_writer_synchronous_write: false, - trace_writer_synchronous_timeout: Duration::from_secs(2), - trace_writer_max_flush_interval: Duration::from_secs(1), - #[cfg(feature = "test-utils")] - wait_agent_info_ready: false, - - telemetry_enabled: ConfigItem::new( - SupportedConfigurations::DD_INSTRUMENTATION_TELEMETRY_ENABLED, - true, - ), - telemetry_log_collection_enabled: ConfigItem::new( - SupportedConfigurations::DD_TELEMETRY_LOG_COLLECTION_ENABLED, - true, - ), - telemetry_heartbeat_interval: ConfigItem::new( - SupportedConfigurations::DD_TELEMETRY_HEARTBEAT_INTERVAL, - 60.0, - ), - trace_partial_flush_enabled: ConfigItem::new( - SupportedConfigurations::DD_TRACE_PARTIAL_FLUSH_ENABLED, - false, - ), - trace_partial_flush_min_spans: ConfigItem::new( - SupportedConfigurations::DD_TRACE_PARTIAL_FLUSH_MIN_SPANS, - 300, - ), - trace_propagation_style: ConfigItem::new( - SupportedConfigurations::DD_TRACE_PROPAGATION_STYLE, - Some(vec![ - TracePropagationStyle::Datadog, - TracePropagationStyle::TraceContext, - ]), - ), - trace_propagation_style_extract: ConfigItem::new( - SupportedConfigurations::DD_TRACE_PROPAGATION_STYLE_EXTRACT, - None, - ), - trace_propagation_style_inject: ConfigItem::new( - SupportedConfigurations::DD_TRACE_PROPAGATION_STYLE_INJECT, - None, - ), - trace_propagation_extract_first: ConfigItem::new( - SupportedConfigurations::DD_TRACE_PROPAGATION_EXTRACT_FIRST, - false, - ), - extra_services_tracker: ExtraServicesTracker::new(), - remote_config_enabled: ConfigItem::new( - SupportedConfigurations::DD_REMOTE_CONFIGURATION_ENABLED, - true, - ), - remote_config_poll_interval: ConfigItem::new( - SupportedConfigurations::DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS, - RC_DEFAULT_POLL_INTERVAL, - ), - remote_config_callbacks: Arc::new(Mutex::new(RemoteConfigCallbacks::new())), - datadog_tags_max_length: ConfigItem::new( - SupportedConfigurations::DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH, - DATADOG_TAGS_MAX_LENGTH, - ), - metrics_otel_enabled: ConfigItem::new( - SupportedConfigurations::DD_METRICS_OTEL_ENABLED, - true, - ), - otlp_metrics_endpoint: ConfigItem::new( - SupportedConfigurations::OTEL_EXPORTER_OTLP_METRICS_ENDPOINT, - Cow::Borrowed(""), - ), - otlp_endpoint: ConfigItem::new( - SupportedConfigurations::OTEL_EXPORTER_OTLP_ENDPOINT, - Cow::Borrowed(""), - ), - otlp_headers: ConfigItem::new( - SupportedConfigurations::OTEL_EXPORTER_OTLP_HEADERS, - Cow::Borrowed(""), - ), - otlp_metrics_protocol: ConfigItem::new( - SupportedConfigurations::OTEL_EXPORTER_OTLP_METRICS_PROTOCOL, - None, - ), - otlp_metrics_headers: ConfigItem::new( - SupportedConfigurations::OTEL_EXPORTER_OTLP_METRICS_HEADERS, - Cow::Borrowed(""), - ), - otlp_protocol: ConfigItem::new(SupportedConfigurations::OTEL_EXPORTER_OTLP_PROTOCOL, None), - otlp_metrics_timeout: ConfigItem::new( - SupportedConfigurations::OTEL_EXPORTER_OTLP_METRICS_TIMEOUT, - 10000u32, - ), - otlp_timeout: ConfigItem::new( - SupportedConfigurations::OTEL_EXPORTER_OTLP_TIMEOUT, - 10000u32, - ), - metric_export_interval: ConfigItem::new( - SupportedConfigurations::OTEL_METRIC_EXPORT_INTERVAL, - 10000u32, - ), - metric_export_timeout: ConfigItem::new( - SupportedConfigurations::OTEL_METRIC_EXPORT_TIMEOUT, - 7500u32, - ), - logs_otel_enabled: ConfigItem::new(SupportedConfigurations::DD_LOGS_OTEL_ENABLED, true), - otel_logs_exporter: ConfigItem::new( - SupportedConfigurations::OTEL_LOGS_EXPORTER, - Cow::Borrowed("otlp"), - ), - otlp_logs_endpoint: ConfigItem::new( - SupportedConfigurations::OTEL_EXPORTER_OTLP_LOGS_ENDPOINT, - Cow::Borrowed(""), - ), - otlp_logs_headers: ConfigItem::new( - SupportedConfigurations::OTEL_EXPORTER_OTLP_LOGS_HEADERS, - Cow::Borrowed(""), - ), - otlp_logs_protocol: ConfigItem::new( - SupportedConfigurations::OTEL_EXPORTER_OTLP_LOGS_PROTOCOL, - None, - ), - otlp_logs_timeout: ConfigItem::new( - SupportedConfigurations::OTEL_EXPORTER_OTLP_LOGS_TIMEOUT, - 10000u32, - ), - } + supported_configurations::default_config() } /// Builder for constructing a [`Config`] instance. @@ -1995,28 +1432,6 @@ impl ConfigBuilder { self } - /// Enable or disable telemetry data collection and sending. - /// - /// **Default**: `true` - /// - /// Env variable: `DD_INSTRUMENTATION_TELEMETRY_ENABLED` - pub fn set_telemetry_enabled(&mut self, enabled: bool) -> &mut Self { - self.config.telemetry_enabled.set_code(enabled); - self - } - - /// Enable or disable log collection for telemetry. - /// - /// **Default**: `true` - /// - /// Env variable: `DD_TELEMETRY_LOG_COLLECTION_ENABLED` - pub fn set_telemetry_log_collection_enabled(&mut self, enabled: bool) -> &mut Self { - self.config - .telemetry_log_collection_enabled - .set_code(enabled); - self - } - /// Interval in seconds for sending telemetry heartbeat messages. /// /// **Default**: `60.0` @@ -2029,73 +1444,6 @@ impl ConfigBuilder { self } - /// Sets the hostname of the Datadog Agent. - /// - /// **Default**: `localhost` - /// - /// Env variable: `DD_AGENT_HOST` - pub fn set_agent_host(&mut self, host: String) -> &mut Self { - self.config - .agent_host - .set_code(Cow::Owned(host.to_string())); - self - } - - /// Sets the port of the Datadog Agent for trace collection. - /// - /// **Default**: `8126` - /// - /// Env variable: `DD_TRACE_AGENT_PORT` - pub fn set_trace_agent_port(&mut self, port: u32) -> &mut Self { - self.config.trace_agent_port.set_code(port); - self - } - - /// Sets the URL of the Datadog Agent. This takes precedence over `DD_AGENT_HOST` and - /// `DD_TRACE_AGENT_PORT`. - /// - /// **Default**: `http://localhost:8126` - /// - /// Env variable: `DD_TRACE_AGENT_URL` - pub fn set_trace_agent_url(&mut self, url: String) -> &mut Self { - self.config - .trace_agent_url - .set_code(Cow::Owned(url.to_string())); - self - } - - /// Enable or disable OpenTelemetry metrics export. - /// - /// **Default**: `false` - /// - /// Env variable: `DD_METRICS_OTEL_ENABLED` - pub fn set_metrics_otel_enabled(&mut self, enabled: bool) -> &mut Self { - self.config.metrics_otel_enabled.set_code(enabled); - self - } - - /// Set the OTLP metrics endpoint URL. - /// - /// **Default**: `(empty, falls back to OTEL_EXPORTER_OTLP_ENDPOINT or agent URL)` - /// - /// Env variable: `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` - pub fn set_otlp_metrics_endpoint(&mut self, endpoint: String) -> &mut Self { - self.config - .otlp_metrics_endpoint - .set_code(Cow::Owned(endpoint)); - self - } - - /// Set the OTLP general endpoint URL (fallback for metrics endpoint). - /// - /// **Default**: `(empty)` - /// - /// Env variable: `OTEL_EXPORTER_OTLP_ENDPOINT` - pub fn set_otlp_endpoint(&mut self, endpoint: String) -> &mut Self { - self.config.otlp_endpoint.set_code(Cow::Owned(endpoint)); - self - } - /// Set the OTLP metrics protocol (grpc, http/protobuf, http/json). /// /// **Default**: `(empty, defaults to grpc)` @@ -2120,48 +1468,6 @@ impl ConfigBuilder { self } - /// Set the OTLP metrics timeout in milliseconds. - /// - /// **Default**: `7500` - /// - /// Env variable: `OTEL_EXPORTER_OTLP_METRICS_TIMEOUT` - pub fn set_otlp_metrics_timeout(&mut self, timeout: u32) -> &mut Self { - self.config.otlp_metrics_timeout.set_code(timeout); - self - } - - /// Set the OTLP general timeout in milliseconds (fallback for metrics timeout). - /// - /// **Default**: `7500` - /// - /// Env variable: `OTEL_EXPORTER_OTLP_TIMEOUT` - pub fn set_otlp_timeout(&mut self, timeout: u32) -> &mut Self { - self.config.otlp_timeout.set_code(timeout); - self - } - - /// Enable or disable OpenTelemetry logs export. - /// - /// **Default**: `true` - /// - /// Env variable: `DD_LOGS_OTEL_ENABLED` - pub fn set_logs_otel_enabled(&mut self, enabled: bool) -> &mut Self { - self.config.logs_otel_enabled.set_code(enabled); - self - } - - /// Set the OTLP logs endpoint URL. - /// - /// **Default**: `""` - /// - /// Env variable: `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` - pub fn set_otlp_logs_endpoint(&mut self, endpoint: String) -> &mut Self { - self.config - .otlp_logs_endpoint - .set_code(Cow::Owned(endpoint)); - self - } - /// Set the OTLP logs protocol (grpc, http/protobuf, http/json). /// /// **Default**: `None` (falls back to `OTEL_EXPORTER_OTLP_PROTOCOL`) @@ -2174,16 +1480,6 @@ impl ConfigBuilder { self } - /// Set the OTLP logs timeout in milliseconds. - /// - /// **Default**: `10000` - /// - /// Env variable: `OTEL_EXPORTER_OTLP_LOGS_TIMEOUT` - pub fn set_otlp_logs_timeout(&mut self, timeout: u32) -> &mut Self { - self.config.otlp_logs_timeout.set_code(timeout); - self - } - /// Set the OTLP metrics temporality preference. /// /// **Default**: `Delta` @@ -2199,58 +1495,6 @@ impl ConfigBuilder { self } - /// Set the metric export interval in milliseconds. - /// - /// **Default**: `10000` - /// - /// Env variable: `OTEL_METRIC_EXPORT_INTERVAL` - pub fn set_metric_export_interval(&mut self, interval: u32) -> &mut Self { - self.config.metric_export_interval.set_code(interval); - self - } - - /// Set the metric export timeout in milliseconds. - /// - /// **Default**: `7500` - /// - /// Env variable: `OTEL_METRIC_EXPORT_TIMEOUT` - pub fn set_metric_export_timeout(&mut self, timeout: u32) -> &mut Self { - self.config.metric_export_timeout.set_code(timeout); - self - } - - /// Sets the hostname for DogStatsD metric collection. - /// - /// **Default**: `localhost` - /// - /// Env variable: `DD_DOGSTATSD_HOST` - pub fn set_dogstatsd_agent_host(&mut self, host: String) -> &mut Self { - self.config - .dogstatsd_agent_host - .set_code(Cow::Owned(host.to_string())); - self - } - - /// Sets the port for DogStatsD metric collection. - /// - /// **Default**: `8125` - /// - /// Env variable: `DD_DOGSTATSD_PORT` - pub fn set_dogstatsd_agent_port(&mut self, port: u32) -> &mut Self { - self.config.dogstatsd_agent_port.set_code(port); - self - } - - /// Enable partial flushing of traces. - /// - /// **Default**: `false` - /// - /// Env variable: `DD_TRACE_PARTIAL_FLUSH_ENABLED` - pub fn set_trace_partial_flush_enabled(&mut self, enabled: bool) -> &mut Self { - self.config.trace_partial_flush_enabled.set_code(enabled); - self - } - /// Minimum number of spans in a trace before partial flush is triggered. /// /// **Default**: `300` @@ -2330,26 +1574,6 @@ impl ConfigBuilder { self } - /// When set to `true`, stops extracting after the first successful trace context extraction. - /// - /// **Default**: `false` - /// - /// Env variable: `DD_TRACE_PROPAGATION_EXTRACT_FIRST` - pub fn set_trace_propagation_extract_first(&mut self, first: bool) -> &mut Self { - self.config.trace_propagation_extract_first.set_code(first); - self - } - - /// Set to `false` to disable tracing. - /// - /// **Default**: `true` - /// - /// Env variable: `DD_TRACE_ENABLED` - pub fn set_enabled(&mut self, enabled: bool) -> &mut Self { - self.config.enabled.set_code(enabled); - self - } - /// Sets the internal log level for the tracer. /// /// **Default**: `Error` @@ -2360,31 +1584,6 @@ impl ConfigBuilder { self } - /// Enable computation of trace statistics. - /// - /// **Default**: `true` - /// - /// Env variable: `DD_TRACE_STATS_COMPUTATION_ENABLED` - pub fn set_trace_stats_computation_enabled( - &mut self, - trace_stats_computation_enabled: bool, - ) -> &mut Self { - self.config - .trace_stats_computation_enabled - .set_code(trace_stats_computation_enabled); - self - } - - /// Enable or disable remote configuration. - /// - /// **Default**: `true` - /// - /// Env variable: `DD_REMOTE_CONFIGURATION_ENABLED` - pub fn set_remote_config_enabled(&mut self, enabled: bool) -> &mut Self { - self.config.remote_config_enabled.set_code(enabled); - self - } - /// Interval in seconds for polling remote configuration updates. /// /// **Default**: `5.0` diff --git a/datadog-opentelemetry/src/core/configuration/mod.rs b/datadog-opentelemetry/src/core/configuration/mod.rs index 4732f820..dce67b9b 100644 --- a/datadog-opentelemetry/src/core/configuration/mod.rs +++ b/datadog-opentelemetry/src/core/configuration/mod.rs @@ -24,8 +24,9 @@ mod configuration; pub(crate) mod remote_config; mod sampling_rule_config; mod sources; -mod supported_configurations; +#[cfg(test)] +pub(crate) use configuration::SupportedConfigurations; pub use configuration::{Config, ConfigBuilder, OtlpProtocol, TracePropagationStyle}; pub(crate) use configuration::{ConfigurationProvider, RemoteConfigUpdate}; pub use sampling_rule_config::SamplingRuleConfig; diff --git a/datadog-opentelemetry/src/core/configuration/remote_config.rs b/datadog-opentelemetry/src/core/configuration/remote_config.rs index aff0bc38..d62a6766 100644 --- a/datadog-opentelemetry/src/core/configuration/remote_config.rs +++ b/datadog-opentelemetry/src/core/configuration/remote_config.rs @@ -426,6 +426,7 @@ struct RemoteConfigClient { impl RemoteConfigClient { /// Creates a new remote configuration client pub fn new(config: Arc) -> Result { + #[allow(clippy::unnecessary_to_owned)] let agent_url = hyper::Uri::from_maybe_shared(config.trace_agent_url().to_string()) .map_err(|_| RemoteConfigClientError::InvalidAgentUri)?; let mut parts = agent_url.into_parts(); diff --git a/datadog-opentelemetry/src/core/configuration/sources.rs b/datadog-opentelemetry/src/core/configuration/sources.rs index bc38c757..61d0d60a 100644 --- a/datadog-opentelemetry/src/core/configuration/sources.rs +++ b/datadog-opentelemetry/src/core/configuration/sources.rs @@ -7,7 +7,7 @@ use libdd_telemetry::data::ConfigurationOrigin; use crate::dd_warn; -use super::supported_configurations::{is_alias_deprecated, SupportedConfigurations}; +use super::configuration::{is_alias_deprecated, SupportedConfigurations}; /// Source of a configuration value #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] @@ -268,7 +268,7 @@ mod tests { HashMapSource, }; use crate::core::configuration::sources::ConfigKey; - use crate::core::configuration::supported_configurations::SupportedConfigurations; + use crate::core::configuration::SupportedConfigurations; #[test] fn test_composite_source_single_origin() { diff --git a/datadog-opentelemetry/src/core/configuration/supported_configurations.rs b/datadog-opentelemetry/src/core/configuration/supported_configurations.rs index 40f0892a..93f95d92 100644 --- a/datadog-opentelemetry/src/core/configuration/supported_configurations.rs +++ b/datadog-opentelemetry/src/core/configuration/supported_configurations.rs @@ -4,10 +4,18 @@ /// This file is generated by the scripts/local_config_map_generate.py script. /// Do not edit this file manually. To add a new configuration, /// add it to the supported-configurations.json file, then run this script. +use std::borrow::Cow; +use std::sync::{Arc, Mutex}; +use std::time::Duration; + +use rustc_version_runtime::version; + +use super::*; + #[allow(nonstandard_style)] #[derive(Debug, PartialEq, Copy, Clone)] #[non_exhaustive] -pub(crate) enum SupportedConfigurations { +pub enum SupportedConfigurations { DD_AGENT_HOST, DD_DOGSTATSD_HOST, DD_DOGSTATSD_PORT, @@ -201,7 +209,7 @@ impl SupportedConfigurations { } } -pub(crate) fn is_alias_deprecated(name: &str) -> bool { +pub fn is_alias_deprecated(name: &str) -> bool { match name { "DD_REMOTE_CONFIG_ENABLED" => true, #[cfg(test)] @@ -209,3 +217,708 @@ pub(crate) fn is_alias_deprecated(name: &str) -> bool { _ => false, } } + +/// Configuration for the Datadog Tracer +/// +/// # Usage +/// ``` +/// use datadog_opentelemetry::configuration::Config; +/// +/// +/// let config = Config::builder() // This pulls configuration from the environment and other sources +/// .set_service("my-service".to_string()) // Override service name +/// .set_version("1.0.0".to_string()) // Override version +/// .build(); +/// ``` +#[derive(Clone)] +#[non_exhaustive] +pub struct Config { + pub(super) runtime_id: &'static str, + pub(super) tracer_version: &'static str, + pub(super) language_version: String, + pub(super) language: &'static str, + pub(super) agent_host: ConfigItem>, + pub(super) dogstatsd_agent_host: ConfigItem>, + pub(super) dogstatsd_agent_port: ConfigItem, + pub(super) dogstatsd_agent_url: ConfigItemWithOverride>, + pub(super) env: ConfigItem>, + pub(super) telemetry_enabled: ConfigItem, + pub(super) logs_otel_enabled: ConfigItem, + pub(super) log_level_filter: ConfigItem, + pub(super) metrics_otel_enabled: ConfigItem, + pub(super) remote_config_enabled: ConfigItem, + pub(super) remote_config_poll_interval: ConfigItem, + pub(super) service: ConfigItemWithOverride, + pub(super) global_tags: ConfigItem>, + pub(super) telemetry_heartbeat_interval: ConfigItem, + pub(super) telemetry_log_collection_enabled: ConfigItem, + pub(super) trace_agent_port: ConfigItem, + pub(super) trace_agent_url: ConfigItemWithOverride>, + pub(super) enabled: ConfigItem, + pub(super) trace_partial_flush_enabled: ConfigItem, + pub(super) trace_partial_flush_min_spans: ConfigItem, + pub(super) trace_propagation_extract_first: ConfigItem, + pub(super) trace_propagation_style: ConfigItem>>, + pub(super) trace_propagation_style_extract: ConfigItem>>, + pub(super) trace_propagation_style_inject: ConfigItem>>, + pub(super) trace_rate_limit: ConfigItem, + pub(super) trace_sampling_rules: ConfigItemWithOverride, + pub(super) trace_stats_computation_enabled: ConfigItem, + pub(super) datadog_tags_max_length: ConfigItem, + pub(super) version: ConfigItem>, + pub(super) otlp_endpoint: ConfigItem>, + pub(super) otlp_headers: ConfigItem>, + pub(super) otlp_logs_endpoint: ConfigItem>, + pub(super) otlp_logs_headers: ConfigItem>, + pub(super) otlp_logs_protocol: ConfigItem>, + pub(super) otlp_logs_timeout: ConfigItem, + pub(super) otlp_metrics_endpoint: ConfigItem>, + pub(super) otlp_metrics_headers: ConfigItem>, + pub(super) otlp_metrics_protocol: ConfigItem>, + pub(super) otel_metrics_temporality_preference: + ConfigItem>, + pub(super) otlp_metrics_timeout: ConfigItem, + pub(super) otlp_protocol: ConfigItem>, + pub(super) otlp_timeout: ConfigItem, + pub(super) otel_logs_exporter: ConfigItem>, + pub(super) otel_metrics_exporter: ConfigItem>, + pub(super) metric_export_interval: ConfigItem, + pub(super) metric_export_timeout: ConfigItem, + pub(super) otel_resource_attributes: ConfigItem>, + pub(super) trace_writer_synchronous_write: bool, + pub(super) trace_writer_synchronous_timeout: Duration, + pub(super) trace_writer_max_flush_interval: Duration, + #[cfg(feature = "test-utils")] + pub(super) wait_agent_info_ready: bool, + pub(super) extra_services_tracker: ExtraServicesTracker, + pub(super) remote_config_callbacks: Arc>, +} + +#[allow(missing_docs)] +impl Config { + /// Returns the value of `DD_AGENT_HOST`. + pub fn agent_host(&self) -> &str { + self.agent_host.value().as_ref() + } + + /// Returns the value of `DD_DOGSTATSD_HOST`. + pub fn dogstatsd_agent_host(&self) -> &str { + self.dogstatsd_agent_host.value().as_ref() + } + + /// Returns the value of `DD_DOGSTATSD_PORT`. + pub fn dogstatsd_agent_port(&self) -> u32 { + *self.dogstatsd_agent_port.value() + } + + /// Returns the value of `DD_INSTRUMENTATION_TELEMETRY_ENABLED`. + pub fn telemetry_enabled(&self) -> bool { + *self.telemetry_enabled.value() + } + + /// Returns the value of `DD_LOGS_OTEL_ENABLED`. + pub fn logs_otel_enabled(&self) -> bool { + *self.logs_otel_enabled.value() + } + + /// Returns the value of `DD_METRICS_OTEL_ENABLED`. + pub fn metrics_otel_enabled(&self) -> bool { + *self.metrics_otel_enabled.value() + } + + /// Returns the value of `DD_REMOTE_CONFIGURATION_ENABLED`. + pub fn remote_config_enabled(&self) -> bool { + *self.remote_config_enabled.value() + } + + /// Returns the value of `DD_TELEMETRY_LOG_COLLECTION_ENABLED`. + pub fn telemetry_log_collection_enabled(&self) -> bool { + *self.telemetry_log_collection_enabled.value() + } + + /// Returns the value of `DD_TRACE_AGENT_PORT`. + pub fn trace_agent_port(&self) -> u32 { + *self.trace_agent_port.value() + } + + /// Returns the value of `DD_TRACE_AGENT_URL`. + pub fn trace_agent_url(&self) -> impl Deref + use<'_> { + self.trace_agent_url.value() + } + + /// Returns the value of `DD_TRACE_ENABLED`. + pub fn enabled(&self) -> bool { + *self.enabled.value() + } + + /// Returns the value of `DD_TRACE_PARTIAL_FLUSH_ENABLED`. + pub fn trace_partial_flush_enabled(&self) -> bool { + *self.trace_partial_flush_enabled.value() + } + + /// Returns the value of `DD_TRACE_PROPAGATION_EXTRACT_FIRST`. + pub fn trace_propagation_extract_first(&self) -> bool { + *self.trace_propagation_extract_first.value() + } + + /// Returns the value of `DD_TRACE_STATS_COMPUTATION_ENABLED`. + pub fn trace_stats_computation_enabled(&self) -> bool { + *self.trace_stats_computation_enabled.value() + } + + /// Returns the value of `OTEL_EXPORTER_OTLP_ENDPOINT`. + pub fn otlp_endpoint(&self) -> &str { + self.otlp_endpoint.value().as_ref() + } + + /// Returns the value of `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT`. + pub fn otlp_logs_endpoint(&self) -> &str { + self.otlp_logs_endpoint.value().as_ref() + } + + /// Returns the value of `OTEL_EXPORTER_OTLP_LOGS_HEADERS`. + pub fn otlp_logs_headers(&self) -> &str { + self.otlp_logs_headers.value().as_ref() + } + + /// Returns the value of `OTEL_EXPORTER_OTLP_LOGS_TIMEOUT`. + pub fn otlp_logs_timeout(&self) -> u32 { + *self.otlp_logs_timeout.value() + } + + /// Returns the value of `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT`. + pub fn otlp_metrics_endpoint(&self) -> &str { + self.otlp_metrics_endpoint.value().as_ref() + } + + /// Returns the value of `OTEL_EXPORTER_OTLP_METRICS_TIMEOUT`. + pub fn otlp_metrics_timeout(&self) -> u32 { + *self.otlp_metrics_timeout.value() + } + + /// Returns the value of `OTEL_EXPORTER_OTLP_TIMEOUT`. + pub fn otlp_timeout(&self) -> u32 { + *self.otlp_timeout.value() + } + + /// Returns the value of `OTEL_LOGS_EXPORTER`. + pub fn otel_logs_exporter(&self) -> &str { + self.otel_logs_exporter.value().as_ref() + } + + /// Returns the value of `OTEL_METRICS_EXPORTER`. + pub fn otel_metrics_exporter(&self) -> &str { + self.otel_metrics_exporter.value().as_ref() + } + + /// Returns the value of `OTEL_METRIC_EXPORT_INTERVAL`. + pub fn metric_export_interval(&self) -> u32 { + *self.metric_export_interval.value() + } + + /// Returns the value of `OTEL_METRIC_EXPORT_TIMEOUT`. + pub fn metric_export_timeout(&self) -> u32 { + *self.metric_export_timeout.value() + } + + pub(crate) fn get_telemetry_configuration(&self) -> Vec<&dyn ConfigurationProvider> { + vec![ + &self.agent_host, + &self.dogstatsd_agent_host, + &self.dogstatsd_agent_port, + &self.dogstatsd_agent_url, + &self.env, + &self.telemetry_enabled, + &self.logs_otel_enabled, + &self.log_level_filter, + &self.metrics_otel_enabled, + &self.remote_config_enabled, + &self.remote_config_poll_interval, + &self.service, + &self.global_tags, + &self.telemetry_heartbeat_interval, + &self.telemetry_log_collection_enabled, + &self.trace_agent_port, + &self.trace_agent_url, + &self.enabled, + &self.trace_partial_flush_enabled, + &self.trace_partial_flush_min_spans, + &self.trace_propagation_extract_first, + &self.trace_propagation_style, + &self.trace_propagation_style_extract, + &self.trace_propagation_style_inject, + &self.trace_rate_limit, + &self.trace_sampling_rules, + &self.trace_stats_computation_enabled, + &self.datadog_tags_max_length, + &self.version, + &self.otlp_endpoint, + &self.otlp_headers, + &self.otlp_logs_endpoint, + &self.otlp_logs_headers, + &self.otlp_logs_protocol, + &self.otlp_logs_timeout, + &self.otlp_metrics_endpoint, + &self.otlp_metrics_headers, + &self.otlp_metrics_protocol, + &self.otel_metrics_temporality_preference, + &self.otlp_metrics_timeout, + &self.otlp_protocol, + &self.otlp_timeout, + &self.otel_logs_exporter, + &self.otel_metrics_exporter, + &self.metric_export_interval, + &self.metric_export_timeout, + &self.otel_resource_attributes, + ] + } +} + +#[allow(missing_docs)] +impl ConfigBuilder { + /// Sets the value of `DD_AGENT_HOST`. + /// + /// **Default**: `localhost` + /// + /// Env variable: `DD_AGENT_HOST` + pub fn set_agent_host(&mut self, val: String) -> &mut Self { + self.config.agent_host.set_code(Cow::Owned(val)); + self + } + + /// Sets the value of `DD_DOGSTATSD_HOST`. + /// + /// **Default**: `localhost` + /// + /// Env variable: `DD_DOGSTATSD_HOST` + pub fn set_dogstatsd_agent_host(&mut self, val: String) -> &mut Self { + self.config.dogstatsd_agent_host.set_code(Cow::Owned(val)); + self + } + + /// Sets the value of `DD_DOGSTATSD_PORT`. + /// + /// **Default**: `8125` + /// + /// Env variable: `DD_DOGSTATSD_PORT` + pub fn set_dogstatsd_agent_port(&mut self, val: u32) -> &mut Self { + self.config.dogstatsd_agent_port.set_code(val); + self + } + + /// Sets the value of `DD_INSTRUMENTATION_TELEMETRY_ENABLED`. + /// + /// **Default**: `true` + /// + /// Env variable: `DD_INSTRUMENTATION_TELEMETRY_ENABLED` + pub fn set_telemetry_enabled(&mut self, val: bool) -> &mut Self { + self.config.telemetry_enabled.set_code(val); + self + } + + /// Sets the value of `DD_LOGS_OTEL_ENABLED`. + /// + /// **Default**: `true` + /// + /// Env variable: `DD_LOGS_OTEL_ENABLED` + pub fn set_logs_otel_enabled(&mut self, val: bool) -> &mut Self { + self.config.logs_otel_enabled.set_code(val); + self + } + + /// Sets the value of `DD_METRICS_OTEL_ENABLED`. + /// + /// **Default**: `true` + /// + /// Env variable: `DD_METRICS_OTEL_ENABLED` + pub fn set_metrics_otel_enabled(&mut self, val: bool) -> &mut Self { + self.config.metrics_otel_enabled.set_code(val); + self + } + + /// Sets the value of `DD_REMOTE_CONFIGURATION_ENABLED`. + /// + /// **Default**: `true` + /// + /// Env variable: `DD_REMOTE_CONFIGURATION_ENABLED` + /// Aliases: `DD_REMOTE_CONFIG_ENABLED` + pub fn set_remote_config_enabled(&mut self, val: bool) -> &mut Self { + self.config.remote_config_enabled.set_code(val); + self + } + + /// Sets the value of `DD_TELEMETRY_LOG_COLLECTION_ENABLED`. + /// + /// **Default**: `true` + /// + /// Env variable: `DD_TELEMETRY_LOG_COLLECTION_ENABLED` + pub fn set_telemetry_log_collection_enabled(&mut self, val: bool) -> &mut Self { + self.config.telemetry_log_collection_enabled.set_code(val); + self + } + + /// Sets the value of `DD_TRACE_AGENT_PORT`. + /// + /// **Default**: `8126` + /// + /// Env variable: `DD_TRACE_AGENT_PORT` + pub fn set_trace_agent_port(&mut self, val: u32) -> &mut Self { + self.config.trace_agent_port.set_code(val); + self + } + + /// Sets the value of `DD_TRACE_AGENT_URL`. + /// + /// **Default**: `` + /// + /// Env variable: `DD_TRACE_AGENT_URL` + pub fn set_trace_agent_url(&mut self, val: String) -> &mut Self { + self.config.trace_agent_url.set_code(Cow::Owned(val)); + self + } + + /// Sets the value of `DD_TRACE_ENABLED`. + /// + /// **Default**: `true` + /// + /// Env variable: `DD_TRACE_ENABLED` + pub fn set_enabled(&mut self, val: bool) -> &mut Self { + self.config.enabled.set_code(val); + self + } + + /// Sets the value of `DD_TRACE_PARTIAL_FLUSH_ENABLED`. + /// + /// **Default**: `false` + /// + /// Env variable: `DD_TRACE_PARTIAL_FLUSH_ENABLED` + pub fn set_trace_partial_flush_enabled(&mut self, val: bool) -> &mut Self { + self.config.trace_partial_flush_enabled.set_code(val); + self + } + + /// Sets the value of `DD_TRACE_PROPAGATION_EXTRACT_FIRST`. + /// + /// **Default**: `false` + /// + /// Env variable: `DD_TRACE_PROPAGATION_EXTRACT_FIRST` + pub fn set_trace_propagation_extract_first(&mut self, val: bool) -> &mut Self { + self.config.trace_propagation_extract_first.set_code(val); + self + } + + /// Sets the value of `DD_TRACE_STATS_COMPUTATION_ENABLED`. + /// + /// **Default**: `true` + /// + /// Env variable: `DD_TRACE_STATS_COMPUTATION_ENABLED` + pub fn set_trace_stats_computation_enabled(&mut self, val: bool) -> &mut Self { + self.config.trace_stats_computation_enabled.set_code(val); + self + } + + /// Sets the value of `OTEL_EXPORTER_OTLP_ENDPOINT`. + /// Env variable: `OTEL_EXPORTER_OTLP_ENDPOINT` + pub fn set_otlp_endpoint(&mut self, val: String) -> &mut Self { + self.config.otlp_endpoint.set_code(Cow::Owned(val)); + self + } + + /// Sets the value of `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT`. + /// Env variable: `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` + pub fn set_otlp_logs_endpoint(&mut self, val: String) -> &mut Self { + self.config.otlp_logs_endpoint.set_code(Cow::Owned(val)); + self + } + + /// Sets the value of `OTEL_EXPORTER_OTLP_LOGS_HEADERS`. + /// Env variable: `OTEL_EXPORTER_OTLP_LOGS_HEADERS` + pub fn set_otlp_logs_headers(&mut self, val: String) -> &mut Self { + self.config.otlp_logs_headers.set_code(Cow::Owned(val)); + self + } + + /// Sets the value of `OTEL_EXPORTER_OTLP_LOGS_TIMEOUT`. + /// + /// **Default**: `10000` + /// + /// Env variable: `OTEL_EXPORTER_OTLP_LOGS_TIMEOUT` + pub fn set_otlp_logs_timeout(&mut self, val: u32) -> &mut Self { + self.config.otlp_logs_timeout.set_code(val); + self + } + + /// Sets the value of `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT`. + /// Env variable: `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` + pub fn set_otlp_metrics_endpoint(&mut self, val: String) -> &mut Self { + self.config.otlp_metrics_endpoint.set_code(Cow::Owned(val)); + self + } + + /// Sets the value of `OTEL_EXPORTER_OTLP_METRICS_TIMEOUT`. + /// + /// **Default**: `10000` + /// + /// Env variable: `OTEL_EXPORTER_OTLP_METRICS_TIMEOUT` + pub fn set_otlp_metrics_timeout(&mut self, val: u32) -> &mut Self { + self.config.otlp_metrics_timeout.set_code(val); + self + } + + /// Sets the value of `OTEL_EXPORTER_OTLP_TIMEOUT`. + /// + /// **Default**: `10000` + /// + /// Env variable: `OTEL_EXPORTER_OTLP_TIMEOUT` + pub fn set_otlp_timeout(&mut self, val: u32) -> &mut Self { + self.config.otlp_timeout.set_code(val); + self + } + + /// Sets the value of `OTEL_LOGS_EXPORTER`. + /// + /// **Default**: `otlp` + /// + /// Env variable: `OTEL_LOGS_EXPORTER` + pub fn set_otel_logs_exporter(&mut self, val: String) -> &mut Self { + self.config.otel_logs_exporter.set_code(Cow::Owned(val)); + self + } + + /// Sets the value of `OTEL_METRICS_EXPORTER`. + /// + /// **Default**: `otlp` + /// + /// Env variable: `OTEL_METRICS_EXPORTER` + pub fn set_otel_metrics_exporter(&mut self, val: String) -> &mut Self { + self.config.otel_metrics_exporter.set_code(Cow::Owned(val)); + self + } + + /// Sets the value of `OTEL_METRIC_EXPORT_INTERVAL`. + /// + /// **Default**: `10000` + /// + /// Env variable: `OTEL_METRIC_EXPORT_INTERVAL` + pub fn set_metric_export_interval(&mut self, val: u32) -> &mut Self { + self.config.metric_export_interval.set_code(val); + self + } + + /// Sets the value of `OTEL_METRIC_EXPORT_TIMEOUT`. + /// + /// **Default**: `7500` + /// + /// Env variable: `OTEL_METRIC_EXPORT_TIMEOUT` + pub fn set_metric_export_timeout(&mut self, val: u32) -> &mut Self { + self.config.metric_export_timeout.set_code(val); + self + } +} + +pub(super) fn default_config() -> Config { + use SupportedConfigurations as S; + Config { + runtime_id: Config::process_runtime_id(), + tracer_version: TRACER_VERSION, + language: "rust", + language_version: version().to_string(), + trace_writer_synchronous_write: false, + trace_writer_synchronous_timeout: Duration::from_secs(2), + trace_writer_max_flush_interval: Duration::from_secs(1), + #[cfg(feature = "test-utils")] + wait_agent_info_ready: false, + extra_services_tracker: ExtraServicesTracker::new(), + remote_config_callbacks: Arc::new(Mutex::new(RemoteConfigCallbacks::new())), + agent_host: ConfigItem::new(S::DD_AGENT_HOST, Cow::Borrowed("localhost")), + dogstatsd_agent_host: ConfigItem::new(S::DD_DOGSTATSD_HOST, Cow::Borrowed("localhost")), + dogstatsd_agent_port: ConfigItem::new(S::DD_DOGSTATSD_PORT, 8125), + dogstatsd_agent_url: ConfigItemWithOverride::new_calculated( + S::DD_DOGSTATSD_URL, + Cow::Borrowed(""), + ), + env: ConfigItem::new(S::DD_ENV, None), + telemetry_enabled: ConfigItem::new(S::DD_INSTRUMENTATION_TELEMETRY_ENABLED, true), + logs_otel_enabled: ConfigItem::new(S::DD_LOGS_OTEL_ENABLED, true), + log_level_filter: ConfigItem::new(S::DD_LOG_LEVEL, LevelFilter::default()), + metrics_otel_enabled: ConfigItem::new(S::DD_METRICS_OTEL_ENABLED, true), + remote_config_enabled: ConfigItem::new(S::DD_REMOTE_CONFIGURATION_ENABLED, true), + remote_config_poll_interval: ConfigItem::new( + S::DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS, + 5.0, + ), + service: ConfigItemWithOverride::new_calculated(S::DD_SERVICE, ServiceName::Default), + global_tags: ConfigItem::new(S::DD_TAGS, Vec::new()), + telemetry_heartbeat_interval: ConfigItem::new(S::DD_TELEMETRY_HEARTBEAT_INTERVAL, 60.0), + telemetry_log_collection_enabled: ConfigItem::new( + S::DD_TELEMETRY_LOG_COLLECTION_ENABLED, + true, + ), + trace_agent_port: ConfigItem::new(S::DD_TRACE_AGENT_PORT, 8126), + trace_agent_url: ConfigItemWithOverride::new_calculated( + S::DD_TRACE_AGENT_URL, + Cow::Borrowed(""), + ), + enabled: ConfigItem::new(S::DD_TRACE_ENABLED, true), + trace_partial_flush_enabled: ConfigItem::new(S::DD_TRACE_PARTIAL_FLUSH_ENABLED, false), + trace_partial_flush_min_spans: ConfigItem::new( + S::DD_TRACE_PARTIAL_FLUSH_MIN_SPANS, + 300usize, + ), + trace_propagation_extract_first: ConfigItem::new( + S::DD_TRACE_PROPAGATION_EXTRACT_FIRST, + false, + ), + trace_propagation_style: ConfigItem::new( + S::DD_TRACE_PROPAGATION_STYLE, + Some(vec![ + TracePropagationStyle::Datadog, + TracePropagationStyle::TraceContext, + ]), + ), + trace_propagation_style_extract: ConfigItem::new( + S::DD_TRACE_PROPAGATION_STYLE_EXTRACT, + None, + ), + trace_propagation_style_inject: ConfigItem::new(S::DD_TRACE_PROPAGATION_STYLE_INJECT, None), + trace_rate_limit: ConfigItem::new(S::DD_TRACE_RATE_LIMIT, 100i32), + trace_sampling_rules: ConfigItemWithOverride::new_rc( + S::DD_TRACE_SAMPLING_RULES, + ParsedSamplingRules::default(), + ), + trace_stats_computation_enabled: ConfigItem::new( + S::DD_TRACE_STATS_COMPUTATION_ENABLED, + true, + ), + datadog_tags_max_length: ConfigItem::new(S::DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH, 512usize), + version: ConfigItem::new(S::DD_VERSION, None), + otlp_endpoint: ConfigItem::new(S::OTEL_EXPORTER_OTLP_ENDPOINT, Cow::Borrowed("")), + otlp_headers: ConfigItem::new(S::OTEL_EXPORTER_OTLP_HEADERS, Cow::Borrowed("")), + otlp_logs_endpoint: ConfigItem::new(S::OTEL_EXPORTER_OTLP_LOGS_ENDPOINT, Cow::Borrowed("")), + otlp_logs_headers: ConfigItem::new(S::OTEL_EXPORTER_OTLP_LOGS_HEADERS, Cow::Borrowed("")), + otlp_logs_protocol: ConfigItem::new(S::OTEL_EXPORTER_OTLP_LOGS_PROTOCOL, None), + otlp_logs_timeout: ConfigItem::new(S::OTEL_EXPORTER_OTLP_LOGS_TIMEOUT, 10000), + otlp_metrics_endpoint: ConfigItem::new( + S::OTEL_EXPORTER_OTLP_METRICS_ENDPOINT, + Cow::Borrowed(""), + ), + otlp_metrics_headers: ConfigItem::new( + S::OTEL_EXPORTER_OTLP_METRICS_HEADERS, + Cow::Borrowed(""), + ), + otlp_metrics_protocol: ConfigItem::new(S::OTEL_EXPORTER_OTLP_METRICS_PROTOCOL, None), + otel_metrics_temporality_preference: ConfigItem::new( + S::OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE, + Some(opentelemetry_sdk::metrics::Temporality::Delta), + ), + otlp_metrics_timeout: ConfigItem::new(S::OTEL_EXPORTER_OTLP_METRICS_TIMEOUT, 10000), + otlp_protocol: ConfigItem::new(S::OTEL_EXPORTER_OTLP_PROTOCOL, None), + otlp_timeout: ConfigItem::new(S::OTEL_EXPORTER_OTLP_TIMEOUT, 10000), + otel_logs_exporter: ConfigItem::new(S::OTEL_LOGS_EXPORTER, Cow::Borrowed("otlp")), + otel_metrics_exporter: ConfigItem::new(S::OTEL_METRICS_EXPORTER, Cow::Borrowed("otlp")), + metric_export_interval: ConfigItem::new(S::OTEL_METRIC_EXPORT_INTERVAL, 10000), + metric_export_timeout: ConfigItem::new(S::OTEL_METRIC_EXPORT_TIMEOUT, 7500), + otel_resource_attributes: ConfigItem::new(S::OTEL_RESOURCE_ATTRIBUTES, Vec::new()), + } +} + +impl std::fmt::Debug for Config { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Config") + .field("runtime_id", &self.runtime_id) + .field("tracer_version", &self.tracer_version) + .field("language_version", &self.language_version) + .field("agent_host", &self.agent_host) + .field("dogstatsd_agent_host", &self.dogstatsd_agent_host) + .field("dogstatsd_agent_port", &self.dogstatsd_agent_port) + .field("dogstatsd_agent_url", &self.dogstatsd_agent_url) + .field("env", &self.env) + .field("telemetry_enabled", &self.telemetry_enabled) + .field("logs_otel_enabled", &self.logs_otel_enabled) + .field("log_level_filter", &self.log_level_filter) + .field("metrics_otel_enabled", &self.metrics_otel_enabled) + .field("remote_config_enabled", &self.remote_config_enabled) + .field( + "remote_config_poll_interval", + &self.remote_config_poll_interval, + ) + .field("service", &self.service) + .field("global_tags", &self.global_tags) + .field( + "telemetry_heartbeat_interval", + &self.telemetry_heartbeat_interval, + ) + .field( + "telemetry_log_collection_enabled", + &self.telemetry_log_collection_enabled, + ) + .field("trace_agent_port", &self.trace_agent_port) + .field("trace_agent_url", &self.trace_agent_url) + .field("enabled", &self.enabled) + .field( + "trace_partial_flush_enabled", + &self.trace_partial_flush_enabled, + ) + .field( + "trace_partial_flush_min_spans", + &self.trace_partial_flush_min_spans, + ) + .field( + "trace_propagation_extract_first", + &self.trace_propagation_extract_first, + ) + .field("trace_propagation_style", &self.trace_propagation_style) + .field( + "trace_propagation_style_extract", + &self.trace_propagation_style_extract, + ) + .field( + "trace_propagation_style_inject", + &self.trace_propagation_style_inject, + ) + .field("trace_rate_limit", &self.trace_rate_limit) + .field("trace_sampling_rules", &self.trace_sampling_rules) + .field( + "trace_stats_computation_enabled", + &self.trace_stats_computation_enabled, + ) + .field("datadog_tags_max_length", &self.datadog_tags_max_length) + .field("version", &self.version) + .field("otlp_endpoint", &self.otlp_endpoint) + .field("otlp_headers", &self.otlp_headers) + .field("otlp_logs_endpoint", &self.otlp_logs_endpoint) + .field("otlp_logs_headers", &self.otlp_logs_headers) + .field("otlp_logs_protocol", &self.otlp_logs_protocol) + .field("otlp_logs_timeout", &self.otlp_logs_timeout) + .field("otlp_metrics_endpoint", &self.otlp_metrics_endpoint) + .field("otlp_metrics_headers", &self.otlp_metrics_headers) + .field("otlp_metrics_protocol", &self.otlp_metrics_protocol) + .field( + "otel_metrics_temporality_preference", + &self.otel_metrics_temporality_preference, + ) + .field("otlp_metrics_timeout", &self.otlp_metrics_timeout) + .field("otlp_protocol", &self.otlp_protocol) + .field("otlp_timeout", &self.otlp_timeout) + .field("otel_logs_exporter", &self.otel_logs_exporter) + .field("otel_metrics_exporter", &self.otel_metrics_exporter) + .field("metric_export_interval", &self.metric_export_interval) + .field("metric_export_timeout", &self.metric_export_timeout) + .field("otel_resource_attributes", &self.otel_resource_attributes) + .field( + "trace_writer_synchronous_write", + &self.trace_writer_synchronous_write, + ) + .field( + "trace_writer_synchronous_timeout", + &self.trace_writer_synchronous_timeout, + ) + .field( + "trace_writer_max_flush_interval", + &self.trace_writer_max_flush_interval, + ) + .field("extra_services_tracker", &self.extra_services_tracker) + .field("remote_config_callbacks", &self.remote_config_callbacks) + .finish() + } +} diff --git a/scripts/local_config_map_generate.py b/scripts/local_config_map_generate.py index e2c26fdc..7d736b09 100644 --- a/scripts/local_config_map_generate.py +++ b/scripts/local_config_map_generate.py @@ -12,7 +12,10 @@ "deprecated": False, }, "DD_NONEXISTANT_CONFIGURATION": { - "aliases": ["DD_NONEXISTANT_CONFIGURATION_ALIAS", "DD_NONEXISTANT_CONFIGURATION_DEPRECATED_ALIAS"], + "aliases": [ + "DD_NONEXISTANT_CONFIGURATION_ALIAS", + "DD_NONEXISTANT_CONFIGURATION_DEPRECATED_ALIAS", + ], "deprecated": False, }, "DD_NONEXISTANT_CONFIGURATION_ALIAS": { @@ -25,61 +28,259 @@ }, } +# JSON type → Rust type +TYPE_MAP = { + "string": "Cow<'static, str>", + "int": "u32", + "decimal": "f64", + "boolean": "bool", + "map": "Vec<(String, String)>", + "array": "Option>", +} + +# ── Build blocks from JSON ─────────────────────────────────────────────────── + enum_block = "" as_str_block = "" aliases_block = [] alias_deprecated_block = [] deprecated_block = [] -for i, key in enumerate(supported_configurations["supportedConfigurations"].keys()): +struct_field_lines = [] +getter_lines = [] +setter_lines = [] +telemetry_lines = [] +debug_lines = [] +default_config_lines = [] + +for i, (key, versions) in enumerate( + supported_configurations["supportedConfigurations"].items() +): if i != 0: enum_block += "\n" as_str_block += "\n" - enum_block += f" {key}," - as_str_block += f" SupportedConfigurations::{key} => \"{key}\"," + + enum_block += " {},".format(key) + as_str_block += ' SupportedConfigurations::{} => "{}",'.format(key, key) + + json_type = versions[0]["type"] + default_val = versions[0].get("default") + property_keys = versions[0].get("propertyKeys", []) + field_name = property_keys[0] if property_keys else None + skip_raw = versions[0].get("skip_default_generation", "") + if skip_raw is True or skip_raw == "all": + skip_set = {"getter", "setter", "default"} + elif skip_raw: + skip_set = {s.strip() for s in skip_raw.split(",")} + else: + skip_set = set() + + # Build struct field line + if field_name: + rust_type = versions[0].get("rust_type", TYPE_MAP.get(json_type)) + config_item_type = versions[0].get("config_item_type") + if config_item_type in ("override_code", "override_rc"): + struct_field_lines.append( + " pub(super) {}: ConfigItemWithOverride<{}>,".format(field_name, rust_type) + ) + else: + struct_field_lines.append( + " pub(super) {}: ConfigItem<{}>,".format(field_name, rust_type) + ) + + # Build doc comment shared by getter and setter + default_display = versions[0].get("default") + all_aliases = [a for v in versions for a in v.get("aliases", [])] + + def getter_doc(): + return " /// Returns the value of `{}`.".format(key) + + def setter_doc(): + lines = [" /// Sets the value of `{}`.".format(key)] + if default_display is not None: + lines += [" ///", " /// **Default**: `{}`".format(default_display), " ///"] + lines.append(" /// Env variable: `{}`".format(key)) + if all_aliases: + lines.append(" /// Aliases: {}".format(", ".join("`{}`".format(a) for a in all_aliases))) + return "\n".join(lines) + + # Build getter/setter lines for simple types + skip_getters = "getter" in skip_set + skip_setters = "setter" in skip_set + if field_name and json_type in ("string", "int", "decimal", "boolean"): + if json_type == "string": + if not skip_getters: + if config_item_type in ("override_code", "override_rc"): + getter_lines.append( + "{}\n pub fn {}(&self) -> impl Deref + use<'_> {{ self.{}.value() }}".format( + getter_doc(), field_name, field_name + ) + ) + else: + getter_lines.append( + "{}\n pub fn {}(&self) -> &str {{ self.{}.value().as_ref() }}".format( + getter_doc(), field_name, field_name + ) + ) + if not skip_setters: + setter_lines.append( + "{}\n pub fn set_{}(&mut self, val: String) -> &mut Self {{ self.config.{}.set_code(Cow::Owned(val)); self }}".format( + setter_doc(), field_name, field_name + ) + ) + elif json_type == "int": + if not skip_getters: + getter_lines.append( + "{}\n pub fn {}(&self) -> u32 {{ *self.{}.value() }}".format( + getter_doc(), field_name, field_name + ) + ) + if not skip_setters: + setter_lines.append( + "{}\n pub fn set_{}(&mut self, val: u32) -> &mut Self {{ self.config.{}.set_code(val); self }}".format( + setter_doc(), field_name, field_name + ) + ) + elif json_type == "decimal": + if not skip_getters: + getter_lines.append( + "{}\n pub fn {}(&self) -> f64 {{ *self.{}.value() }}".format( + getter_doc(), field_name, field_name + ) + ) + if not skip_setters: + setter_lines.append( + "{}\n pub fn set_{}(&mut self, val: f64) -> &mut Self {{ self.config.{}.set_code(val); self }}".format( + setter_doc(), field_name, field_name + ) + ) + elif json_type == "boolean": + if not skip_getters: + getter_lines.append( + "{}\n pub fn {}(&self) -> bool {{ *self.{}.value() }}".format( + getter_doc(), field_name, field_name + ) + ) + if not skip_setters: + setter_lines.append( + "{}\n pub fn set_{}(&mut self, val: bool) -> &mut Self {{ self.config.{}.set_code(val); self }}".format( + setter_doc(), field_name, field_name + ) + ) + + # Build default_config() field line + if field_name: + rust_value = versions[0].get("rust_value") + config_item_type = versions[0].get("config_item_type") + if rust_value is not None: + if config_item_type == "override_code": + default_config_lines.append( + " {}: ConfigItemWithOverride::new_calculated(S::{}, {}),".format( + field_name, key, rust_value + ) + ) + elif config_item_type == "override_rc": + default_config_lines.append( + " {}: ConfigItemWithOverride::new_rc(S::{}, {}),".format( + field_name, key, rust_value + ) + ) + else: + default_config_lines.append( + " {}: ConfigItem::new(S::{}, {}),".format( + field_name, key, rust_value + ) + ) + elif "default" not in skip_set: + rust_val = None + if json_type == "string": + rust_val = 'Cow::Borrowed("{}")'.format(default_val or "") + elif json_type == "int": + rust_val = str(int(default_val)) if default_val is not None else "0" + elif json_type == "decimal": + rust_val = str(float(default_val)) if default_val is not None else "0.0" + elif json_type == "boolean": + rust_val = ("true" if default_val == "true" else "false") if default_val is not None else "false" + elif json_type == "map": + rust_val = "Vec::new()" + if rust_val is not None: + default_config_lines.append( + " {}: ConfigItem::new(S::{}, {}),".format(field_name, key, rust_val) + ) + + # Build telemetry config and Debug lines for ALL configs with propertyKeys + if field_name: + telemetry_lines.append(" &self.{},".format(field_name)) + debug_lines.append( + ' .field("{}", &self.{})'.format(field_name, field_name) + ) + + # Aliases and deprecation aliases_accumulator = [] - deprecated = False - for version in supported_configurations["supportedConfigurations"][key]: + for version in versions: if "aliases" in version: for alias in version["aliases"]: aliases_accumulator.append(alias) - if alias not in supported_configurations["supportedConfigurations"].keys(): - alias_deprecated_block.append(f"\"{alias}\" => true,") + if alias not in supported_configurations["supportedConfigurations"]: + alias_deprecated_block.append('"{}" => true,'.format(alias)) if "deprecated" in version and version["deprecated"]: - deprecated_block.append(f"SupportedConfigurations::{key} => true,") - if len(aliases_accumulator) > 0: - aliases_str = ', '.join(f'"{a}"' for a in aliases_accumulator) - aliases_block.append(f"SupportedConfigurations::{key} => &[{aliases_str}],") - + deprecated_block.append( + "SupportedConfigurations::{} => true,".format(key) + ) + if aliases_accumulator: + quoted = ", ".join('"{}"'.format(a) for a in aliases_accumulator) + aliases_block.append( + "SupportedConfigurations::{} => &[{}],".format(key, quoted) + ) -if len(undocumented_configurations) > 0: +# Undocumented test configurations +if undocumented_configurations: enum_block += "\n\n /// Used for testing purposes only" -for i, key in enumerate(undocumented_configurations): - enum_block += f"\n #[cfg(test)]\n #[allow(unused)]\n {key}," - as_str_block += f"\n #[cfg(test)]\n SupportedConfigurations::{key} => \"{key}\"," - if len(undocumented_configurations[key]["aliases"]) > 0: - aliases_str = ', '.join(f'"{a}"' for a in undocumented_configurations[key]["aliases"]) - aliases_block.append(f"#[cfg(test)]\n SupportedConfigurations::{key} => &[{aliases_str}],") - if undocumented_configurations[key]["deprecated"]: - deprecated_block.append(f"#[cfg(test)]\n SupportedConfigurations::{key} => true,") - for alias in undocumented_configurations[key]["aliases"]: - if alias not in undocumented_configurations.keys(): - alias_deprecated_block.append(f"#[cfg(test)]\n \"{alias}\" => true,") - -aliases_join = "\n ".join(aliases_block) -deprecated_join = "\n ".join(deprecated_block) -alias_deprecated_join = "\n ".join(alias_deprecated_block) - -result = f"""\ +for key in undocumented_configurations: + conf = undocumented_configurations[key] + enum_block += "\n #[cfg(test)]\n #[allow(unused)]\n {},".format(key) + as_str_block += '\n #[cfg(test)]\n SupportedConfigurations::{} => "{}",'.format( + key, key + ) + if conf["aliases"]: + quoted = ", ".join('"{}"'.format(a) for a in conf["aliases"]) + aliases_block.append( + "#[cfg(test)]\n SupportedConfigurations::{} => &[{}],".format( + key, quoted + ) + ) + if conf["deprecated"]: + deprecated_block.append( + "#[cfg(test)]\n SupportedConfigurations::{} => true,".format(key) + ) + for alias in conf["aliases"]: + if alias not in undocumented_configurations: + alias_deprecated_block.append( + '#[cfg(test)]\n "{}" => true,'.format(alias) + ) + +# ── Assemble template ──────────────────────────────────────────────────────── + +NL = "\n " + +result = """\ // Copyright 2025-Present Datadog, Inc. https://www.datadoghq.com/ // SPDX-License-Identifier: Apache-2.0 /// This file is generated by the scripts/local_config_map_generate.py script. /// Do not edit this file manually. To add a new configuration, /// add it to the supported-configurations.json file, then run this script. +use std::borrow::Cow; +use std::sync::{{Arc, Mutex}}; +use std::time::Duration; + +use rustc_version_runtime::version; + +use super::*; + #[allow(nonstandard_style)] #[derive(Debug, PartialEq, Copy, Clone)] #[non_exhaustive] -pub(crate) enum SupportedConfigurations {{ +pub enum SupportedConfigurations {{ {enum_block} }} @@ -92,29 +293,121 @@ pub fn aliases(&self) -> &[&'static str] {{ match self {{ - {aliases_join} + {aliases_joined} _ => &[], }} }} pub fn is_deprecated(&self) -> bool {{ match self {{ - {deprecated_join} + {deprecated_joined} _ => false, }} }} }} -pub(crate) fn is_alias_deprecated(name: &str) -> bool {{ +pub fn is_alias_deprecated(name: &str) -> bool {{ match name {{ - {alias_deprecated_join} + {alias_deprecated_joined} _ => false, }} }} -""" -with open("datadog-opentelemetry/src/core/configuration/supported_configurations.rs", "w") as f: +/// Configuration for the Datadog Tracer +/// +/// # Usage +/// ``` +/// use datadog_opentelemetry::configuration::Config; +/// +/// +/// let config = Config::builder() // This pulls configuration from the environment and other sources +/// .set_service("my-service".to_string()) // Override service name +/// .set_version("1.0.0".to_string()) // Override version +/// .build(); +/// ``` +#[derive(Clone)] +#[non_exhaustive] +pub struct Config {{ + pub(super) runtime_id: &'static str, + pub(super) tracer_version: &'static str, + pub(super) language_version: String, + pub(super) language: &'static str, +{struct_fields_block} + pub(super) trace_writer_synchronous_write: bool, + pub(super) trace_writer_synchronous_timeout: Duration, + pub(super) trace_writer_max_flush_interval: Duration, + #[cfg(feature = "test-utils")] + pub(super) wait_agent_info_ready: bool, + pub(super) extra_services_tracker: ExtraServicesTracker, + pub(super) remote_config_callbacks: Arc>, +}} + +#[allow(missing_docs)] +impl Config {{ +{getters_block} + + pub(crate) fn get_telemetry_configuration(&self) -> Vec<&dyn ConfigurationProvider> {{ + vec![ +{telemetry_block} + ] + }} +}} + +#[allow(missing_docs)] +impl ConfigBuilder {{ +{setters_block} +}} + +pub(super) fn default_config() -> Config {{ + use SupportedConfigurations as S; + Config {{ + runtime_id: Config::process_runtime_id(), + tracer_version: TRACER_VERSION, + language: "rust", + language_version: version().to_string(), + trace_writer_synchronous_write: false, + trace_writer_synchronous_timeout: Duration::from_secs(2), + trace_writer_max_flush_interval: Duration::from_secs(1), + #[cfg(feature = "test-utils")] + wait_agent_info_ready: false, + extra_services_tracker: ExtraServicesTracker::new(), + remote_config_callbacks: Arc::new(Mutex::new(RemoteConfigCallbacks::new())), +{default_config_block} + }} +}} + +impl std::fmt::Debug for Config {{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {{ + f.debug_struct("Config") + .field("runtime_id", &self.runtime_id) + .field("tracer_version", &self.tracer_version) + .field("language_version", &self.language_version) +{debug_block} + .field("trace_writer_synchronous_write", &self.trace_writer_synchronous_write) + .field("trace_writer_synchronous_timeout", &self.trace_writer_synchronous_timeout) + .field("trace_writer_max_flush_interval", &self.trace_writer_max_flush_interval) + .field("extra_services_tracker", &self.extra_services_tracker) + .field("remote_config_callbacks", &self.remote_config_callbacks) + .finish() + }} +}} +""".format( + enum_block=enum_block, + as_str_block=as_str_block, + aliases_joined=NL.join(aliases_block), + deprecated_joined=NL.join(deprecated_block), + alias_deprecated_joined=NL.join(alias_deprecated_block), + struct_fields_block="\n".join(struct_field_lines), + default_config_block="\n".join(default_config_lines), + getters_block="\n\n".join(getter_lines), + setters_block="\n\n".join(setter_lines), + telemetry_block="\n".join(telemetry_lines), + debug_block="\n".join(debug_lines), +) + +OUTPUT = "datadog-opentelemetry/src/core/configuration/supported_configurations.rs" +with open(OUTPUT, "w") as f: f.write(result) -# run cargo fmt -subprocess.run(["rustfmt", "datadog-opentelemetry/src/core/configuration/supported_configurations.rs"]) +subprocess.run(["rustfmt", OUTPUT]) +print("Done.") diff --git a/supported-configurations.json b/supported-configurations.json index 5fecec73..cda6568e 100644 --- a/supported-configurations.json +++ b/supported-configurations.json @@ -31,7 +31,10 @@ "version": "A", "type": "string", "default": "http://localhost:8125", - "propertyKeys": ["dogstatsd_agent_url"] + "propertyKeys": ["dogstatsd_agent_url"], + "skip_default_generation": "all", + "config_item_type": "override_code", + "rust_value": "Cow::Borrowed(\"\")" } ], "DD_ENV": [ @@ -39,7 +42,10 @@ "version": "A", "type": "string", "default": "", - "propertyKeys": ["env"] + "propertyKeys": ["env"], + "rust_type": "Option", + "skip_default_generation": "all", + "rust_value": "None" } ], "DD_INSTRUMENTATION_TELEMETRY_ENABLED": [ @@ -63,7 +69,10 @@ "version": "A", "type": "string", "default": "ERROR", - "propertyKeys": ["log_level_filter"] + "propertyKeys": ["log_level_filter"], + "rust_type": "LevelFilter", + "skip_default_generation": "all", + "rust_value": "LevelFilter::default()" } ], "DD_METRICS_OTEL_ENABLED": [ @@ -88,7 +97,8 @@ "version": "A", "type": "decimal", "default": "5.0", - "propertyKeys": ["remote_config_poll_interval"] + "propertyKeys": ["remote_config_poll_interval"], + "skip_default_generation": "getter,setter" } ], "DD_SERVICE": [ @@ -96,7 +106,11 @@ "version": "C", "type": "string", "default": "unnamed-rust-service", - "propertyKeys": ["service"] + "propertyKeys": ["service"], + "rust_type": "ServiceName", + "skip_default_generation": "all", + "rust_value": "ServiceName::Default", + "config_item_type": "override_code" } ], "DD_TAGS": [ @@ -112,7 +126,8 @@ "version": "B", "type": "decimal", "default": "60.0", - "propertyKeys": ["telemetry_heartbeat_interval"] + "propertyKeys": ["telemetry_heartbeat_interval"], + "skip_default_generation": "getter,setter" } ], "DD_TELEMETRY_LOG_COLLECTION_ENABLED": [ @@ -136,7 +151,9 @@ "version": "A", "type": "string", "default": "", - "propertyKeys": ["trace_agent_url"] + "propertyKeys": ["trace_agent_url"], + "config_item_type": "override_code", + "rust_value": "Cow::Borrowed(\"\")" } ], "DD_TRACE_ENABLED": [ @@ -152,7 +169,7 @@ "version": "A", "type": "boolean", "default": "false", - "propertyKeys": ["trace_partial_flushed_enabled"] + "propertyKeys": ["trace_partial_flush_enabled"] } ], "DD_TRACE_PARTIAL_FLUSH_MIN_SPANS": [ @@ -160,7 +177,10 @@ "version": "A", "type": "int", "default": "300", - "propertyKeys": ["trace_partial_flushed_min_spans"] + "propertyKeys": ["trace_partial_flush_min_spans"], + "rust_type": "usize", + "skip_default_generation": "all", + "rust_value": "300usize" } ], "DD_TRACE_PROPAGATION_EXTRACT_FIRST": [ @@ -176,7 +196,9 @@ "version": "A", "type": "array", "default": "datadog,tracecontext", - "propertyKeys": ["trace_propagation_style"] + "propertyKeys": ["trace_propagation_style"], + "skip_default_generation": "all", + "rust_value": "Some(vec![TracePropagationStyle::Datadog, TracePropagationStyle::TraceContext])" } ], "DD_TRACE_PROPAGATION_STYLE_EXTRACT": [ @@ -184,7 +206,9 @@ "version": "A", "type": "array", "default": "", - "propertyKeys": ["trace_propagation_style_extract"] + "propertyKeys": ["trace_propagation_style_extract"], + "skip_default_generation": "all", + "rust_value": "None" } ], "DD_TRACE_PROPAGATION_STYLE_INJECT": [ @@ -192,7 +216,9 @@ "version": "A", "type": "array", "default": "", - "propertyKeys": ["trace_propagation_style_inject"] + "propertyKeys": ["trace_propagation_style_inject"], + "skip_default_generation": "all", + "rust_value": "None" } ], "DD_TRACE_RATE_LIMIT": [ @@ -200,7 +226,10 @@ "version": "A", "type": "int", "default": "100", - "propertyKeys": ["trace_rate_limit"] + "propertyKeys": ["trace_rate_limit"], + "rust_type": "i32", + "skip_default_generation": "all", + "rust_value": "100i32" } ], "DD_TRACE_SAMPLING_RULES": [ @@ -208,7 +237,11 @@ "version": "A", "type": "array", "default": "", - "propertyKeys": ["trace_sampling_rules"] + "propertyKeys": ["trace_sampling_rules"], + "rust_type": "ParsedSamplingRules", + "skip_default_generation": "all", + "rust_value": "ParsedSamplingRules::default()", + "config_item_type": "override_rc" } ], "DD_TRACE_STATS_COMPUTATION_ENABLED": [ @@ -224,7 +257,10 @@ "version": "A", "type": "int", "default": "512", - "propertyKeys": ["datadog_tags_max_length"] + "propertyKeys": ["datadog_tags_max_length"], + "rust_type": "usize", + "skip_default_generation": "all", + "rust_value": "512usize" } ], "DD_VERSION": [ @@ -232,7 +268,10 @@ "version": "A", "type": "string", "default": "", - "propertyKeys": ["version"] + "propertyKeys": ["version"], + "rust_type": "Option", + "skip_default_generation": "all", + "rust_value": "None" } ], "OTEL_EXPORTER_OTLP_ENDPOINT": [ @@ -248,7 +287,10 @@ "version": "A", "type": "map", "default": "", - "propertyKeys": ["otlp_headers"] + "propertyKeys": ["otlp_headers"], + "rust_type": "Cow<'static, str>", + "skip_default_generation": "all", + "rust_value": "Cow::Borrowed(\"\")" } ], "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT": [ @@ -272,7 +314,10 @@ "version": "A", "type": "string", "default": "SDK-dependent, but will typically be either http/protobuf or grpc.", - "propertyKeys": ["otlp_logs_protocol"] + "propertyKeys": ["otlp_logs_protocol"], + "rust_type": "Option", + "skip_default_generation": "all", + "rust_value": "None" } ], "OTEL_EXPORTER_OTLP_LOGS_TIMEOUT": [ @@ -296,7 +341,10 @@ "version": "A", "type": "map", "default": null, - "propertyKeys": ["otlp_metrics_headers"] + "propertyKeys": ["otlp_metrics_headers"], + "rust_type": "Cow<'static, str>", + "skip_default_generation": "all", + "rust_value": "Cow::Borrowed(\"\")" } ], "OTEL_EXPORTER_OTLP_METRICS_PROTOCOL": [ @@ -304,7 +352,10 @@ "version": "A", "type": "string", "default": null, - "propertyKeys": ["otlp_metrics_protocol"] + "propertyKeys": ["otlp_metrics_protocol"], + "rust_type": "Option", + "skip_default_generation": "all", + "rust_value": "None" } ], "OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE": [ @@ -312,14 +363,17 @@ "version": "A", "type": "string", "default": "delta", - "propertyKeys": ["otel_metrics_temporality_preference"] + "propertyKeys": ["otel_metrics_temporality_preference"], + "rust_type": "Option", + "skip_default_generation": "all", + "rust_value": "Some(opentelemetry_sdk::metrics::Temporality::Delta)" } ], "OTEL_EXPORTER_OTLP_METRICS_TIMEOUT": [ { - "version": "A", + "version": "B", "type": "int", - "default": null, + "default": "10000", "propertyKeys": ["otlp_metrics_timeout"] } ], @@ -328,7 +382,10 @@ "version": "C", "type": "string", "default": "grpc", - "propertyKeys": ["otlp_protocol"] + "propertyKeys": ["otlp_protocol"], + "rust_type": "Option", + "skip_default_generation": "all", + "rust_value": "None" } ], "OTEL_EXPORTER_OTLP_TIMEOUT": [ @@ -375,8 +432,8 @@ { "version": "A", "type": "map", - "default_value": "", - "propertyKeys": [] +"default_value": "", + "propertyKeys": ["otel_resource_attributes"] } ] }