datadog 2.3.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -1
  3. data/ext/datadog_profiling_loader/datadog_profiling_loader.c +9 -1
  4. data/ext/datadog_profiling_loader/extconf.rb +10 -22
  5. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +148 -30
  6. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +4 -2
  7. data/ext/datadog_profiling_native_extension/collectors_stack.c +89 -46
  8. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +580 -29
  9. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +9 -1
  10. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +0 -27
  11. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +0 -4
  12. data/ext/datadog_profiling_native_extension/extconf.rb +38 -21
  13. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +50 -0
  14. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +75 -0
  15. data/ext/datadog_profiling_native_extension/heap_recorder.c +20 -6
  16. data/ext/datadog_profiling_native_extension/http_transport.c +38 -6
  17. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +52 -1
  18. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +3 -0
  19. data/ext/datadog_profiling_native_extension/profiling.c +1 -1
  20. data/ext/datadog_profiling_native_extension/stack_recorder.h +1 -0
  21. data/ext/libdatadog_api/crashtracker.c +20 -18
  22. data/ext/libdatadog_api/datadog_ruby_common.c +0 -27
  23. data/ext/libdatadog_api/datadog_ruby_common.h +0 -4
  24. data/ext/libdatadog_extconf_helpers.rb +1 -1
  25. data/lib/datadog/appsec/assets/waf_rules/recommended.json +2184 -108
  26. data/lib/datadog/appsec/assets/waf_rules/strict.json +1430 -2
  27. data/lib/datadog/appsec/component.rb +29 -8
  28. data/lib/datadog/appsec/configuration/settings.rb +2 -2
  29. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +1 -0
  30. data/lib/datadog/appsec/contrib/devise/patcher/rememberable_patch.rb +21 -0
  31. data/lib/datadog/appsec/contrib/devise/patcher.rb +12 -2
  32. data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +0 -14
  33. data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +67 -31
  34. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +18 -15
  35. data/lib/datadog/appsec/contrib/graphql/integration.rb +14 -1
  36. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +2 -5
  37. data/lib/datadog/appsec/event.rb +1 -1
  38. data/lib/datadog/appsec/processor/rule_loader.rb +3 -1
  39. data/lib/datadog/appsec/processor/rule_merger.rb +33 -15
  40. data/lib/datadog/appsec/processor.rb +36 -37
  41. data/lib/datadog/appsec/rate_limiter.rb +25 -40
  42. data/lib/datadog/appsec/remote.rb +7 -3
  43. data/lib/datadog/appsec.rb +2 -2
  44. data/lib/datadog/core/configuration/components.rb +4 -3
  45. data/lib/datadog/core/configuration/settings.rb +84 -5
  46. data/lib/datadog/core/crashtracking/component.rb +1 -1
  47. data/lib/datadog/core/environment/execution.rb +5 -5
  48. data/lib/datadog/core/metrics/client.rb +7 -0
  49. data/lib/datadog/core/rate_limiter.rb +183 -0
  50. data/lib/datadog/core/remote/client/capabilities.rb +4 -3
  51. data/lib/datadog/core/remote/component.rb +4 -2
  52. data/lib/datadog/core/remote/negotiation.rb +4 -4
  53. data/lib/datadog/core/remote/tie.rb +2 -0
  54. data/lib/datadog/core/runtime/metrics.rb +1 -1
  55. data/lib/datadog/core/telemetry/component.rb +2 -0
  56. data/lib/datadog/core/telemetry/event.rb +12 -7
  57. data/lib/datadog/core/telemetry/logger.rb +51 -0
  58. data/lib/datadog/core/telemetry/logging.rb +50 -14
  59. data/lib/datadog/core/telemetry/request.rb +13 -1
  60. data/lib/datadog/core/utils/time.rb +12 -0
  61. data/lib/datadog/di/code_tracker.rb +168 -0
  62. data/lib/datadog/di/configuration/settings.rb +163 -0
  63. data/lib/datadog/di/configuration.rb +11 -0
  64. data/lib/datadog/di/error.rb +31 -0
  65. data/lib/datadog/di/extensions.rb +16 -0
  66. data/lib/datadog/di/probe.rb +133 -0
  67. data/lib/datadog/di/probe_builder.rb +41 -0
  68. data/lib/datadog/di/redactor.rb +188 -0
  69. data/lib/datadog/di/serializer.rb +193 -0
  70. data/lib/datadog/di.rb +14 -0
  71. data/lib/datadog/opentelemetry/sdk/propagator.rb +2 -0
  72. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +12 -10
  73. data/lib/datadog/profiling/collectors/info.rb +12 -3
  74. data/lib/datadog/profiling/collectors/thread_context.rb +26 -0
  75. data/lib/datadog/profiling/component.rb +20 -4
  76. data/lib/datadog/profiling/http_transport.rb +6 -1
  77. data/lib/datadog/profiling/scheduler.rb +2 -0
  78. data/lib/datadog/profiling/stack_recorder.rb +3 -0
  79. data/lib/datadog/single_step_instrument.rb +12 -0
  80. data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +8 -12
  81. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +5 -0
  82. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +78 -0
  83. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +33 -0
  84. data/lib/datadog/tracing/contrib/action_pack/patcher.rb +2 -0
  85. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +4 -0
  86. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +3 -1
  87. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +3 -1
  88. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +5 -1
  89. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +5 -0
  90. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
  91. data/lib/datadog/tracing/contrib/faraday/middleware.rb +9 -0
  92. data/lib/datadog/tracing/contrib/grape/endpoint.rb +19 -0
  93. data/lib/datadog/tracing/contrib/graphql/patcher.rb +9 -12
  94. data/lib/datadog/tracing/contrib/graphql/trace_patcher.rb +3 -3
  95. data/lib/datadog/tracing/contrib/graphql/tracing_patcher.rb +3 -3
  96. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +13 -9
  97. data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +6 -3
  98. data/lib/datadog/tracing/contrib/http/instrumentation.rb +18 -15
  99. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -5
  100. data/lib/datadog/tracing/contrib/httpclient/patcher.rb +1 -14
  101. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +5 -0
  102. data/lib/datadog/tracing/contrib/httprb/patcher.rb +1 -14
  103. data/lib/datadog/tracing/contrib/lograge/patcher.rb +1 -2
  104. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +2 -0
  105. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +13 -6
  106. data/lib/datadog/tracing/contrib/patcher.rb +2 -1
  107. data/lib/datadog/tracing/contrib/presto/patcher.rb +1 -13
  108. data/lib/datadog/tracing/contrib/rack/middlewares.rb +27 -0
  109. data/lib/datadog/tracing/contrib/redis/tags.rb +4 -0
  110. data/lib/datadog/tracing/contrib/sinatra/tracer.rb +4 -0
  111. data/lib/datadog/tracing/contrib/stripe/request.rb +3 -2
  112. data/lib/datadog/tracing/distributed/propagation.rb +7 -0
  113. data/lib/datadog/tracing/metadata/ext.rb +2 -0
  114. data/lib/datadog/tracing/remote.rb +5 -2
  115. data/lib/datadog/tracing/sampling/matcher.rb +6 -1
  116. data/lib/datadog/tracing/sampling/rate_sampler.rb +1 -1
  117. data/lib/datadog/tracing/sampling/rule.rb +2 -0
  118. data/lib/datadog/tracing/sampling/rule_sampler.rb +9 -5
  119. data/lib/datadog/tracing/sampling/span/ext.rb +1 -1
  120. data/lib/datadog/tracing/sampling/span/rule.rb +2 -2
  121. data/lib/datadog/tracing/trace_operation.rb +26 -2
  122. data/lib/datadog/tracing/tracer.rb +14 -12
  123. data/lib/datadog/tracing/transport/http/client.rb +1 -0
  124. data/lib/datadog/tracing/transport/io/client.rb +1 -0
  125. data/lib/datadog/tracing/workers/trace_writer.rb +1 -1
  126. data/lib/datadog/tracing/workers.rb +1 -1
  127. data/lib/datadog/version.rb +1 -1
  128. metadata +25 -8
  129. data/lib/datadog/tracing/sampling/rate_limiter.rb +0 -185
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_relative '../core/environment/identity'
4
4
  require_relative '../core/utils'
