ddtrace 1.4.1 → 1.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +144 -1
- data/LICENSE-3rdparty.csv +1 -0
- data/ext/ddtrace_profiling_loader/ddtrace_profiling_loader.c +9 -2
- data/ext/ddtrace_profiling_loader/extconf.rb +17 -0
- data/ext/ddtrace_profiling_native_extension/NativeExtensionDesign.md +38 -2
- data/ext/ddtrace_profiling_native_extension/clock_id.h +1 -0
- data/ext/ddtrace_profiling_native_extension/clock_id_from_pthread.c +1 -0
- data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.c +517 -42
- data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.h +3 -0
- data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +208 -30
- data/ext/ddtrace_profiling_native_extension/collectors_stack.c +156 -46
- data/ext/ddtrace_profiling_native_extension/collectors_stack.h +11 -2
- data/ext/ddtrace_profiling_native_extension/extconf.rb +11 -1
- data/ext/ddtrace_profiling_native_extension/http_transport.c +83 -64
- data/ext/ddtrace_profiling_native_extension/libdatadog_helpers.h +4 -4
- data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +3 -4
- data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +59 -0
- data/ext/ddtrace_profiling_native_extension/private_vm_api_access.h +3 -0
- data/ext/ddtrace_profiling_native_extension/profiling.c +10 -0
- data/ext/ddtrace_profiling_native_extension/ruby_helpers.c +0 -1
- data/ext/ddtrace_profiling_native_extension/ruby_helpers.h +4 -2
- data/ext/ddtrace_profiling_native_extension/stack_recorder.c +45 -29
- data/ext/ddtrace_profiling_native_extension/stack_recorder.h +7 -7
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +1169 -275
- data/lib/datadog/appsec/assets/waf_rules/risky.json +78 -78
- data/lib/datadog/appsec/assets/waf_rules/strict.json +278 -88
- data/lib/datadog/appsec/configuration/settings.rb +0 -2
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +25 -20
- data/lib/datadog/appsec/contrib/rack/reactive/request.rb +11 -11
- data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +11 -11
- data/lib/datadog/appsec/contrib/rack/reactive/response.rb +11 -11
- data/lib/datadog/appsec/contrib/rack/request.rb +3 -0
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +46 -19
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +7 -6
- data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/reactive/action.rb +11 -11
- data/lib/datadog/appsec/contrib/rails/request.rb +3 -0
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +14 -12
- data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +11 -11
- data/lib/datadog/appsec/event.rb +6 -10
- data/lib/datadog/appsec/instrumentation/gateway.rb +16 -2
- data/lib/datadog/appsec/processor.rb +18 -2
- data/lib/datadog/ci/ext/environment.rb +16 -4
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +0 -3
- data/lib/datadog/core/configuration/components.rb +28 -16
- data/lib/datadog/core/configuration/settings.rb +127 -8
- data/lib/datadog/core/configuration.rb +1 -1
- data/lib/datadog/core/diagnostics/environment_logger.rb +5 -1
- data/lib/datadog/core/header_collection.rb +41 -0
- data/lib/datadog/core/telemetry/collector.rb +0 -2
- data/lib/datadog/core/utils/compression.rb +5 -1
- data/lib/datadog/core/workers/async.rb +0 -2
- data/lib/datadog/core.rb +0 -54
- data/lib/datadog/opentracer/tracer.rb +4 -6
- data/lib/datadog/profiling/collectors/cpu_and_wall_time.rb +12 -2
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +5 -3
- data/lib/datadog/profiling/collectors/old_stack.rb +1 -1
- data/lib/datadog/profiling/exporter.rb +2 -4
- data/lib/datadog/profiling/http_transport.rb +1 -1
- data/lib/datadog/profiling.rb +1 -1
- data/lib/datadog/tracing/client_ip.rb +164 -0
- data/lib/datadog/tracing/configuration/ext.rb +14 -0
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +2 -0
- data/lib/datadog/tracing/contrib/aws/services.rb +0 -2
- data/lib/datadog/tracing/contrib/dalli/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +4 -0
- data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +2 -0
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +3 -0
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +2 -2
- data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +2 -0
- data/lib/datadog/tracing/contrib/excon/middleware.rb +2 -0
- data/lib/datadog/tracing/contrib/ext.rb +25 -0
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +3 -2
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +0 -2
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +5 -0
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +7 -1
- data/lib/datadog/tracing/contrib/grpc/ext.rb +2 -0
- data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +47 -0
- data/lib/datadog/tracing/contrib/hanami/configuration/settings.rb +22 -0
- data/lib/datadog/tracing/contrib/hanami/ext.rb +24 -0
- data/lib/datadog/tracing/contrib/hanami/integration.rb +44 -0
- data/lib/datadog/tracing/contrib/hanami/patcher.rb +33 -0
- data/lib/datadog/tracing/contrib/hanami/plugin.rb +23 -0
- data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +41 -0
- data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +44 -0
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +2 -0
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +2 -0
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +2 -0
- data/lib/datadog/tracing/contrib/mongodb/ext.rb +7 -0
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +4 -0
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +12 -0
- data/lib/datadog/tracing/contrib/mysql2/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +16 -0
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +12 -0
- data/lib/datadog/tracing/contrib/pg/ext.rb +2 -1
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +38 -21
- data/lib/datadog/tracing/contrib/propagation/sql_comment/comment.rb +43 -0
- data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +32 -0
- data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +28 -0
- data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +49 -0
- data/lib/datadog/tracing/contrib/rack/header_collection.rb +35 -0
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +105 -43
- data/lib/datadog/tracing/contrib/redis/ext.rb +2 -0
- data/lib/datadog/tracing/contrib/redis/instrumentation.rb +4 -2
- data/lib/datadog/tracing/contrib/redis/integration.rb +2 -1
- data/lib/datadog/tracing/contrib/redis/patcher.rb +40 -0
- data/lib/datadog/tracing/contrib/redis/tags.rb +5 -0
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +2 -0
- data/lib/datadog/tracing/contrib/sinatra/env.rb +12 -23
- data/lib/datadog/tracing/contrib/sinatra/ext.rb +7 -3
- data/lib/datadog/tracing/contrib/sinatra/patcher.rb +2 -2
- data/lib/datadog/tracing/contrib/sinatra/tracer.rb +8 -80
- data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +14 -9
- data/lib/datadog/tracing/contrib/utils/quantization/http.rb +92 -10
- data/lib/datadog/tracing/contrib.rb +1 -0
- data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +84 -0
- data/lib/datadog/tracing/distributed/headers/datadog.rb +122 -30
- data/lib/datadog/tracing/distributed/headers/ext.rb +2 -0
- data/lib/datadog/tracing/flush.rb +57 -35
- data/lib/datadog/tracing/metadata/ext.rb +11 -9
- data/lib/datadog/tracing/metadata/tagging.rb +9 -0
- data/lib/datadog/tracing/propagation/http.rb +9 -1
- data/lib/datadog/tracing/sampling/ext.rb +31 -0
- data/lib/datadog/tracing/sampling/priority_sampler.rb +46 -4
- data/lib/datadog/tracing/sampling/rate_by_key_sampler.rb +8 -9
- data/lib/datadog/tracing/sampling/rate_by_service_sampler.rb +29 -5
- data/lib/datadog/tracing/sampling/rate_limiter.rb +3 -0
- data/lib/datadog/tracing/sampling/rate_sampler.rb +20 -3
- data/lib/datadog/tracing/sampling/rule_sampler.rb +4 -3
- data/lib/datadog/tracing/sampling/span/ext.rb +25 -0
- data/lib/datadog/tracing/sampling/span/matcher.rb +9 -0
- data/lib/datadog/tracing/sampling/span/rule.rb +82 -0
- data/lib/datadog/tracing/sampling/span/rule_parser.rb +104 -0
- data/lib/datadog/tracing/sampling/span/sampler.rb +75 -0
- data/lib/datadog/tracing/span_operation.rb +0 -2
- data/lib/datadog/tracing/trace_digest.rb +3 -0
- data/lib/datadog/tracing/trace_operation.rb +32 -3
- data/lib/datadog/tracing/trace_segment.rb +7 -2
- data/lib/datadog/tracing/tracer.rb +34 -6
- data/lib/datadog/tracing/writer.rb +7 -0
- data/lib/ddtrace/transport/trace_formatter.rb +7 -0
- data/lib/ddtrace/transport/traces.rb +3 -1
- data/lib/ddtrace/version.rb +1 -1
- metadata +36 -18
- data/lib/datadog/profiling/old_ext.rb +0 -42
- data/lib/datadog/profiling/transport/http/api/endpoint.rb +0 -85
- data/lib/datadog/profiling/transport/http/api/instance.rb +0 -38
- data/lib/datadog/profiling/transport/http/api/spec.rb +0 -42
- data/lib/datadog/profiling/transport/http/api.rb +0 -45
- data/lib/datadog/profiling/transport/http/builder.rb +0 -30
- data/lib/datadog/profiling/transport/http/client.rb +0 -37
- data/lib/datadog/profiling/transport/http/response.rb +0 -21
- data/lib/datadog/profiling/transport/http.rb +0 -118
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
require_relative 'ext'
|
6
|
+
require_relative 'matcher'
|
7
|
+
require_relative 'rule'
|
8
|
+
|
9
|
+
module Datadog
|
10
|
+
module Tracing
|
11
|
+
module Sampling
|
12
|
+
module Span
|
13
|
+
# Converts user configuration into {Datadog::Tracing::Sampling::Span::Rule} objects,
|
14
|
+
# handling any parsing errors.
|
15
|
+
module RuleParser
|
16
|
+
class << self
|
17
|
+
# Parses the provided JSON string containing the Single Span
|
18
|
+
# Sampling configuration list.
|
19
|
+
# In case of parsing errors, `nil` is returned.
|
20
|
+
#
|
21
|
+
# @param rules [String] the JSON configuration rules to be parsed
|
22
|
+
# @return [Array<Datadog::Tracing::Sampling::Span::Rule>] a list of parsed rules
|
23
|
+
# @return [nil] if parsing failed
|
24
|
+
def parse_json(rules)
|
25
|
+
return nil unless rules
|
26
|
+
|
27
|
+
begin
|
28
|
+
list = JSON.parse(rules)
|
29
|
+
rescue => e
|
30
|
+
Datadog.logger.warn(
|
31
|
+
"Error parsing Span Sampling Rules `#{rules.inspect}`: "\
|
32
|
+
"#{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
|
33
|
+
)
|
34
|
+
return nil
|
35
|
+
end
|
36
|
+
|
37
|
+
parse_list(list)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Parses a list of Hashes containing the parsed JSON information
|
41
|
+
# for Single Span Sampling configuration.
|
42
|
+
# In case of parsing errors, `nil` is returned.
|
43
|
+
#
|
44
|
+
# @param rules [Array<String] the JSON configuration rules to be parsed
|
45
|
+
# @return [Array<Datadog::Tracing::Sampling::Span::Rule>] a list of parsed rules
|
46
|
+
# @return [nil] if parsing failed
|
47
|
+
def parse_list(rules)
|
48
|
+
unless rules.is_a?(Array)
|
49
|
+
Datadog.logger.warn("Span Sampling Rules are not an array: #{rules.inspect}")
|
50
|
+
return nil
|
51
|
+
end
|
52
|
+
|
53
|
+
parsed = rules.map do |hash|
|
54
|
+
unless hash.is_a?(Hash)
|
55
|
+
Datadog.logger.warn("Span Sampling Rule is not a key-value object: #{hash.inspect}")
|
56
|
+
return nil
|
57
|
+
end
|
58
|
+
|
59
|
+
begin
|
60
|
+
parse_rule(hash)
|
61
|
+
rescue => e
|
62
|
+
Datadog.logger.warn(
|
63
|
+
"Cannot parse Span Sampling Rule #{hash.inspect}: " \
|
64
|
+
"#{e.class.name} #{e} at #{Array(e.backtrace).first}"
|
65
|
+
)
|
66
|
+
return nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
parsed.compact!
|
71
|
+
parsed
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def parse_rule(hash)
|
77
|
+
matcher_options = {}
|
78
|
+
if (name_pattern = hash['name'])
|
79
|
+
matcher_options[:name_pattern] = name_pattern
|
80
|
+
end
|
81
|
+
|
82
|
+
if (service_pattern = hash['service'])
|
83
|
+
matcher_options[:service_pattern] = service_pattern
|
84
|
+
end
|
85
|
+
|
86
|
+
matcher = Matcher.new(**matcher_options)
|
87
|
+
|
88
|
+
rule_options = {}
|
89
|
+
if (sample_rate = hash['sample_rate'])
|
90
|
+
rule_options[:sample_rate] = sample_rate
|
91
|
+
end
|
92
|
+
|
93
|
+
if (max_per_second = hash['max_per_second'])
|
94
|
+
rule_options[:rate_limit] = max_per_second
|
95
|
+
end
|
96
|
+
|
97
|
+
Rule.new(matcher, **rule_options)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Datadog
|
2
|
+
module Tracing
|
3
|
+
module Sampling
|
4
|
+
module Span
|
5
|
+
# Applies Single Span Sampling rules to spans.
|
6
|
+
# When matching the configured rules, a span is ensured to
|
7
|
+
# be processed Datadog App. In other words, a single sampled span
|
8
|
+
# will never be dropped by the tracer or Datadog agent.
|
9
|
+
#
|
10
|
+
# All spans in a trace are subject to the single sampling rules, if
|
11
|
+
# any rules are configured.
|
12
|
+
#
|
13
|
+
# Single Span Sampling is distinct from trace-level sampling:
|
14
|
+
# Single Span Sampling can ensure a span is kept, even if its
|
15
|
+
# enclosing trace is rejected by trace-level sampling.
|
16
|
+
#
|
17
|
+
# This class only applies operations to spans that are part
|
18
|
+
# of traces that was rejected by trace sampling.
|
19
|
+
# A trace is rejected if either of the following conditions is true:
|
20
|
+
# * The priority sampling for a trace is set to either {USER_REJECT} or {AUTO_REJECT}.
|
21
|
+
# * The trace was rejected by internal sampling, thus never flushed.
|
22
|
+
#
|
23
|
+
# Single-sampled spans are tagged and the tracer ensures they will
|
24
|
+
# reach the Datadog App, regardless of their enclosing trace sampling decision.
|
25
|
+
#
|
26
|
+
# Single Span Sampling does not inspect spans that are part of a trace
|
27
|
+
# that has been accepted by trace-level sampling rules: all spans from such
|
28
|
+
# trace are guaranteed to reach the Datadog App.
|
29
|
+
class Sampler
|
30
|
+
attr_reader :rules
|
31
|
+
|
32
|
+
# Receives sampling rules to apply to individual spans.
|
33
|
+
#
|
34
|
+
# @param [Array<Datadog::Tracing::Sampling::Span::Rule>] rules list of rules to apply to spans
|
35
|
+
def initialize(rules = [])
|
36
|
+
@rules = rules
|
37
|
+
end
|
38
|
+
|
39
|
+
# Applies Single Span Sampling rules to the span if the trace has been rejected.
|
40
|
+
#
|
41
|
+
# The trace can be outright rejected, and never reach the transport,
|
42
|
+
# or be set as rejected by priority sampling. In both cases, the trace
|
43
|
+
# is considered rejected for Single Span Sampling purposes.
|
44
|
+
#
|
45
|
+
# If multiple rules match, only the first one is applied.
|
46
|
+
#
|
47
|
+
# @param [Datadog::Tracing::TraceOperation] trace_op trace for the provided span
|
48
|
+
# @param [Datadog::Tracing::SpanOperation] span_op Span to apply sampling rules
|
49
|
+
# @return [void]
|
50
|
+
def sample!(trace_op, span_op)
|
51
|
+
return if trace_op.sampled? && trace_op.priority_sampled?
|
52
|
+
|
53
|
+
# Applies the first matching rule
|
54
|
+
@rules.each do |rule|
|
55
|
+
decision = rule.sample!(span_op)
|
56
|
+
|
57
|
+
next if decision == :not_matched # Iterate until we find a matching decision
|
58
|
+
|
59
|
+
if decision == :kept
|
60
|
+
trace_op.set_tag(
|
61
|
+
Metadata::Ext::Distributed::TAG_DECISION_MAKER,
|
62
|
+
Sampling::Ext::Decision::SPAN_SAMPLING_RATE
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
break # Found either a `kept` or `rejected` decision
|
67
|
+
end
|
68
|
+
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -18,7 +18,6 @@ module Datadog
|
|
18
18
|
# It gives a Span a context which can be used to
|
19
19
|
# build a Span. When completed, it yields the Span.
|
20
20
|
#
|
21
|
-
# rubocop:disable Metrics/ClassLength
|
22
21
|
# @public_api
|
23
22
|
class SpanOperation
|
24
23
|
include Metadata
|
@@ -516,6 +515,5 @@ module Datadog
|
|
516
515
|
alias :span_type :type
|
517
516
|
alias :span_type= :type=
|
518
517
|
end
|
519
|
-
# rubocop:enable Metrics/ClassLength
|
520
518
|
end
|
521
519
|
end
|
@@ -12,6 +12,7 @@ module Datadog
|
|
12
12
|
:span_resource,
|
13
13
|
:span_service,
|
14
14
|
:span_type,
|
15
|
+
:trace_distributed_tags,
|
15
16
|
:trace_hostname,
|
16
17
|
:trace_id,
|
17
18
|
:trace_name,
|
@@ -28,6 +29,7 @@ module Datadog
|
|
28
29
|
span_resource: nil,
|
29
30
|
span_service: nil,
|
30
31
|
span_type: nil,
|
32
|
+
trace_distributed_tags: nil,
|
31
33
|
trace_hostname: nil,
|
32
34
|
trace_id: nil,
|
33
35
|
trace_name: nil,
|
@@ -43,6 +45,7 @@ module Datadog
|
|
43
45
|
@span_resource = span_resource && span_resource.dup.freeze
|
44
46
|
@span_service = span_service && span_service.dup.freeze
|
45
47
|
@span_type = span_type && span_type.dup.freeze
|
48
|
+
@trace_distributed_tags = trace_distributed_tags && trace_distributed_tags.dup.freeze
|
46
49
|
@trace_hostname = trace_hostname && trace_hostname.dup.freeze
|
47
50
|
@trace_id = trace_id
|
48
51
|
@trace_name = trace_name && trace_name.dup.freeze
|
@@ -22,7 +22,6 @@ module Datadog
|
|
22
22
|
# For async support, a {Datadog::Tracing::TraceOperation} should be employed
|
23
23
|
# per execution context (e.g. Thread, etc.)
|
24
24
|
#
|
25
|
-
# rubocop:disable Metrics/ClassLength
|
26
25
|
# @public_api
|
27
26
|
class TraceOperation
|
28
27
|
include Metadata::Tagging
|
@@ -113,18 +112,34 @@ module Datadog
|
|
113
112
|
@finished == true
|
114
113
|
end
|
115
114
|
|
115
|
+
# Will this trace be flushed by the tracer transport?
|
116
|
+
# This includes cases where the span is kept solely due to priority sampling.
|
117
|
+
#
|
118
|
+
# This is not the ultimate Datadog App sampling decision. Downstream systems
|
119
|
+
# can decide to reject this trace, especially for cases where priority
|
120
|
+
# sampling is set to AUTO_KEEP.
|
121
|
+
#
|
122
|
+
# @return [Boolean]
|
116
123
|
def sampled?
|
117
|
-
@sampled == true ||
|
124
|
+
@sampled == true || priority_sampled?
|
125
|
+
end
|
126
|
+
|
127
|
+
# Has the priority sampling chosen to keep this span?
|
128
|
+
# @return [Boolean]
|
129
|
+
def priority_sampled?
|
130
|
+
!@sampling_priority.nil? && @sampling_priority > 0
|
118
131
|
end
|
119
132
|
|
120
133
|
def keep!
|
121
134
|
self.sampled = true
|
122
135
|
self.sampling_priority = Sampling::Ext::Priority::USER_KEEP
|
136
|
+
set_tag(Tracing::Metadata::Ext::Distributed::TAG_DECISION_MAKER, Tracing::Sampling::Ext::Decision::MANUAL)
|
123
137
|
end
|
124
138
|
|
125
139
|
def reject!
|
126
140
|
self.sampled = false
|
127
141
|
self.sampling_priority = Sampling::Ext::Priority::USER_REJECT
|
142
|
+
set_tag(Tracing::Metadata::Ext::Distributed::TAG_DECISION_MAKER, Tracing::Sampling::Ext::Decision::MANUAL)
|
128
143
|
end
|
129
144
|
|
130
145
|
def name
|
@@ -233,6 +248,11 @@ module Datadog
|
|
233
248
|
end
|
234
249
|
end
|
235
250
|
|
251
|
+
# Returns a {TraceSegment} with all finished spans that can be flushed
|
252
|
+
# at invocation time. All other **finished** spans are discarded.
|
253
|
+
#
|
254
|
+
# @yield [spans] spans that will be returned as part of the trace segment returned
|
255
|
+
# @return [TraceSegment]
|
236
256
|
def flush!
|
237
257
|
finished = finished?
|
238
258
|
|
@@ -240,6 +260,8 @@ module Datadog
|
|
240
260
|
spans = @spans.dup
|
241
261
|
@spans = []
|
242
262
|
|
263
|
+
spans = yield(spans) if block_given?
|
264
|
+
|
243
265
|
# Use them to build a trace
|
244
266
|
build_trace(spans, !finished)
|
245
267
|
end
|
@@ -258,6 +280,7 @@ module Datadog
|
|
258
280
|
span_resource: (@active_span && @active_span.resource),
|
259
281
|
span_service: (@active_span && @active_span.service),
|
260
282
|
span_type: (@active_span && @active_span.type),
|
283
|
+
trace_distributed_tags: distributed_tags,
|
261
284
|
trace_hostname: @hostname,
|
262
285
|
trace_id: @id,
|
263
286
|
trace_name: name,
|
@@ -432,7 +455,13 @@ module Datadog
|
|
432
455
|
root_span_id: !partial ? root_span && root_span.id : nil
|
433
456
|
)
|
434
457
|
end
|
458
|
+
|
459
|
+
# Returns tracer tags that will be propagated if this span's context
|
460
|
+
# is exported through {.to_digest}.
|
461
|
+
# @return [Hash] key value pairs of distributed tags
|
462
|
+
def distributed_tags
|
463
|
+
meta.select { |name, _| name.start_with?(Metadata::Ext::Distributed::TAGS_PREFIX) }
|
464
|
+
end
|
435
465
|
end
|
436
|
-
# rubocop:enable Metrics/ClassLength
|
437
466
|
end
|
438
467
|
end
|
@@ -11,7 +11,6 @@ module Datadog
|
|
11
11
|
module Tracing
|
12
12
|
# Serializable construct representing a trace
|
13
13
|
# @public_api
|
14
|
-
# rubocop:disable Metrics/ClassLength
|
15
14
|
class TraceSegment
|
16
15
|
TAG_NAME = 'name'.freeze
|
17
16
|
TAG_RESOURCE = 'resource'.freeze
|
@@ -31,11 +30,13 @@ module Datadog
|
|
31
30
|
:rule_sample_rate,
|
32
31
|
:runtime_id,
|
33
32
|
:sample_rate,
|
33
|
+
:sampling_decision_maker,
|
34
34
|
:sampling_priority,
|
35
35
|
:service
|
36
36
|
|
37
37
|
# rubocop:disable Metrics/CyclomaticComplexity
|
38
38
|
# rubocop:disable Metrics/PerceivedComplexity
|
39
|
+
# @param spans [Array<Datadog::Span>]
|
39
40
|
def initialize(
|
40
41
|
spans,
|
41
42
|
agent_sample_rate: nil,
|
@@ -77,6 +78,7 @@ module Datadog
|
|
77
78
|
@rule_sample_rate = rule_sample_rate_tag || rule_sample_rate
|
78
79
|
@runtime_id = runtime_id || runtime_id_tag
|
79
80
|
@sample_rate = sample_rate || sample_rate_tag
|
81
|
+
@sampling_decision_maker = sampling_decision_maker_tag
|
80
82
|
@sampling_priority = sampling_priority || sampling_priority_tag
|
81
83
|
@service = Core::Utils::SafeDup.frozen_or_dup(service || service_tag)
|
82
84
|
end
|
@@ -194,6 +196,10 @@ module Datadog
|
|
194
196
|
metrics[Metadata::Ext::Sampling::TAG_SAMPLE_RATE]
|
195
197
|
end
|
196
198
|
|
199
|
+
def sampling_decision_maker_tag
|
200
|
+
meta[Metadata::Ext::Distributed::TAG_DECISION_MAKER]
|
201
|
+
end
|
202
|
+
|
197
203
|
def sampling_priority_tag
|
198
204
|
meta[Metadata::Ext::Distributed::TAG_SAMPLING_PRIORITY]
|
199
205
|
end
|
@@ -202,6 +208,5 @@ module Datadog
|
|
202
208
|
meta[TAG_SERVICE]
|
203
209
|
end
|
204
210
|
end
|
205
|
-
# rubocop:enable Metrics/ClassLength
|
206
211
|
end
|
207
212
|
end
|
@@ -11,6 +11,7 @@ require_relative 'context_provider'
|
|
11
11
|
require_relative 'sampling/all_sampler'
|
12
12
|
require_relative 'sampling/rule_sampler'
|
13
13
|
require_relative 'sampling/priority_sampler'
|
14
|
+
require_relative 'sampling/span/sampler'
|
14
15
|
require_relative 'span_operation'
|
15
16
|
require_relative 'trace_digest'
|
16
17
|
require_relative 'trace_operation'
|
@@ -22,12 +23,12 @@ module Datadog
|
|
22
23
|
# example, a trace can be used to track the entire time spent processing a complicated web request.
|
23
24
|
# Even though the request may require multiple resources and machines to handle the request, all
|
24
25
|
# of these function calls and sub-requests would be encapsulated within a single trace.
|
25
|
-
# rubocop:disable Metrics/ClassLength
|
26
26
|
class Tracer
|
27
27
|
attr_reader \
|
28
28
|
:trace_flush,
|
29
29
|
:provider,
|
30
30
|
:sampler,
|
31
|
+
:span_sampler,
|
31
32
|
:tags
|
32
33
|
|
33
34
|
attr_accessor \
|
@@ -56,6 +57,7 @@ module Datadog
|
|
56
57
|
base_sampler: Sampling::AllSampler.new,
|
57
58
|
post_sampler: Sampling::RuleSampler.new
|
58
59
|
),
|
60
|
+
span_sampler: Sampling::Span::Sampler.new,
|
59
61
|
tags: {},
|
60
62
|
writer: Writer.new
|
61
63
|
)
|
@@ -64,6 +66,7 @@ module Datadog
|
|
64
66
|
@enabled = enabled
|
65
67
|
@provider = context_provider
|
66
68
|
@sampler = sampler
|
69
|
+
@span_sampler = span_sampler
|
67
70
|
@tags = tags
|
68
71
|
@writer = writer
|
69
72
|
end
|
@@ -323,7 +326,9 @@ module Datadog
|
|
323
326
|
id: digest.trace_id,
|
324
327
|
origin: digest.trace_origin,
|
325
328
|
parent_span_id: digest.span_id,
|
326
|
-
sampling_priority: digest.trace_sampling_priority
|
329
|
+
sampling_priority: digest.trace_sampling_priority,
|
330
|
+
# Distributed tags are just regular trace tags with special meaning to Datadog
|
331
|
+
tags: digest.trace_distributed_tags,
|
327
332
|
)
|
328
333
|
else
|
329
334
|
TraceOperation.new(
|
@@ -341,7 +346,8 @@ module Datadog
|
|
341
346
|
sample_trace(event_trace_op) if event_span_op && event_span_op.parent_id == 0
|
342
347
|
end
|
343
348
|
|
344
|
-
events.span_finished.subscribe do |
|
349
|
+
events.span_finished.subscribe do |event_span, event_trace_op|
|
350
|
+
sample_span(event_trace_op, event_span)
|
345
351
|
flush_trace(event_trace_op)
|
346
352
|
end
|
347
353
|
end
|
@@ -461,20 +467,43 @@ module Datadog
|
|
461
467
|
begin
|
462
468
|
@sampler.sample!(trace_op)
|
463
469
|
rescue StandardError => e
|
464
|
-
|
470
|
+
SAMPLE_TRACE_LOG_ONLY_ONCE.run do
|
471
|
+
Datadog.logger.warn { "Failed to sample trace: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
|
472
|
+
end
|
465
473
|
end
|
466
474
|
end
|
467
475
|
|
476
|
+
SAMPLE_TRACE_LOG_ONLY_ONCE = Core::Utils::OnlyOnce.new
|
477
|
+
private_constant :SAMPLE_TRACE_LOG_ONLY_ONCE
|
478
|
+
|
479
|
+
def sample_span(trace_op, span)
|
480
|
+
begin
|
481
|
+
@span_sampler.sample!(trace_op, span)
|
482
|
+
rescue StandardError => e
|
483
|
+
SAMPLE_SPAN_LOG_ONLY_ONCE.run do
|
484
|
+
Datadog.logger.warn { "Failed to sample span: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
|
485
|
+
end
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
SAMPLE_SPAN_LOG_ONLY_ONCE = Core::Utils::OnlyOnce.new
|
490
|
+
private_constant :SAMPLE_SPAN_LOG_ONLY_ONCE
|
491
|
+
|
468
492
|
# Flush finished spans from the trace buffer, send them to writer.
|
469
493
|
def flush_trace(trace_op)
|
470
494
|
begin
|
471
495
|
trace = @trace_flush.consume!(trace_op)
|
472
496
|
write(trace) if trace && !trace.empty?
|
473
497
|
rescue StandardError => e
|
474
|
-
|
498
|
+
FLUSH_TRACE_LOG_ONLY_ONCE.run do
|
499
|
+
Datadog.logger.warn { "Failed to flush trace: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
|
500
|
+
end
|
475
501
|
end
|
476
502
|
end
|
477
503
|
|
504
|
+
FLUSH_TRACE_LOG_ONLY_ONCE = Core::Utils::OnlyOnce.new
|
505
|
+
private_constant :FLUSH_TRACE_LOG_ONLY_ONCE
|
506
|
+
|
478
507
|
# Send the trace to the writer to enqueue the spans list in the agent
|
479
508
|
# sending queue.
|
480
509
|
def write(trace)
|
@@ -500,6 +529,5 @@ module Datadog
|
|
500
529
|
end
|
501
530
|
end
|
502
531
|
end
|
503
|
-
# rubocop:enable Metrics/ClassLength
|
504
532
|
end
|
505
533
|
end
|
@@ -48,6 +48,7 @@ module Datadog
|
|
48
48
|
tag_runtime_id!
|
49
49
|
tag_rate_limiter_rate!
|
50
50
|
tag_sample_rate!
|
51
|
+
tag_sampling_decision_maker!
|
51
52
|
tag_sampling_priority!
|
52
53
|
|
53
54
|
trace
|
@@ -155,6 +156,12 @@ module Datadog
|
|
155
156
|
)
|
156
157
|
end
|
157
158
|
|
159
|
+
def tag_sampling_decision_maker!
|
160
|
+
return unless (decision = trace.sampling_decision_maker)
|
161
|
+
|
162
|
+
root_span.set_tag(Tracing::Metadata::Ext::Distributed::TAG_DECISION_MAKER, decision)
|
163
|
+
end
|
164
|
+
|
158
165
|
def tag_sampling_priority!
|
159
166
|
return unless trace.sampling_priority
|
160
167
|
|
@@ -80,7 +80,7 @@ module Datadog
|
|
80
80
|
|
81
81
|
if encoded.size > max_size
|
82
82
|
# This single trace is too large, we can't flush it
|
83
|
-
Datadog.logger.debug { "Dropping trace. Payload too large: '#{trace.
|
83
|
+
Datadog.logger.debug { "Dropping trace. Payload too large: '#{trace.inspect}'" }
|
84
84
|
Datadog.health_metrics.transport_trace_too_large(1)
|
85
85
|
|
86
86
|
return nil
|
@@ -101,6 +101,8 @@ module Datadog
|
|
101
101
|
# Make the trace serializable
|
102
102
|
serializable_trace = SerializableTrace.new(trace)
|
103
103
|
|
104
|
+
Datadog.logger.debug { "Flushing trace: #{JSON.dump(serializable_trace)}" }
|
105
|
+
|
104
106
|
# Encode the trace
|
105
107
|
encoder.encode(serializable_trace)
|
106
108
|
end
|