datadog 2.17.0 → 2.19.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 +90 -1
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +63 -56
- data/ext/datadog_profiling_native_extension/collectors_stack.c +263 -76
- data/ext/datadog_profiling_native_extension/collectors_stack.h +20 -3
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +62 -12
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +1 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +7 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.c +239 -363
- data/ext/datadog_profiling_native_extension/heap_recorder.h +4 -6
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +22 -0
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +8 -5
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +38 -26
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +6 -4
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +1 -13
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +3 -11
- data/ext/datadog_profiling_native_extension/stack_recorder.c +154 -57
- data/ext/libdatadog_api/extconf.rb +2 -2
- data/ext/libdatadog_api/library_config.c +54 -12
- data/ext/libdatadog_api/library_config.h +6 -0
- data/ext/libdatadog_api/process_discovery.c +2 -7
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/appsec/api_security/lru_cache.rb +9 -2
- data/lib/datadog/appsec/api_security/route_extractor.rb +71 -0
- data/lib/datadog/appsec/api_security/sampler.rb +59 -0
- data/lib/datadog/appsec/api_security.rb +14 -0
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +257 -85
- data/lib/datadog/appsec/assets/waf_rules/strict.json +10 -78
- data/lib/datadog/appsec/component.rb +30 -54
- data/lib/datadog/appsec/configuration/settings.rb +60 -2
- data/lib/datadog/appsec/context.rb +6 -6
- data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +27 -16
- data/lib/datadog/appsec/instrumentation/gateway/argument.rb +1 -1
- data/lib/datadog/appsec/processor/rule_loader.rb +5 -6
- data/lib/datadog/appsec/remote.rb +15 -55
- data/lib/datadog/appsec/security_engine/engine.rb +194 -0
- data/lib/datadog/appsec/security_engine/runner.rb +10 -11
- data/lib/datadog/appsec.rb +4 -7
- data/lib/datadog/core/configuration/agent_settings.rb +52 -0
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +1 -43
- data/lib/datadog/core/configuration/components.rb +2 -4
- data/lib/datadog/core/configuration/option.rb +9 -9
- data/lib/datadog/core/configuration/settings.rb +42 -10
- data/lib/datadog/core/configuration/stable_config.rb +1 -2
- data/lib/datadog/core/crashtracking/tag_builder.rb +4 -22
- data/lib/datadog/core/process_discovery/tracer_memfd.rb +15 -0
- data/lib/datadog/core/process_discovery.rb +5 -1
- data/lib/datadog/core/remote/configuration/repository.rb +12 -0
- data/lib/datadog/core/tag_builder.rb +56 -0
- data/lib/datadog/core/telemetry/component.rb +8 -4
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +1 -0
- data/lib/datadog/core/telemetry/event/app_started.rb +148 -40
- data/lib/datadog/core/telemetry/logger.rb +5 -4
- data/lib/datadog/core/telemetry/logging.rb +11 -5
- data/lib/datadog/core/transport/http/adapters/net.rb +17 -2
- data/lib/datadog/core/transport/http/builder.rb +2 -2
- data/lib/datadog/core/transport/http/env.rb +8 -0
- data/lib/datadog/core/utils.rb +7 -0
- data/lib/datadog/di/instrumenter.rb +48 -5
- data/lib/datadog/di/probe_notification_builder.rb +37 -42
- data/lib/datadog/di/probe_notifier_worker.rb +9 -1
- data/lib/datadog/di/serializer.rb +10 -2
- data/lib/datadog/di/transport/http/input.rb +10 -0
- data/lib/datadog/di/transport/input.rb +10 -2
- data/lib/datadog/di.rb +0 -6
- data/lib/datadog/kit/appsec/events/v2.rb +195 -0
- data/lib/datadog/profiling/collectors/code_provenance.rb +17 -8
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +6 -0
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -0
- data/lib/datadog/profiling/collectors/info.rb +41 -0
- data/lib/datadog/profiling/collectors/thread_context.rb +16 -1
- data/lib/datadog/profiling/component.rb +8 -9
- data/lib/datadog/profiling/exporter.rb +9 -3
- data/lib/datadog/profiling/ext.rb +0 -12
- data/lib/datadog/profiling/http_transport.rb +2 -2
- data/lib/datadog/profiling/profiler.rb +2 -0
- data/lib/datadog/profiling/scheduler.rb +2 -1
- data/lib/datadog/profiling/sequence_tracker.rb +44 -0
- data/lib/datadog/profiling/stack_recorder.rb +5 -5
- data/lib/datadog/profiling/tag_builder.rb +7 -37
- data/lib/datadog/profiling/tasks/setup.rb +2 -0
- data/lib/datadog/profiling.rb +1 -0
- data/lib/datadog/single_step_instrument.rb +9 -0
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +15 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +19 -12
- data/lib/datadog/tracing/contrib/action_pack/ext.rb +2 -0
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +7 -1
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +13 -0
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +4 -2
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +16 -6
- data/lib/datadog/tracing/contrib/rails/patcher.rb +4 -1
- data/lib/datadog/tracing/contrib/rails/runner.rb +61 -40
- data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +5 -2
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +3 -1
- data/lib/datadog/tracing/span_event.rb +1 -1
- data/lib/datadog/tracing/span_operation.rb +22 -0
- data/lib/datadog/tracing/sync_writer.rb +1 -1
- data/lib/datadog/tracing/trace_operation.rb +12 -4
- data/lib/datadog/tracing/tracer.rb +6 -2
- data/lib/datadog/version.rb +1 -1
- data/lib/datadog.rb +7 -0
- metadata +14 -10
- data/lib/datadog/appsec/assets/waf_rules/processors.json +0 -321
- data/lib/datadog/appsec/assets/waf_rules/scanners.json +0 -1023
- data/lib/datadog/appsec/processor/rule_merger.rb +0 -171
- data/lib/datadog/appsec/processor.rb +0 -107
@@ -237,6 +237,10 @@ module Datadog
|
|
237
237
|
@path = path
|
238
238
|
@previous = previous
|
239
239
|
end
|
240
|
+
|
241
|
+
def type
|
242
|
+
:delete
|
243
|
+
end
|
240
244
|
end
|
241
245
|
|
242
246
|
# Insert change
|
@@ -247,6 +251,10 @@ module Datadog
|
|
247
251
|
@path = path
|
248
252
|
@content = content
|
249
253
|
end
|
254
|
+
|
255
|
+
def type
|
256
|
+
:insert
|
257
|
+
end
|
250
258
|
end
|
251
259
|
|
252
260
|
# Update change
|
@@ -258,6 +266,10 @@ module Datadog
|
|
258
266
|
@content = content
|
259
267
|
@previous = previous
|
260
268
|
end
|
269
|
+
|
270
|
+
def type
|
271
|
+
:update
|
272
|
+
end
|
261
273
|
end
|
262
274
|
end
|
263
275
|
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'environment/socket'
|
4
|
+
require_relative 'environment/identity'
|
5
|
+
require_relative 'environment/git'
|
6
|
+
|
7
|
+
module Datadog
|
8
|
+
module Core
|
9
|
+
# This module builds a hash of tags.
|
10
|
+
#
|
11
|
+
# When changing or adding the tags, make sure they are kept in sync with
|
12
|
+
# https://docs.google.com/spreadsheets/d/1LOGMf4c4Avbtn36uZ2SWvhIGKRPLM1BoWkUP4JYj7hA/
|
13
|
+
# (Datadog internal link).
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
module TagBuilder
|
17
|
+
def self.fixed_environment_tags
|
18
|
+
@fixed_environment_tags ||= {
|
19
|
+
'language' => Environment::Identity.lang,
|
20
|
+
'runtime' => Environment::Identity.lang, # Known to be duplicated from language above
|
21
|
+
'runtime_engine' => Environment::Identity.lang_engine,
|
22
|
+
'runtime_platform' => Environment::Identity.lang_platform,
|
23
|
+
'runtime_version' => Environment::Identity.lang_version,
|
24
|
+
'library_version' => Environment::Identity.gem_datadog_version,
|
25
|
+
'git.repository_url' => Environment::Git.git_repository_url,
|
26
|
+
'git.commit.sha' => Environment::Git.git_commit_sha,
|
27
|
+
}.compact.freeze
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.tags(settings)
|
31
|
+
# Note that user tags get overwritten by our tags, and also
|
32
|
+
# that user tags do not get compacted (nil values are sent as
|
33
|
+
# empty strings).
|
34
|
+
settings.tags.merge(fixed_environment_tags).merge({
|
35
|
+
# Hostname can possibly change during application runtime.
|
36
|
+
'host' => Environment::Socket.hostname,
|
37
|
+
# Runtime ID changes upon a fork.
|
38
|
+
'runtime-id' => Environment::Identity.id,
|
39
|
+
# Process ID changes upon a fork.
|
40
|
+
'process_id' => Process.pid.to_s,
|
41
|
+
# Unified service tagging.
|
42
|
+
'env' => settings.env,
|
43
|
+
'service' => settings.service,
|
44
|
+
'version' => settings.version,
|
45
|
+
}.compact)
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.serialize_tags(tags)
|
49
|
+
# DEV: Should there be some sort of escaping done here?
|
50
|
+
tags.map do |key, value|
|
51
|
+
"#{key}:#{value}"
|
52
|
+
end.join(',')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -62,7 +62,9 @@ module Datadog
|
|
62
62
|
return unless @enabled
|
63
63
|
|
64
64
|
@transport = if settings.telemetry.agentless_enabled
|
65
|
-
agent_settings
|
65
|
+
# We don't touch the `agent_settings` since we still want the telemetry payloads to refer to the original
|
66
|
+
# settings, even though the telemetry itself may be using a different path.
|
67
|
+
telemetry_specific_agent_settings = Core::Configuration::AgentlessSettingsResolver.call(
|
66
68
|
settings,
|
67
69
|
host_prefix: 'instrumentation-telemetry-intake',
|
68
70
|
url_override: settings.telemetry.agentless_url_override,
|
@@ -70,7 +72,7 @@ module Datadog
|
|
70
72
|
logger: logger,
|
71
73
|
)
|
72
74
|
Telemetry::Transport::HTTP.agentless_telemetry(
|
73
|
-
agent_settings:
|
75
|
+
agent_settings: telemetry_specific_agent_settings,
|
74
76
|
logger: logger,
|
75
77
|
# api_key should have already validated to be
|
76
78
|
# not nil by +build+ method above.
|
@@ -96,6 +98,8 @@ module Datadog
|
|
96
98
|
logger: logger,
|
97
99
|
shutdown_timeout: settings.telemetry.shutdown_timeout_seconds,
|
98
100
|
)
|
101
|
+
|
102
|
+
@agent_settings = agent_settings
|
99
103
|
end
|
100
104
|
|
101
105
|
def disable!
|
@@ -107,9 +111,9 @@ module Datadog
|
|
107
111
|
return if !@enabled
|
108
112
|
|
109
113
|
initial_event = if initial_event_is_change
|
110
|
-
Event::SynthAppClientConfigurationChange.new
|
114
|
+
Event::SynthAppClientConfigurationChange.new(agent_settings: @agent_settings)
|
111
115
|
else
|
112
|
-
Event::AppStarted.new
|
116
|
+
Event::AppStarted.new(agent_settings: @agent_settings)
|
113
117
|
end
|
114
118
|
|
115
119
|
@worker.start(initial_event)
|
@@ -8,6 +8,10 @@ module Datadog
|
|
8
8
|
module Event
|
9
9
|
# Telemetry class for the 'app-started' event
|
10
10
|
class AppStarted < Base
|
11
|
+
def initialize(agent_settings:)
|
12
|
+
@agent_settings = agent_settings
|
13
|
+
end
|
14
|
+
|
11
15
|
def type
|
12
16
|
'app-started'
|
13
17
|
end
|
@@ -25,7 +29,7 @@ module Datadog
|
|
25
29
|
private
|
26
30
|
|
27
31
|
def products
|
28
|
-
# @type var products: Hash[Symbol, Hash[Symbol,
|
32
|
+
# @type var products: Hash[Symbol, Hash[Symbol, Hash[Symbol, String | Integer] | bool | nil]]
|
29
33
|
products = {
|
30
34
|
appsec: {
|
31
35
|
enabled: Datadog::AppSec.enabled?,
|
@@ -64,6 +68,7 @@ module Datadog
|
|
64
68
|
tracing.partial_flush.min_spans_threshold
|
65
69
|
tracing.report_hostname
|
66
70
|
tracing.sampling.rate_limit
|
71
|
+
apm.tracing.enabled
|
67
72
|
].freeze
|
68
73
|
|
69
74
|
# standard:disable Metrics/AbcSize
|
@@ -72,23 +77,70 @@ module Datadog
|
|
72
77
|
config = Datadog.configuration
|
73
78
|
seq_id = Event.configuration_sequence.next
|
74
79
|
|
80
|
+
# tracing.writer_options.buffer_size and tracing.writer_options.flush_interval have the same origin.
|
81
|
+
writer_option_origin = get_telemetry_origin(config, 'tracing.writer_options')
|
82
|
+
|
75
83
|
list = [
|
84
|
+
# Only set using env var as of June 2025
|
76
85
|
conf_value('DD_GIT_REPOSITORY_URL', Core::Environment::Git.git_repository_url, seq_id, 'env_var'),
|
77
86
|
conf_value('DD_GIT_COMMIT_SHA', Core::Environment::Git.git_commit_sha, seq_id, 'env_var'),
|
78
87
|
|
79
|
-
|
80
|
-
conf_value(
|
81
|
-
|
88
|
+
# Set by the customer application (eg. `require 'datadog/auto_instrument'`)
|
89
|
+
conf_value(
|
90
|
+
'tracing.auto_instrument.enabled',
|
91
|
+
!defined?(Datadog::AutoInstrument::LOADED).nil?,
|
92
|
+
seq_id,
|
93
|
+
'code'
|
94
|
+
),
|
95
|
+
conf_value(
|
96
|
+
'tracing.opentelemetry.enabled',
|
97
|
+
!defined?(Datadog::OpenTelemetry::LOADED).nil?,
|
98
|
+
seq_id,
|
99
|
+
'code'
|
100
|
+
),
|
101
|
+
|
102
|
+
# Mix of env var, programmatic and default config, so we use unknown
|
103
|
+
conf_value('DD_AGENT_TRANSPORT', agent_transport, seq_id, 'unknown'),
|
104
|
+
|
105
|
+
# writer_options is defined as an option that has a Hash value.
|
106
|
+
conf_value(
|
107
|
+
'tracing.writer_options.buffer_size',
|
108
|
+
to_value(config.tracing.writer_options[:buffer_size]),
|
109
|
+
seq_id,
|
110
|
+
writer_option_origin
|
111
|
+
),
|
112
|
+
conf_value(
|
113
|
+
'tracing.writer_options.flush_interval',
|
114
|
+
to_value(config.tracing.writer_options[:flush_interval]),
|
115
|
+
seq_id,
|
116
|
+
writer_option_origin
|
117
|
+
),
|
118
|
+
|
119
|
+
conf_value('DD_AGENT_HOST', config.agent.host, seq_id, get_telemetry_origin(config, 'agent.host')),
|
120
|
+
conf_value(
|
121
|
+
'DD_TRACE_SAMPLE_RATE',
|
122
|
+
to_value(config.tracing.sampling.default_rate),
|
123
|
+
seq_id,
|
124
|
+
get_telemetry_origin(config, 'tracing.sampling.default_rate')
|
125
|
+
),
|
82
126
|
conf_value(
|
83
127
|
'DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED',
|
84
128
|
config.tracing.contrib.global_default_service_name.enabled,
|
85
|
-
seq_id
|
129
|
+
seq_id,
|
130
|
+
get_telemetry_origin(config, 'tracing.contrib.global_default_service_name.enabled')
|
86
131
|
),
|
87
132
|
conf_value(
|
88
133
|
'DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED',
|
89
134
|
config.tracing.contrib.peer_service_defaults,
|
90
|
-
seq_id
|
135
|
+
seq_id,
|
136
|
+
get_telemetry_origin(config, 'tracing.contrib.peer_service_defaults')
|
91
137
|
),
|
138
|
+
conf_value(
|
139
|
+
'DD_TRACE_DEBUG',
|
140
|
+
config.diagnostics.debug,
|
141
|
+
seq_id,
|
142
|
+
get_telemetry_origin(config, 'diagnostics.debug')
|
143
|
+
)
|
92
144
|
]
|
93
145
|
|
94
146
|
peer_service_mapping_str = ''
|
@@ -96,39 +148,69 @@ module Datadog
|
|
96
148
|
peer_service_mapping = config.tracing.contrib.peer_service_mapping
|
97
149
|
peer_service_mapping_str = peer_service_mapping.map { |key, value| "#{key}:#{value}" }.join(',')
|
98
150
|
end
|
99
|
-
list << conf_value(
|
151
|
+
list << conf_value(
|
152
|
+
'DD_TRACE_PEER_SERVICE_MAPPING',
|
153
|
+
peer_service_mapping_str,
|
154
|
+
seq_id,
|
155
|
+
get_telemetry_origin(config, 'tracing.contrib.peer_service_mapping')
|
156
|
+
)
|
100
157
|
|
101
158
|
# Whitelist of configuration options to send in additional payload object
|
102
|
-
TARGET_OPTIONS.each do |
|
103
|
-
split_option =
|
104
|
-
list << conf_value(
|
159
|
+
TARGET_OPTIONS.each do |option_path|
|
160
|
+
split_option = option_path.split('.')
|
161
|
+
list << conf_value(
|
162
|
+
option_path,
|
163
|
+
to_value(config.dig(*split_option)),
|
164
|
+
seq_id,
|
165
|
+
get_telemetry_origin(config, option_path)
|
166
|
+
)
|
105
167
|
end
|
106
168
|
|
107
|
-
|
169
|
+
instrumentation_source = if Datadog.const_defined?(:SingleStepInstrument, false) &&
|
170
|
+
Datadog::SingleStepInstrument.const_defined?(:LOADED, false) &&
|
171
|
+
Datadog::SingleStepInstrument::LOADED
|
172
|
+
'ssi'
|
173
|
+
else
|
174
|
+
'manual'
|
175
|
+
end
|
176
|
+
# Track ssi configurations
|
108
177
|
list.push(
|
109
|
-
conf_value('
|
110
|
-
conf_value(
|
111
|
-
|
112
|
-
to_value(config.tracing.writer_options[:buffer_size]),
|
113
|
-
seq_id
|
114
|
-
),
|
115
|
-
conf_value(
|
116
|
-
'tracing.writer_options.flush_interval',
|
117
|
-
to_value(config.tracing.writer_options[:flush_interval]),
|
118
|
-
seq_id
|
119
|
-
),
|
120
|
-
conf_value(
|
121
|
-
'tracing.opentelemetry.enabled',
|
122
|
-
!defined?(Datadog::OpenTelemetry::LOADED).nil?,
|
123
|
-
seq_id
|
124
|
-
),
|
178
|
+
conf_value('instrumentation_source', instrumentation_source, seq_id, 'code'),
|
179
|
+
conf_value('DD_INJECT_FORCE', Core::Environment::VariableHelpers.env_to_bool('DD_INJECT_FORCE', false), seq_id, 'env_var'),
|
180
|
+
conf_value('DD_INJECTION_ENABLED', ENV['DD_INJECTION_ENABLED'] || '', seq_id, 'env_var'),
|
125
181
|
)
|
126
|
-
|
182
|
+
|
183
|
+
# Add some more custom additional payload values here
|
184
|
+
if config.logger.instance
|
185
|
+
list << conf_value(
|
186
|
+
'logger.instance',
|
187
|
+
config.logger.instance.class.to_s,
|
188
|
+
seq_id,
|
189
|
+
get_telemetry_origin(config, 'logger.instance')
|
190
|
+
)
|
191
|
+
end
|
127
192
|
if config.respond_to?('appsec')
|
128
|
-
list << conf_value(
|
129
|
-
|
193
|
+
list << conf_value(
|
194
|
+
'appsec.enabled',
|
195
|
+
config.dig('appsec', 'enabled'),
|
196
|
+
seq_id,
|
197
|
+
get_telemetry_origin(config, 'appsec.enabled')
|
198
|
+
)
|
199
|
+
list << conf_value(
|
200
|
+
'appsec.sca_enabled',
|
201
|
+
config.dig('appsec', 'sca_enabled'),
|
202
|
+
seq_id,
|
203
|
+
get_telemetry_origin(config, 'appsec.sca_enabled')
|
204
|
+
)
|
205
|
+
end
|
206
|
+
if config.respond_to?('ci')
|
207
|
+
list << conf_value(
|
208
|
+
'ci.enabled',
|
209
|
+
config.dig('ci', 'enabled'),
|
210
|
+
seq_id,
|
211
|
+
get_telemetry_origin(config, 'ci.enabled')
|
212
|
+
)
|
130
213
|
end
|
131
|
-
list << conf_value('ci.enabled', config.dig('ci', 'enabled'), seq_id) if config.respond_to?('ci')
|
132
214
|
|
133
215
|
list.reject! { |entry| entry[:value].nil? }
|
134
216
|
list
|
@@ -136,8 +218,8 @@ module Datadog
|
|
136
218
|
# standard:enable Metrics/AbcSize
|
137
219
|
# standard:enable Metrics/MethodLength
|
138
220
|
|
139
|
-
def agent_transport
|
140
|
-
adapter =
|
221
|
+
def agent_transport
|
222
|
+
adapter = @agent_settings.adapter
|
141
223
|
if adapter == Datadog::Core::Transport::Ext::UnixSocket::ADAPTER
|
142
224
|
'UDS'
|
143
225
|
else
|
@@ -145,13 +227,27 @@ module Datadog
|
|
145
227
|
end
|
146
228
|
end
|
147
229
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
230
|
+
# `origin`: Source of the configuration. One of :
|
231
|
+
# - `fleet_stable_config`: configuration is set via the fleet automation Datadog UI
|
232
|
+
# - `local_stable_config`: configuration set via a user-managed file
|
233
|
+
# - `env_var`: configurations that are set through environment variables
|
234
|
+
# - `jvm_prop`: JVM system properties passed on the command line
|
235
|
+
# - `code`: configurations that are set through the customer application
|
236
|
+
# - `dd_config`: set by the dd.yaml file or json
|
237
|
+
# - `remote_config`: values that are set using remote config
|
238
|
+
# - `app.config`: only applies to .NET
|
239
|
+
# - `default`: set when the user has not set any configuration for the key (defaults to a value)
|
240
|
+
# - `unknown`: set for cases where it is difficult/not possible to determine the source of a config.
|
241
|
+
def conf_value(name, value, seq_id, origin)
|
242
|
+
result = {name: name, value: value, origin: origin, seq_id: seq_id}
|
243
|
+
if origin == 'fleet_stable_config'
|
244
|
+
fleet_id = Core::Configuration::StableConfig.configuration.dig(:fleet, :id)
|
245
|
+
result[:config_id] = fleet_id if fleet_id
|
246
|
+
elsif origin == 'local_stable_config'
|
247
|
+
local_id = Core::Configuration::StableConfig.configuration.dig(:local, :id)
|
248
|
+
result[:config_id] = local_id if local_id
|
249
|
+
end
|
250
|
+
result
|
155
251
|
end
|
156
252
|
|
157
253
|
def to_value(value)
|
@@ -172,6 +268,18 @@ module Datadog
|
|
172
268
|
install_time: config.dig('telemetry', 'install_time'),
|
173
269
|
}
|
174
270
|
end
|
271
|
+
|
272
|
+
def get_telemetry_origin(config, config_path)
|
273
|
+
split_option = config_path.split('.')
|
274
|
+
option_name = split_option.pop
|
275
|
+
return 'unknown' if option_name.nil?
|
276
|
+
|
277
|
+
# @type var parent_setting: Core::Configuration::Options
|
278
|
+
# @type var option: Core::Configuration::Option
|
279
|
+
parent_setting = config.dig(*split_option)
|
280
|
+
option = parent_setting.send(:resolve_option, option_name.to_sym)
|
281
|
+
option.precedence_set&.origin || 'unknown'
|
282
|
+
end
|
175
283
|
end
|
176
284
|
end
|
177
285
|
end
|
@@ -14,8 +14,8 @@ module Datadog
|
|
14
14
|
# read: lib/datadog/core/telemetry/logging.rb
|
15
15
|
module Logger
|
16
16
|
class << self
|
17
|
-
def report(exception, level: :error, description: nil)
|
18
|
-
instance&.report(exception, level: level, description: description)
|
17
|
+
def report(exception, level: :error, description: nil, pii_safe: false)
|
18
|
+
instance&.report(exception, level: level, description: description, pii_safe: pii_safe)
|
19
19
|
end
|
20
20
|
|
21
21
|
def error(description)
|
@@ -34,9 +34,10 @@ module Datadog
|
|
34
34
|
#
|
35
35
|
# The downside is: this leaves us unable to report telemetry during component initialization.
|
36
36
|
components = Datadog.send(:components, allow_initialization: false)
|
37
|
+
telemetry = components&.telemetry
|
37
38
|
|
38
|
-
if
|
39
|
-
|
39
|
+
if telemetry
|
40
|
+
telemetry
|
40
41
|
else
|
41
42
|
Datadog.logger.warn(
|
42
43
|
'Failed to send telemetry before components initialization or within components lifecycle'
|
@@ -45,11 +45,17 @@ module Datadog
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
def report(exception, level: :error, description: nil)
|
49
|
-
#
|
50
|
-
message = +
|
51
|
-
|
52
|
-
|
48
|
+
def report(exception, level: :error, description: nil, pii_safe: false)
|
49
|
+
# Anonymous exceptions to be logged as <Class:0x00007f8b1c0b3b40>
|
50
|
+
message = +"#{exception.class.name || exception.class.inspect}" # standard:disable Style/RedundantInterpolation
|
51
|
+
|
52
|
+
exception_message = pii_safe ? exception.message : nil
|
53
|
+
|
54
|
+
if description || exception_message
|
55
|
+
message << ':'
|
56
|
+
message << " #{description}" if description
|
57
|
+
message << " (#{exception.message})" if exception_message
|
58
|
+
end
|
53
59
|
|
54
60
|
event = Event::Log.new(
|
55
61
|
message: message,
|
@@ -48,7 +48,7 @@ module Datadog
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def get(env)
|
51
|
-
get = ::Net::HTTP::Get.new(env
|
51
|
+
get = ::Net::HTTP::Get.new(net_http_path_from_env(env), env.headers)
|
52
52
|
|
53
53
|
# Connect and send the request
|
54
54
|
http_response = open do |http|
|
@@ -63,7 +63,7 @@ module Datadog
|
|
63
63
|
post = nil
|
64
64
|
|
65
65
|
if env.form.nil? || env.form.empty?
|
66
|
-
post = ::Net::HTTP::Post.new(env
|
66
|
+
post = ::Net::HTTP::Post.new(net_http_path_from_env(env), env.headers)
|
67
67
|
post.body = env.body
|
68
68
|
else
|
69
69
|
post = ::Datadog::Core::Vendor::Net::HTTP::Post::Multipart.new(
|
@@ -86,6 +86,21 @@ module Datadog
|
|
86
86
|
"http://#{hostname}:#{port}?timeout=#{timeout}"
|
87
87
|
end
|
88
88
|
|
89
|
+
def net_http_path_from_env(env)
|
90
|
+
path = env.path
|
91
|
+
case query = env.query
|
92
|
+
when Hash
|
93
|
+
path = path + '?' + URI.encode_www_form(query)
|
94
|
+
when String
|
95
|
+
path = path + '?' + query
|
96
|
+
when nil
|
97
|
+
# Nothing
|
98
|
+
else
|
99
|
+
raise ArgumentError, "Invalid type for query: #{query}"
|
100
|
+
end
|
101
|
+
path
|
102
|
+
end
|
103
|
+
|
89
104
|
# Raised when called with an unknown HTTP method
|
90
105
|
class UnknownHTTPMethod < StandardError
|
91
106
|
attr_reader :verb
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../../configuration/
|
3
|
+
require_relative '../../configuration/agent_settings'
|
4
4
|
require_relative 'adapters/registry'
|
5
5
|
require_relative 'api/map'
|
6
6
|
|
@@ -41,7 +41,7 @@ module Datadog
|
|
41
41
|
|
42
42
|
def adapter(config, *args, **kwargs)
|
43
43
|
@default_adapter = case config
|
44
|
-
when Core::Configuration::
|
44
|
+
when Core::Configuration::AgentSettings
|
45
45
|
registry_klass = REGISTRY.get(config.adapter)
|
46
46
|
raise UnknownAdapterError, config.adapter if registry_klass.nil?
|
47
47
|
|
data/lib/datadog/core/utils.rb
CHANGED
@@ -66,6 +66,13 @@ module Datadog
|
|
66
66
|
placeholder
|
67
67
|
end
|
68
68
|
|
69
|
+
def self.encode_tags(hash)
|
70
|
+
# Make sure everything is an utf-8 string, to avoid encoding issues in downstream
|
71
|
+
hash.each_with_object({}) do |(key, value), h|
|
72
|
+
h[utf8_encode(key)] = utf8_encode(value)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
69
76
|
# @!visibility private
|
70
77
|
def self.without_warnings
|
71
78
|
# This is typically used when monkey patching functions such as
|
@@ -52,6 +52,17 @@ module Datadog
|
|
52
52
|
# (however, Probe instances can be replaced by OpenStruct instances
|
53
53
|
# providing the same interface with not much effort).
|
54
54
|
#
|
55
|
+
# Instrumenter (this class) is responsible for building snapshots.
|
56
|
+
# This is because to capture values on method entry, those values need to
|
57
|
+
# be duplicated or serialized into immutable values to prevent their
|
58
|
+
# modification by the instrumented method. Therefore this class must
|
59
|
+
# do at least some serialization/snapshot building and to keep the code
|
60
|
+
# well-encapsulated, all serialization/snapshot building should thus be
|
61
|
+
# initiated from this class rather than downstream code.
|
62
|
+
#
|
63
|
+
# As a consequence of Instrumenter building snapshots, it should not
|
64
|
+
# expose TracePoint objects to any downstream code.
|
65
|
+
#
|
55
66
|
# @api private
|
56
67
|
class Instrumenter
|
57
68
|
def initialize(settings, serializer, logger, code_tracker: nil, telemetry: nil)
|
@@ -110,8 +121,8 @@ module Datadog
|
|
110
121
|
if rate_limiter.nil? || rate_limiter.allow?
|
111
122
|
# Arguments may be mutated by the method, therefore
|
112
123
|
# they need to be serialized prior to method invocation.
|
113
|
-
|
114
|
-
serializer.serialize_args(args, kwargs,
|
124
|
+
serialized_entry_args = if probe.capture_snapshot?
|
125
|
+
serializer.serialize_args(args, kwargs, self,
|
115
126
|
depth: probe.max_capture_depth || settings.dynamic_instrumentation.max_capture_depth,
|
116
127
|
attribute_count: probe.max_capture_attribute_count || settings.dynamic_instrumentation.max_capture_attribute_count)
|
117
128
|
end
|
@@ -148,8 +159,10 @@ module Datadog
|
|
148
159
|
caller_locs = method_frame + caller_locations # steep:ignore
|
149
160
|
# TODO capture arguments at exit
|
150
161
|
# & is to stop steep complaints, block is always present here.
|
151
|
-
block&.call(probe: probe, rv: rv,
|
152
|
-
|
162
|
+
block&.call(probe: probe, rv: rv,
|
163
|
+
duration: duration, caller_locations: caller_locs,
|
164
|
+
target_self: self,
|
165
|
+
serialized_entry_args: serialized_entry_args)
|
153
166
|
rv
|
154
167
|
else
|
155
168
|
# stop standard from trying to mess up my code
|
@@ -298,8 +311,21 @@ module Datadog
|
|
298
311
|
probe.file == tp.path || probe.file_matches?(tp.path)
|
299
312
|
)
|
300
313
|
if rate_limiter.nil? || rate_limiter.allow?
|
314
|
+
serialized_locals = if probe.capture_snapshot?
|
315
|
+
serializer.serialize_vars(Instrumenter.get_local_variables(tp),
|
316
|
+
depth: probe.max_capture_depth || settings.dynamic_instrumentation.max_capture_depth,
|
317
|
+
attribute_count: probe.max_capture_attribute_count || settings.dynamic_instrumentation.max_capture_attribute_count,)
|
318
|
+
end
|
319
|
+
if probe.capture_snapshot?
|
320
|
+
serializer.serialize_value(tp.self,
|
321
|
+
depth: probe.max_capture_depth || settings.dynamic_instrumentation.max_capture_depth,
|
322
|
+
attribute_count: probe.max_capture_attribute_count || settings.dynamic_instrumentation.max_capture_attribute_count,)
|
323
|
+
end
|
301
324
|
# & is to stop steep complaints, block is always present here.
|
302
|
-
block&.call(probe: probe,
|
325
|
+
block&.call(probe: probe,
|
326
|
+
serialized_locals: serialized_locals,
|
327
|
+
target_self: tp.self,
|
328
|
+
path: tp.path, caller_locations: caller_locations)
|
303
329
|
end
|
304
330
|
end
|
305
331
|
rescue => exc
|
@@ -371,6 +397,23 @@ module Datadog
|
|
371
397
|
end
|
372
398
|
end
|
373
399
|
|
400
|
+
class << self
|
401
|
+
def get_local_variables(trace_point)
|
402
|
+
# binding appears to be constructed on access, therefore
|
403
|
+
# 1) we should attempt to cache it and
|
404
|
+
# 2) we should not call +binding+ until we actually need variable values.
|
405
|
+
binding = trace_point.binding
|
406
|
+
|
407
|
+
# steep hack - should never happen
|
408
|
+
return {} unless binding
|
409
|
+
|
410
|
+
binding.local_variables.each_with_object({}) do |name, map|
|
411
|
+
value = binding.local_variable_get(name)
|
412
|
+
map[name] = value
|
413
|
+
end
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
374
417
|
private
|
375
418
|
|
376
419
|
attr_reader :lock
|