ddtrace 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -16
  3. data/CHANGELOG.md +31 -2
  4. data/LICENSE-3rdparty.csv +3 -2
  5. data/README.md +2 -2
  6. data/ddtrace.gemspec +12 -3
  7. data/docs/GettingStarted.md +19 -2
  8. data/docs/ProfilingDevelopment.md +8 -8
  9. data/docs/UpgradeGuide.md +3 -3
  10. data/ext/ddtrace_profiling_loader/ddtrace_profiling_loader.c +118 -0
  11. data/ext/ddtrace_profiling_loader/extconf.rb +53 -0
  12. data/ext/ddtrace_profiling_native_extension/NativeExtensionDesign.md +31 -5
  13. data/ext/ddtrace_profiling_native_extension/clock_id_from_pthread.c +0 -8
  14. data/ext/ddtrace_profiling_native_extension/collectors_stack.c +278 -0
  15. data/ext/ddtrace_profiling_native_extension/extconf.rb +70 -100
  16. data/ext/ddtrace_profiling_native_extension/libddprof_helpers.h +13 -0
  17. data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +186 -0
  18. data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +579 -7
  19. data/ext/ddtrace_profiling_native_extension/private_vm_api_access.h +30 -0
  20. data/ext/ddtrace_profiling_native_extension/profiling.c +7 -0
  21. data/ext/ddtrace_profiling_native_extension/stack_recorder.c +139 -0
  22. data/ext/ddtrace_profiling_native_extension/stack_recorder.h +28 -0
  23. data/lib/datadog/appsec/autoload.rb +2 -2
  24. data/lib/datadog/appsec/configuration/settings.rb +19 -0
  25. data/lib/datadog/appsec/configuration.rb +8 -0
  26. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +76 -33
  27. data/lib/datadog/appsec/contrib/rack/integration.rb +1 -0
  28. data/lib/datadog/appsec/contrib/rack/patcher.rb +0 -1
  29. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +64 -0
  30. data/lib/datadog/appsec/contrib/rack/request.rb +6 -0
  31. data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +41 -0
  32. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +60 -5
  33. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +81 -0
  34. data/lib/datadog/appsec/contrib/rails/patcher.rb +34 -1
  35. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +68 -0
  36. data/lib/datadog/appsec/contrib/rails/request.rb +33 -0
  37. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +124 -0
  38. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +69 -2
  39. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +63 -0
  40. data/lib/datadog/appsec/event.rb +33 -18
  41. data/lib/datadog/appsec/extensions.rb +0 -3
  42. data/lib/datadog/appsec/processor.rb +45 -2
  43. data/lib/datadog/appsec/rate_limiter.rb +5 -0
  44. data/lib/datadog/appsec/reactive/operation.rb +0 -1
  45. data/lib/datadog/ci/ext/environment.rb +21 -7
  46. data/lib/datadog/core/configuration/agent_settings_resolver.rb +1 -1
  47. data/lib/datadog/core/configuration/components.rb +22 -4
  48. data/lib/datadog/core/configuration/settings.rb +3 -3
  49. data/lib/datadog/core/configuration.rb +7 -5
  50. data/lib/datadog/core/environment/cgroup.rb +3 -1
  51. data/lib/datadog/core/environment/container.rb +2 -1
  52. data/lib/datadog/core/environment/variable_helpers.rb +26 -2
  53. data/lib/datadog/core/logging/ext.rb +11 -0
  54. data/lib/datadog/core/metrics/client.rb +15 -5
  55. data/lib/datadog/core/runtime/metrics.rb +1 -1
  56. data/lib/datadog/core/workers/async.rb +3 -1
  57. data/lib/datadog/core/workers/runtime_metrics.rb +0 -3
  58. data/lib/datadog/core.rb +6 -0
  59. data/lib/datadog/kit/enable_core_dumps.rb +50 -0
  60. data/lib/datadog/kit/identity.rb +63 -0
  61. data/lib/datadog/kit.rb +11 -0
  62. data/lib/datadog/opentracer/tracer.rb +0 -2
  63. data/lib/datadog/profiling/collectors/old_stack.rb +298 -0
  64. data/lib/datadog/profiling/collectors/stack.rb +6 -287
  65. data/lib/datadog/profiling/encoding/profile.rb +0 -1
  66. data/lib/datadog/profiling/ext.rb +1 -1
  67. data/lib/datadog/profiling/flush.rb +1 -1
  68. data/lib/datadog/profiling/load_native_extension.rb +22 -0
  69. data/lib/datadog/profiling/recorder.rb +1 -1
  70. data/lib/datadog/profiling/scheduler.rb +1 -1
  71. data/lib/datadog/profiling/stack_recorder.rb +33 -0
  72. data/lib/datadog/profiling/tag_builder.rb +48 -0
  73. data/lib/datadog/profiling/tasks/exec.rb +2 -2
  74. data/lib/datadog/profiling/tasks/setup.rb +6 -4
  75. data/lib/datadog/profiling.rb +29 -27
  76. data/lib/datadog/tracing/buffer.rb +9 -3
  77. data/lib/datadog/tracing/contrib/action_view/patcher.rb +0 -1
  78. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +2 -2
  79. data/lib/datadog/tracing/contrib/active_record/utils.rb +1 -1
  80. data/lib/datadog/tracing/contrib/active_record/vendor/connection_specification.rb +1 -1
  81. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +4 -2
  82. data/lib/datadog/tracing/contrib/concurrent_ruby/context_composite_executor_service.rb +10 -3
  83. data/lib/datadog/tracing/contrib/dalli/patcher.rb +0 -1
  84. data/lib/datadog/tracing/contrib/delayed_job/patcher.rb +0 -1
  85. data/lib/datadog/tracing/contrib/elasticsearch/integration.rb +9 -3
  86. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +38 -2
  87. data/lib/datadog/tracing/contrib/ethon/patcher.rb +0 -1
  88. data/lib/datadog/tracing/contrib/extensions.rb +0 -2
  89. data/lib/datadog/tracing/contrib/faraday/patcher.rb +0 -1
  90. data/lib/datadog/tracing/contrib/grape/patcher.rb +0 -1
  91. data/lib/datadog/tracing/contrib/graphql/patcher.rb +0 -1
  92. data/lib/datadog/tracing/contrib/grpc/patcher.rb +0 -1
  93. data/lib/datadog/tracing/contrib/kafka/patcher.rb +0 -1
  94. data/lib/datadog/tracing/contrib/lograge/instrumentation.rb +2 -1
  95. data/lib/datadog/tracing/contrib/qless/patcher.rb +0 -1
  96. data/lib/datadog/tracing/contrib/que/patcher.rb +0 -1
  97. data/lib/datadog/tracing/contrib/racecar/patcher.rb +0 -1
  98. data/lib/datadog/tracing/contrib/rails/log_injection.rb +3 -16
  99. data/lib/datadog/tracing/contrib/rake/instrumentation.rb +2 -2
  100. data/lib/datadog/tracing/contrib/rake/patcher.rb +0 -1
  101. data/lib/datadog/tracing/contrib/redis/patcher.rb +0 -1
  102. data/lib/datadog/tracing/contrib/resque/patcher.rb +0 -1
  103. data/lib/datadog/tracing/contrib/rest_client/patcher.rb +0 -1
  104. data/lib/datadog/tracing/contrib/semantic_logger/instrumentation.rb +2 -1
  105. data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +1 -0
  106. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +20 -1
  107. data/lib/datadog/tracing/contrib/sinatra/framework.rb +11 -0
  108. data/lib/datadog/tracing/contrib/sinatra/patcher.rb +0 -1
  109. data/lib/datadog/tracing/contrib/sneakers/patcher.rb +0 -1
  110. data/lib/datadog/tracing/contrib/sucker_punch/patcher.rb +0 -1
  111. data/lib/datadog/tracing/event.rb +2 -1
  112. data/lib/datadog/tracing/sampling/priority_sampler.rb +4 -5
  113. data/lib/datadog/tracing/sampling/rule.rb +12 -6
  114. data/lib/datadog/tracing/sampling/rule_sampler.rb +3 -5
  115. data/lib/datadog/tracing/span_operation.rb +2 -3
  116. data/lib/datadog/tracing/trace_operation.rb +0 -1
  117. data/lib/ddtrace/transport/http/client.rb +2 -1
  118. data/lib/ddtrace/transport/http/response.rb +34 -4
  119. data/lib/ddtrace/transport/io/client.rb +3 -1
  120. data/lib/ddtrace/version.rb +1 -1
  121. data/lib/ddtrace.rb +1 -0
  122. metadata +43 -6
