datadog 2.3.0 → 2.4.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.
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