ddtrace 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -1
  3. data/README.md +1 -1
  4. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.c +5 -4
  5. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.h +1 -1
  6. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +391 -0
  7. data/ext/ddtrace_profiling_native_extension/extconf.rb +2 -0
  8. data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +9 -0
  9. data/ext/ddtrace_profiling_native_extension/profiling.c +2 -0
  10. data/ext/ddtrace_profiling_native_extension/stack_recorder.c +2 -1
  11. data/ext/ddtrace_profiling_native_extension/stack_recorder.h +8 -7
  12. data/lib/datadog/ci/contrib/cucumber/integration.rb +1 -1
  13. data/lib/datadog/ci/contrib/rspec/integration.rb +1 -1
  14. data/lib/datadog/core/configuration/base.rb +9 -0
  15. data/lib/datadog/core/configuration/components.rb +26 -6
  16. data/lib/datadog/core/configuration/settings.rb +25 -0
  17. data/lib/datadog/core/configuration.rb +4 -1
  18. data/lib/datadog/core/telemetry/client.rb +79 -0
  19. data/lib/datadog/core/telemetry/collector.rb +234 -0
  20. data/lib/datadog/core/telemetry/emitter.rb +48 -0
  21. data/lib/datadog/core/telemetry/event.rb +71 -0
  22. data/lib/datadog/core/telemetry/ext.rb +11 -0
  23. data/lib/datadog/core/telemetry/heartbeat.rb +37 -0
  24. data/lib/datadog/core/telemetry/http/adapters/net.rb +113 -0
  25. data/lib/datadog/core/telemetry/http/env.rb +20 -0
  26. data/lib/datadog/core/telemetry/http/ext.rb +20 -0
  27. data/lib/datadog/core/telemetry/http/response.rb +68 -0
  28. data/lib/datadog/core/telemetry/http/transport.rb +53 -0
  29. data/lib/datadog/core/telemetry/v1/app_event.rb +52 -0
  30. data/lib/datadog/core/telemetry/v1/application.rb +86 -0
  31. data/lib/datadog/core/telemetry/v1/configuration.rb +25 -0
  32. data/lib/datadog/core/telemetry/v1/dependency.rb +36 -0
  33. data/lib/datadog/core/telemetry/v1/host.rb +51 -0
  34. data/lib/datadog/core/telemetry/v1/integration.rb +58 -0
  35. data/lib/datadog/core/telemetry/v1/product.rb +28 -0
  36. data/lib/datadog/core/telemetry/v1/telemetry_request.rb +100 -0
  37. data/lib/datadog/core/utils/sequence.rb +5 -0
  38. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +74 -0
  39. data/lib/datadog/profiling/stack_recorder.rb +1 -1
  40. data/lib/datadog/profiling.rb +1 -0
  41. data/lib/datadog/tracing/contrib/extensions.rb +2 -0
  42. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +9 -0
  43. data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
  44. data/lib/datadog/tracing/contrib/patcher.rb +11 -0
  45. data/lib/datadog/tracing/contrib/rack/patcher.rb +8 -0
  46. data/lib/ddtrace/auto_instrument.rb +7 -0
  47. data/lib/ddtrace/transport/ext.rb +0 -1
  48. data/lib/ddtrace/transport/http/adapters/net.rb +1 -0
  49. data/lib/ddtrace/version.rb +1 -1
  50. 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 = Thread::Mutex.new
16
+ @no_concurrent_synchronize_mutex = Mutex.new
17
17
  end
18
18
 
19
19
  def serialize
@@ -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
@@ -15,6 +15,7 @@ module Datadog
15
15
  :timeout,
16
16
  :ssl
17
17
 
18
+ # in seconds
18
19
  DEFAULT_TIMEOUT = 30
19
20
 
20
21
  # @deprecated Positional parameters are deprecated. Use named parameters instead.
@@ -3,7 +3,7 @@
3
3
  module DDTrace
4
4
  module VERSION
5
5
  MAJOR = 1
6
- MINOR = 3
6
+ MINOR = 4
7
7
  PATCH = 0
8
8
  PRE = nil
9
9
 
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.3.0
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-04 00:00:00.000000000 Z
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.0
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.0
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