@@ -16,9 +16,40 @@ module Datadog
16
16
  end
17
17
  end
18
18
 
19
+ # Context manages a sequence of runs
20
+ class Context
21
+ attr_reader :time_ns, :time_ext_ns, :timeouts, :events
22
+
23
+ def initialize(processor)
24
+ @context = Datadog::AppSec::WAF::Context.new(processor.send(:handle))
25
+ @time_ns = 0.0
26
+ @time_ext_ns = 0.0
27
+ @timeouts = 0
28
+ @events = []
29
+ end
30
+
31
+ def run(*args)
32
+ start_ns = Core::Utils::Time.get_time(:nanosecond)
33
+
34
+ ret, res = @context.run(*args)
35
+
36
+ stop_ns = Core::Utils::Time.get_time(:nanosecond)
37
+
38
+ @time_ns += res.total_runtime
39
+ @time_ext_ns += (stop_ns - start_ns)
40
+ @timeouts += 1 if res.timeout
41
+
42
+ [ret, res]
43
+ end
44
+ end
45
+
46
+ attr_reader :ruleset_info, :addresses
47
+
19
48
  def initialize
20
49
  @ruleset = nil
21
50
  @handle = nil
51
+ @ruleset_info = nil
52
+ @addresses = nil
22
53
 
