ddtrace 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -1
- data/README.md +1 -1
- data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.c +5 -4
- data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.h +1 -1
- data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +391 -0
- data/ext/ddtrace_profiling_native_extension/extconf.rb +2 -0
- data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +9 -0
- data/ext/ddtrace_profiling_native_extension/profiling.c +2 -0
- data/ext/ddtrace_profiling_native_extension/stack_recorder.c +2 -1
- data/ext/ddtrace_profiling_native_extension/stack_recorder.h +8 -7
- data/lib/datadog/ci/contrib/cucumber/integration.rb +1 -1
- data/lib/datadog/ci/contrib/rspec/integration.rb +1 -1
- data/lib/datadog/core/configuration/base.rb +9 -0
- data/lib/datadog/core/configuration/components.rb +26 -6
- data/lib/datadog/core/configuration/settings.rb +25 -0
- data/lib/datadog/core/configuration.rb +4 -1
- data/lib/datadog/core/telemetry/client.rb +79 -0
- data/lib/datadog/core/telemetry/collector.rb +234 -0
- data/lib/datadog/core/telemetry/emitter.rb +48 -0
- data/lib/datadog/core/telemetry/event.rb +71 -0
- data/lib/datadog/core/telemetry/ext.rb +11 -0
- data/lib/datadog/core/telemetry/heartbeat.rb +37 -0
- data/lib/datadog/core/telemetry/http/adapters/net.rb +113 -0
- data/lib/datadog/core/telemetry/http/env.rb +20 -0
- data/lib/datadog/core/telemetry/http/ext.rb +20 -0
- data/lib/datadog/core/telemetry/http/response.rb +68 -0
- data/lib/datadog/core/telemetry/http/transport.rb +53 -0
- data/lib/datadog/core/telemetry/v1/app_event.rb +52 -0
- data/lib/datadog/core/telemetry/v1/application.rb +86 -0
- data/lib/datadog/core/telemetry/v1/configuration.rb +25 -0
- data/lib/datadog/core/telemetry/v1/dependency.rb +36 -0
- data/lib/datadog/core/telemetry/v1/host.rb +51 -0
- data/lib/datadog/core/telemetry/v1/integration.rb +58 -0
- data/lib/datadog/core/telemetry/v1/product.rb +28 -0
- data/lib/datadog/core/telemetry/v1/telemetry_request.rb +100 -0
- data/lib/datadog/core/utils/sequence.rb +5 -0
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +74 -0
- data/lib/datadog/profiling/stack_recorder.rb +1 -1
- data/lib/datadog/profiling.rb +1 -0
- data/lib/datadog/tracing/contrib/extensions.rb +2 -0
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +9 -0
- data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/patcher.rb +11 -0
- data/lib/datadog/tracing/contrib/rack/patcher.rb +8 -0
- data/lib/ddtrace/auto_instrument.rb +7 -0
- data/lib/ddtrace/transport/ext.rb +0 -1
- data/lib/ddtrace/transport/http/adapters/net.rb +1 -0
- data/lib/ddtrace/version.rb +1 -1
- metadata +25 -4
@@ -0,0 +1,100 @@
|
|
1
|
+
module Datadog
|
2
|
+
module Core
|
3
|
+
module Telemetry
|
4
|
+
module V1
|
5
|
+
# Describes attributes for telemetry API request
|
6
|
+
class TelemetryRequest
|
7
|
+
ERROR_NIL_API_VERSION_MESSAGE = ':api_version must not be nil'.freeze
|
8
|
+
ERROR_NIL_APPLICATION_MESSAGE = ':application must not be nil'.freeze
|
9
|
+
ERROR_NIL_HOST_MESSAGE = ':host must not be nil'.freeze
|
10
|
+
ERROR_NIL_PAYLOAD_MESSAGE = ':payload must not be nil'.freeze
|
11
|
+
ERROR_NIL_REQUEST_TYPE_MESSAGE = ':request_type must not be nil'.freeze
|
12
|
+
ERROR_NIL_RUNTIME_ID_MESSAGE = ':runtime_id must not be nil'.freeze
|
13
|
+
ERROR_NIL_SEQ_ID_MESSAGE = ':seq_id must not be nil'.freeze
|
14
|
+
ERROR_NIL_TRACER_TIME_MESSAGE = ':tracer_time must not be nil'.freeze
|
15
|
+
|
16
|
+
attr_reader \
|
17
|
+
:api_version,
|
18
|
+
:application,
|
19
|
+
:debug,
|
20
|
+
:host,
|
21
|
+
:payload,
|
22
|
+
:request_type,
|
23
|
+
:runtime_id,
|
24
|
+
:seq_id,
|
25
|
+
:session_id,
|
26
|
+
:tracer_time
|
27
|
+
|
28
|
+
# @param api_version [String] Requested API version, `v1`
|
29
|
+
# @param application [Telemetry::V1::Application] Object that contains information about the environment of the
|
30
|
+
# application
|
31
|
+
# @param host [Telemetry::V1::Host] Object that holds host related information
|
32
|
+
# @param payload [Telemetry::V1::AppEvent] The payload of the request, type impacted by :request_type
|
33
|
+
# @param request_type [String] Requested API function impacting the Payload type, `app-started`
|
34
|
+
# @param runtime_id [String] V4 UUID that represents a tracer session
|
35
|
+
# @param seq_id [Integer] Counter that should be auto incremented every time an API call is being made
|
36
|
+
# @param tracer_time [Integer] Unix timestamp (in seconds) of when the message is being sent
|
37
|
+
# @param debug [Boolean] Flag that enables payload debug mode
|
38
|
+
# @param session_id [String] V4 UUID that represents the session of the top level tracer process, often same\
|
39
|
+
# as runtime_id
|
40
|
+
def initialize(
|
41
|
+
api_version:, application:, host:, payload:, request_type:, runtime_id:, seq_id:, tracer_time:,
|
42
|
+
debug: nil, session_id: nil
|
43
|
+
)
|
44
|
+
validate(
|
45
|
+
api_version: api_version,
|
46
|
+
application: application,
|
47
|
+
host: host,
|
48
|
+
payload: payload,
|
49
|
+
request_type: request_type,
|
50
|
+
runtime_id: runtime_id,
|
51
|
+
seq_id: seq_id,
|
52
|
+
tracer_time: tracer_time
|
53
|
+
)
|
54
|
+
@api_version = api_version
|
55
|
+
@application = application
|
56
|
+
@debug = debug
|
57
|
+
@host = host
|
58
|
+
@payload = payload
|
59
|
+
@request_type = request_type
|
60
|
+
@runtime_id = runtime_id
|
61
|
+
@seq_id = seq_id
|
62
|
+
@session_id = session_id
|
63
|
+
@tracer_time = tracer_time
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_h
|
67
|
+
{
|
68
|
+
api_version: @api_version,
|
69
|
+
application: @application.to_h,
|
70
|
+
debug: @debug,
|
71
|
+
host: @host.to_h,
|
72
|
+
payload: @payload.to_h,
|
73
|
+
request_type: @request_type,
|
74
|
+
runtime_id: @runtime_id,
|
75
|
+
seq_id: @seq_id,
|
76
|
+
session_id: @session_id,
|
77
|
+
tracer_time: @tracer_time
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
# Validates all required arguments passed to the class on initialization are not nil
|
84
|
+
#
|
85
|
+
# @!visibility private
|
86
|
+
def validate(api_version:, application:, host:, payload:, request_type:, runtime_id:, seq_id:, tracer_time:)
|
87
|
+
raise ArgumentError, ERROR_NIL_API_VERSION_MESSAGE if api_version.nil?
|
88
|
+
raise ArgumentError, ERROR_NIL_APPLICATION_MESSAGE if application.nil?
|
89
|
+
raise ArgumentError, ERROR_NIL_HOST_MESSAGE if host.nil?
|
90
|
+
raise ArgumentError, ERROR_NIL_PAYLOAD_MESSAGE if payload.nil?
|
91
|
+
raise ArgumentError, ERROR_NIL_REQUEST_TYPE_MESSAGE if request_type.nil?
|
92
|
+
raise ArgumentError, ERROR_NIL_RUNTIME_ID_MESSAGE if runtime_id.nil?
|
93
|
+
raise ArgumentError, ERROR_NIL_SEQ_ID_MESSAGE if seq_id.nil?
|
94
|
+
raise ArgumentError, ERROR_NIL_TRACER_TIME_MESSAGE if tracer_time.nil?
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -6,6 +6,7 @@ module Datadog
|
|
6
6
|
# Generates values from a consistent sequence
|
7
7
|
class Sequence
|
8
8
|
def initialize(seed = 0, &block)
|
9
|
+
@seed = seed
|
9
10
|
@current = seed
|
10
11
|
@next_item = block
|
11
12
|
end
|
@@ -15,6 +16,10 @@ module Datadog
|
|
15
16
|
@current += 1
|
16
17
|
next_item
|
17
18
|
end
|
19
|
+
|
20
|
+
def reset!
|
21
|
+
@current = @seed
|
22
|
+
end
|
18
23
|
end
|
19
24
|
end
|
20
25
|
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# typed: false
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module Profiling
|
5
|
+
module Collectors
|
6
|
+
# Used to trigger the periodic execution of Collectors::CpuAndWallTime, which implements all of the sampling logic
|
7
|
+
# itself; this class only implements the "doing it periodically" part.
|
8
|
+
# Almost all of this class is implemented as native code.
|
9
|
+
#
|
10
|
+
# Methods prefixed with _native_ are implemented in `collectors_cpu_and_wall_time_worker.c`
|
11
|
+
class CpuAndWallTimeWorker
|
12
|
+
private
|
13
|
+
|
14
|
+
attr_accessor :failure_exception
|
15
|
+
|
16
|
+
public
|
17
|
+
|
18
|
+
def initialize(
|
19
|
+
recorder:,
|
20
|
+
max_frames:,
|
21
|
+
cpu_and_wall_time_collector: CpuAndWallTime.new(recorder: recorder, max_frames: max_frames)
|
22
|
+
)
|
23
|
+
self.class._native_initialize(self, cpu_and_wall_time_collector)
|
24
|
+
@worker_thread = nil
|
25
|
+
@failure_exception = nil
|
26
|
+
@start_stop_mutex = Mutex.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def start
|
30
|
+
@start_stop_mutex.synchronize do
|
31
|
+
return if @worker_thread
|
32
|
+
|
33
|
+
Datadog.logger.debug { "Starting thread for: #{self}" }
|
34
|
+
@worker_thread = Thread.new do
|
35
|
+
begin
|
36
|
+
Thread.current.name = self.class.name unless Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.3')
|
37
|
+
|
38
|
+
self.class._native_sampling_loop(self)
|
39
|
+
|
40
|
+
Datadog.logger.debug('CpuAndWallTimeWorker thread stopping cleanly')
|
41
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
42
|
+
@failure_exception = e
|
43
|
+
Datadog.logger.warn(
|
44
|
+
"Worker thread error. Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
# TODO: Provided only for compatibility with the API for Collectors::OldStack used in the Profiler class.
|
54
|
+
# Can be removed once we remove OldStack.
|
55
|
+
def enabled=(_); end
|
56
|
+
|
57
|
+
def stop(*_)
|
58
|
+
@start_stop_mutex.synchronize do
|
59
|
+
Datadog.logger.debug('Requesting CpuAndWallTimeWorker thread shut down')
|
60
|
+
|
61
|
+
return unless @worker_thread
|
62
|
+
|
63
|
+
@worker_thread.kill
|
64
|
+
self.class._native_stop(self)
|
65
|
+
|
66
|
+
@worker_thread.join
|
67
|
+
@worker_thread = nil
|
68
|
+
@failure_exception = nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -13,7 +13,7 @@ module Datadog
|
|
13
13
|
# This isn't something we expect to happen normally, but because it would break the assumptions of the
|
14
14
|
# C-level mutexes (that there is a single serializer thread), we add it here as an extra safeguard against it
|
15
15
|
# accidentally happening.
|
16
|
-
@no_concurrent_synchronize_mutex =
|
16
|
+
@no_concurrent_synchronize_mutex = Mutex.new
|
17
17
|
end
|
18
18
|
|
19
19
|
def serialize
|
data/lib/datadog/profiling.rb
CHANGED
@@ -148,6 +148,7 @@ module Datadog
|
|
148
148
|
require_relative 'profiling/ext/forking'
|
149
149
|
require_relative 'profiling/collectors/code_provenance'
|
150
150
|
require_relative 'profiling/collectors/cpu_and_wall_time'
|
151
|
+
require_relative 'profiling/collectors/cpu_and_wall_time_worker'
|
151
152
|
require_relative 'profiling/collectors/old_stack'
|
152
153
|
require_relative 'profiling/collectors/stack'
|
153
154
|
require_relative 'profiling/stack_recorder'
|
@@ -97,6 +97,8 @@ module Datadog
|
|
97
97
|
Datadog.logger.warn("Unable to patch #{patch_results[:name]} (#{desc})")
|
98
98
|
end
|
99
99
|
|
100
|
+
components.telemetry.integrations_change! if configuration.integrations_pending_activation
|
101
|
+
|
100
102
|
configuration.integrations_pending_activation.clear
|
101
103
|
end
|
102
104
|
|
@@ -44,6 +44,9 @@ module Datadog
|
|
44
44
|
host, _port = find_host_port(call)
|
45
45
|
span.set_tag(Tracing::Metadata::Ext::TAG_PEER_HOSTNAME, host) if host
|
46
46
|
|
47
|
+
deadline = find_deadline(call)
|
48
|
+
span.set_tag(Ext::TAG_CLIENT_DEADLINE, deadline) if deadline
|
49
|
+
|
47
50
|
# Set analytics sample rate
|
48
51
|
Contrib::Analytics.set_sample_rate(span, analytics_sample_rate) if analytics_enabled?
|
49
52
|
|
@@ -60,6 +63,12 @@ module Datadog
|
|
60
63
|
.join('.')
|
61
64
|
end
|
62
65
|
|
66
|
+
def find_deadline(call)
|
67
|
+
return unless call.respond_to?(:deadline) && call.deadline.is_a?(Time)
|
68
|
+
|
69
|
+
call.deadline.utc.iso8601(3)
|
70
|
+
end
|
71
|
+
|
63
72
|
def find_host_port(call)
|
64
73
|
return unless call
|
65
74
|
|
@@ -13,6 +13,7 @@ module Datadog
|
|
13
13
|
DEFAULT_PEER_SERVICE_NAME = 'grpc'.freeze
|
14
14
|
SPAN_CLIENT = 'grpc.client'.freeze
|
15
15
|
SPAN_SERVICE = 'grpc.service'.freeze
|
16
|
+
TAG_CLIENT_DEADLINE = 'grpc.client.deadline'.freeze
|
16
17
|
TAG_COMPONENT = 'grpc'.freeze
|
17
18
|
TAG_OPERATION_CLIENT = 'client'.freeze
|
18
19
|
TAG_OPERATION_SERVICE = 'service'.freeze
|
@@ -19,6 +19,10 @@ module Datadog
|
|
19
19
|
# Prepended instance methods for all patchers
|
20
20
|
# @public_api
|
21
21
|
module CommonMethods
|
22
|
+
attr_accessor \
|
23
|
+
:patch_error_result,
|
24
|
+
:patch_successful
|
25
|
+
|
22
26
|
def patch_name
|
23
27
|
self.class != Class && self.class != Module ? self.class.name : name
|
24
28
|
end
|
@@ -35,6 +39,7 @@ module Datadog
|
|
35
39
|
super.tap do
|
36
40
|
# Emit a metric
|
37
41
|
Datadog.health_metrics.instrumentation_patched(1, tags: default_tags)
|
42
|
+
@patch_successful = true
|
38
43
|
end
|
39
44
|
rescue StandardError => e
|
40
45
|
on_patch_error(e)
|
@@ -48,6 +53,12 @@ module Datadog
|
|
48
53
|
# Log the error
|
49
54
|
Datadog.logger.error("Failed to apply #{patch_name} patch. Cause: #{e} Location: #{Array(e.backtrace).first}")
|
50
55
|
|
56
|
+
@patch_error_result = {
|
57
|
+
type: e.class.name,
|
58
|
+
message: e.message,
|
59
|
+
line: Array(e.backtrace).first
|
60
|
+
}
|
61
|
+
|
51
62
|
# Emit a metric
|
52
63
|
tags = default_tags
|
53
64
|
tags << "error:#{e.class.name}"
|
@@ -104,6 +104,14 @@ module Datadog
|
|
104
104
|
def get_option(option)
|
105
105
|
Datadog.configuration.tracing[:rack].get_option(option)
|
106
106
|
end
|
107
|
+
|
108
|
+
def patch_successful
|
109
|
+
MiddlewarePatcher.patch_successful || MiddlewareNamePatcher.patch_successful
|
110
|
+
end
|
111
|
+
|
112
|
+
def patch_error_result
|
113
|
+
MiddlewarePatcher.patch_error_result || MiddlewareNamePatcher.patch_error_result
|
114
|
+
end
|
107
115
|
end
|
108
116
|
end
|
109
117
|
end
|
@@ -7,3 +7,10 @@ require_relative '../ddtrace'
|
|
7
7
|
require_relative '../datadog/tracing/contrib/auto_instrument'
|
8
8
|
|
9
9
|
Datadog::Profiling.start_if_enabled
|
10
|
+
|
11
|
+
module Datadog
|
12
|
+
module AutoInstrument
|
13
|
+
# Flag to determine if Auto Instrumentation was used
|
14
|
+
LOADED = true
|
15
|
+
end
|
16
|
+
end
|
@@ -9,7 +9,6 @@ module Datadog
|
|
9
9
|
ADAPTER = :net_http # DEV: Rename to simply `:http`, as Net::HTTP is an implementation detail.
|
10
10
|
DEFAULT_HOST = '127.0.0.1'.freeze
|
11
11
|
DEFAULT_PORT = 8126
|
12
|
-
DEFAULT_TIMEOUT_SECONDS = 1
|
13
12
|
|
14
13
|
HEADER_CONTAINER_ID = 'Datadog-Container-ID'.freeze
|
15
14
|
HEADER_DD_API_KEY = 'DD-API-KEY'.freeze
|
data/lib/ddtrace/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ddtrace
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Datadog, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-08-
|
11
|
+
date: 2022-08-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msgpack
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0.7.0.1.
|
61
|
+
version: 0.7.0.1.1
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 0.7.0.1.
|
68
|
+
version: 0.7.0.1.1
|
69
69
|
description: |
|
70
70
|
ddtrace is Datadog's tracing client for Ruby. It is used to trace requests
|
71
71
|
as they flow across web servers, databases and microservices so that developers
|
@@ -95,6 +95,7 @@ files:
|
|
95
95
|
- ext/ddtrace_profiling_native_extension/clock_id_noop.c
|
96
96
|
- ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.c
|
97
97
|
- ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.h
|
98
|
+
- ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time_worker.c
|
98
99
|
- ext/ddtrace_profiling_native_extension/collectors_stack.c
|
99
100
|
- ext/ddtrace_profiling_native_extension/collectors_stack.h
|
100
101
|
- ext/ddtrace_profiling_native_extension/extconf.rb
|
@@ -227,6 +228,25 @@ files:
|
|
227
228
|
- lib/datadog/core/pin.rb
|
228
229
|
- lib/datadog/core/runtime/ext.rb
|
229
230
|
- lib/datadog/core/runtime/metrics.rb
|
231
|
+
- lib/datadog/core/telemetry/client.rb
|
232
|
+
- lib/datadog/core/telemetry/collector.rb
|
233
|
+
- lib/datadog/core/telemetry/emitter.rb
|
234
|
+
- lib/datadog/core/telemetry/event.rb
|
235
|
+
- lib/datadog/core/telemetry/ext.rb
|
236
|
+
- lib/datadog/core/telemetry/heartbeat.rb
|
237
|
+
- lib/datadog/core/telemetry/http/adapters/net.rb
|
238
|
+
- lib/datadog/core/telemetry/http/env.rb
|
239
|
+
- lib/datadog/core/telemetry/http/ext.rb
|
240
|
+
- lib/datadog/core/telemetry/http/response.rb
|
241
|
+
- lib/datadog/core/telemetry/http/transport.rb
|
242
|
+
- lib/datadog/core/telemetry/v1/app_event.rb
|
243
|
+
- lib/datadog/core/telemetry/v1/application.rb
|
244
|
+
- lib/datadog/core/telemetry/v1/configuration.rb
|
245
|
+
- lib/datadog/core/telemetry/v1/dependency.rb
|
246
|
+
- lib/datadog/core/telemetry/v1/host.rb
|
247
|
+
- lib/datadog/core/telemetry/v1/integration.rb
|
248
|
+
- lib/datadog/core/telemetry/v1/product.rb
|
249
|
+
- lib/datadog/core/telemetry/v1/telemetry_request.rb
|
230
250
|
- lib/datadog/core/utils.rb
|
231
251
|
- lib/datadog/core/utils/compression.rb
|
232
252
|
- lib/datadog/core/utils/forking.rb
|
@@ -274,6 +294,7 @@ files:
|
|
274
294
|
- lib/datadog/profiling/buffer.rb
|
275
295
|
- lib/datadog/profiling/collectors/code_provenance.rb
|
276
296
|
- lib/datadog/profiling/collectors/cpu_and_wall_time.rb
|
297
|
+
- lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb
|
277
298
|
- lib/datadog/profiling/collectors/old_stack.rb
|
278
299
|
- lib/datadog/profiling/collectors/stack.rb
|
279
300
|
- lib/datadog/profiling/encoding/profile.rb
|