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
|
@@ -13,6 +13,7 @@ require_relative 'ext'
|
|
|
13
13
|
require_relative 'header_collection'
|
|
14
14
|
require_relative 'header_tagging'
|
|
15
15
|
require_relative 'request_queue'
|
|
16
|
+
require_relative 'route_inference'
|
|
16
17
|
require_relative 'trace_proxy_middleware'
|
|
17
18
|
|
|
18
19
|
module Datadog
|
|
@@ -138,28 +139,7 @@ module Datadog
|
|
|
138
139
|
request_span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_REQUEST)
|
|
139
140
|
request_span.set_tag(Tracing::Metadata::Ext::TAG_KIND, Tracing::Metadata::Ext::SpanKind::TAG_SERVER)
|
|
140
141
|
|
|
141
|
-
|
|
142
|
-
last_script_name = trace.get_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH) || ''
|
|
143
|
-
|
|
144
|
-
# If the last_script_name is empty but the env['SCRIPT_NAME'] is NOT empty
|
|
145
|
-
# then the current rack request was not routed and must be accounted for
|
|
146
|
-
# which only happens in pure nested rack requests i.e /rack/rack/hello/world
|
|
147
|
-
#
|
|
148
|
-
# To account for the unaccounted nested rack requests of /rack/hello/world,
|
|
149
|
-
# we use 'PATH_INFO knowing that rack cannot have named parameters
|
|
150
|
-
if last_script_name == '' && env['SCRIPT_NAME'] && env['SCRIPT_NAME'] != ''
|
|
151
|
-
last_script_name = last_route
|
|
152
|
-
last_route = env['PATH_INFO']
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
# Clear the route and route path tags from the request trace to avoid possibility of misplacement
|
|
156
|
-
trace.clear_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE)
|
|
157
|
-
trace.clear_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH)
|
|
158
|
-
|
|
159
|
-
# Ensure tags are placed in rack.request span as desired
|
|
160
|
-
request_span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE, last_script_name + last_route)
|
|
161
|
-
request_span.clear_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH)
|
|
162
|
-
end
|
|
142
|
+
set_route_and_endpoint_tags(trace: trace, request_span: request_span, status: status, env: env)
|
|
163
143
|
|
|
164
144
|
# Set analytics sample rate
|
|
165
145
|
if Contrib::Analytics.enabled?(configuration[:analytics_enabled])
|
|
@@ -218,16 +198,14 @@ module Datadog
|
|
|
218
198
|
request_span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_USER_AGENT, user_agent)
|
|
219
199
|
end
|
|
220
200
|
|
|
221
|
-
if request_span.get_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE).nil? && status != 404
|
|
222
|
-
request_span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE, env['PATH_INFO'])
|
|
223
|
-
end
|
|
224
|
-
|
|
225
201
|
HeaderTagging.tag_request_headers(request_span, request_header_collection, configuration)
|
|
226
202
|
HeaderTagging.tag_response_headers(request_span, headers, configuration) if headers
|
|
227
203
|
|
|
228
204
|
# detect if the status code is a 5xx and flag the request span as an error
|
|
229
205
|
# unless it has been already set by the underlying framework
|
|
230
|
-
request_span.status
|
|
206
|
+
if request_span.status.zero? && Datadog.configuration.tracing.http_error_statuses.server.include?(status)
|
|
207
|
+
request_span.status = Tracing::Metadata::Ext::Errors::STATUS
|
|
208
|
+
end
|
|
231
209
|
end
|
|
232
210
|
# rubocop:enable Metrics/AbcSize
|
|
233
211
|
# rubocop:enable Metrics/CyclomaticComplexity
|
|
@@ -240,6 +218,60 @@ module Datadog
|
|
|
240
218
|
Datadog.configuration.tracing[:rack]
|
|
241
219
|
end
|
|
242
220
|
|
|
221
|
+
# rubocop:disable Metrics/AbcSize
|
|
222
|
+
# rubocop:disable Metrics/MethodLength
|
|
223
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
224
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
|
225
|
+
def set_route_and_endpoint_tags(trace:, request_span:, status:, env:)
|
|
226
|
+
return if status == 404
|
|
227
|
+
|
|
228
|
+
if (last_route = trace.get_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE))
|
|
229
|
+
last_script_name = trace.get_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH) || ''
|
|
230
|
+
|
|
231
|
+
# This happens when processing requests to a nested rack application,
|
|
232
|
+
# when parent app is instrumented, and the nested app is not instrumented
|
|
233
|
+
#
|
|
234
|
+
# When resource_renaming.always_simplified_endpoint is set to true,
|
|
235
|
+
# we infer the route from the full request path.
|
|
236
|
+
if last_script_name == '' && env['SCRIPT_NAME'] != '' &&
|
|
237
|
+
!Datadog.configuration.tracing.resource_renaming.always_simplified_endpoint &&
|
|
238
|
+
(inferred_route = RouteInference.infer(env['PATH_INFO']))
|
|
239
|
+
set_endpoint_tag(request_span, last_route + inferred_route)
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# Clear the route and route path tags from the request trace to avoid possibility of misplacement
|
|
243
|
+
trace.clear_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE)
|
|
244
|
+
trace.clear_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH)
|
|
245
|
+
|
|
246
|
+
# Ensure tags are placed in rack.request span as desired
|
|
247
|
+
request_span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE, last_script_name + last_route)
|
|
248
|
+
request_span.clear_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH)
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
if Datadog.configuration.tracing.resource_renaming.always_simplified_endpoint ||
|
|
252
|
+
request_span.get_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE).nil?
|
|
253
|
+
if (inferred_route = RouteInference.read_or_infer(env))
|
|
254
|
+
set_endpoint_tag(request_span, inferred_route) if inferred_route
|
|
255
|
+
end
|
|
256
|
+
elsif !request_span.get_tag(Tracing::Metadata::Ext::HTTP::TAG_ENDPOINT)
|
|
257
|
+
set_endpoint_tag(request_span, request_span.get_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE))
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
# rubocop:enable Metrics/AbcSize
|
|
261
|
+
# rubocop:enable Metrics/MethodLength
|
|
262
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
263
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
|
264
|
+
|
|
265
|
+
def set_endpoint_tag(request_span, value)
|
|
266
|
+
# In the first iteration, http.endpoint must be reported in 2 cases:
|
|
267
|
+
# 1. resource renaming is enabled
|
|
268
|
+
# 2. AppSec is enabled and resource renaming is disabled (by default, not explicitly)
|
|
269
|
+
if Datadog.configuration.tracing.resource_renaming.enabled ||
|
|
270
|
+
Datadog.configuration.appsec.enabled && Datadog.configuration.tracing.resource_renaming.options[:enabled].default_precedence?
|
|
271
|
+
request_span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_ENDPOINT, value)
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
243
275
|
# rubocop:disable Metrics/AbcSize
|
|
244
276
|
# rubocop:disable Metrics/MethodLength
|
|
245
277
|
def parse_url(env, original_env)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datadog
|
|
4
|
+
module Tracing
|
|
5
|
+
module Contrib
|
|
6
|
+
module Rack
|
|
7
|
+
# This module provides logic for inferring HTTP route pattern
|
|
8
|
+
# from an HTTP path.
|
|
9
|
+
module RouteInference
|
|
10
|
+
MAX_NUMBER_OF_SEGMENTS = 8
|
|
11
|
+
|
|
12
|
+
INT_PARAM_REGEX = /\A[0-9]+\z/.freeze
|
|
13
|
+
INT_ID_PARAM_REGEX = /\A(?=.*\d)[\d._-]{3,}\z/.freeze
|
|
14
|
+
HEX_PARAM_REGEX = /\A(?=.*\d)[A-Fa-f0-9]{6,}\z/.freeze
|
|
15
|
+
HEX_ID_PARAM_REGEX = /\A(?=.*\d)[A-Fa-f0-9._-]{6,}\z/.freeze
|
|
16
|
+
STRING_PARAM_REGEX = /\A.{20,}|.*[%&'()*+,:=@].*\z/.freeze
|
|
17
|
+
|
|
18
|
+
DATADOG_INFERRED_ROUTE_ENV_KEY = 'datadog.inferred_route'
|
|
19
|
+
|
|
20
|
+
module_function
|
|
21
|
+
|
|
22
|
+
def read_or_infer(request_env)
|
|
23
|
+
request_env[DATADOG_INFERRED_ROUTE_ENV_KEY] ||=
|
|
24
|
+
infer(request_env['SCRIPT_NAME'].to_s + request_env['PATH_INFO'].to_s)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def infer(path)
|
|
28
|
+
segments = path.delete_prefix('/').split('/', MAX_NUMBER_OF_SEGMENTS + 1).first(MAX_NUMBER_OF_SEGMENTS)
|
|
29
|
+
|
|
30
|
+
segments.map! do |segment| #: Array[String?]
|
|
31
|
+
next if segment.empty?
|
|
32
|
+
|
|
33
|
+
case segment
|
|
34
|
+
when INT_PARAM_REGEX then '{param:int}'
|
|
35
|
+
when INT_ID_PARAM_REGEX then '{param:int_id}'
|
|
36
|
+
when HEX_PARAM_REGEX then '{param:hex}'
|
|
37
|
+
when HEX_ID_PARAM_REGEX then '{param:hex_id}'
|
|
38
|
+
when STRING_PARAM_REGEX then '{param:str}'
|
|
39
|
+
else segment
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
segments.compact! #: Array[String]
|
|
44
|
+
|
|
45
|
+
"/#{segments.join("/")}"
|
|
46
|
+
rescue
|
|
47
|
+
nil
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -26,8 +26,8 @@ module Datadog
|
|
|
26
26
|
rescue Exception => e
|
|
27
27
|
span = Tracing.active_span
|
|
28
28
|
if !span.nil? && ActionPack::Utils.exception_is_error?(e)
|
|
29
|
-
#
|
|
30
|
-
#
|
|
29
|
+
# By default, only 5XX exceptions are actually errors (e.g. don't flag 404s).
|
|
30
|
+
# This can be changed by setting `DD_TRACE_HTTP_SERVER_ERROR_STATUSES` environment variable.
|
|
31
31
|
# You can add custom errors via `config.action_dispatch.rescue_responses`
|
|
32
32
|
span.set_error(e)
|
|
33
33
|
|
|
@@ -99,7 +99,10 @@ module Datadog
|
|
|
99
99
|
end
|
|
100
100
|
end
|
|
101
101
|
rescue ::RestClient::ExceptionWithResponse => e
|
|
102
|
-
|
|
102
|
+
# DEV-3.0: This was previously checking against a 500..599 range.
|
|
103
|
+
# To not introduce breaking change, this was changed to use `http_error_statuses.server`,
|
|
104
|
+
# but `rest_client` is a client library, this check should use `http_error_statuses.client` instead.
|
|
105
|
+
span.set_error(e) if Datadog.configuration.tracing.http_error_statuses.server.include?(e.http_code)
|
|
103
106
|
span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_STATUS_CODE, e.http_code)
|
|
104
107
|
|
|
105
108
|
raise e
|
|
@@ -61,7 +61,9 @@ module Datadog
|
|
|
61
61
|
# Adds status code to the resource name once the resource comes back
|
|
62
62
|
span.resource = "#{request_method} #{status_code}"
|
|
63
63
|
span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_STATUS_CODE, status_code)
|
|
64
|
-
|
|
64
|
+
if Datadog.configuration.tracing.http_error_statuses.server.include?(status_code)
|
|
65
|
+
span.status = Tracing::Metadata::Ext::Errors::STATUS
|
|
66
|
+
end
|
|
65
67
|
response
|
|
66
68
|
end
|
|
67
69
|
end
|
|
@@ -70,7 +70,9 @@ module Datadog
|
|
|
70
70
|
sinatra_response = ::Sinatra::Response.new([], status) # Build object to use status code helpers
|
|
71
71
|
|
|
72
72
|
span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_STATUS_CODE, sinatra_response.status)
|
|
73
|
-
|
|
73
|
+
if Datadog.configuration.tracing.http_error_statuses.server.include?(sinatra_response.status)
|
|
74
|
+
span.set_error(env['sinatra.error'])
|
|
75
|
+
end
|
|
74
76
|
end
|
|
75
77
|
|
|
76
78
|
if (headers = response[1])
|
|
@@ -5,10 +5,17 @@ module Datadog
|
|
|
5
5
|
module Contrib
|
|
6
6
|
# Useful checking whether the defined range covers status code
|
|
7
7
|
class StatusRangeMatcher
|
|
8
|
+
attr_reader :ranges
|
|
9
|
+
|
|
8
10
|
def initialize(ranges)
|
|
9
11
|
@ranges = Array(ranges)
|
|
10
12
|
end
|
|
11
13
|
|
|
14
|
+
def +(other)
|
|
15
|
+
StatusRangeMatcher.new(@ranges + other.ranges)
|
|
16
|
+
end
|
|
17
|
+
alias_method :concat, :+
|
|
18
|
+
|
|
12
19
|
def include?(status)
|
|
13
20
|
@ranges.any? do |e|
|
|
14
21
|
case e
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../configuration/settings'
|
|
4
|
+
require_relative '../ext'
|
|
5
|
+
|
|
6
|
+
module Datadog
|
|
7
|
+
module Tracing
|
|
8
|
+
module Contrib
|
|
9
|
+
module WaterDrop
|
|
10
|
+
module Configuration
|
|
11
|
+
# @public_api
|
|
12
|
+
class Settings < Contrib::Configuration::Settings
|
|
13
|
+
option :enabled do |o|
|
|
14
|
+
o.type :bool
|
|
15
|
+
o.env Ext::ENV_ENABLED
|
|
16
|
+
o.default true
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
option :service_name
|
|
20
|
+
|
|
21
|
+
option :distributed_tracing, default: false, type: :bool
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../../distributed/fetcher'
|
|
4
|
+
require_relative '../../../distributed/propagation'
|
|
5
|
+
require_relative '../../../distributed/b3_multi'
|
|
6
|
+
require_relative '../../../distributed/b3_single'
|
|
7
|
+
require_relative '../../../distributed/datadog'
|
|
8
|
+
require_relative '../../../distributed/none'
|
|
9
|
+
require_relative '../../../distributed/trace_context'
|
|
10
|
+
require_relative '../../../configuration/ext'
|
|
11
|
+
|
|
12
|
+
module Datadog
|
|
13
|
+
module Tracing
|
|
14
|
+
module Contrib
|
|
15
|
+
module WaterDrop
|
|
16
|
+
module Distributed
|
|
17
|
+
# Extracts and injects propagation through Kafka message headers.
|
|
18
|
+
class Propagation < Tracing::Distributed::Propagation
|
|
19
|
+
def initialize(
|
|
20
|
+
propagation_style_inject:,
|
|
21
|
+
propagation_style_extract:,
|
|
22
|
+
propagation_extract_first:
|
|
23
|
+
)
|
|
24
|
+
super(
|
|
25
|
+
propagation_styles: {
|
|
26
|
+
Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_MULTI_HEADER =>
|
|
27
|
+
Tracing::Distributed::B3Multi.new(fetcher: Tracing::Distributed::Fetcher),
|
|
28
|
+
Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER =>
|
|
29
|
+
Tracing::Distributed::B3Single.new(fetcher: Tracing::Distributed::Fetcher),
|
|
30
|
+
Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG =>
|
|
31
|
+
Tracing::Distributed::Datadog.new(fetcher: Tracing::Distributed::Fetcher),
|
|
32
|
+
Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_TRACE_CONTEXT =>
|
|
33
|
+
Tracing::Distributed::TraceContext.new(fetcher: Tracing::Distributed::Fetcher),
|
|
34
|
+
Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_BAGGAGE =>
|
|
35
|
+
Tracing::Distributed::Baggage.new(fetcher: Tracing::Distributed::Fetcher),
|
|
36
|
+
Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_NONE => Tracing::Distributed::None.new
|
|
37
|
+
},
|
|
38
|
+
propagation_style_inject: propagation_style_inject,
|
|
39
|
+
propagation_style_extract: propagation_style_extract,
|
|
40
|
+
propagation_extract_first: propagation_extract_first
|
|
41
|
+
)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datadog
|
|
4
|
+
module Tracing
|
|
5
|
+
module Contrib
|
|
6
|
+
module WaterDrop
|
|
7
|
+
module Ext
|
|
8
|
+
ENV_ENABLED = 'DD_TRACE_WATERDROP_ENABLED'
|
|
9
|
+
|
|
10
|
+
SPAN_PRODUCER = 'karafka.produce'
|
|
11
|
+
|
|
12
|
+
TAG_PRODUCER = 'kafka.producer'
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../integration'
|
|
4
|
+
require_relative 'configuration/settings'
|
|
5
|
+
require_relative 'patcher'
|
|
6
|
+
|
|
7
|
+
module Datadog
|
|
8
|
+
module Tracing
|
|
9
|
+
module Contrib
|
|
10
|
+
module WaterDrop
|
|
11
|
+
# Description of WaterDrop integration
|
|
12
|
+
class Integration
|
|
13
|
+
include Contrib::Integration
|
|
14
|
+
|
|
15
|
+
# WaterDrop added class-level instrumentation in version 2.8.8.rc1
|
|
16
|
+
MINIMUM_VERSION = Gem::Version.new('2.8.8.rc1')
|
|
17
|
+
|
|
18
|
+
register_as :waterdrop, auto_patch: false
|
|
19
|
+
|
|
20
|
+
def self.version
|
|
21
|
+
Gem.loaded_specs['waterdrop']&.version
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.loaded?
|
|
25
|
+
!defined?(::WaterDrop).nil?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.compatible?
|
|
29
|
+
super && version >= MINIMUM_VERSION
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def new_configuration
|
|
33
|
+
Configuration::Settings.new
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def patcher
|
|
37
|
+
Patcher
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'ext'
|
|
4
|
+
|
|
5
|
+
module Datadog
|
|
6
|
+
module Tracing
|
|
7
|
+
module Contrib
|
|
8
|
+
module WaterDrop
|
|
9
|
+
# Middleware to propagate tracing context in messages produced by WaterDrop
|
|
10
|
+
module Middleware
|
|
11
|
+
class << self
|
|
12
|
+
def call(message)
|
|
13
|
+
trace_op = Datadog::Tracing.active_trace
|
|
14
|
+
|
|
15
|
+
if trace_op && Datadog::Tracing::Distributed::PropagationPolicy.enabled?(
|
|
16
|
+
global_config: configuration,
|
|
17
|
+
trace: trace_op
|
|
18
|
+
)
|
|
19
|
+
WaterDrop.inject(trace_op.to_digest, message[:headers] ||= {})
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
if Datadog::DataStreams.enabled?
|
|
23
|
+
Datadog::DataStreams.set_produce_checkpoint(
|
|
24
|
+
type: 'kafka',
|
|
25
|
+
destination: message[:topic],
|
|
26
|
+
auto_instrumentation: true
|
|
27
|
+
) do |key, value|
|
|
28
|
+
message[:headers] ||= {}
|
|
29
|
+
message[:headers][key] = value
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
message
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def configuration
|
|
39
|
+
Datadog.configuration.tracing[:waterdrop]
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../patcher'
|
|
4
|
+
require_relative 'ext'
|
|
5
|
+
require_relative 'distributed/propagation'
|
|
6
|
+
|
|
7
|
+
module Datadog
|
|
8
|
+
module Tracing
|
|
9
|
+
module Contrib
|
|
10
|
+
module WaterDrop
|
|
11
|
+
# Patcher enables patching of 'waterdrop' module.
|
|
12
|
+
module Patcher
|
|
13
|
+
include Contrib::Patcher
|
|
14
|
+
|
|
15
|
+
module_function
|
|
16
|
+
|
|
17
|
+
def target_version
|
|
18
|
+
Integration.version
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def patch
|
|
22
|
+
require_relative 'producer'
|
|
23
|
+
require_relative 'middleware'
|
|
24
|
+
|
|
25
|
+
::WaterDrop::Producer.prepend(Producer)
|
|
26
|
+
::WaterDrop.instrumentation.subscribe('producer.configured') do |event|
|
|
27
|
+
producer = event[:producer]
|
|
28
|
+
|
|
29
|
+
included_middlewares = producer.middleware.instance_variable_get(:@steps)
|
|
30
|
+
producer.middleware.append(Middleware) unless included_middlewares.include?(Middleware)
|
|
31
|
+
|
|
32
|
+
if Datadog.configuration.data_streams.enabled
|
|
33
|
+
producer.monitor.subscribe('message.acknowledged') do |ack_event|
|
|
34
|
+
if Datadog::DataStreams.enabled?
|
|
35
|
+
payload = ack_event.payload
|
|
36
|
+
Datadog::DataStreams.track_kafka_produce(payload[:topic], payload[:partition], payload[:offset])
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'ext'
|
|
4
|
+
|
|
5
|
+
module Datadog
|
|
6
|
+
module Tracing
|
|
7
|
+
module Contrib
|
|
8
|
+
module WaterDrop
|
|
9
|
+
# Producer integration for WaterDrop
|
|
10
|
+
module Producer
|
|
11
|
+
%i[
|
|
12
|
+
produce_many_sync
|
|
13
|
+
produce_many_async
|
|
14
|
+
produce_sync
|
|
15
|
+
produce_async
|
|
16
|
+
].each do |method|
|
|
17
|
+
define_method(method) do |messages|
|
|
18
|
+
Datadog::Tracing.trace(Ext::SPAN_PRODUCER, resource: "waterdrop.#{__method__}") do
|
|
19
|
+
extract_span_tags(messages)
|
|
20
|
+
super(messages)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def extract_span_tags(messages)
|
|
28
|
+
messages = [messages] if messages.is_a?(Hash)
|
|
29
|
+
span = Datadog::Tracing.active_span
|
|
30
|
+
return unless span
|
|
31
|
+
|
|
32
|
+
topics = []
|
|
33
|
+
partitions = []
|
|
34
|
+
messages.each do |message|
|
|
35
|
+
topics << message[:topic]
|
|
36
|
+
partitions << message[:partition] if message.key?(:partition)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
span.set_tag(Ext::TAG_PRODUCER, id)
|
|
40
|
+
span.set_tag(Contrib::Karafka::Ext::TAG_MESSAGE_COUNT, messages.size)
|
|
41
|
+
span.set_tag(Contrib::Ext::Messaging::TAG_SYSTEM, Contrib::Karafka::Ext::TAG_SYSTEM)
|
|
42
|
+
|
|
43
|
+
span.set_tag(Contrib::Ext::Messaging::TAG_DESTINATION, topics.uniq.sort.join(','))
|
|
44
|
+
span.set_tag(Contrib::Karafka::Ext::TAG_PARTITION, partitions.uniq.sort.join(',')) if partitions.any?
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'component'
|
|
4
|
+
require_relative 'waterdrop/integration'
|
|
5
|
+
require_relative 'waterdrop/distributed/propagation'
|
|
6
|
+
|
|
7
|
+
module Datadog
|
|
8
|
+
module Tracing
|
|
9
|
+
module Contrib
|
|
10
|
+
# `WaterDrop` integration public API
|
|
11
|
+
module WaterDrop
|
|
12
|
+
def self.inject(digest, data)
|
|
13
|
+
raise 'Please invoke Datadog.configure at least once before calling this method' unless @propagation
|
|
14
|
+
|
|
15
|
+
@propagation.inject!(digest, data)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.extract(data)
|
|
19
|
+
raise 'Please invoke Datadog.configure at least once before calling this method' unless @propagation
|
|
20
|
+
|
|
21
|
+
@propagation.extract(data)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
Contrib::Component.register('waterdrop') do |config|
|
|
25
|
+
tracing = config.tracing
|
|
26
|
+
tracing.propagation_style
|
|
27
|
+
|
|
28
|
+
@propagation = WaterDrop::Distributed::Propagation.new(
|
|
29
|
+
propagation_style_inject: tracing.propagation_style_inject,
|
|
30
|
+
propagation_style_extract: tracing.propagation_style_extract,
|
|
31
|
+
propagation_extract_first: tracing.propagation_extract_first
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -55,6 +55,7 @@ require_relative 'contrib/httpclient/integration'
|
|
|
55
55
|
require_relative 'contrib/httprb/integration'
|
|
56
56
|
require_relative 'contrib/integration'
|
|
57
57
|
require_relative 'contrib/kafka/integration'
|
|
58
|
+
require_relative 'contrib/waterdrop'
|
|
58
59
|
require_relative 'contrib/karafka'
|
|
59
60
|
require_relative 'contrib/lograge/integration'
|
|
60
61
|
require_relative 'contrib/mongodb/integration'
|
|
@@ -94,8 +94,8 @@ module Datadog
|
|
|
94
94
|
|
|
95
95
|
# @public_api
|
|
96
96
|
module HTTP
|
|
97
|
-
ERROR_RANGE = (500...600).freeze
|
|
98
97
|
TAG_BASE_URL = 'http.base_url'
|
|
98
|
+
TAG_ENDPOINT = 'http.endpoint'
|
|
99
99
|
TAG_METHOD = 'http.method'
|
|
100
100
|
TAG_STATUS_CODE = 'http.status_code'
|
|
101
101
|
TAG_USER_AGENT = 'http.useragent'
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative 'statistics'
|
|
4
|
+
require_relative '../../../core/transport/http/client'
|
|
4
5
|
require_relative '../../../core/transport/http/env'
|
|
5
6
|
require_relative '../../../core/transport/http/response'
|
|
6
7
|
|
|
@@ -9,33 +10,24 @@ module Datadog
|
|
|
9
10
|
module Transport
|
|
10
11
|
module HTTP
|
|
11
12
|
# Routes, encodes, and sends tracer data to the trace agent via HTTP.
|
|
12
|
-
class Client
|
|
13
|
+
class Client < Core::Transport::HTTP::Client
|
|
13
14
|
include Datadog::Tracing::Transport::HTTP::Statistics
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
private
|
|
16
17
|
|
|
17
|
-
def
|
|
18
|
-
|
|
19
|
-
@logger = logger
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def send_request(request, &block)
|
|
23
|
-
# Build request into env
|
|
24
|
-
env = build_env(request)
|
|
25
|
-
|
|
26
|
-
# Get responses from API
|
|
27
|
-
response = yield(api, env)
|
|
18
|
+
def on_response(response)
|
|
19
|
+
super
|
|
28
20
|
|
|
29
21
|
# Update statistics
|
|
30
22
|
update_stats_from_response!(response)
|
|
23
|
+
end
|
|
31
24
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
25
|
+
def on_exception(exception)
|
|
26
|
+
# Note: this method does NOT call super - it has replacement
|
|
27
|
+
# logic for how to log the exception.
|
|
28
|
+
|
|
29
|
+
message = build_exception_message(exception)
|
|
37
30
|
|
|
38
|
-
# Log error
|
|
39
31
|
if stats.consecutive_errors > 0
|
|
40
32
|
logger.debug(message)
|
|
41
33
|
else
|
|
@@ -44,13 +36,7 @@ module Datadog
|
|
|
44
36
|
end
|
|
45
37
|
|
|
46
38
|
# Update statistics
|
|
47
|
-
update_stats_from_exception!(
|
|
48
|
-
|
|
49
|
-
Datadog::Core::Transport::InternalErrorResponse.new(e)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def build_env(request)
|
|
53
|
-
Datadog::Core::Transport::HTTP::Env.new(request)
|
|
39
|
+
update_stats_from_exception!(exception)
|
|
54
40
|
end
|
|
55
41
|
end
|
|
56
42
|
end
|