23
54
  unless load_libddwaf && load_ruleset && create_waf_handle
24
55
  Datadog.logger.warn { 'AppSec is disabled, see logged errors above' }
@@ -30,9 +61,13 @@ module Datadog
30
61
  end
31
62
 
32
63
  def new_context
33
- Datadog::AppSec::WAF::Context.new(@handle)
64
+ Context.new(self)
34
65
  end
35
66
 
67
+ protected
68
+
69
+ attr_reader :handle
70
+
36
71
  private
37
72
 
38
73
  def load_libddwaf
@@ -70,7 +105,13 @@ module Datadog
70
105
  # TODO: this may need to be reset if the main Datadog logging level changes after initialization
71
106
  Datadog::AppSec::WAF.logger = Datadog.logger if Datadog.logger.debug? && Datadog::AppSec.settings.waf_debug
72
107
 
73
- @handle = Datadog::AppSec::WAF::Handle.new(@ruleset)
108
+ obfuscator_config = {
109
+ key_regex: Datadog::AppSec.settings.obfuscator_key_regex,
110
+ value_regex: Datadog::AppSec.settings.obfuscator_value_regex,
111
+ }
112
+ @handle = Datadog::AppSec::WAF::Handle.new(@ruleset, obfuscator: obfuscator_config)
113
+ @ruleset_info = @handle.ruleset_info
114
+ @addresses = @handle.required_addresses
74
115
 
75
116
  true
76
117
  rescue StandardError => e
@@ -78,6 +119,8 @@ module Datadog
78
119
  "libddwaf failed to initialize, error: #{e.inspect}"
79
120
  end
80
121
 
122
+ @ruleset_info = e.ruleset_info if e.respond_to?(:ruleset_info)
123
+
81
124
  false
82
125
  end
83
126
 
@@ -35,6 +35,11 @@ module Datadog
35
35
  rate_limiter(name).limit(&block)
36
36
  end
37
37
 
38
+ # reset a rate limiter: used for testing
39
+ def reset!(name)
40
+ Thread.current[:datadog_security_trace_rate_limiter] = nil
41
+ end
42
+
38
43
  protected
39
44
 
40
45
  def rate_limiter(name)
@@ -1,6 +1,5 @@
1
1
  # typed: true
2
2
 
3
- require 'datadog/appsec'
4
3
  require 'datadog/appsec/reactive/engine'
