datadog 2.22.0 → 2.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +59 -2
- data/ext/LIBDATADOG_DEVELOPMENT.md +1 -58
- data/ext/datadog_profiling_native_extension/collectors_stack.c +4 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +1 -1
- data/ext/datadog_profiling_native_extension/extconf.rb +6 -4
- data/ext/datadog_profiling_native_extension/heap_recorder.c +1 -1
- data/ext/libdatadog_api/datadog_ruby_common.h +1 -1
- data/ext/libdatadog_api/feature_flags.c +554 -0
- data/ext/libdatadog_api/feature_flags.h +5 -0
- data/ext/libdatadog_api/init.c +2 -0
- data/ext/libdatadog_api/library_config.c +12 -11
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/appsec/api_security/route_extractor.rb +23 -6
- data/lib/datadog/appsec/api_security/sampler.rb +7 -4
- data/lib/datadog/appsec/assets/blocked.html +8 -0
- data/lib/datadog/appsec/assets/blocked.json +1 -1
- data/lib/datadog/appsec/assets/blocked.text +3 -1
- data/lib/datadog/appsec/assets.rb +1 -1
- data/lib/datadog/appsec/remote.rb +4 -0
- data/lib/datadog/appsec/response.rb +18 -4
- data/lib/datadog/core/configuration/components.rb +30 -3
- data/lib/datadog/core/configuration/config_helper.rb +1 -1
- data/lib/datadog/core/configuration/settings.rb +14 -0
- data/lib/datadog/core/configuration/supported_configurations.rb +330 -301
- data/lib/datadog/core/ddsketch.rb +0 -2
- data/lib/datadog/core/environment/ext.rb +6 -0
- data/lib/datadog/core/environment/process.rb +79 -0
- data/lib/datadog/core/feature_flags.rb +61 -0
- data/lib/datadog/core/remote/client/capabilities.rb +7 -0
- data/lib/datadog/core/remote/transport/config.rb +2 -10
- data/lib/datadog/core/remote/transport/http/config.rb +9 -9
- data/lib/datadog/core/remote/transport/http/negotiation.rb +17 -8
- data/lib/datadog/core/remote/transport/http.rb +2 -0
- data/lib/datadog/core/remote/transport/negotiation.rb +2 -18
- data/lib/datadog/core/remote/worker.rb +25 -37
- data/lib/datadog/core/tag_builder.rb +0 -4
- data/lib/datadog/core/tag_normalizer.rb +84 -0
- data/lib/datadog/core/telemetry/component.rb +7 -3
- data/lib/datadog/core/telemetry/event/app_started.rb +52 -49
- data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +1 -1
- data/lib/datadog/core/telemetry/logger.rb +2 -2
- data/lib/datadog/core/telemetry/logging.rb +2 -8
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +5 -6
- data/lib/datadog/core/telemetry/transport/telemetry.rb +1 -2
- data/lib/datadog/core/transport/http/client.rb +69 -0
- data/lib/datadog/core/utils/array.rb +29 -0
- data/lib/datadog/{appsec/api_security → core/utils}/lru_cache.rb +10 -21
- data/lib/datadog/core/utils/network.rb +3 -1
- data/lib/datadog/core/utils/only_once_successful.rb +6 -2
- data/lib/datadog/core/utils.rb +2 -0
- data/lib/datadog/data_streams/configuration/settings.rb +49 -0
- data/lib/datadog/data_streams/configuration.rb +11 -0
- data/lib/datadog/data_streams/ext.rb +11 -0
- data/lib/datadog/data_streams/extensions.rb +16 -0
- data/lib/datadog/data_streams/pathway_context.rb +169 -0
- data/lib/datadog/data_streams/processor.rb +509 -0
- data/lib/datadog/data_streams/transport/http/api.rb +33 -0
- data/lib/datadog/data_streams/transport/http/client.rb +21 -0
- data/lib/datadog/data_streams/transport/http/stats.rb +87 -0
- data/lib/datadog/data_streams/transport/http.rb +41 -0
- data/lib/datadog/data_streams/transport/stats.rb +60 -0
- data/lib/datadog/data_streams.rb +100 -0
- data/lib/datadog/di/component.rb +0 -16
- data/lib/datadog/di/el/evaluator.rb +1 -1
- data/lib/datadog/di/error.rb +4 -0
- data/lib/datadog/di/instrumenter.rb +76 -30
- data/lib/datadog/di/probe.rb +20 -0
- data/lib/datadog/di/probe_manager.rb +10 -2
- data/lib/datadog/di/probe_notification_builder.rb +62 -23
- data/lib/datadog/di/proc_responder.rb +32 -0
- data/lib/datadog/di/transport/diagnostics.rb +2 -2
- data/lib/datadog/di/transport/http/diagnostics.rb +2 -4
- data/lib/datadog/di/transport/http/input.rb +2 -4
- data/lib/datadog/di/transport/http.rb +6 -2
- data/lib/datadog/di/transport/input.rb +64 -4
- data/lib/datadog/open_feature/component.rb +60 -0
- data/lib/datadog/open_feature/configuration.rb +27 -0
- data/lib/datadog/open_feature/evaluation_engine.rb +69 -0
- data/lib/datadog/open_feature/exposures/batch_builder.rb +32 -0
- data/lib/datadog/open_feature/exposures/buffer.rb +43 -0
- data/lib/datadog/open_feature/exposures/deduplicator.rb +30 -0
- data/lib/datadog/open_feature/exposures/event.rb +60 -0
- data/lib/datadog/open_feature/exposures/reporter.rb +40 -0
- data/lib/datadog/open_feature/exposures/worker.rb +116 -0
- data/lib/datadog/open_feature/ext.rb +14 -0
- data/lib/datadog/open_feature/native_evaluator.rb +38 -0
- data/lib/datadog/open_feature/noop_evaluator.rb +26 -0
- data/lib/datadog/open_feature/provider.rb +141 -0
- data/lib/datadog/open_feature/remote.rb +74 -0
- data/lib/datadog/open_feature/resolution_details.rb +35 -0
- data/lib/datadog/open_feature/transport.rb +72 -0
- data/lib/datadog/open_feature.rb +19 -0
- data/lib/datadog/opentelemetry/configuration/settings.rb +159 -0
- data/lib/datadog/opentelemetry/metrics.rb +110 -0
- data/lib/datadog/opentelemetry/sdk/configurator.rb +25 -1
- data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +38 -0
- data/lib/datadog/opentelemetry.rb +3 -0
- data/lib/datadog/profiling/collectors/code_provenance.rb +15 -6
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +1 -1
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -1
- data/lib/datadog/profiling/profiler.rb +4 -0
- data/lib/datadog/profiling/tag_builder.rb +36 -3
- data/lib/datadog/profiling.rb +1 -2
- data/lib/datadog/single_step_instrument.rb +1 -1
- data/lib/datadog/tracing/configuration/ext.rb +9 -0
- data/lib/datadog/tracing/configuration/settings.rb +74 -0
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +4 -4
- data/lib/datadog/tracing/contrib/action_pack/utils.rb +1 -2
- data/lib/datadog/tracing/contrib/active_job/log_injection.rb +21 -7
- data/lib/datadog/tracing/contrib/active_job/patcher.rb +5 -1
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +4 -2
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -1
- data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +11 -3
- data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +11 -7
- data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +7 -3
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +22 -17
- data/lib/datadog/tracing/contrib/http/configuration/settings.rb +11 -3
- data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +11 -3
- data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +11 -3
- data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +66 -0
- data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +66 -0
- data/lib/datadog/tracing/contrib/kafka/patcher.rb +14 -0
- data/lib/datadog/tracing/contrib/karafka/framework.rb +30 -0
- data/lib/datadog/tracing/contrib/karafka/monitor.rb +11 -0
- data/lib/datadog/tracing/contrib/karafka/patcher.rb +32 -0
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +59 -27
- data/lib/datadog/tracing/contrib/rack/route_inference.rb +53 -0
- data/lib/datadog/tracing/contrib/rails/middlewares.rb +2 -2
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +4 -1
- data/lib/datadog/tracing/contrib/roda/instrumentation.rb +3 -1
- data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +3 -1
- data/lib/datadog/tracing/contrib/status_range_matcher.rb +7 -0
- data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +27 -0
- data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +48 -0
- data/lib/datadog/tracing/contrib/waterdrop/ext.rb +17 -0
- data/lib/datadog/tracing/contrib/waterdrop/integration.rb +43 -0
- data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +46 -0
- data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +46 -0
- data/lib/datadog/tracing/contrib/waterdrop/producer.rb +50 -0
- data/lib/datadog/tracing/contrib/waterdrop.rb +37 -0
- data/lib/datadog/tracing/contrib.rb +1 -0
- data/lib/datadog/tracing/metadata/ext.rb +1 -1
- data/lib/datadog/tracing/transport/http/client.rb +12 -26
- data/lib/datadog/tracing/transport/trace_formatter.rb +11 -0
- data/lib/datadog/tracing/transport/traces.rb +3 -5
- data/lib/datadog/version.rb +2 -2
- data/lib/datadog.rb +2 -0
- metadata +78 -15
- data/lib/datadog/core/remote/transport/http/client.rb +0 -49
- data/lib/datadog/core/telemetry/transport/http/client.rb +0 -49
- data/lib/datadog/di/transport/http/client.rb +0 -47
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../core/configuration/ext'
|
|
4
|
+
|
|
5
|
+
module Datadog
|
|
6
|
+
module OpenTelemetry
|
|
7
|
+
module Configuration
|
|
8
|
+
module Settings
|
|
9
|
+
def self.extended(base)
|
|
10
|
+
base = base.singleton_class unless base.is_a?(Class)
|
|
11
|
+
add_settings!(base)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.normalize_temporality_preference(env_var_name)
|
|
15
|
+
proc do |value|
|
|
16
|
+
if value && value.to_s.downcase != 'delta' && value.to_s.downcase != 'cumulative'
|
|
17
|
+
Datadog.logger.warn("#{env_var_name}=#{value} is not supported. Using delta instead.")
|
|
18
|
+
'delta'
|
|
19
|
+
else
|
|
20
|
+
value
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.normalize_protocol(env_var_name)
|
|
26
|
+
proc do |value|
|
|
27
|
+
if value && value.to_s.downcase != 'http/protobuf'
|
|
28
|
+
Datadog.logger.warn("#{env_var_name}=#{value} is not supported. Using http/protobuf instead.")
|
|
29
|
+
end
|
|
30
|
+
'http/protobuf'
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.headers_parser(env_var_name)
|
|
35
|
+
lambda do |value|
|
|
36
|
+
return {} if value.nil? || value.empty?
|
|
37
|
+
|
|
38
|
+
headers = {}
|
|
39
|
+
header_items = value.split(',')
|
|
40
|
+
header_items.each do |key_value|
|
|
41
|
+
key, header_value = key_value.split('=', 2)
|
|
42
|
+
# If header is malformed, return an empty hash
|
|
43
|
+
if key.nil? || header_value.nil?
|
|
44
|
+
Datadog.logger.warn("#{env_var_name} has malformed header: #{key_value.inspect}")
|
|
45
|
+
return {}
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
key.strip!
|
|
49
|
+
header_value.strip!
|
|
50
|
+
if key.empty? || header_value.empty?
|
|
51
|
+
Datadog.logger.warn("#{env_var_name} has empty key or value in: #{key_value.inspect}")
|
|
52
|
+
return {}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
headers[key] = header_value
|
|
56
|
+
end
|
|
57
|
+
headers
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def self.add_settings!(base)
|
|
62
|
+
base.class_eval do
|
|
63
|
+
settings :opentelemetry do
|
|
64
|
+
settings :exporter do
|
|
65
|
+
option :protocol do |o|
|
|
66
|
+
o.type :string
|
|
67
|
+
o.setter(&Settings.normalize_protocol('OTEL_EXPORTER_OTLP_PROTOCOL'))
|
|
68
|
+
o.env 'OTEL_EXPORTER_OTLP_PROTOCOL'
|
|
69
|
+
o.default 'http/protobuf'
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
option :timeout_millis do |o|
|
|
73
|
+
o.type :int
|
|
74
|
+
o.env 'OTEL_EXPORTER_OTLP_TIMEOUT'
|
|
75
|
+
o.default 10_000
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
option :headers do |o|
|
|
79
|
+
o.type :hash
|
|
80
|
+
o.env 'OTEL_EXPORTER_OTLP_HEADERS'
|
|
81
|
+
o.default { {} }
|
|
82
|
+
o.env_parser(&Settings.headers_parser('OTEL_EXPORTER_OTLP_HEADERS'))
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
option :endpoint do |o|
|
|
86
|
+
o.type :string, nilable: true
|
|
87
|
+
o.env 'OTEL_EXPORTER_OTLP_ENDPOINT'
|
|
88
|
+
o.default nil
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
settings :metrics do
|
|
93
|
+
# Metrics-specific options default to nil to detect unset state.
|
|
94
|
+
# If a metrics-specific env var (e.g., OTEL_EXPORTER_OTLP_METRICS_TIMEOUT) is not set,
|
|
95
|
+
# we fall back to the general OTLP env var (e.g., OTEL_EXPORTER_OTLP_TIMEOUT) per OpenTelemetry spec.
|
|
96
|
+
option :enabled do |o|
|
|
97
|
+
o.type :bool
|
|
98
|
+
o.env 'DD_METRICS_OTEL_ENABLED'
|
|
99
|
+
o.default false
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
option :exporter do |o|
|
|
103
|
+
o.type :string
|
|
104
|
+
o.env 'OTEL_METRICS_EXPORTER'
|
|
105
|
+
o.default 'otlp'
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
option :export_interval_millis do |o|
|
|
109
|
+
o.type :int
|
|
110
|
+
o.env 'OTEL_METRIC_EXPORT_INTERVAL'
|
|
111
|
+
o.default 10_000
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
option :export_timeout_millis do |o|
|
|
115
|
+
o.type :int
|
|
116
|
+
o.env 'OTEL_METRIC_EXPORT_TIMEOUT'
|
|
117
|
+
o.default 7_500
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
option :temporality_preference do |o|
|
|
121
|
+
o.type :string
|
|
122
|
+
o.env 'OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE'
|
|
123
|
+
o.default 'delta'
|
|
124
|
+
o.setter(&Settings.normalize_temporality_preference('OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE'))
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
option :endpoint do |o|
|
|
128
|
+
o.type :string, nilable: true
|
|
129
|
+
o.env 'OTEL_EXPORTER_OTLP_METRICS_ENDPOINT'
|
|
130
|
+
o.default nil
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
option :headers do |o|
|
|
134
|
+
o.type :hash, nilable: true
|
|
135
|
+
o.env 'OTEL_EXPORTER_OTLP_METRICS_HEADERS'
|
|
136
|
+
o.default nil
|
|
137
|
+
o.env_parser(&Settings.headers_parser('OTEL_EXPORTER_OTLP_METRICS_HEADERS'))
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
option :timeout_millis do |o|
|
|
141
|
+
o.type :int, nilable: true
|
|
142
|
+
o.env 'OTEL_EXPORTER_OTLP_METRICS_TIMEOUT'
|
|
143
|
+
o.default nil
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
option :protocol do |o|
|
|
147
|
+
o.type :string, nilable: true
|
|
148
|
+
o.env 'OTEL_EXPORTER_OTLP_METRICS_PROTOCOL'
|
|
149
|
+
o.default nil
|
|
150
|
+
o.setter(&Settings.normalize_protocol('OTEL_EXPORTER_OTLP_METRICS_PROTOCOL'))
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../core/configuration/ext'
|
|
4
|
+
|
|
5
|
+
module Datadog
|
|
6
|
+
module OpenTelemetry
|
|
7
|
+
class Metrics
|
|
8
|
+
EXPORTER_NONE = 'none'
|
|
9
|
+
|
|
10
|
+
def self.initialize!(components)
|
|
11
|
+
new(components).configure_metrics_sdk
|
|
12
|
+
true
|
|
13
|
+
rescue => exc
|
|
14
|
+
components.logger.error("Failed to initialize OpenTelemetry metrics: #{exc.class}: #{exc}: #{exc.backtrace.join("\n")}")
|
|
15
|
+
false
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def initialize(components)
|
|
19
|
+
@logger = components.logger
|
|
20
|
+
@settings = components.settings
|
|
21
|
+
@agent_host = components.agent_settings.hostname
|
|
22
|
+
@agent_ssl = components.agent_settings.ssl
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def configure_metrics_sdk
|
|
26
|
+
provider = ::OpenTelemetry.meter_provider
|
|
27
|
+
provider.shutdown if provider.is_a?(::OpenTelemetry::SDK::Metrics::MeterProvider)
|
|
28
|
+
|
|
29
|
+
# The OpenTelemetry SDK defaults to cumulative temporality, but Datadog prefers delta temporality.
|
|
30
|
+
# Here is an example of how this config is applied: https://github.com/open-telemetry/opentelemetry-ruby/blob/1933d4c18e5f5e45c53fa9e902e58aa91e85cc38/metrics_sdk/lib/opentelemetry/sdk/metrics/aggregation/sum.rb#L14
|
|
31
|
+
if DATADOG_ENV['OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE'].nil?
|
|
32
|
+
ENV['OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE'] = 'delta' # rubocop:disable CustomCops/EnvUsageCop
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
resource = create_resource
|
|
36
|
+
provider = ::OpenTelemetry::SDK::Metrics::MeterProvider.new(resource: resource)
|
|
37
|
+
configure_metric_reader(provider)
|
|
38
|
+
::OpenTelemetry.meter_provider = provider
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def create_resource
|
|
44
|
+
resource_attributes = {}
|
|
45
|
+
resource_attributes['host.name'] = Datadog::Core::Environment::Socket.hostname if @settings.tracing.report_hostname
|
|
46
|
+
|
|
47
|
+
@settings.tags&.each do |key, value|
|
|
48
|
+
otel_key = case key
|
|
49
|
+
when 'service' then 'service.name'
|
|
50
|
+
when 'env' then 'deployment.environment'
|
|
51
|
+
when 'version' then 'service.version'
|
|
52
|
+
else key
|
|
53
|
+
end
|
|
54
|
+
resource_attributes[otel_key] = value
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
resource_attributes['service.name'] = @settings.service_without_fallback || resource_attributes['service.name'] || Datadog::Core::Environment::Ext::FALLBACK_SERVICE_NAME
|
|
58
|
+
resource_attributes['deployment.environment'] = @settings.env if @settings.env
|
|
59
|
+
resource_attributes['service.version'] = @settings.version if @settings.version
|
|
60
|
+
|
|
61
|
+
::OpenTelemetry::SDK::Resources::Resource.create(resource_attributes)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def configure_metric_reader(provider)
|
|
65
|
+
exporter_name = @settings.opentelemetry.metrics.exporter
|
|
66
|
+
return if exporter_name == EXPORTER_NONE
|
|
67
|
+
|
|
68
|
+
configure_otlp_exporter(provider)
|
|
69
|
+
rescue => e
|
|
70
|
+
@logger.warn("Failed to configure OTLP metrics exporter: #{e.class}: #{e}")
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def resolve_metrics_endpoint
|
|
74
|
+
metrics_config = @settings.opentelemetry.metrics
|
|
75
|
+
exporter_config = @settings.opentelemetry.exporter
|
|
76
|
+
|
|
77
|
+
return metrics_config.endpoint if metrics_config.endpoint
|
|
78
|
+
return exporter_config.endpoint if exporter_config.endpoint
|
|
79
|
+
"#{@agent_ssl ? "https" : "http"}://#{@agent_host}:4318/v1/metrics"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def configure_otlp_exporter(provider)
|
|
83
|
+
require 'opentelemetry/exporter/otlp_metrics'
|
|
84
|
+
require_relative 'sdk/metrics_exporter'
|
|
85
|
+
|
|
86
|
+
metrics_config = @settings.opentelemetry.metrics
|
|
87
|
+
exporter_config = @settings.opentelemetry.exporter
|
|
88
|
+
timeout = metrics_config.timeout_millis || exporter_config.timeout_millis
|
|
89
|
+
headers = metrics_config.headers || exporter_config.headers || {}
|
|
90
|
+
|
|
91
|
+
protocol = metrics_config.protocol || exporter_config.protocol
|
|
92
|
+
exporter = Datadog::OpenTelemetry::SDK::MetricsExporter.new(
|
|
93
|
+
endpoint: resolve_metrics_endpoint,
|
|
94
|
+
timeout: timeout / 1000.0,
|
|
95
|
+
headers: headers,
|
|
96
|
+
protocol: protocol
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
reader = ::OpenTelemetry::SDK::Metrics::Export::PeriodicMetricReader.new(
|
|
100
|
+
exporter: exporter,
|
|
101
|
+
export_interval_millis: metrics_config.export_interval_millis,
|
|
102
|
+
export_timeout_millis: metrics_config.export_timeout_millis
|
|
103
|
+
)
|
|
104
|
+
provider.add_metric_reader(reader)
|
|
105
|
+
rescue LoadError => e
|
|
106
|
+
@logger.warn("Could not load OTLP metrics exporter: #{e.class}: #{e}")
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
@@ -30,7 +30,31 @@ module Datadog
|
|
|
30
30
|
[SpanProcessor.new]
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
def metrics_configuration_hook
|
|
34
|
+
components = Datadog.send(:components)
|
|
35
|
+
return super unless components.settings.opentelemetry.metrics.enabled
|
|
36
|
+
|
|
37
|
+
begin
|
|
38
|
+
require 'opentelemetry-metrics-sdk'
|
|
39
|
+
rescue LoadError => exc
|
|
40
|
+
components.logger.warn("Failed to load OpenTelemetry metrics gems: #{exc.class}: #{exc}")
|
|
41
|
+
return super
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
success = Datadog::OpenTelemetry::Metrics.initialize!(components)
|
|
45
|
+
super unless success
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Prepend to ConfiguratorPatch (not Configurator) so our hook runs first.
|
|
49
|
+
begin
|
|
50
|
+
require 'opentelemetry-metrics-sdk' if defined?(OpenTelemetry::SDK) && !defined?(OpenTelemetry::SDK::Metrics::ConfiguratorPatch)
|
|
51
|
+
rescue LoadError
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
if defined?(::OpenTelemetry::SDK::Metrics::ConfiguratorPatch)
|
|
55
|
+
::OpenTelemetry::SDK::Metrics::ConfiguratorPatch.prepend(self) unless ::OpenTelemetry::SDK::Metrics::ConfiguratorPatch.ancestors.include?(self)
|
|
56
|
+
end
|
|
57
|
+
::OpenTelemetry::SDK::Configurator.prepend(self) unless ::OpenTelemetry::SDK::Configurator.ancestors.include?(self)
|
|
34
58
|
end
|
|
35
59
|
end
|
|
36
60
|
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'opentelemetry/exporter/otlp_metrics'
|
|
4
|
+
|
|
5
|
+
module Datadog
|
|
6
|
+
module OpenTelemetry
|
|
7
|
+
module SDK
|
|
8
|
+
class MetricsExporter < ::OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter
|
|
9
|
+
METRIC_EXPORT_ATTEMPTS = 'otel.metrics_export_attempts'
|
|
10
|
+
METRIC_EXPORT_SUCCESSES = 'otel.metrics_export_successes'
|
|
11
|
+
METRIC_EXPORT_FAILURES = 'otel.metrics_export_failures'
|
|
12
|
+
|
|
13
|
+
def initialize(endpoint:, timeout:, headers:, protocol:)
|
|
14
|
+
super(endpoint: endpoint, timeout: timeout, headers: headers)
|
|
15
|
+
@telemetry_tags = {'protocol' => protocol, 'encoding' => 'protobuf'}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def export(metrics, timeout: nil)
|
|
19
|
+
telemetry&.inc('tracers', METRIC_EXPORT_ATTEMPTS, 1, tags: @telemetry_tags)
|
|
20
|
+
result = super
|
|
21
|
+
metric_name = (result == 0) ? METRIC_EXPORT_SUCCESSES : METRIC_EXPORT_FAILURES
|
|
22
|
+
telemetry&.inc('tracers', metric_name, 1, tags: @telemetry_tags)
|
|
23
|
+
result
|
|
24
|
+
rescue => e
|
|
25
|
+
Datadog.logger.error("Failed to export OpenTelemetry Metrics: #{e.class}: #{e}")
|
|
26
|
+
telemetry&.inc('tracers', METRIC_EXPORT_FAILURES, 1, tags: @telemetry_tags)
|
|
27
|
+
raise
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def telemetry
|
|
33
|
+
Datadog.send(:components).telemetry
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -22,6 +22,8 @@ require_relative 'opentelemetry/api/baggage'
|
|
|
22
22
|
require_relative 'opentelemetry/sdk/configurator' if defined?(OpenTelemetry::SDK)
|
|
23
23
|
require_relative 'opentelemetry/sdk/trace/span' if defined?(OpenTelemetry::SDK)
|
|
24
24
|
|
|
25
|
+
require_relative 'opentelemetry/metrics' if defined?(OpenTelemetry::SDK::Metrics)
|
|
26
|
+
|
|
25
27
|
module Datadog
|
|
26
28
|
# Datadog OpenTelemetry integration.
|
|
27
29
|
module OpenTelemetry
|
|
@@ -47,6 +49,7 @@ end
|
|
|
47
49
|
# Currently, this closely translates to Datadog's partial flushing.
|
|
48
50
|
#
|
|
49
51
|
# @see OpenTelemetry::SDK::Trace::SpanProcessor#on_finish
|
|
52
|
+
|
|
50
53
|
Datadog.configure do |c|
|
|
51
54
|
c.tracing.partial_flush.enabled = true
|
|
52
55
|
end
|
|
@@ -22,6 +22,7 @@ module Datadog
|
|
|
22
22
|
@libraries_by_path = {}
|
|
23
23
|
@seen_files = Set.new
|
|
24
24
|
@seen_libraries = Set.new
|
|
25
|
+
@executable_paths = [Gem.bindir, (Bundler.bin_path.to_s if defined?(Bundler))].uniq.compact.freeze
|
|
25
26
|
|
|
26
27
|
record_library(
|
|
27
28
|
Library.new(
|
|
@@ -29,7 +30,7 @@ module Datadog
|
|
|
29
30
|
name: "stdlib",
|
|
30
31
|
version: RUBY_VERSION,
|
|
31
32
|
path: standard_library_path,
|
|
32
|
-
|
|
33
|
+
extra_paths: [ruby_native_filename],
|
|
33
34
|
)
|
|
34
35
|
)
|
|
35
36
|
end
|
|
@@ -51,7 +52,8 @@ module Datadog
|
|
|
51
52
|
:libraries_by_name,
|
|
52
53
|
:libraries_by_path,
|
|
53
54
|
:seen_files,
|
|
54
|
-
:seen_libraries
|
|
55
|
+
:seen_libraries,
|
|
56
|
+
:executable_paths
|
|
55
57
|
|
|
56
58
|
def record_library(library)
|
|
57
59
|
libraries_by_name[library.name] = library
|
|
@@ -79,13 +81,20 @@ module Datadog
|
|
|
79
81
|
loaded_specs.each do |spec|
|
|
80
82
|
next if libraries_by_name.key?(spec.name)
|
|
81
83
|
|
|
84
|
+
extra_paths = [(spec.extension_dir if spec.extensions.any?)]
|
|
85
|
+
spec.executables&.each do |executable|
|
|
86
|
+
executable_paths.each do |path|
|
|
87
|
+
extra_paths << File.join(path, executable)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
82
91
|
record_library(
|
|
83
92
|
Library.new(
|
|
84
93
|
kind: "library",
|
|
85
94
|
name: spec.name,
|
|
86
95
|
version: spec.version,
|
|
87
96
|
path: spec.gem_dir,
|
|
88
|
-
|
|
97
|
+
extra_paths: extra_paths,
|
|
89
98
|
)
|
|
90
99
|
)
|
|
91
100
|
recorded_library = true
|
|
@@ -118,12 +127,12 @@ module Datadog
|
|
|
118
127
|
class Library
|
|
119
128
|
attr_reader :kind, :name, :version
|
|
120
129
|
|
|
121
|
-
def initialize(kind:, name:, version:, path:,
|
|
122
|
-
|
|
130
|
+
def initialize(kind:, name:, version:, path:, extra_paths:)
|
|
131
|
+
extra_paths = Array(extra_paths).compact.reject(&:empty?).map { |p| p.dup.freeze }
|
|
123
132
|
@kind = kind.freeze
|
|
124
133
|
@name = name.dup.freeze
|
|
125
134
|
@version = version.to_s.dup.freeze
|
|
126
|
-
@paths = [path.dup.freeze,
|
|
135
|
+
@paths = [path.dup.freeze, *extra_paths].freeze
|
|
127
136
|
freeze
|
|
128
137
|
end
|
|
129
138
|
|
|
@@ -82,7 +82,7 @@ module Datadog
|
|
|
82
82
|
"Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
|
|
83
83
|
)
|
|
84
84
|
on_failure_proc&.call
|
|
85
|
-
Datadog::Core::Telemetry::Logger.report(e, description: "CpuAndWallTimeWorker thread error"
|
|
85
|
+
Datadog::Core::Telemetry::Logger.report(e, description: "CpuAndWallTimeWorker thread error")
|
|
86
86
|
end
|
|
87
87
|
@worker_thread.name = self.class.name # Repeated from above to make sure thread gets named asap
|
|
88
88
|
@worker_thread.thread_variable_set(:fork_safe, true)
|
|
@@ -41,7 +41,7 @@ module Datadog
|
|
|
41
41
|
"IdleSamplingHelper thread error. " \
|
|
42
42
|
"Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
|
|
43
43
|
)
|
|
44
|
-
Datadog::Core::Telemetry::Logger.report(e, description: "IdleSamplingHelper thread error"
|
|
44
|
+
Datadog::Core::Telemetry::Logger.report(e, description: "IdleSamplingHelper thread error")
|
|
45
45
|
end
|
|
46
46
|
@worker_thread.name = self.class.name # Repeated from above to make sure thread gets named asap
|
|
47
47
|
@worker_thread.thread_variable_set(:fork_safe, true)
|
|
@@ -1,17 +1,48 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
4
|
-
require_relative
|
|
3
|
+
require_relative '../core/tag_builder'
|
|
4
|
+
require_relative '../core/utils'
|
|
5
|
+
|
|
6
|
+
require 'set'
|
|
5
7
|
|
|
6
8
|
module Datadog
|
|
7
9
|
module Profiling
|
|
8
10
|
# Builds a hash of default plus user tags to be included in a profile
|
|
11
|
+
#
|
|
12
|
+
# @api private
|
|
9
13
|
module TagBuilder
|
|
10
14
|
include Datadog::Profiling::Ext::Transport::HTTP # Tag name constants
|
|
11
15
|
|
|
16
|
+
# When changing or adding profiling-related tags, make sure they are
|
|
17
|
+
# kept in sync with
|
|
18
|
+
# https://docs.google.com/spreadsheets/d/1LOGMf4c4Avbtn36uZ2SWvhIGKRPLM1BoWkUP4JYj7hA/
|
|
19
|
+
# (Datadog internal link).
|
|
20
|
+
#
|
|
21
|
+
# For consistency between the different profilers, every tag should be
|
|
22
|
+
# vetted before it gets reported with a profile, as otherwise it's too
|
|
23
|
+
# easy to end up with different tags in different languages.
|
|
24
|
+
ALLOWED_TAGS = Set.new(
|
|
25
|
+
[
|
|
26
|
+
'env',
|
|
27
|
+
'service',
|
|
28
|
+
'version',
|
|
29
|
+
'git.commit.sha',
|
|
30
|
+
'git.repository_url',
|
|
31
|
+
'host',
|
|
32
|
+
'language',
|
|
33
|
+
'runtime',
|
|
34
|
+
'runtime_engine',
|
|
35
|
+
'runtime_platform',
|
|
36
|
+
'runtime_version',
|
|
37
|
+
'runtime-id',
|
|
38
|
+
'process_id',
|
|
39
|
+
'profiler_version',
|
|
40
|
+
'profile_seq',
|
|
41
|
+
]
|
|
42
|
+
).freeze
|
|
43
|
+
|
|
12
44
|
def self.call(
|
|
13
45
|
settings:,
|
|
14
|
-
# Other metadata
|
|
15
46
|
profile_seq:,
|
|
16
47
|
profiler_version: Core::Environment::Identity.gem_datadog_version
|
|
17
48
|
)
|
|
@@ -19,6 +50,8 @@ module Datadog
|
|
|
19
50
|
FORM_FIELD_TAG_PROFILER_VERSION => profiler_version,
|
|
20
51
|
'profile_seq' => profile_seq.to_s,
|
|
21
52
|
)
|
|
53
|
+
user_tag_keys = settings.tags.keys
|
|
54
|
+
hash.keep_if { |tag| user_tag_keys.include?(tag) || ALLOWED_TAGS.include?(tag) }
|
|
22
55
|
Core::Utils.encode_tags(hash)
|
|
23
56
|
end
|
|
24
57
|
end
|
data/lib/datadog/profiling.rb
CHANGED
|
@@ -62,8 +62,7 @@ module Datadog
|
|
|
62
62
|
|
|
63
63
|
def self.enabled?
|
|
64
64
|
profiler = Datadog.send(:components).profiler
|
|
65
|
-
|
|
66
|
-
!!profiler&.send(:scheduler)&.running?
|
|
65
|
+
!!profiler&.enabled?
|
|
67
66
|
end
|
|
68
67
|
|
|
69
68
|
def self.wait_until_running(timeout_seconds: 5)
|
|
@@ -15,7 +15,7 @@ end
|
|
|
15
15
|
|
|
16
16
|
begin
|
|
17
17
|
require_relative 'auto_instrument'
|
|
18
|
-
Datadog::SingleStepInstrument
|
|
18
|
+
Datadog::SingleStepInstrument.const_set(:LOADED, true)
|
|
19
19
|
rescue StandardError, LoadError => e
|
|
20
20
|
warn "Single step instrumentation failed: #{e.class}:#{e.message}\n\tSource:\n\t#{Array(e.backtrace).join("\n\t")}"
|
|
21
21
|
end
|
|
@@ -13,6 +13,9 @@ module Datadog
|
|
|
13
13
|
ENV_BAGGAGE_TAG_KEYS = 'DD_TRACE_BAGGAGE_TAG_KEYS'
|
|
14
14
|
ENV_TRACE_ID_128_BIT_GENERATION_ENABLED = 'DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED'
|
|
15
15
|
ENV_NATIVE_SPAN_EVENTS = 'DD_TRACE_NATIVE_SPAN_EVENTS'
|
|
16
|
+
ENV_RESOURCE_RENAMING_ENABLED = 'DD_TRACE_RESOURCE_RENAMING_ENABLED'
|
|
17
|
+
ENV_RESOURCE_RENAMING_ALWAYS_SIMPLIFIED_ENDPOINT = 'DD_TRACE_RESOURCE_RENAMING_ALWAYS_SIMPLIFIED_ENDPOINT'
|
|
18
|
+
ENV_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED = 'DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED'
|
|
16
19
|
|
|
17
20
|
# @public_api
|
|
18
21
|
module SpanAttributeSchema
|
|
@@ -104,6 +107,12 @@ module Datadog
|
|
|
104
107
|
ENV_ENABLED = 'DD_TRACE_CLIENT_IP_ENABLED'
|
|
105
108
|
ENV_HEADER_NAME = 'DD_TRACE_CLIENT_IP_HEADER'
|
|
106
109
|
end
|
|
110
|
+
|
|
111
|
+
# @public_api
|
|
112
|
+
module HTTPErrorStatuses
|
|
113
|
+
ENV_SERVER_ERROR_STATUSES = 'DD_TRACE_HTTP_SERVER_ERROR_STATUSES'
|
|
114
|
+
ENV_CLIENT_ERROR_STATUSES = 'DD_TRACE_HTTP_CLIENT_ERROR_STATUSES'
|
|
115
|
+
end
|
|
107
116
|
end
|
|
108
117
|
end
|
|
109
118
|
end
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative '../../tracing/configuration/ext'
|
|
4
4
|
require_relative '../../core/environment/variable_helpers'
|
|
5
|
+
require_relative '../contrib/status_range_matcher'
|
|
6
|
+
require_relative '../contrib/status_range_env_parser'
|
|
5
7
|
require_relative 'http'
|
|
6
8
|
|
|
7
9
|
module Datadog
|
|
@@ -272,6 +274,38 @@ module Datadog
|
|
|
272
274
|
o.type :bool
|
|
273
275
|
end
|
|
274
276
|
|
|
277
|
+
settings :resource_renaming do
|
|
278
|
+
# Whether resource renaming is enabled. When enabled, http.endpoint tag
|
|
279
|
+
# containing a route will be reported in traces. If AppSec is enabled,
|
|
280
|
+
# this feature will be enabled by default.
|
|
281
|
+
#
|
|
282
|
+
# For web applications built with instrumented frameworks, http.endpoint tag
|
|
283
|
+
# will contain the route as it is defined in the application.
|
|
284
|
+
# For basic Rack applications, or applications that are mounted and are not instrumented,
|
|
285
|
+
# the route will be inferred from the request path.
|
|
286
|
+
#
|
|
287
|
+
# @default `DD_TRACE_RESOURCE_RENAMING_ENABLED` environment variable, otherwise `false`.
|
|
288
|
+
# @return [Boolean]
|
|
289
|
+
option :enabled do |o|
|
|
290
|
+
o.type :bool, nilable: false
|
|
291
|
+
o.env Configuration::Ext::ENV_RESOURCE_RENAMING_ENABLED
|
|
292
|
+
o.default false
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
# When set to true, http.endoint is always inferred from path,
|
|
296
|
+
# instead of using http.route value when it is set.
|
|
297
|
+
#
|
|
298
|
+
# This is useful for testing purposes.
|
|
299
|
+
#
|
|
300
|
+
# @default false
|
|
301
|
+
# @return [Boolean]
|
|
302
|
+
option :always_simplified_endpoint do |o|
|
|
303
|
+
o.type :bool, nilable: false
|
|
304
|
+
o.env Configuration::Ext::ENV_RESOURCE_RENAMING_ALWAYS_SIMPLIFIED_ENDPOINT
|
|
305
|
+
o.default false
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
275
309
|
# Forces the tracer to always send span events with the native span events format
|
|
276
310
|
# regardless of the agent support. This is useful in agent-less setups.
|
|
277
311
|
#
|
|
@@ -490,6 +524,46 @@ module Datadog
|
|
|
490
524
|
o.env Tracing::Configuration::Ext::Distributed::ENV_X_DATADOG_TAGS_MAX_LENGTH
|
|
491
525
|
o.default 512
|
|
492
526
|
end
|
|
527
|
+
|
|
528
|
+
# HTTP error statuses configuration
|
|
529
|
+
# @public_api
|
|
530
|
+
settings :http_error_statuses do
|
|
531
|
+
# Defines the range of status codes to be considered errors on http.server span kinds.
|
|
532
|
+
# Once set, only the values within the specified range are considered errors.
|
|
533
|
+
#
|
|
534
|
+
# Format of env var: comma-separated list of values like 500,501,502 or ranges like 500-599 (e.g. `500,502,504-510`)
|
|
535
|
+
#
|
|
536
|
+
# @default `DD_TRACE_HTTP_SERVER_ERROR_STATUSES` environment variable, otherwise `500..599`.
|
|
537
|
+
# @return [Tracing::Contrib::StatusRangeMatcher]
|
|
538
|
+
option :server do |o|
|
|
539
|
+
o.env Tracing::Configuration::Ext::HTTPErrorStatuses::ENV_SERVER_ERROR_STATUSES
|
|
540
|
+
o.default 500..599
|
|
541
|
+
o.setter do |v|
|
|
542
|
+
Tracing::Contrib::StatusRangeMatcher.new(v) if v
|
|
543
|
+
end
|
|
544
|
+
o.env_parser do |values|
|
|
545
|
+
Tracing::Contrib::StatusRangeEnvParser.call(values)
|
|
546
|
+
end
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
# Defines the range of status codes to be considered errors on http.client span kinds.
|
|
550
|
+
# Once set, only the values within the specified range are considered errors.
|
|
551
|
+
#
|
|
552
|
+
# Format of env var: comma-separated list of values like 400,401,402 or ranges like 400-499 (e.g. `400,402,404-410`)
|
|
553
|
+
#
|
|
554
|
+
# @default `DD_TRACE_HTTP_CLIENT_ERROR_STATUSES` environment variable, otherwise `400..499`.
|
|
555
|
+
# @return [Tracing::Contrib::StatusRangeMatcher]
|
|
556
|
+
option :client do |o|
|
|
557
|
+
o.env Tracing::Configuration::Ext::HTTPErrorStatuses::ENV_CLIENT_ERROR_STATUSES
|
|
558
|
+
o.default 400..499
|
|
559
|
+
o.setter do |v|
|
|
560
|
+
Tracing::Contrib::StatusRangeMatcher.new(v) if v
|
|
561
|
+
end
|
|
562
|
+
o.env_parser do |values|
|
|
563
|
+
Tracing::Contrib::StatusRangeEnvParser.call(values)
|
|
564
|
+
end
|
|
565
|
+
end
|
|
566
|
+
end
|
|
493
567
|
end
|
|
494
568
|
end
|
|
495
569
|
end
|
|
@@ -77,10 +77,10 @@ module Datadog
|
|
|
77
77
|
|
|
78
78
|
exception = payload[:exception_object]
|
|
79
79
|
if exception.nil?
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
status = payload[:status]
|
|
81
|
+
if status && Datadog.configuration.tracing.http_error_statuses.server.include?(status)
|
|
82
|
+
span.status = Tracing::Metadata::Ext::Errors::STATUS
|
|
83
|
+
end
|
|
84
84
|
elsif Utils.exception_is_error?(exception)
|
|
85
85
|
span.set_error(exception)
|
|
86
86
|
end
|