5
-
5
+ require_relative 'tracer'
6
6
  require_relative 'event'
7
7
  require_relative 'metadata/tagging'
8
8
  require_relative 'sampling/ext'
@@ -75,7 +75,9 @@ module Datadog
75
75
  metrics: nil,
76
76
  trace_state: nil,
77
77
  trace_state_unknown_fields: nil,
78
- remote_parent: false
78
+ remote_parent: false,
79
+ tracer: nil
80
+
79
81
  )
80
82
  # Attributes
81
83
  @id = id || Tracing::Utils::TraceId.next_id
@@ -98,6 +100,7 @@ module Datadog
98
100
  @profiling_enabled = profiling_enabled
99
101
  @trace_state = trace_state
100
102
  @trace_state_unknown_fields = trace_state_unknown_fields
103
+ @tracer = tracer
101
104
 
102
105
  # Generic tags
103
106
  set_tags(tags) if tags
@@ -161,6 +164,23 @@ module Datadog
161
164
  @resource || (root_span && root_span.resource)
162
165
  end
163
166
 
167
+ # When retrieving tags or metrics we need to include root span tags for sampling purposes
168
+ def get_tag(key)
169
+ super || (root_span && root_span.get_tag(key))
170
+ end
171
+
172
+ def get_metric(key)
173
+ super || (root_span && root_span.get_metric(key))
174
+ end
175
+
176
+ def tags
177
+ all_tags = {}
178
+ all_tags.merge!(root_span&.tags || {}) if root_span
179
+ all_tags.merge!(super)
180
+
181
+ all_tags
182
+ end
183
+
164
184
  # Returns true if the resource has been explicitly set