5
4
 
6
5
  module Datadog
@@ -379,49 +379,63 @@ module Datadog
379
379
  committer_date: Time.at(fields[5].to_i).utc.to_datetime.iso8601
380
380
  }
381
381
  rescue => e
382
- Datadog.logger.debug("Unable to read git commit users: #{e.message} at #{Array(e.backtrace).first}")
382
+ Datadog.logger.debug(
383
+ "Unable to read git commit users: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
384
+ )
383
385
  nil
384
386
  end
385
387
 
386
388
  def git_repository_url
387
389
  exec_git_command('git ls-remote --get-url')
388
390
  rescue => e
389
- Datadog.logger.debug("Unable to read git repository url: #{e.message} at #{Array(e.backtrace).first}")
391
+ Datadog.logger.debug(
392
+ "Unable to read git repository url: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
393
+ )
390
394
  nil
391
395
  end
392
396
 
393
397
  def git_commit_message
394
398
  exec_git_command('git show -s --format=%s')
395
399
  rescue => e
396
- Datadog.logger.debug("Unable to read git commit message: #{e.message} at #{Array(e.backtrace).first}")
400
+ Datadog.logger.debug(
401
+ "Unable to read git commit message: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
402
+ )
397
403
  nil
398
404
  end
399
405
 
400
406
  def git_branch
401
407
  exec_git_command('git rev-parse --abbrev-ref HEAD')
402
408
  rescue => e
403
- Datadog.logger.debug("Unable to read git branch: #{e.message} at #{Array(e.backtrace).first}")
409
+ Datadog.logger.debug(
410
+ "Unable to read git branch: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
411
+ )
404
412
  nil
405
413
  end
406
414
 
407
415
  def git_commit_sha
408
416
  exec_git_command('git rev-parse HEAD')
409
417
  rescue => e
410
- Datadog.logger.debug("Unable to read git commit SHA: #{e.message} at #{Array(e.backtrace).first}")
418
+ Datadog.logger.debug(
419
+ "Unable to read git commit SHA: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
420
+ )
411
421
  nil
412
422
  end
413
423
 
414
424
  def git_tag
415
425
  exec_git_command('git tag --points-at HEAD')
416
426
  rescue => e
417
- Datadog.logger.debug("Unable to read git tag: #{e.message} at #{Array(e.backtrace).first}")
427
+ Datadog.logger.debug(
428
+ "Unable to read git tag: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
429
+ )
418
430
  nil
419
431
  end
420
432
 
421
433
  def git_base_directory
422
434
  exec_git_command('git rev-parse --show-toplevel')
423
435
  rescue => e
424
- Datadog.logger.debug("Unable to read git base directory: #{e.message} at #{Array(e.backtrace).first}")
436
+ Datadog.logger.debug(
437
+ "Unable to read git base directory: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
438
+ )
425
439
  nil
426
440
  end
427
441
 
@@ -303,7 +303,7 @@ module Datadog
303
303
  if logger
304
304
  logger.debug do
305
305
  'Could not extract configuration from transport_options proc. ' \
306
- "Cause: #{e.message} Source: #{Array(e.backtrace).first}"
306
+ "Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
307
307
  end
308
308
  end
309
309
 
@@ -11,8 +11,6 @@ require 'datadog/tracing/tracer'
11
11
  require 'datadog/tracing/flush'
12
12
  require 'datadog/tracing/sync_writer'
13
13
 
14
- require 'datadog/profiling'
15
-
16
14
  module Datadog
17
15
  module Core
18
16
  module Configuration
@@ -181,7 +179,27 @@ module Datadog
181
179
  end
182
180
 
183
181
  def build_profiler(settings, agent_settings, tracer)
