datadog 2.3.0 → 2.5.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 +64 -2
- data/ext/datadog_profiling_loader/datadog_profiling_loader.c +9 -1
- data/ext/datadog_profiling_loader/extconf.rb +10 -22
- data/ext/datadog_profiling_native_extension/NativeExtensionDesign.md +3 -3
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +198 -41
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +4 -2
- data/ext/datadog_profiling_native_extension/collectors_stack.c +89 -46
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +645 -107
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +15 -1
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +0 -27
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +0 -4
- data/ext/datadog_profiling_native_extension/extconf.rb +42 -25
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +50 -0
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +75 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.c +194 -34
- data/ext/datadog_profiling_native_extension/heap_recorder.h +11 -0
- data/ext/datadog_profiling_native_extension/http_transport.c +38 -6
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +1 -1
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +53 -2
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +3 -0
- data/ext/datadog_profiling_native_extension/profiling.c +1 -1
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +14 -11
- data/ext/datadog_profiling_native_extension/stack_recorder.c +58 -22
- data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -0
- data/ext/libdatadog_api/crashtracker.c +20 -18
- data/ext/libdatadog_api/datadog_ruby_common.c +0 -27
- data/ext/libdatadog_api/datadog_ruby_common.h +0 -4
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +2184 -108
- data/lib/datadog/appsec/assets/waf_rules/strict.json +1430 -2
- data/lib/datadog/appsec/component.rb +29 -8
- data/lib/datadog/appsec/configuration/settings.rb +10 -2
- data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +1 -0
- data/lib/datadog/appsec/contrib/devise/patcher/rememberable_patch.rb +21 -0
- data/lib/datadog/appsec/contrib/devise/patcher.rb +12 -2
- data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +0 -14
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +67 -31
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +14 -15
- data/lib/datadog/appsec/contrib/graphql/integration.rb +14 -1
- data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +7 -20
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +2 -5
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +9 -15
- data/lib/datadog/appsec/contrib/rack/reactive/request.rb +6 -18
- data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +7 -20
- data/lib/datadog/appsec/contrib/rack/reactive/response.rb +5 -18
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +3 -1
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +3 -5
- data/lib/datadog/appsec/contrib/rails/reactive/action.rb +5 -18
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +6 -10
- data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +7 -20
- data/lib/datadog/appsec/event.rb +25 -1
- data/lib/datadog/appsec/ext.rb +4 -0
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +3 -5
- data/lib/datadog/appsec/monitor/reactive/set_user.rb +7 -20
- data/lib/datadog/appsec/processor/context.rb +109 -0
- data/lib/datadog/appsec/processor/rule_loader.rb +3 -1
- data/lib/datadog/appsec/processor/rule_merger.rb +33 -15
- data/lib/datadog/appsec/processor.rb +42 -107
- data/lib/datadog/appsec/rate_limiter.rb +25 -40
- data/lib/datadog/appsec/remote.rb +7 -3
- data/lib/datadog/appsec/scope.rb +1 -4
- data/lib/datadog/appsec/utils/trace_operation.rb +15 -0
- data/lib/datadog/appsec/utils.rb +2 -0
- data/lib/datadog/appsec.rb +3 -2
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +26 -25
- data/lib/datadog/core/configuration/components.rb +4 -3
- data/lib/datadog/core/configuration/settings.rb +96 -5
- data/lib/datadog/core/configuration.rb +1 -3
- data/lib/datadog/core/crashtracking/component.rb +9 -6
- data/lib/datadog/core/environment/execution.rb +5 -5
- data/lib/datadog/core/environment/yjit.rb +5 -0
- data/lib/datadog/core/metrics/client.rb +7 -0
- data/lib/datadog/core/rate_limiter.rb +183 -0
- data/lib/datadog/core/remote/client/capabilities.rb +4 -3
- data/lib/datadog/core/remote/component.rb +4 -2
- data/lib/datadog/core/remote/negotiation.rb +4 -4
- data/lib/datadog/core/remote/tie.rb +2 -0
- data/lib/datadog/core/remote/transport/http.rb +5 -0
- data/lib/datadog/core/remote/worker.rb +1 -1
- data/lib/datadog/core/runtime/ext.rb +1 -0
- data/lib/datadog/core/runtime/metrics.rb +5 -1
- data/lib/datadog/core/semaphore.rb +35 -0
- data/lib/datadog/core/telemetry/component.rb +2 -0
- data/lib/datadog/core/telemetry/event.rb +12 -7
- data/lib/datadog/core/telemetry/logger.rb +51 -0
- data/lib/datadog/core/telemetry/logging.rb +50 -14
- data/lib/datadog/core/telemetry/request.rb +13 -1
- data/lib/datadog/core/transport/ext.rb +1 -0
- data/lib/datadog/core/utils/time.rb +12 -0
- data/lib/datadog/core/workers/async.rb +1 -1
- data/lib/datadog/di/code_tracker.rb +166 -0
- data/lib/datadog/di/configuration/settings.rb +163 -0
- data/lib/datadog/di/configuration.rb +11 -0
- data/lib/datadog/di/error.rb +31 -0
- data/lib/datadog/di/extensions.rb +16 -0
- data/lib/datadog/di/instrumenter.rb +301 -0
- data/lib/datadog/di/probe.rb +162 -0
- data/lib/datadog/di/probe_builder.rb +47 -0
- data/lib/datadog/di/probe_notification_builder.rb +207 -0
- data/lib/datadog/di/probe_notifier_worker.rb +244 -0
- data/lib/datadog/di/redactor.rb +188 -0
- data/lib/datadog/di/serializer.rb +215 -0
- data/lib/datadog/di/transport.rb +67 -0
- data/lib/datadog/di/utils.rb +39 -0
- data/lib/datadog/di.rb +57 -0
- data/lib/datadog/opentelemetry/sdk/propagator.rb +2 -0
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +12 -10
- data/lib/datadog/profiling/collectors/info.rb +12 -3
- data/lib/datadog/profiling/collectors/thread_context.rb +32 -8
- data/lib/datadog/profiling/component.rb +21 -4
- data/lib/datadog/profiling/http_transport.rb +6 -1
- data/lib/datadog/profiling/scheduler.rb +2 -0
- data/lib/datadog/profiling/stack_recorder.rb +40 -9
- data/lib/datadog/single_step_instrument.rb +12 -0
- data/lib/datadog/tracing/component.rb +13 -0
- data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +8 -12
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +5 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +78 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +33 -0
- data/lib/datadog/tracing/contrib/action_pack/patcher.rb +2 -0
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +4 -0
- data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +3 -1
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +3 -1
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +5 -1
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +5 -0
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -0
- data/lib/datadog/tracing/contrib/excon/middleware.rb +3 -0
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +12 -0
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +24 -2
- data/lib/datadog/tracing/contrib/graphql/patcher.rb +9 -12
- data/lib/datadog/tracing/contrib/graphql/trace_patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/graphql/tracing_patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +13 -9
- data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +6 -3
- data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +9 -0
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +22 -15
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +10 -5
- data/lib/datadog/tracing/contrib/httpclient/patcher.rb +1 -14
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +9 -0
- data/lib/datadog/tracing/contrib/httprb/patcher.rb +1 -14
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +1 -2
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +2 -0
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +13 -6
- data/lib/datadog/tracing/contrib/patcher.rb +2 -1
- data/lib/datadog/tracing/contrib/presto/patcher.rb +1 -13
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +27 -0
- data/lib/datadog/tracing/contrib/rails/runner.rb +1 -1
- data/lib/datadog/tracing/contrib/redis/tags.rb +4 -0
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +3 -0
- data/lib/datadog/tracing/contrib/sinatra/tracer.rb +4 -0
- data/lib/datadog/tracing/contrib/stripe/request.rb +3 -2
- data/lib/datadog/tracing/distributed/propagation.rb +7 -0
- data/lib/datadog/tracing/metadata/ext.rb +2 -0
- data/lib/datadog/tracing/remote.rb +5 -2
- data/lib/datadog/tracing/sampling/matcher.rb +6 -1
- data/lib/datadog/tracing/sampling/rate_sampler.rb +1 -1
- data/lib/datadog/tracing/sampling/rule.rb +2 -0
- data/lib/datadog/tracing/sampling/rule_sampler.rb +15 -9
- data/lib/datadog/tracing/sampling/span/ext.rb +1 -1
- data/lib/datadog/tracing/sampling/span/rule.rb +2 -2
- data/lib/datadog/tracing/trace_operation.rb +26 -2
- data/lib/datadog/tracing/tracer.rb +29 -22
- data/lib/datadog/tracing/transport/http/client.rb +1 -0
- data/lib/datadog/tracing/transport/http.rb +4 -0
- data/lib/datadog/tracing/transport/io/client.rb +1 -0
- data/lib/datadog/tracing/workers/trace_writer.rb +1 -1
- data/lib/datadog/tracing/workers.rb +2 -2
- data/lib/datadog/tracing/writer.rb +26 -28
- data/lib/datadog/version.rb +1 -1
- metadata +40 -15
- data/lib/datadog/tracing/sampling/rate_limiter.rb +0 -185
@@ -3,6 +3,7 @@
|
|
3
3
|
require_relative '../configuration/ext'
|
4
4
|
require_relative '../trace_digest'
|
5
5
|
require_relative '../trace_operation'
|
6
|
+
require_relative '../../core/telemetry/logger'
|
6
7
|
|
7
8
|
module Datadog
|
8
9
|
module Tracing
|
@@ -43,6 +44,7 @@ module Datadog
|
|
43
44
|
# DEV-2.0: if needed.
|
44
45
|
# DEV-2.0: Ideally, we'd have a separate stream to report tracer errors and never
|
45
46
|
# DEV-2.0: touch the active span.
|
47
|
+
# DEV-3.0: Sample trace here instead of when generating digest.
|
46
48
|
#
|
47
49
|
# @param digest [TraceDigest]
|
48
50
|
# @param data [Hash]
|
@@ -72,6 +74,10 @@ module Datadog
|
|
72
74
|
::Datadog.logger.error(
|
73
75
|
"Error injecting distributed trace data. Cause: #{e} Location: #{Array(e.backtrace).first}"
|
74
76
|
)
|
77
|
+
::Datadog::Core::Telemetry::Logger.report(
|
78
|
+
e,
|
79
|
+
description: "Error injecting distributed trace data with #{propagator.class.name}"
|
80
|
+
)
|
75
81
|
end
|
76
82
|
|
77
83
|
result
|
@@ -127,6 +133,7 @@ module Datadog
|
|
127
133
|
)
|
128
134
|
end
|
129
135
|
rescue => e
|
136
|
+
# TODO: Not to report Telemetry logs for now
|
130
137
|
::Datadog.logger.error(
|
131
138
|
"Error extracting distributed trace data. Cause: #{e} Location: #{Array(e.backtrace).first}"
|
132
139
|
)
|
@@ -87,6 +87,8 @@ module Datadog
|
|
87
87
|
TAG_STATUS_CODE = 'http.status_code'
|
88
88
|
TAG_USER_AGENT = 'http.useragent'
|
89
89
|
TAG_URL = 'http.url'
|
90
|
+
TAG_ROUTE = 'http.route'
|
91
|
+
TAG_ROUTE_PATH = 'http.route.path'
|
90
92
|
TYPE_INBOUND = AppTypes::TYPE_WEB.freeze
|
91
93
|
TYPE_OUTBOUND = 'http'
|
92
94
|
TYPE_PROXY = 'proxy'
|
@@ -13,7 +13,10 @@ module Datadog
|
|
13
13
|
PRODUCT = 'APM_TRACING'
|
14
14
|
|
15
15
|
CAPABILITIES = [
|
16
|
-
1 <<
|
16
|
+
1 << 12, # APM_TRACING_SAMPLE_RATE: Dynamic trace sampling rate configuration
|
17
|
+
1 << 13, # APM_TRACING_LOGS_INJECTION: Dynamic trace logs injection configuration
|
18
|
+
1 << 14, # APM_TRACING_HTTP_HEADER_TAGS: Dynamic trace HTTP header tags configuration
|
19
|
+
1 << 29, # APM_TRACING_SAMPLE_RULES: Dynamic trace sampling rules configuration
|
17
20
|
].freeze
|
18
21
|
|
19
22
|
def products
|
@@ -45,7 +48,7 @@ module Datadog
|
|
45
48
|
content.errored("#{e.class.name} #{e.message}: #{Array(e.backtrace).join("\n")}")
|
46
49
|
end
|
47
50
|
|
48
|
-
def receivers
|
51
|
+
def receivers(_telemetry)
|
49
52
|
receiver do |repository, _changes|
|
50
53
|
# DEV: Filter our by product. Given it will be very common
|
51
54
|
# DEV: we can filter this out before we receive the data in this method.
|
@@ -28,7 +28,7 @@ module Datadog
|
|
28
28
|
# @return [#match?(String)]
|
29
29
|
def self.glob_to_regex(glob)
|
30
30
|
# Optimization for match-all case
|
31
|
-
return MATCH_ALL if glob
|
31
|
+
return MATCH_ALL if /\A\*+\z/.match?(glob)
|
32
32
|
|
33
33
|
# Ensure no undesired characters are treated as regex.
|
34
34
|
glob = Regexp.quote(glob)
|
@@ -100,6 +100,11 @@ module Datadog
|
|
100
100
|
@tags.all? do |name, matcher|
|
101
101
|
tag = trace.get_tag(name)
|
102
102
|
|
103
|
+
# Floats: Matching floating point values with a non-zero decimal part is not supported.
|
104
|
+
# For floating point values with a non-zero decimal part, any all * pattern always returns true.
|
105
|
+
# Other patterns always return false.
|
106
|
+
return false if tag.is_a?(Float) && tag.truncate != tag && matcher != MATCH_ALL
|
107
|
+
|
103
108
|
# Format metrics as strings, to allow for partial number matching (/4.*/ matching '400', '404', etc.).
|
104
109
|
# Because metrics are floats, we use the '%g' format specifier to avoid trailing zeros, which
|
105
110
|
# can affect exact string matching (e.g. '400' matching '400.0').
|
@@ -20,7 +20,7 @@ module Datadog
|
|
20
20
|
super()
|
21
21
|
|
22
22
|
unless sample_rate >= 0.0 && sample_rate <= 1.0
|
23
|
-
Datadog.logger.
|
23
|
+
Datadog.logger.warn('sample rate is not between 0 and 1, falling back to 1')
|
24
24
|
sample_rate = 1.0
|
25
25
|
end
|
26
26
|
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative 'matcher'
|
4
4
|
require_relative 'rate_sampler'
|
5
|
+
require_relative '../../core/telemetry/logger'
|
5
6
|
|
6
7
|
module Datadog
|
7
8
|
module Tracing
|
@@ -35,6 +36,7 @@ module Datadog
|
|
35
36
|
Datadog.logger.error(
|
36
37
|
"Matcher failed. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
37
38
|
)
|
39
|
+
Datadog::Core::Telemetry::Logger.report(e, description: 'Matcher failed')
|
38
40
|
nil
|
39
41
|
end
|
40
42
|
|
@@ -1,8 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'ext'
|
4
|
-
require_relative 'rate_limiter'
|
4
|
+
require_relative '../../core/rate_limiter'
|
5
5
|
require_relative 'rule'
|
6
|
+
require_relative '../../core/telemetry/logger'
|
6
7
|
|
7
8
|
module Datadog
|
8
9
|
module Tracing
|
@@ -28,20 +29,22 @@ module Datadog
|
|
28
29
|
default_sample_rate: Datadog.configuration.tracing.sampling.default_rate,
|
29
30
|
default_sampler: nil
|
30
31
|
)
|
31
|
-
@rules =
|
32
|
+
@rules = if default_sample_rate && !default_sampler
|
33
|
+
# Add to the end of the rule list a rule always matches any trace
|
34
|
+
rules << SimpleRule.new(sample_rate: default_sample_rate)
|
35
|
+
else
|
36
|
+
rules
|
37
|
+
end
|
32
38
|
@rate_limiter = if rate_limiter
|
33
39
|
rate_limiter
|
34
40
|
elsif rate_limit
|
35
|
-
TokenBucket.new(rate_limit)
|
41
|
+
Core::TokenBucket.new(rate_limit)
|
36
42
|
else
|
37
|
-
UnlimitedLimiter.new
|
43
|
+
Core::UnlimitedLimiter.new
|
38
44
|
end
|
39
|
-
|
40
45
|
@default_sampler = if default_sampler
|
41
46
|
default_sampler
|
42
47
|
elsif default_sample_rate
|
43
|
-
# Add to the end of the rule list a rule always matches any trace
|
44
|
-
@rules << SimpleRule.new(sample_rate: default_sample_rate)
|
45
48
|
nil
|
46
49
|
else
|
47
50
|
# TODO: Simplify .tags access, as `Tracer#tags` can't be arbitrarily changed anymore
|
@@ -80,9 +83,10 @@ module Datadog
|
|
80
83
|
|
81
84
|
new(parsed_rules, rate_limit: rate_limit, default_sample_rate: default_sample_rate)
|
82
85
|
rescue => e
|
83
|
-
Datadog.logger.
|
86
|
+
Datadog.logger.warn do
|
84
87
|
"Could not parse trace sampling rules '#{rules}': #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
|
85
88
|
end
|
89
|
+
|
86
90
|
nil
|
87
91
|
end
|
88
92
|
|
@@ -121,7 +125,7 @@ module Datadog
|
|
121
125
|
|
122
126
|
return false unless sampled
|
123
127
|
|
124
|
-
rate_limiter.allow
|
128
|
+
rate_limiter.allow?.tap do |allowed|
|
125
129
|
set_priority(trace, allowed)
|
126
130
|
set_limiter_metrics(trace, rate_limiter.effective_rate)
|
127
131
|
|
@@ -140,6 +144,8 @@ module Datadog
|
|
140
144
|
Datadog.logger.error(
|
141
145
|
"Rule sampling failed. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
142
146
|
)
|
147
|
+
Datadog::Core::Telemetry::Logger.report(e, description: 'Rule sampling failed')
|
148
|
+
|
143
149
|
yield(trace)
|
144
150
|
end
|
145
151
|
|
@@ -9,7 +9,7 @@ module Datadog
|
|
9
9
|
# Accept all spans (100% retention).
|
10
10
|
DEFAULT_SAMPLE_RATE = 1.0
|
11
11
|
# Unlimited.
|
12
|
-
# @see Datadog::
|
12
|
+
# @see Datadog::Core::TokenBucket
|
13
13
|
DEFAULT_MAX_PER_SECOND = -1
|
14
14
|
|
15
15
|
# Sampling decision method used to come to the sampling decision for this span
|
@@ -30,7 +30,7 @@ module Datadog
|
|
30
30
|
@rate_limit = rate_limit
|
31
31
|
|
32
32
|
@sampler = Sampling::RateSampler.new(sample_rate)
|
33
|
-
@rate_limiter =
|
33
|
+
@rate_limiter = Core::TokenBucket.new(rate_limit)
|
34
34
|
end
|
35
35
|
|
36
36
|
# This method should only be invoked for spans that are part
|
@@ -54,7 +54,7 @@ module Datadog
|
|
54
54
|
def sample!(trace_op, span_op)
|
55
55
|
return :not_matched unless @matcher.match?(span_op)
|
56
56
|
|
57
|
-
if @rate_limiter.allow?
|
57
|
+
if @rate_limiter.allow? && @sampler.sample!(trace_op)
|
58
58
|
span_op.set_metric(Span::Ext::TAG_MECHANISM, Sampling::Ext::Mechanism::SPAN_SAMPLING_RATE)
|
59
59
|
span_op.set_metric(Span::Ext::TAG_RULE_RATE, @sample_rate)
|
60
60
|
span_op.set_metric(Span::Ext::TAG_MAX_PER_SECOND, @rate_limit)
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative '../core/environment/identity'
|
4
4
|
require_relative '../core/utils'
|
5
|
-
|
5
|
+
require_relative 'tracer'
|
6
6
|
require_relative 'event'
|
7
7
|
require_relative 'metadata/tagging'
|
8
8
|
require_relative 'sampling/ext'
|
@@ -75,7 +75,9 @@ module Datadog
|
|
75
75
|
metrics: nil,
|
76
76
|
trace_state: nil,
|
77
77
|
trace_state_unknown_fields: nil,
|
78
|
-
remote_parent: false
|
78
|
+
remote_parent: false,
|
79
|
+
tracer: nil
|
80
|
+
|
79
81
|
)
|
80
82
|
# Attributes
|
81
83
|
@id = id || Tracing::Utils::TraceId.next_id
|
@@ -98,6 +100,7 @@ module Datadog
|
|
98
100
|
@profiling_enabled = profiling_enabled
|
99
101
|
@trace_state = trace_state
|
100
102
|
@trace_state_unknown_fields = trace_state_unknown_fields
|
103
|
+
@tracer = tracer
|
101
104
|
|
102
105
|
# Generic tags
|
103
106
|
set_tags(tags) if tags
|
@@ -161,6 +164,23 @@ module Datadog
|
|
161
164
|
@resource || (root_span && root_span.resource)
|
162
165
|
end
|
163
166
|
|
167
|
+
# When retrieving tags or metrics we need to include root span tags for sampling purposes
|
168
|
+
def get_tag(key)
|
169
|
+
super || (root_span && root_span.get_tag(key))
|
170
|
+
end
|
171
|
+
|
172
|
+
def get_metric(key)
|
173
|
+
super || (root_span && root_span.get_metric(key))
|
174
|
+
end
|
175
|
+
|
176
|
+
def tags
|
177
|
+
all_tags = {}
|
178
|
+
all_tags.merge!(root_span&.tags || {}) if root_span
|
179
|
+
all_tags.merge!(super)
|
180
|
+
|
181
|
+
all_tags
|
182
|
+
end
|
183
|
+
|
164
184
|
# Returns true if the resource has been explicitly set
|
165
185
|
#
|
166
186
|
# @return [Boolean]
|
@@ -284,10 +304,14 @@ module Datadog
|
|
284
304
|
# Returns a set of trace headers used for continuing traces.
|
285
305
|
# Used for propagation across execution contexts.
|
286
306
|
# Data should reflect the active state of the trace.
|
307
|
+
# DEV-3.0: Sampling is a side effect of generating the digest.
|
308
|
+
# We should move the sample call to inject and right before moving to new contexts(threads, forking etc.)
|
287
309
|
def to_digest
|
288
310
|
# Resolve current span ID
|
289
311
|
span_id = @active_span && @active_span.id
|
290
312
|
span_id ||= @parent_span_id unless finished?
|
313
|
+
# sample the trace_operation with the tracer
|
314
|
+
@tracer&.sample_trace(self) unless sampling_priority
|
291
315
|
|
292
316
|
TraceDigest.new(
|
293
317
|
span_id: span_id,
|
@@ -262,6 +262,17 @@ module Datadog
|
|
262
262
|
context.activate!(trace, &block)
|
263
263
|
end
|
264
264
|
|
265
|
+
# Sample a span, tagging the trace as appropriate.
|
266
|
+
def sample_trace(trace_op)
|
267
|
+
begin
|
268
|
+
@sampler.sample!(trace_op)
|
269
|
+
rescue StandardError => e
|
270
|
+
SAMPLE_TRACE_LOG_ONLY_ONCE.run do
|
271
|
+
Datadog.logger.warn { "Failed to sample trace: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
265
276
|
# @!visibility private
|
266
277
|
# TODO: make this private
|
267
278
|
def trace_completed
|
@@ -331,12 +342,14 @@ module Datadog
|
|
331
342
|
trace_state: digest.trace_state,
|
332
343
|
trace_state_unknown_fields: digest.trace_state_unknown_fields,
|
333
344
|
remote_parent: digest.span_remote,
|
345
|
+
tracer: self
|
334
346
|
)
|
335
347
|
else
|
336
348
|
TraceOperation.new(
|
337
349
|
hostname: hostname,
|
338
350
|
profiling_enabled: profiling_enabled,
|
339
351
|
remote_parent: false,
|
352
|
+
tracer: self
|
340
353
|
)
|
341
354
|
end
|
342
355
|
end
|
@@ -347,7 +360,6 @@ module Datadog
|
|
347
360
|
events.span_before_start.subscribe do |event_span_op, event_trace_op|
|
348
361
|
event_trace_op.service ||= @default_service
|
349
362
|
event_span_op.service ||= @default_service
|
350
|
-
sample_trace(event_trace_op) if event_span_op && event_span_op.parent_id == 0
|
351
363
|
end
|
352
364
|
|
353
365
|
events.span_finished.subscribe do |event_span, event_trace_op|
|
@@ -394,7 +406,7 @@ module Datadog
|
|
394
406
|
on_error: on_error,
|
395
407
|
resource: resource,
|
396
408
|
service: service,
|
397
|
-
tags: resolve_tags(tags),
|
409
|
+
tags: resolve_tags(tags, service),
|
398
410
|
type: type,
|
399
411
|
id: id,
|
400
412
|
&block
|
@@ -408,7 +420,7 @@ module Datadog
|
|
408
420
|
resource: resource,
|
409
421
|
service: service,
|
410
422
|
start_time: start_time,
|
411
|
-
tags: resolve_tags(tags),
|
423
|
+
tags: resolve_tags(tags, service),
|
412
424
|
type: type,
|
413
425
|
id: id
|
414
426
|
)
|
@@ -420,15 +432,20 @@ module Datadog
|
|
420
432
|
end
|
421
433
|
# rubocop:enable Lint/UnderscorePrefixedVariableName
|
422
434
|
|
423
|
-
def resolve_tags(tags)
|
424
|
-
if @tags.any? && tags
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
435
|
+
def resolve_tags(tags, service)
|
436
|
+
merged_tags = if @tags.any? && tags
|
437
|
+
# Combine default tags with provided tags,
|
438
|
+
# preferring provided tags.
|
439
|
+
@tags.merge(tags)
|
440
|
+
else
|
441
|
+
# Use provided tags or default tags if none.
|
442
|
+
tags || @tags.dup
|
443
|
+
end
|
444
|
+
# Remove version tag if service is not the default service
|
445
|
+
if merged_tags.key?(Core::Environment::Ext::TAG_VERSION) && service != @default_service
|
446
|
+
merged_tags.delete(Core::Environment::Ext::TAG_VERSION)
|
431
447
|
end
|
448
|
+
merged_tags
|
432
449
|
end
|
433
450
|
|
434
451
|
# Manually activate and deactivate the trace, when the span completes.
|
@@ -463,17 +480,6 @@ module Datadog
|
|
463
480
|
end
|
464
481
|
end
|
465
482
|
|
466
|
-
# Sample a span, tagging the trace as appropriate.
|
467
|
-
def sample_trace(trace_op)
|
468
|
-
begin
|
469
|
-
@sampler.sample!(trace_op)
|
470
|
-
rescue StandardError => e
|
471
|
-
SAMPLE_TRACE_LOG_ONLY_ONCE.run do
|
472
|
-
Datadog.logger.warn { "Failed to sample trace: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
|
473
|
-
end
|
474
|
-
end
|
475
|
-
end
|
476
|
-
|
477
483
|
SAMPLE_TRACE_LOG_ONLY_ONCE = Core::Utils::OnlyOnce.new
|
478
484
|
private_constant :SAMPLE_TRACE_LOG_ONLY_ONCE
|
479
485
|
|
@@ -492,6 +498,7 @@ module Datadog
|
|
492
498
|
|
493
499
|
# Flush finished spans from the trace buffer, send them to writer.
|
494
500
|
def flush_trace(trace_op)
|
501
|
+
sample_trace(trace_op) unless trace_op.sampling_priority
|
495
502
|
begin
|
496
503
|
trace = @trace_flush.consume!(trace_op)
|
497
504
|
write(trace) if trace && !trace.empty?
|
@@ -74,6 +74,10 @@ module Datadog
|
|
74
74
|
# Add container ID, if present.
|
75
75
|
container_id = Datadog::Core::Environment::Container.container_id
|
76
76
|
headers[Datadog::Core::Transport::Ext::HTTP::HEADER_CONTAINER_ID] = container_id unless container_id.nil?
|
77
|
+
# Pretend that stats computation are already done by the client
|
78
|
+
if Datadog.configuration.appsec.standalone.enabled
|
79
|
+
headers[Datadog::Core::Transport::Ext::HTTP::HEADER_CLIENT_COMPUTED_STATS] = 'yes'
|
80
|
+
end
|
77
81
|
end
|
78
82
|
end
|
79
83
|
|
@@ -43,7 +43,7 @@ module Datadog
|
|
43
43
|
traces = process_traces(traces)
|
44
44
|
flush_traces(traces)
|
45
45
|
rescue StandardError => e
|
46
|
-
Datadog.logger.
|
46
|
+
Datadog.logger.warn(
|
47
47
|
"Error while writing traces: dropped #{traces.length} items. Cause: #{e} Location: #{Array(e.backtrace).first}"
|
48
48
|
)
|
49
49
|
end
|
@@ -56,7 +56,7 @@ module Datadog
|
|
56
56
|
# ensures that the thread will not die because of an exception.
|
57
57
|
# TODO[manu]: findout the reason and reschedule the send if it's not
|
58
58
|
# a fatal exception
|
59
|
-
Datadog.logger.
|
59
|
+
Datadog.logger.warn(
|
60
60
|
"Error during traces flush: dropped #{traces.length} items. Cause: #{e} Location: #{Array(e.backtrace).first}"
|
61
61
|
)
|
62
62
|
end
|
@@ -70,7 +70,7 @@ module Datadog
|
|
70
70
|
@run = true
|
71
71
|
Datadog.logger.debug { "Starting thread for: #{self}" }
|
72
72
|
@worker = Thread.new { perform }
|
73
|
-
@worker.name = self.class.name
|
73
|
+
@worker.name = self.class.name
|
74
74
|
@worker.thread_variable_set(:fork_safe, true)
|
75
75
|
|
76
76
|
nil
|
@@ -68,21 +68,6 @@ module Datadog
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
-
# spawns a worker for spans; they share the same transport which is thread-safe
|
72
|
-
# @!visibility private
|
73
|
-
def start_worker
|
74
|
-
@trace_handler = ->(items, transport) { send_spans(items, transport) }
|
75
|
-
@worker = Workers::AsyncTransport.new(
|
76
|
-
transport: @transport,
|
77
|
-
buffer_size: @buff_size,
|
78
|
-
on_trace: @trace_handler,
|
79
|
-
interval: @flush_interval,
|
80
|
-
shutdown_timeout: @shutdown_timeout
|
81
|
-
)
|
82
|
-
|
83
|
-
@worker.start
|
84
|
-
end
|
85
|
-
|
86
71
|
# Gracefully shuts down this writer.
|
87
72
|
#
|
88
73
|
# Once stopped methods calls won't fail, but
|
@@ -93,19 +78,6 @@ module Datadog
|
|
93
78
|
@mutex_after_fork.synchronize { stop_worker }
|
94
79
|
end
|
95
80
|
|
96
|
-
def stop_worker
|
97
|
-
@stopped = true
|
98
|
-
|
99
|
-
return if @worker.nil?
|
100
|
-
|
101
|
-
@worker.stop
|
102
|
-
@worker = nil
|
103
|
-
|
104
|
-
true
|
105
|
-
end
|
106
|
-
|
107
|
-
private :start_worker, :stop_worker
|
108
|
-
|
109
81
|
# flush spans to the trace-agent, handles spans only
|
110
82
|
# @!visibility private
|
111
83
|
def send_spans(traces, transport)
|
@@ -179,6 +151,32 @@ module Datadog
|
|
179
151
|
|
180
152
|
private
|
181
153
|
|
154
|
+
# spawns a worker for spans; they share the same transport which is thread-safe
|
155
|
+
# @!visibility private
|
156
|
+
def start_worker
|
157
|
+
@trace_handler = ->(items, transport) { send_spans(items, transport) }
|
158
|
+
@worker = Workers::AsyncTransport.new(
|
159
|
+
transport: @transport,
|
160
|
+
buffer_size: @buff_size,
|
161
|
+
on_trace: @trace_handler,
|
162
|
+
interval: @flush_interval,
|
163
|
+
shutdown_timeout: @shutdown_timeout
|
164
|
+
)
|
165
|
+
|
166
|
+
@worker.start
|
167
|
+
end
|
168
|
+
|
169
|
+
def stop_worker
|
170
|
+
@stopped = true
|
171
|
+
|
172
|
+
return if @worker.nil?
|
173
|
+
|
174
|
+
@worker.stop
|
175
|
+
@worker = nil
|
176
|
+
|
177
|
+
true
|
178
|
+
end
|
179
|
+
|
182
180
|
def reset_stats!
|
183
181
|
@traces_flushed = 0
|
184
182
|
@transport.stats.reset!
|