165
185
  #
166
186
  # @return [Boolean]
@@ -284,10 +304,14 @@ module Datadog
284
304
  # Returns a set of trace headers used for continuing traces.
285
305
  # Used for propagation across execution contexts.
286
306
  # Data should reflect the active state of the trace.
307
+ # DEV-3.0: Sampling is a side effect of generating the digest.
308
+ # We should move the sample call to inject and right before moving to new contexts(threads, forking etc.)
287
309
  def to_digest
288
310
  # Resolve current span ID
289
311
  span_id = @active_span && @active_span.id
290
312
  span_id ||= @parent_span_id unless finished?
313
+ # sample the trace_operation with the tracer
314
+ @tracer&.sample_trace(self) unless sampling_priority
291
315
 
292
316
  TraceDigest.new(
293
317
  span_id: span_id,
@@ -262,6 +262,17 @@ module Datadog
262
262
  context.activate!(trace, &block)
263
263
  end
264
264
 
265
+ # Sample a span, tagging the trace as appropriate.
266
+ def sample_trace(trace_op)
267
+ begin
268
+ @sampler.sample!(trace_op)
269
+ rescue StandardError => e
270
+ SAMPLE_TRACE_LOG_ONLY_ONCE.run do
271
+ Datadog.logger.warn { "Failed to sample trace: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
272
+ end
273
+ end
274
+ end
275
+
265
276
  # @!visibility private
266
277
  # TODO: make this private
267
278
  def trace_completed
@@ -331,12 +342,14 @@ module Datadog
331
342
  trace_state: digest.trace_state,
332
343
  trace_state_unknown_fields: digest.trace_state_unknown_fields,
333
344
  remote_parent: digest.span_remote,
345
+ tracer: self
334
346
  )
335
347
  else
336
348
  TraceOperation.new(
337
349
  hostname: hostname,
338
350
  profiling_enabled: profiling_enabled,
339
351
  remote_parent: false,
352
+ tracer: self
340
353
  )
341
354
  end
342
355
  end
@@ -347,7 +360,6 @@ module Datadog
347
360
  events.span_before_start.subscribe do |event_span_op, event_trace_op|
348
361
  event_trace_op.service ||= @default_service
349
362
  event_span_op.service ||= @default_service
350
- sample_trace(event_trace_op) if event_span_op && event_span_op.parent_id == 0
351
363
  end
352
364
 
353
365
  events.span_finished.subscribe do |event_span, event_trace_op|
@@ -463,17 +475,6 @@ module Datadog
463
475
  end
464
476
  end
465
477
 
466
- # Sample a span, tagging the trace as appropriate.
467
- def sample_trace(trace_op)
468
- begin
469
- @sampler.sample!(trace_op)
470
- rescue StandardError => e
471
- SAMPLE_TRACE_LOG_ONLY_ONCE.run do
472
- Datadog.logger.warn { "Failed to sample trace: #{e.class.name} #{e} at #{Array(e.backtrace).first}" }
473
- end
474
- end
475
- end
476
-
477
478
  SAMPLE_TRACE_LOG_ONLY_ONCE = Core::Utils::OnlyOnce.new
478
479
  private_constant :SAMPLE_TRACE_LOG_ONLY_ONCE
479
480
 
@@ -492,6 +493,7 @@ module Datadog
492
493
 
493
494
  # Flush finished spans from the trace buffer, send them to writer.
494
495
  def flush_trace(trace_op)
496
+ sample_trace(trace_op) unless trace_op.sampling_priority
495
497
  begin
496
498
  trace = @trace_flush.consume!(trace_op)
497
499
  write(trace) if trace && !trace.empty?
@@ -38,6 +38,7 @@ module Datadog
38
38
  if stats.consecutive_errors > 0
39
39
  Datadog.logger.debug(message)
40
40
  else
41
+ # Not to report telemetry logs
41
42
  Datadog.logger.error(message)
42
43
  end
43
44
 
@@ -49,6 +49,7 @@ module Datadog
49
49
  if stats.consecutive_errors > 0
50
50
  Datadog.logger.debug(message)
51
51
  else
52
+ # Not to report telemetry logs
52
53
  Datadog.logger.error(message)
53
54
  end
54
55
 
@@ -43,7 +43,7 @@ module Datadog
43
43
  traces = process_traces(traces)
44
44
  flush_traces(traces)
45
45
  rescue StandardError => e
46
- Datadog.logger.error(
46
+ Datadog.logger.warn(
47
47
  "Error while writing traces: dropped #{traces.length} items. Cause: #{e} Location: #{Array(e.backtrace).first}"
48
48
  )
49
49
  end
@@ -56,7 +56,7 @@ module Datadog
56
56
  # ensures that the thread will not die because of an exception.
57
57
  # TODO[manu]: findout the reason and reschedule the send if it's not
58
58
  # a fatal exception
59
- Datadog.logger.error(
59
+ Datadog.logger.warn(
60
60
  "Error during traces flush: dropped #{traces.length} items. Cause: #{e} Location: #{Array(e.backtrace).first}"
61
61
  )
62
62
  end
@@ -3,7 +3,7 @@
3
3
  module Datadog
4
4
  module VERSION
5
5
  MAJOR = 2
6
- MINOR = 3
6
+ MINOR = 4
7
7
  PATCH = 0
8
8
  PRE = nil
9
9
  BUILD = nil
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datadog
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.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: 2024-08-22 00:00:00.000000000 Z
11
+ date: 2024-10-11 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: 11.0.0.1.0
61
+ version: 12.0.0.1.0
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: 11.0.0.1.0
68
+ version: 12.0.0.1.0
69
69
  description: |
70
70
  datadog is Datadog's client library for Ruby. It includes a suite of tools
71
71
  which provide visibility into the performance and security of Ruby applications,
@@ -110,6 +110,8 @@ files:
110
110
  - ext/datadog_profiling_native_extension/datadog_ruby_common.c
111
111
  - ext/datadog_profiling_native_extension/datadog_ruby_common.h
112
112
  - ext/datadog_profiling_native_extension/extconf.rb
113
+ - ext/datadog_profiling_native_extension/gvl_profiling_helper.c
114
+ - ext/datadog_profiling_native_extension/gvl_profiling_helper.h
113
115
  - ext/datadog_profiling_native_extension/heap_recorder.c
114
116
  - ext/datadog_profiling_native_extension/heap_recorder.h
115
117
  - ext/datadog_profiling_native_extension/helpers.h
@@ -156,6 +158,7 @@ files:
156
158
  - lib/datadog/appsec/contrib/devise/patcher.rb
157
159
  - lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb
158
160
  - lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb
161
+ - lib/datadog/appsec/contrib/devise/patcher/rememberable_patch.rb
159
162
  - lib/datadog/appsec/contrib/devise/resource.rb
160
163
  - lib/datadog/appsec/contrib/devise/tracking.rb
161
164
  - lib/datadog/appsec/contrib/graphql/appsec_trace.rb
@@ -271,6 +274,7 @@ files:
271
274
  - lib/datadog/core/metrics/metric.rb
272
275
  - lib/datadog/core/metrics/options.rb
273
276
  - lib/datadog/core/pin.rb
277
+ - lib/datadog/core/rate_limiter.rb
274
278
  - lib/datadog/core/remote.rb
275
279
  - lib/datadog/core/remote/client.rb
276
280
  - lib/datadog/core/remote/client/capabilities.rb
@@ -308,6 +312,7 @@ files:
308
312
  - lib/datadog/core/telemetry/http/ext.rb
309
313
  - lib/datadog/core/telemetry/http/response.rb
310
314
  - lib/datadog/core/telemetry/http/transport.rb
315
+ - lib/datadog/core/telemetry/logger.rb
311
316
  - lib/datadog/core/telemetry/logging.rb
312
317
  - lib/datadog/core/telemetry/metric.rb
313
318
  - lib/datadog/core/telemetry/metrics_collection.rb
@@ -354,6 +359,16 @@ files:
354
359
  - lib/datadog/core/workers/polling.rb
355
360
  - lib/datadog/core/workers/queue.rb
356
361
  - lib/datadog/core/workers/runtime_metrics.rb
362
+ - lib/datadog/di.rb
363
+ - lib/datadog/di/code_tracker.rb
364
+ - lib/datadog/di/configuration.rb
365
+ - lib/datadog/di/configuration/settings.rb
366
+ - lib/datadog/di/error.rb
367
+ - lib/datadog/di/extensions.rb
368
+ - lib/datadog/di/probe.rb
369
+ - lib/datadog/di/probe_builder.rb
370
+ - lib/datadog/di/redactor.rb
371
+ - lib/datadog/di/serializer.rb
357
372
  - lib/datadog/kit.rb
358
373
  - lib/datadog/kit/appsec/events.rb
359
374
  - lib/datadog/kit/enable_core_dumps.rb
@@ -391,6 +406,7 @@ files:
391
406
  - lib/datadog/profiling/tasks/exec.rb
392
407
  - lib/datadog/profiling/tasks/help.rb
393
408
  - lib/datadog/profiling/tasks/setup.rb
409
+ - lib/datadog/single_step_instrument.rb
394
410
  - lib/datadog/tracing.rb
395
411
  - lib/datadog/tracing/analytics.rb
396
412
  - lib/datadog/tracing/buffer.rb
@@ -424,6 +440,8 @@ files:
424
440
  - lib/datadog/tracing/contrib/action_mailer/patcher.rb
425
441
  - lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb
426
442
  - lib/datadog/tracing/contrib/action_pack/action_controller/patcher.rb
443
+ - lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb
444
+ - lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb
427
445
  - lib/datadog/tracing/contrib/action_pack/configuration/settings.rb
428
446
  - lib/datadog/tracing/contrib/action_pack/ext.rb
429
447
  - lib/datadog/tracing/contrib/action_pack/integration.rb
@@ -824,7 +842,6 @@ files:
824
842
  - lib/datadog/tracing/sampling/priority_sampler.rb
825
843
  - lib/datadog/tracing/sampling/rate_by_key_sampler.rb
826
844
  - lib/datadog/tracing/sampling/rate_by_service_sampler.rb
827
- - lib/datadog/tracing/sampling/rate_limiter.rb
828
845
  - lib/datadog/tracing/sampling/rate_sampler.rb
829
846
  - lib/datadog/tracing/sampling/rule.rb
830
847
  - lib/datadog/tracing/sampling/rule_sampler.rb
@@ -870,8 +887,8 @@ licenses:
870
887
  - Apache-2.0
871
888
  metadata:
872
889
  allowed_push_host: https://rubygems.org
873
- changelog_uri: https://github.com/DataDog/dd-trace-rb/blob/v2.3.0/CHANGELOG.md
874
- source_code_uri: https://github.com/DataDog/dd-trace-rb/tree/v2.3.0
890
+ changelog_uri: https://github.com/DataDog/dd-trace-rb/blob/v2.4.0/CHANGELOG.md
891
+ source_code_uri: https://github.com/DataDog/dd-trace-rb/tree/v2.4.0
875
892
  post_install_message:
876
893
  rdoc_options: []
877
894
  require_paths:
@@ -890,7 +907,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
890
907
  - !ruby/object:Gem::Version
891
908
  version: 2.0.0
892
909
  requirements: []
893
- rubygems_version: 3.5.16
910
+ rubygems_version: 3.5.17
894
911
  signing_key:
895
912
  specification_version: 4
896
913
  summary: Datadog tracing code for your Ruby applications
@@ -1,185 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../../core/utils/time'
4
-
5
- module Datadog
6
- module Tracing
7
- module Sampling
8
- # Checks for rate limiting on a resource.
9
- class RateLimiter
10
- # Checks if resource of specified size can be
11
- # conforms with the current limit.
12
- #
13
- # Implementations of this method are not guaranteed
14
- # to be side-effect free.
15
- #
16
- # @return [Boolean] whether a resource conforms with the current limit
17
- def allow?(size); end
18
-
19
- # The effective rate limiting ratio based on
20
- # recent calls to `allow?`.
21
- #
22
- # @return [Float] recent allowance ratio
23
- def effective_rate; end
24
- end
25
-
26
- # Implementation of the Token Bucket metering algorithm
27
- # for rate limiting.
28
- #
29
- # @see https://en.wikipedia.org/wiki/Token_bucket Token bucket
30
- class TokenBucket < RateLimiter
31
- attr_reader :rate, :max_tokens
32
-
33
- # @param rate [Numeric] Allowance rate, in units per second
34
- # if rate is negative, always allow
35
- # if rate is zero, never allow
36
- # @param max_tokens [Numeric] Limit of available tokens
37
- def initialize(rate, max_tokens = rate)
38
- super()
39
-
40
- raise ArgumentError, "rate must be a number: #{rate}" unless rate.is_a?(Numeric)
41
- raise ArgumentError, "max_tokens must be a number: #{max_tokens}" unless max_tokens.is_a?(Numeric)
42
-
43
- @rate = rate
44
- @max_tokens = max_tokens
45
-
46
- @tokens = max_tokens
47
- @total_messages = 0
48
- @conforming_messages = 0
49
- @prev_conforming_messages = nil
50
- @prev_total_messages = nil
51
- @current_window = nil
52
-
53
- @last_refill = Core::Utils::Time.get_time
54
- end
55
-
56
- # Checks if a message of provided +size+
57
- # conforms with the current bucket limit.
58
- #
59
- # If it does, return +true+ and remove +size+
60
- # tokens from the bucket.
61
- # If it does not, return +false+ without affecting
62
- # the tokens from the bucket.
63
- #
64
- # @return [Boolean] +true+ if message conforms with current bucket limit
65
- def allow?(size)
66
- allowed = should_allow?(size)
67
- update_rate_counts(allowed)
68
- allowed
69
- end
70
-
71
- # Ratio of 'conformance' per 'total messages' checked
72
- # averaged for the past 2 buckets
73
- #
74
- # Returns +1.0+ when no messages have been checked yet.
75
- #
76
- # @return [Float] Conformance ratio, between +[0,1]+
77
- def effective_rate
78
- return 0.0 if @rate.zero?
79
- return 1.0 if @rate < 0 || @total_messages.zero?
80
-
81
- return current_window_rate if @prev_conforming_messages.nil? || @prev_total_messages.nil?
82
-
83
- (@conforming_messages.to_f + @prev_conforming_messages.to_f) / (@total_messages + @prev_total_messages)
84
- end
85
-
86
- # Ratio of 'conformance' per 'total messages' checked
87
- # on this bucket
88
- #
89
- # Returns +1.0+ when no messages have been checked yet.
90
- #
91
- # @return [Float] Conformance ratio, between +[0,1]+
92
- def current_window_rate
93
- return 1.0 if @total_messages.zero?
94
-
95
- @conforming_messages.to_f / @total_messages
96
- end
97
-
98
- # @return [Numeric] number of tokens currently available
99
- def available_tokens
100
- @tokens
101
- end
102
-
103
- private
104
-
105
- def refill_since_last_message
106
- now = Core::Utils::Time.get_time
107
- elapsed = now - @last_refill
108
-
109
- # Update the number of available tokens, but ensure we do not exceed the max
110
- # we return the min of tokens + rate*elapsed, or max tokens
111
- refill_tokens(@rate * elapsed)
112
-
113
- @last_refill = now
114
- end
115
-
116
- def refill_tokens(size)
117
- @tokens += size
118
- @tokens = @max_tokens if @tokens > @max_tokens
119
- end
120
-
121
- def increment_total_count
122
- @total_messages += 1
123
- end
124
-
125
- def increment_conforming_count
126
- @conforming_messages += 1
127
- end
128
-
129
- def should_allow?(size)
130
- # rate limit of 0 blocks everything
131
- return false if @rate.zero?
132
-
133
- # negative rate limit disables rate limiting
134
- return true if @rate < 0
135
-
136
- refill_since_last_message
137
-
138
- # if tokens < 1 we don't allow?
139
- return false if @tokens < size
140
-
141
- @tokens -= size
142
-
143
- true
144
- end
145
-
146
- # Sets and Updates the past two 1 second windows for which
147
- # the rate limiter must compute it's rate over and updates
148
- # the total count, and conforming message count if +allowed+
149
- def update_rate_counts(allowed)
150
- now = Core::Utils::Time.get_time
151
-
152
- # No tokens have been seen yet, start a new window
153
- if @current_window.nil?
154
- @current_window = now
155
- # If more than 1 second has past since last window, reset
156
- elsif now - @current_window >= 1
157
- @prev_conforming_messages = @conforming_messages
158
- @prev_total_messages = @total_messages
159
- @conforming_messages = 0
160
- @total_messages = 0
161
- @current_window = now
162
- end
163
-
164
- increment_conforming_count if allowed
165
-
166
- increment_total_count
167
- end
168
- end
169
-
170
- # {Datadog::Tracing::Sampling::RateLimiter} that accepts all resources,
171
- # with no limits.
172
- class UnlimitedLimiter < RateLimiter
173
- # @return [Boolean] always +true+
174
- def allow?(_)
175
- true
176
- end
177
-
178
- # @return [Float] always 100%
179
- def effective_rate
180
- 1.0
181
- end
182
- end
183
- end
184
- end
185
- end