184
- return unless Profiling.supported? && settings.profiling.enabled
182
+ return unless settings.profiling.enabled
183
+
184
+ # Workaround for weird dependency direction: the Core::Configuration::Components class currently has a
185
+ # dependency on individual products, in this case the Profiler.
186
+ # (Note "currently": in the future we want to change this so core classes don't depend on specific products)
187
+ #
188
+ # If the current file included a `require 'datadog/profiler'` at its beginning, we would generate circular
189
+ # requires when used from profiling:
190
+ #
191
+ # datadog/profiling
192
+ # └─requires─> datadog/core
193
+ # └─requires─> datadog/core/configuration/components
194
+ # └─requires─> datadog/profiling # Loop!
195
+ #
196
+ # ...thus in #1998 we removed such a require.
197
+ #
198
+ # On the other hand, if datadog/core is loaded by a different product and no general `require 'ddtrace'` is
199
+ # done, then profiling may not be loaded, and thus to avoid this issue we do a require here (which is a
200
+ # no-op if profiling is already loaded).
201
+ require 'datadog/profiling'
202
+ return unless Profiling.supported?
185
203
 
186
204
  unless defined?(Profiling::Tasks::Setup)
187
205
  # In #1545 a user reported a NameError due to this constant being uninitialized
@@ -278,7 +296,7 @@ module Datadog
278
296
 
279
297
  def build_profiler_collectors(settings, recorder, trace_identifiers_helper)
280
298
  [
281
- Profiling::Collectors::Stack.new(
299
+ Profiling::Collectors::OldStack.new(
282
300
  recorder,
283
301
  trace_identifiers_helper: trace_identifiers_helper,
284
302
  max_frames: settings.profiling.advanced.max_frames
@@ -305,7 +305,7 @@ module Datadog
305
305
  tags = {}
306
306
 
307
307
  # Parse tags from environment
308
- env_to_list(Core::Environment::Ext::ENV_TAGS).each do |tag|
308
+ env_to_list(Core::Environment::Ext::ENV_TAGS, comma_separated_only: false).each do |tag|
309
309
  pair = tag.split(':')
310
310
  tags[pair.first] = pair.last if pair.length == 2
311
311
  end
@@ -412,7 +412,7 @@ module Datadog
412
412
  Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG,
413
413
  Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3,
414
414
  Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER
415
- ]
415
+ ], comma_separated_only: true
416
416
  )
417
417
  end
418
418
 
@@ -430,7 +430,7 @@ module Datadog
430
430
  o.default do
431
431
  env_to_list(
432
432
  Tracing::Configuration::Ext::Distributed::ENV_PROPAGATION_STYLE_INJECT,
433
- [Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG] # Only inject Datadog headers by default
433
+ [Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG], comma_separated_only: true # Only inject Datadog headers by default
434
434
  )
435
435
  end
436
436
 
@@ -1,6 +1,5 @@
1
1
  # typed: true
2
2
 
3
- require 'forwardable'
4
3
  require 'datadog/core/configuration/components'
5
4
  require 'datadog/core/configuration/settings'
6
5
  require 'datadog/core/logger'
@@ -11,7 +10,6 @@ module Datadog
11
10
  # Configuration provides a unique access point for configurations
12
11
  module Configuration # rubocop:disable Metrics/ModuleLength
13
12
  include Kernel # Ensure that kernel methods are always available (https://sorbet.org/docs/error-reference#7003)
14
- extend Forwardable
15
13
 
16
14
  # Used to ensure that @components initialization/reconfiguration is performed one-at-a-time, by a single thread.
17
15
  #
@@ -154,9 +152,13 @@ module Datadog
154
152
  pin[option] if pin
155
153
  end
156
154
 
157
- def_delegators \
158
- :components,
159
- :health_metrics
155
+ # Internal {Datadog::Statsd} metrics collection.
156
+ #
157
+ # The list of metrics collected can be found in {Datadog::Core::Diagnostics::Ext::Health::Metrics}.
158
+ # @public_api
159
+ def health_metrics
160
+ components.health_metrics
161
+ end
160
162
 
161
163
  def logger
162
164
  # avoid initializing components if they didn't already exist
@@ -35,7 +35,9 @@ module Datadog
35
35
  end
36
36
  end
37
37
  rescue StandardError => e
38
- Datadog.logger.error("Error while parsing cgroup. Cause: #{e.message} Location: #{Array(e.backtrace).first}")
38
+ Datadog.logger.error(
39
+ "Error while parsing cgroup. Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
40
+ )
39
41
  end
40
42
  end
41
43
  end
