ddtrace 0.46.0 → 0.47.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 +5 -5
- data/.circleci/config.yml +52 -12
- data/.circleci/images/primary/{Dockerfile-jruby-9.2 → Dockerfile-jruby-9.2-latest} +2 -1
- data/.circleci/images/primary/Dockerfile-jruby-9.2.0.0 +73 -0
- data/.circleci/images/primary/Dockerfile-truffleruby-21.0.0 +73 -0
- data/.github/workflows/create-next-milestone.yml +2 -2
- data/.rubocop_todo.yml +3 -2
- data/.simplecov +6 -0
- data/Appraisals +1 -1
- data/CHANGELOG.md +83 -1
- data/Gemfile +19 -4
- data/LICENSE-3rdparty.csv +2 -0
- data/docker-compose.yml +75 -7
- data/docs/GettingStarted.md +61 -8
- data/lib/ddtrace/configuration.rb +92 -23
- data/lib/ddtrace/configuration/options.rb +2 -4
- data/lib/ddtrace/context_provider.rb +0 -2
- data/lib/ddtrace/contrib/active_record/configuration/resolver.rb +97 -26
- data/lib/ddtrace/contrib/aws/services.rb +1 -0
- data/lib/ddtrace/contrib/configurable.rb +63 -39
- data/lib/ddtrace/contrib/configuration/resolver.rb +70 -5
- data/lib/ddtrace/contrib/configuration/resolvers/pattern_resolver.rb +19 -17
- data/lib/ddtrace/contrib/configuration/settings.rb +7 -6
- data/lib/ddtrace/contrib/elasticsearch/patcher.rb +1 -0
- data/lib/ddtrace/contrib/extensions.rb +26 -3
- data/lib/ddtrace/contrib/httpclient/instrumentation.rb +12 -16
- data/lib/ddtrace/contrib/httpclient/patcher.rb +5 -2
- data/lib/ddtrace/contrib/httprb/instrumentation.rb +12 -17
- data/lib/ddtrace/contrib/httprb/patcher.rb +5 -2
- data/lib/ddtrace/contrib/patcher.rb +8 -5
- data/lib/ddtrace/contrib/presto/patcher.rb +5 -2
- data/lib/ddtrace/contrib/rails/patcher.rb +6 -2
- data/lib/ddtrace/contrib/redis/configuration/resolver.rb +11 -4
- data/lib/ddtrace/contrib/resque/integration.rb +1 -1
- data/lib/ddtrace/ext/runtime.rb +2 -0
- data/lib/ddtrace/patcher.rb +23 -1
- data/lib/ddtrace/pin.rb +5 -9
- data/lib/ddtrace/runtime/cgroup.rb +1 -1
- data/lib/ddtrace/runtime/container.rb +25 -27
- data/lib/ddtrace/runtime/identity.rb +8 -0
- data/lib/ddtrace/sync_writer.rb +5 -2
- data/lib/ddtrace/tracer.rb +6 -4
- data/lib/ddtrace/transport/http.rb +14 -5
- data/lib/ddtrace/transport/http/adapters/net.rb +18 -4
- data/lib/ddtrace/transport/http/builder.rb +5 -1
- data/lib/ddtrace/transport/http/env.rb +8 -0
- data/lib/ddtrace/transport/io/response.rb +1 -3
- data/lib/ddtrace/transport/io/traces.rb +6 -0
- data/lib/ddtrace/transport/traces.rb +15 -1
- data/lib/ddtrace/utils/compression.rb +27 -0
- data/lib/ddtrace/utils/object_set.rb +41 -0
- data/lib/ddtrace/utils/only_once.rb +40 -0
- data/lib/ddtrace/utils/sequence.rb +17 -0
- data/lib/ddtrace/utils/string_table.rb +45 -0
- data/lib/ddtrace/utils/time.rb +7 -0
- data/lib/ddtrace/vendor/multipart-post/LICENSE +11 -0
- data/lib/ddtrace/vendor/multipart-post/multipart.rb +12 -0
- data/lib/ddtrace/vendor/multipart-post/multipart/post.rb +8 -0
- data/lib/ddtrace/vendor/multipart-post/multipart/post/composite_read_io.rb +116 -0
- data/lib/ddtrace/vendor/multipart-post/multipart/post/multipartable.rb +57 -0
- data/lib/ddtrace/vendor/multipart-post/multipart/post/parts.rb +135 -0
- data/lib/ddtrace/vendor/multipart-post/multipart/post/version.rb +9 -0
- data/lib/ddtrace/vendor/multipart-post/net/http/post/multipart.rb +32 -0
- data/lib/ddtrace/version.rb +1 -1
- data/lib/ddtrace/workers/async.rb +3 -3
- data/lib/ddtrace/workers/loop.rb +14 -3
- data/lib/ddtrace/workers/queue.rb +1 -0
- data/lib/ddtrace/workers/trace_writer.rb +1 -0
- data/lib/ddtrace/writer.rb +4 -1
- metadata +21 -4
@@ -21,7 +21,7 @@ module Datadog
|
|
21
21
|
filepath = "/proc/#{process}/cgroup"
|
22
22
|
|
23
23
|
if File.exist?(filepath)
|
24
|
-
File.
|
24
|
+
File.foreach("/proc/#{process}/cgroup") do |line|
|
25
25
|
line = line.strip
|
26
26
|
descriptors << parse(line) unless line.empty?
|
27
27
|
end
|
@@ -32,39 +32,37 @@ module Datadog
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def descriptor
|
35
|
-
@descriptor ||=
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
next if path.nil?
|
35
|
+
@descriptor ||= Descriptor.new.tap do |descriptor|
|
36
|
+
begin
|
37
|
+
Cgroup.descriptors.each do |cgroup_descriptor|
|
38
|
+
# Parse container data from cgroup descriptor
|
39
|
+
path = cgroup_descriptor.path
|
40
|
+
next if path.nil?
|
42
41
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
42
|
+
# Split path into parts
|
43
|
+
parts = path.split('/')
|
44
|
+
parts.shift # Remove leading empty part
|
45
|
+
next if parts.length < 2
|
47
46
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
47
|
+
# Read info from path
|
48
|
+
platform = parts[0]
|
49
|
+
container_id = parts[-1][CONTAINER_REGEX]
|
50
|
+
task_uid = parts[-2][POD_REGEX]
|
52
51
|
|
53
|
-
|
54
|
-
|
55
|
-
|
52
|
+
# If container ID wasn't found, ignore.
|
53
|
+
# Path might describe a non-container environment.
|
54
|
+
next if container_id.nil?
|
56
55
|
|
57
|
-
|
58
|
-
|
59
|
-
|
56
|
+
descriptor.platform = platform
|
57
|
+
descriptor.container_id = container_id
|
58
|
+
descriptor.task_uid = task_uid
|
60
59
|
|
61
|
-
|
62
|
-
end
|
63
|
-
rescue StandardError => e
|
64
|
-
Datadog.logger.error(
|
65
|
-
"Error while parsing container info. Cause: #{e.message} Location: #{e.backtrace.first}"
|
66
|
-
)
|
60
|
+
break
|
67
61
|
end
|
62
|
+
rescue StandardError => e
|
63
|
+
Datadog.logger.error(
|
64
|
+
"Error while parsing container info. Cause: #{e.message} Location: #{e.backtrace.first}"
|
65
|
+
)
|
68
66
|
end
|
69
67
|
end
|
70
68
|
end
|
@@ -24,10 +24,18 @@ module Datadog
|
|
24
24
|
Ext::Runtime::LANG
|
25
25
|
end
|
26
26
|
|
27
|
+
def lang_engine
|
28
|
+
Ext::Runtime::LANG_ENGINE
|
29
|
+
end
|
30
|
+
|
27
31
|
def lang_interpreter
|
28
32
|
Ext::Runtime::LANG_INTERPRETER
|
29
33
|
end
|
30
34
|
|
35
|
+
def lang_platform
|
36
|
+
Ext::Runtime::LANG_PLATFORM
|
37
|
+
end
|
38
|
+
|
31
39
|
def lang_version
|
32
40
|
Ext::Runtime::LANG_VERSION
|
33
41
|
end
|
data/lib/ddtrace/sync_writer.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'ddtrace/ext/net'
|
2
2
|
require 'ddtrace/runtime/socket'
|
3
3
|
require 'ddtrace/runtime/metrics'
|
4
|
+
require 'ddtrace/utils/only_once'
|
4
5
|
|
5
6
|
module Datadog
|
6
7
|
# SyncWriter flushes both services and traces synchronously
|
@@ -10,6 +11,8 @@ module Datadog
|
|
10
11
|
# the separate `datadog-lambda` uses it as of February 2021:
|
11
12
|
# <https://github.com/DataDog/datadog-lambda-rb/blob/c15f0f0916c90123416dc44e7d6800ef4a7cfdbf/lib/datadog/lambda.rb#L38>
|
12
13
|
class SyncWriter
|
14
|
+
DEPRECATION_WARN_ONLY_ONCE = Datadog::Utils::OnlyOnce.new
|
15
|
+
|
13
16
|
attr_reader \
|
14
17
|
:priority_sampler,
|
15
18
|
:transport
|
@@ -25,10 +28,10 @@ module Datadog
|
|
25
28
|
|
26
29
|
def write(trace, services = nil)
|
27
30
|
unless services.nil?
|
28
|
-
|
31
|
+
DEPRECATION_WARN_ONLY_ONCE.run do
|
29
32
|
Datadog.logger.warn(%(
|
30
33
|
write: Writing services has been deprecated and no longer need to be provided.
|
31
|
-
write(traces, services) can be
|
34
|
+
write(traces, services) can be updated to write(traces)
|
32
35
|
))
|
33
36
|
end
|
34
37
|
end
|
data/lib/ddtrace/tracer.rb
CHANGED
@@ -10,6 +10,7 @@ require 'ddtrace/runtime/identity'
|
|
10
10
|
require 'ddtrace/sampler'
|
11
11
|
require 'ddtrace/sampling'
|
12
12
|
require 'ddtrace/correlation'
|
13
|
+
require 'ddtrace/utils/only_once'
|
13
14
|
|
14
15
|
# \Datadog global namespace that includes all tracing functionality for Tracer and Span classes.
|
15
16
|
module Datadog
|
@@ -19,6 +20,9 @@ module Datadog
|
|
19
20
|
# of these function calls and sub-requests would be encapsulated within a single trace.
|
20
21
|
# rubocop:disable Metrics/ClassLength
|
21
22
|
class Tracer
|
23
|
+
SERVICES_DEPRECATION_WARN_ONLY_ONCE = Datadog::Utils::OnlyOnce.new
|
24
|
+
SET_SERVICE_INFO_DEPRECATION_WARN_ONLY_ONCE = Datadog::Utils::OnlyOnce.new
|
25
|
+
|
22
26
|
attr_reader :sampler, :tags, :provider, :context_flush
|
23
27
|
attr_accessor :enabled, :writer
|
24
28
|
attr_writer :default_service
|
@@ -27,8 +31,7 @@ module Datadog
|
|
27
31
|
DEFAULT_ON_ERROR = proc { |span, error| span.set_error(error) unless span.nil? }
|
28
32
|
|
29
33
|
def services
|
30
|
-
|
31
|
-
Datadog::Patcher.do_once('Tracer#set_service_info') do
|
34
|
+
SERVICES_DEPRECATION_WARN_ONLY_ONCE.run do
|
32
35
|
Datadog.logger.warn('services: Usage of Tracer.services has been deprecated')
|
33
36
|
end
|
34
37
|
|
@@ -129,8 +132,7 @@ module Datadog
|
|
129
132
|
#
|
130
133
|
# set_service_info is deprecated, no service information needs to be tracked
|
131
134
|
def set_service_info(service, app, app_type)
|
132
|
-
|
133
|
-
Datadog::Patcher.do_once('Tracer#set_service_info') do
|
135
|
+
SET_SERVICE_INFO_DEPRECATION_WARN_ONLY_ONCE.run do
|
134
136
|
Datadog.logger.warn(%(
|
135
137
|
set_service_info: Usage of set_service_info has been deprecated,
|
136
138
|
service information no longer needs to be reported to the trace agent.
|
@@ -27,7 +27,7 @@ module Datadog
|
|
27
27
|
# Pass a block to override any settings.
|
28
28
|
def default(options = {})
|
29
29
|
new do |transport|
|
30
|
-
transport.adapter
|
30
|
+
transport.adapter default_adapter, default_hostname, default_port, timeout: 1
|
31
31
|
transport.headers default_headers
|
32
32
|
|
33
33
|
apis = API.defaults
|
@@ -39,10 +39,15 @@ module Datadog
|
|
39
39
|
# Apply any settings given by options
|
40
40
|
unless options.empty?
|
41
41
|
# Change hostname/port
|
42
|
-
if
|
43
|
-
hostname = options
|
44
|
-
port = options
|
45
|
-
|
42
|
+
if [:hostname, :port, :timeout, :ssl].any? { |key| options.key?(key) }
|
43
|
+
hostname = options[:hostname] || default_hostname
|
44
|
+
port = options[:port] || default_port
|
45
|
+
|
46
|
+
adapter_options = { timeout: 1 }
|
47
|
+
adapter_options[:timeout] = options[:timeout] if options.key?(:timeout)
|
48
|
+
adapter_options[:ssl] = options[:ssl] if options.key?(:ssl)
|
49
|
+
|
50
|
+
transport.adapter default_adapter, hostname, port, adapter_options
|
46
51
|
end
|
47
52
|
|
48
53
|
# Change default API
|
@@ -73,6 +78,10 @@ module Datadog
|
|
73
78
|
end
|
74
79
|
end
|
75
80
|
|
81
|
+
def default_adapter
|
82
|
+
:net_http
|
83
|
+
end
|
84
|
+
|
76
85
|
def default_hostname
|
77
86
|
return default_url.hostname if default_url
|
78
87
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'ddtrace/transport/response'
|
2
|
+
require 'ddtrace/vendor/multipart-post/net/http/post/multipart'
|
2
3
|
|
3
4
|
module Datadog
|
4
5
|
module Transport
|
@@ -9,14 +10,16 @@ module Datadog
|
|
9
10
|
attr_reader \
|
10
11
|
:hostname,
|
11
12
|
:port,
|
12
|
-
:timeout
|
13
|
+
:timeout,
|
14
|
+
:ssl
|
13
15
|
|
14
|
-
DEFAULT_TIMEOUT =
|
16
|
+
DEFAULT_TIMEOUT = 30
|
15
17
|
|
16
18
|
def initialize(hostname, port, options = {})
|
17
19
|
@hostname = hostname
|
18
20
|
@port = port
|
19
21
|
@timeout = options[:timeout] || DEFAULT_TIMEOUT
|
22
|
+
@ssl = options.key?(:ssl) ? options[:ssl] == true : false
|
20
23
|
end
|
21
24
|
|
22
25
|
def open(&block)
|
@@ -25,6 +28,7 @@ module Datadog
|
|
25
28
|
# https://github.com/ruby/ruby/blob/b2d96abb42abbe2e01f010ffc9ac51f0f9a50002/lib/net/http.rb#L614-L618
|
26
29
|
req = ::Net::HTTP.new(hostname, port, nil)
|
27
30
|
|
31
|
+
req.use_ssl = ssl
|
28
32
|
req.open_timeout = req.read_timeout = timeout
|
29
33
|
|
30
34
|
req.start(&block)
|
@@ -39,8 +43,18 @@ module Datadog
|
|
39
43
|
end
|
40
44
|
|
41
45
|
def post(env)
|
42
|
-
post =
|
43
|
-
|
46
|
+
post = nil
|
47
|
+
|
48
|
+
if env.form.nil? || env.form.empty?
|
49
|
+
post = ::Net::HTTP::Post.new(env.path, env.headers)
|
50
|
+
post.body = env.body
|
51
|
+
else
|
52
|
+
post = ::Datadog::Vendor::Net::HTTP::Post::Multipart.new(
|
53
|
+
env.path,
|
54
|
+
env.form,
|
55
|
+
env.headers
|
56
|
+
)
|
57
|
+
end
|
44
58
|
|
45
59
|
# Connect and send the request
|
46
60
|
http_response = open do |http|
|
@@ -95,7 +95,7 @@ module Datadog
|
|
95
95
|
api_options[:headers] = @default_headers.merge((api_options[:headers] || {}))
|
96
96
|
|
97
97
|
# Add API::Instance with all settings
|
98
|
-
instances[key] =
|
98
|
+
instances[key] = api_instance_class.new(
|
99
99
|
spec,
|
100
100
|
adapter,
|
101
101
|
api_options
|
@@ -107,6 +107,10 @@ module Datadog
|
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
110
|
+
def api_instance_class
|
111
|
+
API::Instance
|
112
|
+
end
|
113
|
+
|
110
114
|
# Raised when the API key does not match known APIs.
|
111
115
|
class UnknownApiError < StandardError
|
112
116
|
attr_reader :key
|
@@ -6,14 +6,12 @@ module Datadog
|
|
6
6
|
# Response from HTTP transport for traces
|
7
7
|
class Response
|
8
8
|
include Transport::Response
|
9
|
-
include Transport::Traces::Response
|
10
9
|
|
11
10
|
attr_reader \
|
12
11
|
:result
|
13
12
|
|
14
|
-
def initialize(result
|
13
|
+
def initialize(result)
|
15
14
|
@result = result
|
16
|
-
@trace_count = trace_count
|
17
15
|
end
|
18
16
|
|
19
17
|
def ok?
|
@@ -10,6 +10,12 @@ module Datadog
|
|
10
10
|
module Traces
|
11
11
|
# Response from HTTP transport for traces
|
12
12
|
class Response < IO::Response
|
13
|
+
include Transport::Traces::Response
|
14
|
+
|
15
|
+
def initialize(result, trace_count = 1)
|
16
|
+
super(result)
|
17
|
+
@trace_count = trace_count
|
18
|
+
end
|
13
19
|
end
|
14
20
|
|
15
21
|
# Extensions for HTTP client
|
@@ -123,7 +123,21 @@ module Datadog
|
|
123
123
|
return send_traces(traces)
|
124
124
|
end
|
125
125
|
end
|
126
|
-
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Force resolution of lazy enumerator.
|
129
|
+
#
|
130
|
+
# The "correct" method to call here would be `#force`,
|
131
|
+
# as this method was created to force the eager loading
|
132
|
+
# of a lazy enumerator.
|
133
|
+
#
|
134
|
+
# Unfortunately, JRuby < 9.2.9.0 erroneously eagerly loads
|
135
|
+
# the lazy Enumerator during intermediate steps.
|
136
|
+
# This forces us to use `#to_a`, as this method works for both
|
137
|
+
# lazy and regular Enumerators.
|
138
|
+
# Using `#to_a` can mask the fact that we expect a lazy
|
139
|
+
# Enumerator.
|
140
|
+
responses = responses.to_a
|
127
141
|
|
128
142
|
Datadog.health_metrics.transport_chunked(responses.size)
|
129
143
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'zlib'
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module Utils
|
5
|
+
# Common database-related utility functions.
|
6
|
+
module Compression
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def gzip(string, level: nil, strategy: nil)
|
10
|
+
sio = StringIO.new
|
11
|
+
sio.binmode
|
12
|
+
gz = Zlib::GzipWriter.new(sio, level, strategy)
|
13
|
+
gz.write(string)
|
14
|
+
gz.close
|
15
|
+
sio.string
|
16
|
+
end
|
17
|
+
|
18
|
+
def gunzip(string, encoding = ::Encoding::ASCII_8BIT)
|
19
|
+
sio = StringIO.new(string)
|
20
|
+
gz = Zlib::GzipReader.new(sio, encoding: encoding)
|
21
|
+
gz.read
|
22
|
+
ensure
|
23
|
+
gz && gz.close
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'ddtrace/utils/sequence'
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module Utils
|
5
|
+
# Acts as a unique dictionary of objects
|
6
|
+
class ObjectSet
|
7
|
+
# You can provide a block that defines how the key
|
8
|
+
# for this message type is resolved.
|
9
|
+
def initialize(seed = 0, &block)
|
10
|
+
@sequence = Utils::Sequence.new(seed)
|
11
|
+
@items = {}
|
12
|
+
@key_block = block
|
13
|
+
end
|
14
|
+
|
15
|
+
# Submit an array of arguments that define the message.
|
16
|
+
# If they match an existing message, it will return the
|
17
|
+
# matching object. If it doesn't match, it will yield to
|
18
|
+
# the block with the next ID & args given.
|
19
|
+
def fetch(*args, &block)
|
20
|
+
key = @key_block ? @key_block.call(*args) : args.hash
|
21
|
+
# TODO: Ruby 2.0 doesn't like yielding here... switch when 2.0 is dropped.
|
22
|
+
# rubocop:disable Performance/RedundantBlockCall
|
23
|
+
@items[key] ||= block.call(@sequence.next, *args)
|
24
|
+
# rubocop:enable Performance/RedundantBlockCall
|
25
|
+
end
|
26
|
+
|
27
|
+
def length
|
28
|
+
@items.length
|
29
|
+
end
|
30
|
+
|
31
|
+
def objects
|
32
|
+
@items.values
|
33
|
+
end
|
34
|
+
|
35
|
+
def freeze
|
36
|
+
super
|
37
|
+
@items.freeze
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module Utils
|
5
|
+
# Helper class to execute something only once such as not repeating warning logs, and instrumenting classes
|
6
|
+
# only once.
|
7
|
+
#
|
8
|
+
# Thread-safe when used correctly (e.g. be careful of races when lazily initializing instances of this class).
|
9
|
+
#
|
10
|
+
# Note: In its current state, this class is not Ractor-safe.
|
11
|
+
# In https://github.com/DataDog/dd-trace-rb/pull/1398#issuecomment-797378810 we have a discussion of alternatives,
|
12
|
+
# including an alternative implementation that is Ractor-safe once spent.
|
13
|
+
class OnlyOnce
|
14
|
+
def initialize
|
15
|
+
@mutex = Mutex.new
|
16
|
+
@ran_once = false
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
@mutex.synchronize do
|
21
|
+
return if @ran_once
|
22
|
+
|
23
|
+
@ran_once = true
|
24
|
+
|
25
|
+
yield
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def ran?
|
30
|
+
@mutex.synchronize { @ran_once }
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def reset_ran_once_state_for_tests
|
36
|
+
@mutex.synchronize { @ran_once = false }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|