ddtrace 0.36.0 → 0.41.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/.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
|