@@ -81,7 +81,8 @@ module Datadog
81
81
  end
82
82
  rescue StandardError => e
83
83
  Datadog.logger.error(
84
- "Error while parsing container info. Cause: #{e.message} Location: #{Array(e.backtrace).first}"
84
+ "Error while parsing container info. Cause: #{e.class.name} #{e.message} " \
85
+ "Location: #{Array(e.backtrace).first}"
85
86
  )
86
87
  end
87
88
  end
@@ -24,10 +24,34 @@ module Datadog
24
24
  var && ENV.key?(var) ? ENV[var].to_f : default
25
25
  end
26
26
 
27
- def env_to_list(var, default = [])
27
+ # Parses comma- or space-separated lists.
28
+ #
29
+ # If a comma is present, then the list is considered comma-separated.
30
+ # Otherwise, it is considered space-separated.
31
+ #
32
+ # After the entries are separated, commas and whitespaces that are
33
+ # either trailing or leading are trimmed.
34
+ #
35
+ # Empty entries, after trimmed, are also removed from the result.
36
+ def env_to_list(var, default = [], comma_separated_only:)
28
37
  var = decode_array(var)
29
38
  if var && ENV.key?(var)
30
- ENV[var].split(',').map(&:strip)
39
+ value = ENV[var]
40
+
41
+ values = if value.include?(',') || comma_separated_only
42
+ value.split(',')
43
+ else
44
+ value.split(' ') # rubocop:disable Style/RedundantArgument
45
+ end
46
+
47
+ values.map! do |v|
48
+ v.gsub!(/\A[\s,]*|[\s,]*\Z/, '')
49
+
50
+ v.empty? ? nil : v
51
+ end
52
+
53
+ values.compact!
54
+ values
31
55
  else
32
56
  default
33
57
  end
@@ -0,0 +1,11 @@
1
+ module Datadog
2
+ module Core
3
+ module Logging
4
+ module Ext
5
+ # The technology from which the log originated.
6
+ # @see https://docs.datadoghq.com/api/latest/logs/#send-logs
7
+ DD_SOURCE = 'ruby'.freeze
8
+ end
9
+ end
10
+ end
11
+ end
@@ -96,7 +96,9 @@ module Datadog
96
96
 
97
97
  statsd.count(stat, value, metric_options(options))
98
98
  rescue StandardError => e
99
- Datadog.logger.error("Failed to send count stat. Cause: #{e.message} Source: #{Array(e.backtrace).first}")
99
+ Datadog.logger.error(
100
+ "Failed to send count stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
101
+ )
100
102
  end
101
103
 
102
104
  def distribution(stat, value = nil, options = nil, &block)
@@ -107,7 +109,9 @@ module Datadog
107
109
 
108
110
  statsd.distribution(stat, value, metric_options(options))
109
111
  rescue StandardError => e
110
- Datadog.logger.error("Failed to send distribution stat. Cause: #{e.message} Source: #{Array(e.backtrace).first}")
112
+ Datadog.logger.error(
113
+ "Failed to send distribution stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
114
+ )
111
115
  end
112
116
 
113
117
  def increment(stat, options = nil)
@@ -117,7 +121,9 @@ module Datadog
117
121
 
118
122
  statsd.increment(stat, metric_options(options))
119
123
  rescue StandardError => e
120
- Datadog.logger.error("Failed to send increment stat. Cause: #{e.message} Source: #{Array(e.backtrace).first}")
124
+ Datadog.logger.error(
125
+ "Failed to send increment stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
126
+ )
121
127
  end
122
128
 
123
129
  def gauge(stat, value = nil, options = nil, &block)
@@ -128,7 +134,9 @@ module Datadog
128
134
 
129
135
  statsd.gauge(stat, value, metric_options(options))
130
136
  rescue StandardError => e
131
- Datadog.logger.error("Failed to send gauge stat. Cause: #{e.message} Source: #{Array(e.backtrace).first}")
137
+ Datadog.logger.error(
138
+ "Failed to send gauge stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
139
+ )
132
140
  end
133
141
 
134
142
  def time(stat, options = nil)
