ddtrace 0.36.0 → 0.41.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +59 -1
- data/.gitignore +2 -0
- data/.gitlab-ci.yml +27 -0
- data/.simplecov +38 -0
- data/Appraisals +131 -6
- data/CHANGELOG.md +198 -1
- data/Rakefile +504 -467
- data/ddtrace.gemspec +7 -0
- data/docker-compose.yml +2 -2
- data/docs/DevelopmentGuide.md +16 -0
- data/docs/GettingStarted.md +192 -111
- data/lib/ddtrace.rb +4 -0
- data/lib/ddtrace/buffer.rb +154 -43
- data/lib/ddtrace/configuration.rb +39 -5
- data/lib/ddtrace/configuration/components.rb +4 -7
- data/lib/ddtrace/configuration/options.rb +3 -1
- data/lib/ddtrace/configuration/pin_setup.rb +3 -2
- data/lib/ddtrace/configuration/settings.rb +32 -4
- data/lib/ddtrace/contrib/action_cable/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/action_cable/ext.rb +5 -2
- data/lib/ddtrace/contrib/action_pack/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/action_pack/ext.rb +5 -2
- data/lib/ddtrace/contrib/action_view/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/action_view/ext.rb +5 -2
- data/lib/ddtrace/contrib/active_model_serializers/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/active_model_serializers/ext.rb +5 -2
- data/lib/ddtrace/contrib/active_record/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/active_record/events/sql.rb +4 -0
- data/lib/ddtrace/contrib/active_record/ext.rb +5 -2
- data/lib/ddtrace/contrib/active_support/cache/redis.rb +1 -1
- data/lib/ddtrace/contrib/active_support/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/active_support/ext.rb +5 -2
- data/lib/ddtrace/contrib/active_support/notifications/event.rb +3 -1
- data/lib/ddtrace/contrib/active_support/notifications/subscription.rb +3 -3
- data/lib/ddtrace/contrib/aws/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/aws/ext.rb +5 -2
- data/lib/ddtrace/contrib/aws/instrumentation.rb +4 -0
- data/lib/ddtrace/contrib/concurrent_ruby/configuration/settings.rb +5 -0
- data/lib/ddtrace/contrib/concurrent_ruby/context_composite_executor_service.rb +9 -3
- data/lib/ddtrace/contrib/concurrent_ruby/ext.rb +1 -0
- data/lib/ddtrace/contrib/configuration/settings.rb +19 -0
- data/lib/ddtrace/contrib/dalli/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/dalli/ext.rb +5 -2
- data/lib/ddtrace/contrib/dalli/instrumentation.rb +4 -0
- data/lib/ddtrace/contrib/dalli/patcher.rb +1 -5
- data/lib/ddtrace/contrib/delayed_job/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/delayed_job/ext.rb +5 -2
- data/lib/ddtrace/contrib/elasticsearch/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/elasticsearch/ext.rb +5 -2
- data/lib/ddtrace/contrib/elasticsearch/patcher.rb +5 -2
- data/lib/ddtrace/contrib/ethon/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/ethon/easy_patch.rb +4 -2
- data/lib/ddtrace/contrib/ethon/ext.rb +5 -2
- data/lib/ddtrace/contrib/ethon/multi_patch.rb +4 -0
- data/lib/ddtrace/contrib/excon/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/excon/ext.rb +5 -2
- data/lib/ddtrace/contrib/excon/middleware.rb +4 -0
- data/lib/ddtrace/contrib/extensions.rb +11 -1
- data/lib/ddtrace/contrib/faraday/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/faraday/ext.rb +5 -2
- data/lib/ddtrace/contrib/faraday/middleware.rb +9 -3
- data/lib/ddtrace/contrib/faraday/patcher.rb +13 -5
- data/lib/ddtrace/contrib/grape/configuration/settings.rb +7 -3
- data/lib/ddtrace/contrib/grape/endpoint.rb +6 -4
- data/lib/ddtrace/contrib/grape/ext.rb +5 -2
- data/lib/ddtrace/contrib/grape/patcher.rb +1 -1
- data/lib/ddtrace/contrib/graphql/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/graphql/ext.rb +5 -2
- data/lib/ddtrace/contrib/graphql/patcher.rb +6 -3
- data/lib/ddtrace/contrib/grpc/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/grpc/datadog_interceptor.rb +1 -1
- data/lib/ddtrace/contrib/grpc/datadog_interceptor/client.rb +5 -3
- data/lib/ddtrace/contrib/grpc/datadog_interceptor/server.rb +4 -0
- data/lib/ddtrace/contrib/grpc/ext.rb +5 -2
- data/lib/ddtrace/contrib/grpc/patcher.rb +1 -5
- data/lib/ddtrace/contrib/http/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/http/ext.rb +5 -2
- data/lib/ddtrace/contrib/http/instrumentation.rb +16 -7
- data/lib/ddtrace/contrib/httprb/configuration/settings.rb +32 -0
- data/lib/ddtrace/contrib/httprb/ext.rb +17 -0
- data/lib/ddtrace/contrib/httprb/instrumentation.rb +163 -0
- data/lib/ddtrace/contrib/httprb/integration.rb +43 -0
- data/lib/ddtrace/contrib/httprb/patcher.rb +35 -0
- data/lib/ddtrace/contrib/kafka/configuration/settings.rb +30 -0
- data/lib/ddtrace/contrib/kafka/consumer_event.rb +14 -0
- data/lib/ddtrace/contrib/kafka/consumer_group_event.rb +14 -0
- data/lib/ddtrace/contrib/kafka/event.rb +51 -0
- data/lib/ddtrace/contrib/kafka/events.rb +44 -0
- data/lib/ddtrace/contrib/kafka/events/connection/request.rb +34 -0
- data/lib/ddtrace/contrib/kafka/events/consumer/process_batch.rb +41 -0
- data/lib/ddtrace/contrib/kafka/events/consumer/process_message.rb +39 -0
- data/lib/ddtrace/contrib/kafka/events/consumer_group/heartbeat.rb +39 -0
- data/lib/ddtrace/contrib/kafka/events/consumer_group/join_group.rb +29 -0
- data/lib/ddtrace/contrib/kafka/events/consumer_group/leave_group.rb +29 -0
- data/lib/ddtrace/contrib/kafka/events/consumer_group/sync_group.rb +29 -0
- data/lib/ddtrace/contrib/kafka/events/produce_operation/send_messages.rb +32 -0
- data/lib/ddtrace/contrib/kafka/events/producer/deliver_messages.rb +35 -0
- data/lib/ddtrace/contrib/kafka/ext.rb +41 -0
- data/lib/ddtrace/contrib/kafka/integration.rb +39 -0
- data/lib/ddtrace/contrib/kafka/patcher.rb +26 -0
- data/lib/ddtrace/contrib/mongodb/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/mongodb/ext.rb +5 -2
- data/lib/ddtrace/contrib/mongodb/instrumentation.rb +1 -2
- data/lib/ddtrace/contrib/mongodb/subscribers.rb +4 -0
- data/lib/ddtrace/contrib/mysql2/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/mysql2/ext.rb +5 -2
- data/lib/ddtrace/contrib/mysql2/instrumentation.rb +5 -1
- data/lib/ddtrace/contrib/patcher.rb +14 -8
- data/lib/ddtrace/contrib/presto/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/presto/ext.rb +5 -2
- data/lib/ddtrace/contrib/presto/instrumentation.rb +3 -0
- data/lib/ddtrace/contrib/que/configuration/settings.rb +42 -0
- data/lib/ddtrace/contrib/que/ext.rb +30 -0
- data/lib/ddtrace/contrib/que/integration.rb +42 -0
- data/lib/ddtrace/contrib/que/patcher.rb +24 -0
- data/lib/ddtrace/contrib/que/tracer.rb +56 -0
- data/lib/ddtrace/contrib/racecar/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/racecar/event.rb +4 -0
- data/lib/ddtrace/contrib/racecar/events.rb +2 -0
- data/lib/ddtrace/contrib/racecar/events/consume.rb +27 -0
- data/lib/ddtrace/contrib/racecar/ext.rb +6 -2
- data/lib/ddtrace/contrib/rack/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/rack/ext.rb +5 -2
- data/lib/ddtrace/contrib/rack/middlewares.rb +17 -12
- data/lib/ddtrace/contrib/rails/configuration/settings.rb +10 -12
- data/lib/ddtrace/contrib/rails/ext.rb +6 -2
- data/lib/ddtrace/contrib/rails/framework.rb +14 -21
- data/lib/ddtrace/contrib/rails/log_injection.rb +81 -0
- data/lib/ddtrace/contrib/rails/middlewares.rb +7 -2
- data/lib/ddtrace/contrib/rails/patcher.rb +15 -0
- data/lib/ddtrace/contrib/rake/configuration/settings.rb +7 -3
- data/lib/ddtrace/contrib/rake/ext.rb +5 -2
- data/lib/ddtrace/contrib/redis/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/redis/ext.rb +5 -2
- data/lib/ddtrace/contrib/redis/patcher.rb +1 -1
- data/lib/ddtrace/contrib/redis/tags.rb +4 -0
- data/lib/ddtrace/contrib/resque/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/resque/ext.rb +5 -2
- data/lib/ddtrace/contrib/rest_client/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/rest_client/ext.rb +5 -2
- data/lib/ddtrace/contrib/rest_client/request_patch.rb +6 -2
- data/lib/ddtrace/contrib/sequel/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/sequel/database.rb +4 -2
- data/lib/ddtrace/contrib/sequel/dataset.rb +3 -2
- data/lib/ddtrace/contrib/sequel/ext.rb +6 -2
- data/lib/ddtrace/contrib/sequel/utils.rb +35 -6
- data/lib/ddtrace/contrib/shoryuken/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/shoryuken/ext.rb +5 -2
- data/lib/ddtrace/contrib/sidekiq/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/sidekiq/ext.rb +6 -2
- data/lib/ddtrace/contrib/sidekiq/patcher.rb +8 -1
- data/lib/ddtrace/contrib/sidekiq/server_tracer.rb +1 -0
- data/lib/ddtrace/contrib/sinatra/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/sinatra/env.rb +5 -4
- data/lib/ddtrace/contrib/sinatra/ext.rb +5 -2
- data/lib/ddtrace/contrib/sinatra/tracer.rb +21 -42
- data/lib/ddtrace/contrib/sinatra/tracer_middleware.rb +50 -23
- data/lib/ddtrace/contrib/sneakers/configuration/settings.rb +32 -0
- data/lib/ddtrace/contrib/sneakers/ext.rb +22 -0
- data/lib/ddtrace/contrib/sneakers/integration.rb +41 -0
- data/lib/ddtrace/contrib/sneakers/patcher.rb +24 -0
- data/lib/ddtrace/contrib/sneakers/tracer.rb +58 -0
- data/lib/ddtrace/contrib/sucker_punch/configuration/settings.rb +7 -2
- data/lib/ddtrace/contrib/sucker_punch/ext.rb +5 -2
- data/lib/ddtrace/contrib/sucker_punch/patcher.rb +1 -1
- data/lib/ddtrace/diagnostics/environment_logger.rb +278 -0
- data/lib/ddtrace/environment.rb +17 -3
- data/lib/ddtrace/ext/diagnostics.rb +3 -0
- data/lib/ddtrace/ext/environment.rb +2 -0
- data/lib/ddtrace/ext/integration.rb +8 -0
- data/lib/ddtrace/ext/runtime.rb +1 -0
- data/lib/ddtrace/ext/transport.rb +1 -0
- data/lib/ddtrace/logger.rb +1 -1
- data/lib/ddtrace/opentracer/distributed_headers.rb +1 -1
- data/lib/ddtrace/pin.rb +25 -2
- data/lib/ddtrace/pipeline/span_filter.rb +15 -15
- data/lib/ddtrace/propagation/grpc_propagator.rb +2 -2
- data/lib/ddtrace/runtime/metrics.rb +24 -6
- data/lib/ddtrace/sampler.rb +4 -2
- data/lib/ddtrace/span.rb +162 -27
- data/lib/ddtrace/tracer.rb +18 -12
- data/lib/ddtrace/transport/http.rb +15 -0
- data/lib/ddtrace/transport/http/adapters/net.rb +16 -2
- data/lib/ddtrace/transport/http/adapters/test.rb +6 -0
- data/lib/ddtrace/transport/http/adapters/unix_socket.rb +4 -0
- data/lib/ddtrace/transport/http/statistics.rb +14 -1
- data/lib/ddtrace/transport/response.rb +11 -0
- data/lib/ddtrace/transport/traces.rb +7 -2
- data/lib/ddtrace/utils.rb +7 -3
- data/lib/ddtrace/version.rb +1 -1
- data/lib/ddtrace/workers/async.rb +2 -2
- data/lib/ddtrace/workers/loop.rb +1 -1
- data/lib/ddtrace/workers/polling.rb +1 -1
- data/lib/ddtrace/workers/trace_writer.rb +3 -0
- data/lib/ddtrace/writer.rb +33 -12
- metadata +138 -2
data/lib/ddtrace/ext/runtime.rb
CHANGED
@@ -7,6 +7,7 @@ module Datadog
|
|
7
7
|
LANG = 'ruby'.freeze
|
8
8
|
LANG_INTERPRETER = (RUBY_ENGINE + '-' + RUBY_PLATFORM).freeze
|
9
9
|
LANG_VERSION = RUBY_VERSION
|
10
|
+
RUBY_ENGINE = ::RUBY_ENGINE # e.g. 'ruby', 'jruby', 'truffleruby'
|
10
11
|
TRACER_VERSION = Datadog::VERSION::STRING
|
11
12
|
|
12
13
|
TAG_LANG = 'language'.freeze
|
@@ -6,6 +6,7 @@ module Datadog
|
|
6
6
|
DEFAULT_PORT = 8126
|
7
7
|
ENV_DEFAULT_HOST = 'DD_AGENT_HOST'.freeze
|
8
8
|
ENV_DEFAULT_PORT = 'DD_TRACE_AGENT_PORT'.freeze
|
9
|
+
ENV_DEFAULT_URL = 'DD_TRACE_AGENT_URL'.freeze
|
9
10
|
HEADER_CONTAINER_ID = 'Datadog-Container-ID'.freeze
|
10
11
|
HEADER_META_LANG = 'Datadog-Meta-Lang'.freeze
|
11
12
|
HEADER_META_LANG_VERSION = 'Datadog-Meta-Lang-Version'.freeze
|
data/lib/ddtrace/logger.rb
CHANGED
@@ -44,7 +44,7 @@ module Datadog
|
|
44
44
|
|
45
45
|
def id(header)
|
46
46
|
value = @carrier[header].to_i
|
47
|
-
return if value.zero? || value >= Datadog::Span::
|
47
|
+
return if value.zero? || value >= Datadog::Span::EXTERNAL_MAX_ID
|
48
48
|
value < 0 ? value + 0x1_0000_0000_0000_0000 : value
|
49
49
|
end
|
50
50
|
end
|
data/lib/ddtrace/pin.rb
CHANGED
@@ -18,13 +18,15 @@ module Datadog
|
|
18
18
|
attr_accessor :name
|
19
19
|
attr_accessor :service_name
|
20
20
|
attr_accessor :tags
|
21
|
-
|
21
|
+
attr_reader :tracer
|
22
22
|
attr_accessor :writer
|
23
23
|
|
24
24
|
alias service= service_name=
|
25
25
|
alias service service_name
|
26
26
|
|
27
27
|
def initialize(service_name, options = {})
|
28
|
+
deprecation_warning unless options[:tracer].is_a?(Proc) || options[:tracer].nil?
|
29
|
+
|
28
30
|
@app = options[:app]
|
29
31
|
@app_type = options[:app_type]
|
30
32
|
@config = options[:config]
|
@@ -35,7 +37,7 @@ module Datadog
|
|
35
37
|
end
|
36
38
|
|
37
39
|
def tracer
|
38
|
-
@tracer || Datadog.tracer
|
40
|
+
@tracer.is_a?(Proc) ? @tracer.call : (@tracer || Datadog.tracer)
|
39
41
|
end
|
40
42
|
|
41
43
|
def enabled?
|
@@ -67,6 +69,27 @@ module Datadog
|
|
67
69
|
def to_s
|
68
70
|
"Pin(service:#{service},app:#{app},app_type:#{app_type},name:#{name})"
|
69
71
|
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
DEPRECATION_WARNING = %(
|
76
|
+
Explicitly providing a tracer instance is DEPRECATED.
|
77
|
+
It's recommended to not provide an explicit tracer instance
|
78
|
+
and let Datadog::Pin resolve the correct tracer internally.
|
79
|
+
).freeze
|
80
|
+
|
81
|
+
def deprecation_warning
|
82
|
+
log_deprecation_warning('Datadog::Pin.new')
|
83
|
+
end
|
84
|
+
|
85
|
+
include Datadog::Patcher
|
86
|
+
|
87
|
+
def log_deprecation_warning(method_name)
|
88
|
+
# Only log each deprecation warning once (safeguard against log spam)
|
89
|
+
do_once(method_name) do
|
90
|
+
Datadog.logger.warn("#{method_name}:#{DEPRECATION_WARNING}")
|
91
|
+
end
|
92
|
+
end
|
70
93
|
end
|
71
94
|
|
72
95
|
# Modification to Pin which logs deprecation warnings if accessed.
|
@@ -10,12 +10,22 @@ module Datadog
|
|
10
10
|
@criteria = filter || block
|
11
11
|
end
|
12
12
|
|
13
|
+
# Note: this SpanFilter implementation only handles traces in which child spans appear
|
14
|
+
# after parent spans in the trace array. If in the future child spans can be before
|
15
|
+
# parent spans, then the code below will need to be updated.
|
13
16
|
def call(trace)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
deleted = Set.new
|
18
|
+
|
19
|
+
trace.delete_if do |span|
|
20
|
+
if deleted.include?(span.parent)
|
21
|
+
deleted << span
|
22
|
+
true
|
23
|
+
else
|
24
|
+
drop = drop_it?(span)
|
25
|
+
deleted << span if drop
|
26
|
+
drop
|
27
|
+
end
|
28
|
+
end
|
19
29
|
end
|
20
30
|
|
21
31
|
private
|
@@ -23,16 +33,6 @@ module Datadog
|
|
23
33
|
def drop_it?(span)
|
24
34
|
@criteria.call(span) rescue false
|
25
35
|
end
|
26
|
-
|
27
|
-
def clean_trace(black_list, trace)
|
28
|
-
current = black_list.shift
|
29
|
-
|
30
|
-
trace.delete(current)
|
31
|
-
|
32
|
-
trace.each do |span|
|
33
|
-
black_list << span if span.parent == current
|
34
|
-
end
|
35
|
-
end
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
@@ -39,12 +39,12 @@ module Datadog
|
|
39
39
|
|
40
40
|
def trace_id
|
41
41
|
value = @metadata[GRPC_METADATA_TRACE_ID].to_i
|
42
|
-
value if (1..Span::
|
42
|
+
value if (1..Span::EXTERNAL_MAX_ID).cover? value
|
43
43
|
end
|
44
44
|
|
45
45
|
def parent_id
|
46
46
|
value = @metadata[GRPC_METADATA_PARENT_ID].to_i
|
47
|
-
value if (1..Span::
|
47
|
+
value if (1..Span::EXTERNAL_MAX_ID).cover? value
|
48
48
|
end
|
49
49
|
|
50
50
|
def sampling_priority
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'ddtrace/ext/integration'
|
1
2
|
require 'ddtrace/ext/runtime'
|
2
3
|
|
3
4
|
require 'ddtrace/metrics'
|
@@ -25,8 +26,11 @@ module Datadog
|
|
25
26
|
# Register service as associated with metrics
|
26
27
|
register_service(span.service) unless span.service.nil?
|
27
28
|
|
28
|
-
# Tag span with language and runtime ID for association with metrics
|
29
|
-
|
29
|
+
# Tag span with language and runtime ID for association with metrics.
|
30
|
+
# We only tag spans that performed internal application work.
|
31
|
+
unless span.get_tag(Datadog::Ext::Integration::TAG_PEER_SERVICE)
|
32
|
+
span.set_tag(Ext::Runtime::TAG_LANG, Runtime::Identity.lang)
|
33
|
+
end
|
30
34
|
end
|
31
35
|
|
32
36
|
# Associate service with runtime metrics
|
@@ -55,10 +59,8 @@ module Datadog
|
|
55
59
|
|
56
60
|
def gc_metrics
|
57
61
|
Hash[
|
58
|
-
GC.stat.
|
59
|
-
|
60
|
-
|
61
|
-
["#{Ext::Runtime::Metrics::METRIC_GC_PREFIX}.#{k}", v]
|
62
|
+
GC.stat.flat_map do |k, v|
|
63
|
+
nested_gc_metric(Ext::Runtime::Metrics::METRIC_GC_PREFIX, k, v)
|
62
64
|
end
|
63
65
|
]
|
64
66
|
end
|
@@ -91,6 +93,22 @@ module Datadog
|
|
91
93
|
"#{Ext::Runtime::Metrics::TAG_SERVICE}:#{service}".freeze
|
92
94
|
end
|
93
95
|
end
|
96
|
+
|
97
|
+
def nested_gc_metric(prefix, k, v)
|
98
|
+
path = "#{prefix}.#{k}"
|
99
|
+
|
100
|
+
if v.is_a?(Hash)
|
101
|
+
v.flat_map do |key, value|
|
102
|
+
nested_gc_metric(path, key, value)
|
103
|
+
end
|
104
|
+
else
|
105
|
+
[[to_metric_name(path), v]]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def to_metric_name(str)
|
110
|
+
str.downcase.gsub(/[-\s]/, '_')
|
111
|
+
end
|
94
112
|
end
|
95
113
|
end
|
96
114
|
end
|
data/lib/ddtrace/sampler.rb
CHANGED
@@ -61,11 +61,11 @@ module Datadog
|
|
61
61
|
|
62
62
|
def sample_rate=(sample_rate)
|
63
63
|
@sample_rate = sample_rate
|
64
|
-
@sampling_id_threshold = sample_rate * Span::
|
64
|
+
@sampling_id_threshold = sample_rate * Span::EXTERNAL_MAX_ID
|
65
65
|
end
|
66
66
|
|
67
67
|
def sample?(span)
|
68
|
-
((span.trace_id * KNUTH_FACTOR) % Datadog::Span::
|
68
|
+
((span.trace_id * KNUTH_FACTOR) % Datadog::Span::EXTERNAL_MAX_ID) <= @sampling_id_threshold
|
69
69
|
end
|
70
70
|
|
71
71
|
def sample!(span)
|
@@ -193,6 +193,8 @@ module Datadog
|
|
193
193
|
class PrioritySampler
|
194
194
|
extend Forwardable
|
195
195
|
|
196
|
+
attr_reader :pre_sampler, :priority_sampler
|
197
|
+
|
196
198
|
SAMPLE_RATE_METRIC_KEY = '_sample_rate'.freeze
|
197
199
|
|
198
200
|
def initialize(opts = {})
|
data/lib/ddtrace/span.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'time'
|
2
4
|
require 'thread'
|
3
5
|
|
@@ -8,6 +10,7 @@ require 'ddtrace/environment'
|
|
8
10
|
require 'ddtrace/analytics'
|
9
11
|
require 'ddtrace/forced_tracing'
|
10
12
|
require 'ddtrace/diagnostics/health'
|
13
|
+
require 'ddtrace/utils/time'
|
11
14
|
|
12
15
|
module Datadog
|
13
16
|
# Represents a logical unit of work in the system. Each trace consists of one or more spans.
|
@@ -24,24 +27,26 @@ module Datadog
|
|
24
27
|
# The max value for a \Span identifier.
|
25
28
|
# Span and trace identifiers should be strictly positive and strictly inferior to this limit.
|
26
29
|
#
|
27
|
-
# Limited to
|
28
|
-
#
|
29
|
-
|
30
|
+
# Limited to +2<<62-1+ positive integers, as Ruby is able to represent such numbers "inline",
|
31
|
+
# inside a +VALUE+ scalar, thus not requiring memory allocation.
|
32
|
+
#
|
33
|
+
# The range of IDs also has to consider portability across different languages and platforms.
|
34
|
+
RUBY_MAX_ID = (1 << 62) - 1
|
30
35
|
|
31
36
|
# While we only generate 63-bit integers due to limitations in other languages, we support
|
32
37
|
# parsing 64-bit integers for distributed tracing since an upstream system may generate one
|
33
|
-
EXTERNAL_MAX_ID =
|
38
|
+
EXTERNAL_MAX_ID = 1 << 64
|
34
39
|
|
35
40
|
# This limit is for numeric tags because uint64 could end up rounded.
|
36
|
-
NUMERIC_TAG_SIZE_RANGE = (-
|
41
|
+
NUMERIC_TAG_SIZE_RANGE = (-1 << 53..1 << 53)
|
37
42
|
|
38
43
|
attr_accessor :name, :service, :resource, :span_type,
|
39
|
-
:start_time, :end_time,
|
40
44
|
:span_id, :trace_id, :parent_id,
|
41
45
|
:status, :sampled,
|
42
|
-
:tracer, :context
|
46
|
+
:tracer, :context, :duration, :start_time, :end_time
|
43
47
|
|
44
48
|
attr_reader :parent
|
49
|
+
|
45
50
|
# Create a new span linked to the given tracer. Call the \Tracer method <tt>start_span()</tt>
|
46
51
|
# and then <tt>finish()</tt> once the tracer operation is over.
|
47
52
|
#
|
@@ -72,11 +77,20 @@ module Datadog
|
|
72
77
|
@parent = nil
|
73
78
|
@sampled = true
|
74
79
|
|
75
|
-
@start_time = nil # set by Tracer.start_span
|
76
|
-
@end_time = nil # set by Span.finish
|
77
|
-
|
78
80
|
@allocation_count_start = now_allocations
|
79
81
|
@allocation_count_finish = @allocation_count_start
|
82
|
+
|
83
|
+
# start_time and end_time track wall clock. In Ruby, wall clock
|
84
|
+
# has less accuracy than monotonic clock, so if possible we look to only use wall clock
|
85
|
+
# to measure duration when a time is supplied by the user, or if monotonic clock
|
86
|
+
# is unsupported.
|
87
|
+
@start_time = nil
|
88
|
+
@end_time = nil
|
89
|
+
|
90
|
+
# duration_start and duration_end track monotonic clock, and may remain nil in cases where it
|
91
|
+
# is known that we have to use wall clock to measure duration.
|
92
|
+
@duration_start = nil
|
93
|
+
@duration_end = nil
|
80
94
|
end
|
81
95
|
|
82
96
|
# Set the given key / value tag pair on the span. Keys and values
|
@@ -107,6 +121,16 @@ module Datadog
|
|
107
121
|
Datadog.logger.debug("Unable to set the tag #{key}, ignoring it. Caused by: #{e}")
|
108
122
|
end
|
109
123
|
|
124
|
+
# Sets tags from given hash, for each key in hash it sets the tag with that key
|
125
|
+
# and associated value from the hash. It is shortcut for `set_tag`. Keys and values
|
126
|
+
# of the hash must be strings. Note that nested hashes are not supported.
|
127
|
+
# A valid example is:
|
128
|
+
#
|
129
|
+
# span.set_tags({ "http.method" => "GET", "user.id" => "234" })
|
130
|
+
def set_tags(tags)
|
131
|
+
tags.each { |k, v| set_tag(k, v) }
|
132
|
+
end
|
133
|
+
|
110
134
|
# This method removes a tag for the given key.
|
111
135
|
def clear_tag(key)
|
112
136
|
@meta.delete(key)
|
@@ -150,6 +174,28 @@ module Datadog
|
|
150
174
|
set_tag(Ext::Errors::STACK, e.backtrace) unless e.backtrace.empty?
|
151
175
|
end
|
152
176
|
|
177
|
+
# Mark the span started at the current time.
|
178
|
+
def start(start_time = nil)
|
179
|
+
# A span should not be started twice. However, this is existing
|
180
|
+
# behavior and so we maintain it for backward compatibility for those
|
181
|
+
# who are using async manual instrumentation that may rely on this
|
182
|
+
|
183
|
+
@start_time = start_time || Time.now.utc
|
184
|
+
@duration_start = start_time.nil? ? duration_marker : nil
|
185
|
+
|
186
|
+
self
|
187
|
+
end
|
188
|
+
|
189
|
+
# for backwards compatibility
|
190
|
+
def start_time=(time)
|
191
|
+
time.tap { start(time) }
|
192
|
+
end
|
193
|
+
|
194
|
+
# for backwards compatibility
|
195
|
+
def end_time=(time)
|
196
|
+
time.tap { finish(time) }
|
197
|
+
end
|
198
|
+
|
153
199
|
# Mark the span finished at the current time and submit it.
|
154
200
|
def finish(finish_time = nil)
|
155
201
|
# A span should not be finished twice. Note that this is not thread-safe,
|
@@ -160,12 +206,15 @@ module Datadog
|
|
160
206
|
|
161
207
|
@allocation_count_finish = now_allocations
|
162
208
|
|
163
|
-
|
164
|
-
|
165
|
-
#
|
166
|
-
|
209
|
+
now = Time.now.utc
|
210
|
+
|
211
|
+
# Provide a default start_time if unset.
|
212
|
+
# Using `now` here causes duration to be 0; this is expected
|
213
|
+
# behavior when start_time is unknown.
|
214
|
+
start(finish_time || now) unless started?
|
167
215
|
|
168
|
-
@end_time = finish_time
|
216
|
+
@end_time = finish_time || now
|
217
|
+
@duration_end = finish_time.nil? ? duration_marker : nil
|
169
218
|
|
170
219
|
# Finish does not really do anything if the span is not bound to a tracer and a context.
|
171
220
|
return self if @tracer.nil? || @context.nil?
|
@@ -185,11 +234,6 @@ module Datadog
|
|
185
234
|
self
|
186
235
|
end
|
187
236
|
|
188
|
-
# Return whether the span is finished or not.
|
189
|
-
def finished?
|
190
|
-
!@end_time.nil?
|
191
|
-
end
|
192
|
-
|
193
237
|
# Return a string representation of the span.
|
194
238
|
def to_s
|
195
239
|
"Span(name:#{@name},sid:#{@span_id},tid:#{@trace_id},pid:#{@parent_id})"
|
@@ -236,19 +280,76 @@ module Datadog
|
|
236
280
|
error: @status
|
237
281
|
}
|
238
282
|
|
239
|
-
if
|
240
|
-
h[:start] =
|
241
|
-
h[:duration] =
|
283
|
+
if finished?
|
284
|
+
h[:start] = start_time_nano
|
285
|
+
h[:duration] = duration_nano
|
242
286
|
end
|
243
287
|
|
244
288
|
h
|
245
289
|
end
|
246
290
|
|
291
|
+
# MessagePack serializer interface. Making this object
|
292
|
+
# respond to `#to_msgpack` allows it to be automatically
|
293
|
+
# serialized by MessagePack.
|
294
|
+
#
|
295
|
+
# This is more efficient than doing +MessagePack.pack(span.to_hash)+
|
296
|
+
# as we don't have to create an intermediate Hash.
|
297
|
+
#
|
298
|
+
# @param packer [MessagePack::Packer] serialization buffer, can be +nil+ with JRuby
|
299
|
+
def to_msgpack(packer = nil)
|
300
|
+
# As of 1.3.3, JRuby implementation doesn't pass an existing packer
|
301
|
+
packer ||= MessagePack::Packer.new
|
302
|
+
|
303
|
+
if finished?
|
304
|
+
packer.write_map_header(13) # Set header with how many elements in the map
|
305
|
+
|
306
|
+
packer.write('start')
|
307
|
+
packer.write(start_time_nano)
|
308
|
+
|
309
|
+
packer.write('duration')
|
310
|
+
packer.write(duration_nano)
|
311
|
+
else
|
312
|
+
packer.write_map_header(11) # Set header with how many elements in the map
|
313
|
+
end
|
314
|
+
|
315
|
+
# DEV: We use strings as keys here, instead of symbols, as
|
316
|
+
# DEV: MessagePack will ultimately convert them to strings.
|
317
|
+
# DEV: By providing strings directly, we skip this indirection operation.
|
318
|
+
packer.write('span_id')
|
319
|
+
packer.write(@span_id)
|
320
|
+
packer.write('parent_id')
|
321
|
+
packer.write(@parent_id)
|
322
|
+
packer.write('trace_id')
|
323
|
+
packer.write(@trace_id)
|
324
|
+
packer.write('name')
|
325
|
+
packer.write(@name)
|
326
|
+
packer.write('service')
|
327
|
+
packer.write(@service)
|
328
|
+
packer.write('resource')
|
329
|
+
packer.write(@resource)
|
330
|
+
packer.write('type')
|
331
|
+
packer.write(@span_type)
|
332
|
+
packer.write('meta')
|
333
|
+
packer.write(@meta)
|
334
|
+
packer.write('metrics')
|
335
|
+
packer.write(@metrics)
|
336
|
+
packer.write('allocations')
|
337
|
+
packer.write(allocations)
|
338
|
+
packer.write('error')
|
339
|
+
packer.write(@status)
|
340
|
+
packer
|
341
|
+
end
|
342
|
+
|
343
|
+
# JSON serializer interface.
|
344
|
+
# Used by older version of the transport.
|
345
|
+
def to_json(*args)
|
346
|
+
to_hash.to_json(*args)
|
347
|
+
end
|
348
|
+
|
247
349
|
# Return a human readable version of the span
|
248
350
|
def pretty_print(q)
|
249
|
-
start_time = (
|
250
|
-
end_time = (
|
251
|
-
duration = ((@end_time - @start_time) * 1e9).to_i rescue 0
|
351
|
+
start_time = (self.start_time.to_f * 1e9).to_i
|
352
|
+
end_time = (self.end_time.to_f * 1e9).to_i
|
252
353
|
q.group 0 do
|
253
354
|
q.breakable
|
254
355
|
q.text "Name: #{@name}\n"
|
@@ -261,7 +362,7 @@ module Datadog
|
|
261
362
|
q.text "Error: #{@status}\n"
|
262
363
|
q.text "Start: #{start_time}\n"
|
263
364
|
q.text "End: #{end_time}\n"
|
264
|
-
q.text "Duration: #{duration}\n"
|
365
|
+
q.text "Duration: #{duration.to_f if finished?}\n"
|
265
366
|
q.text "Allocations: #{allocations}\n"
|
266
367
|
q.group(2, 'Tags: [', "]\n") do
|
267
368
|
q.breakable
|
@@ -278,8 +379,30 @@ module Datadog
|
|
278
379
|
end
|
279
380
|
end
|
280
381
|
|
382
|
+
# Return whether the duration is started or not
|
383
|
+
def started?
|
384
|
+
!@start_time.nil?
|
385
|
+
end
|
386
|
+
|
387
|
+
# Return whether the duration is finished or not.
|
388
|
+
def finished?
|
389
|
+
!@end_time.nil?
|
390
|
+
end
|
391
|
+
|
392
|
+
def duration
|
393
|
+
if @duration_end.nil? || @duration_start.nil?
|
394
|
+
@end_time - @start_time
|
395
|
+
else
|
396
|
+
@duration_end - @duration_start
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
281
400
|
private
|
282
401
|
|
402
|
+
def duration_marker
|
403
|
+
Utils::Time.get_time
|
404
|
+
end
|
405
|
+
|
283
406
|
if defined?(JRUBY_VERSION) || Gem::Version.new(RUBY_VERSION) < Gem::Version.new(VERSION::MINIMUM_RUBY_VERSION)
|
284
407
|
def now_allocations
|
285
408
|
0
|
@@ -293,5 +416,17 @@ module Datadog
|
|
293
416
|
GC.stat(:total_allocated_objects)
|
294
417
|
end
|
295
418
|
end
|
419
|
+
|
420
|
+
# Used for serialization
|
421
|
+
# @return [Integer] in nanoseconds since Epoch
|
422
|
+
def start_time_nano
|
423
|
+
@start_time.to_i * 1000000000 + @start_time.nsec
|
424
|
+
end
|
425
|
+
|
426
|
+
# Used for serialization
|
427
|
+
# @return [Integer] in nanoseconds since Epoch
|
428
|
+
def duration_nano
|
429
|
+
(duration * 1e9).to_i
|
430
|
+
end
|
296
431
|
end
|
297
432
|
end
|