ddtrace 1.4.1 → 1.6.1
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 +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
|