@@ -144,7 +152,9 @@ module Datadog
144
152
  distribution(stat, ((finished - start) * 1000), options)
145
153
  end
146
154
  rescue StandardError => e
147
- Datadog.logger.error("Failed to send time stat. Cause: #{e.message} Source: #{Array(e.backtrace).first}")
155
+ Datadog.logger.error(
156
+ "Failed to send time stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
157
+ )
148
158
  end
149
159
  end
150
160
 
@@ -79,7 +79,7 @@ module Datadog
79
79
  def try_flush
80
80
  yield
81
81
  rescue StandardError => e
82
- Datadog.logger.error("Error while sending runtime metric. Cause: #{e.message}")
82
+ Datadog.logger.error("Error while sending runtime metric. Cause: #{e.class.name} #{e.message}")
83
83
  end
84
84
 
85
85
  def default_metric_options
@@ -138,7 +138,9 @@ module Datadog
138
138
  # rubocop:disable Lint/RescueException
139
139
  rescue Exception => e
140
140
  @error = e
141
- Datadog.logger.debug("Worker thread error. Cause #{e.message} Location: #{Array(e.backtrace).first}")
141
+ Datadog.logger.debug(
142
+ "Worker thread error. Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
143
+ )
142
144
  raise
143
145
  end
144
146
  # rubocop:enable Lint/RescueException
@@ -1,7 +1,5 @@
1
1
  # typed: false
2
2
 
3
- require 'forwardable'
4
-
5
3
  require 'datadog/core/runtime/metrics'
6
4
 
7
5
  require 'datadog/core/worker'
@@ -13,7 +11,6 @@ module Datadog
13
11
  module Workers
14
12
  # Emits runtime metrics asynchronously on a timed loop
15
13
  class RuntimeMetrics < Worker
16
- extend Forwardable
17
14
  include Workers::Polling
18
15
 
19
16
  # In seconds
data/lib/datadog/core.rb CHANGED
@@ -59,6 +59,12 @@ require 'datadog/core/extensions'
59
59
  # We must load core extensions to make certain global APIs
60
60
  # accessible: both for Datadog features and the core itself.
61
61
  module Datadog
62
+ # Common, lower level, internal code used (or usable) by two or more
63
+ # products. It is a dependency of each product. Contrast with Datadog::Kit
64
+ # for higher-level features.
65
+ module Core
66
+ end
67
+
62
68
  extend Core::Extensions
63
69
 
64
70
  # Add shutdown hook:
@@ -0,0 +1,50 @@
1
+ # typed: ignore
2
+
3
+ module Datadog
4
+ module Kit
5
+ # This helper is used to enable core dumps for the current Ruby app. This is useful when debugging native-level
6
+ # crashes.
7
+ #
8
+ # It can be enabled simply by adding `require 'datadog/kit/enable_core_dumps'` to start of the app.
9
+ module EnableCoreDumps
10
+ def self.call
11
+ current_size, maximum_size = Process.getrlimit(:CORE)
12
+ core_pattern =
13
+ begin
14
+ File.read('/proc/sys/kernel/core_pattern').strip
15
+ rescue
16
+ '(Could not open /proc/sys/kernel/core_pattern)'
17
+ end
18
+
19
+ if maximum_size <= 0
20
+ Kernel.warn("[DDTRACE] Could not enable core dumps on crash, maximum size is #{maximum_size} (disabled).")
21
+ return
22
+ elsif maximum_size == current_size
23
+ Kernel.warn('[DDTRACE] Core dumps already enabled, nothing to do!')
24
+ return
25
+ end
26
+
27
+ begin
28
+ Process.setrlimit(:CORE, maximum_size)
29
+ rescue => e
30
+ Kernel.warn(
31
+ "[DDTRACE] Failed to enable core dumps. Cause: #{e.class.name} #{e.message} " \
32
+ "Location: #{Array(e.backtrace).first}"
33
+ )
34
+ return
35
+ end
36
+
37
+ if current_size == 0
38
+ Kernel.warn("[DDTRACE] Enabled core dumps. Maximum size: #{maximum_size} Output pattern: '#{core_pattern}'")
39
+ else
40
+ Kernel.warn(
41
+ "[DDTRACE] Raised core dump limit. Old size: #{current_size} " \
42
+ "Maximum size: #{maximum_size} Output pattern: '#{core_pattern}'"
43
+ )
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ Datadog::Kit::EnableCoreDumps.call
@@ -0,0 +1,63 @@
1
+ # typed: false
2
+
3
+ module Datadog
4
+ module Kit
5
+ # Tracking identity via traces
6
+ module Identity
7
+ # Attach user information to the trace
8
+ #
9
+ # @param trace [TraceOperation] Trace to attach data to.
10
+ # @param id [String] Mandatory. Username or client id extracted
11
+ # from the access token or Authorization header in the inbound request
12
+ # from outside the system.
13
+ # @param email [String] Email of the authenticated user associated
14
+ # to the trace.
15
+ # @param name [String] User-friendly name. To be displayed in the
16
+ # UI if set.
17
+ # @param session_id [String] Session ID of the authenticated user.
18
+ # @param role [String] Actual/assumed role the client is making
19
+ # the request under extracted from token or application security
20
+ # context.
21
+ # @param scope [String] Scopes or granted authorities the client
22
+ # currently possesses extracted from token or application security
23
+ # context. The value would come from the scope associated with an OAuth
24
+ # 2.0 Access Token or an attribute value in a SAML 2.0 Assertion.
25
+ # @param others [Hash<String || Symbol, String>] Additional free-form
26
+ # user information to attach to the trace.
27
+ #
28
+ # rubocop:disable Metrics/CyclomaticComplexity
29
+ # rubocop:disable Metrics/PerceivedComplexity
30
+ def self.set_user(trace, id:, email: nil, name: nil, session_id: nil, role: nil, scope: nil, **others)
31
+ raise ArgumentError, 'missing required key: :id' if id.nil?
32
+
33
+ # enforce types
34
+
35
+ raise TypeError, 'id must be a String' unless id.is_a?(String)
36
+ raise TypeError, 'email must be a String' unless email.nil? || email.is_a?(String)
37
+ raise TypeError, 'name must be a String' unless name.nil? || name.is_a?(String)
38
+ raise TypeError, 'session_id must be a String' unless session_id.nil? || session_id.is_a?(String)
39
+ raise TypeError, 'role must be a String' unless role.nil? || role.is_a?(String)
40
+ raise TypeError, 'scope must be a String' unless scope.nil? || scope.is_a?(String)
41
+
42
+ others.each do |k, v|
43
+ raise TypeError, "#{k.inspect} must be a String" unless v.nil? || v.is_a?(String)
44
+ end
45
+
46
+ # set tags once data is known consistent
47
+
48
+ trace.set_tag('usr.id', id)
49
+ trace.set_tag('usr.email', email) unless email.nil?
50
+ trace.set_tag('usr.name', name) unless name.nil?
51
+ trace.set_tag('usr.session_id', session_id) unless session_id.nil?
52
+ trace.set_tag('usr.role', role) unless role.nil?
53
+ trace.set_tag('usr.scope', scope) unless scope.nil?
54
+
55
+ others.each do |k, v|
56
+ trace.set_tag("usr.#{k}", v) unless v.nil?
57
+ end
58
+ end
59
+ # rubocop:enable Metrics/PerceivedComplexity
60
+ # rubocop:enable Metrics/CyclomaticComplexity
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,11 @@
1
+ # typed: false
2
+
3
+ module Datadog
4
+ # Datadog::Kit holds public-facing APIs for higher level user-facing
5
+ # features, these features not belonging to a specific product. Contrary to
6
+ # Datadog::Core, Kit depends on products.
7
+ module Kit
8
+ end
9
+ end
10
+
11
+ require 'datadog/kit/identity'
@@ -10,8 +10,6 @@ module Datadog
10
10
  # OpenTracing adapter for Datadog::Tracer
11
11
  # @public_api
12
12
  class Tracer < ::OpenTracing::Tracer
13
- extend Forwardable
14
-
15
13
  # (see Datadog::Tracer)
16
14
  # @return [Datadog::Tracer]
17
15
  attr_reader \