datadog 2.0.0 → 2.2.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 (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -2
  3. data/README.md +1 -1
  4. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +19 -1
  5. data/ext/datadog_profiling_native_extension/collectors_stack.c +41 -0
  6. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +1 -1
  7. data/ext/datadog_profiling_native_extension/crashtracker.c +1 -1
  8. data/ext/datadog_profiling_native_extension/extconf.rb +6 -4
  9. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +47 -1
  10. data/ext/datadog_profiling_native_extension/setup_signal_handler.c +1 -1
  11. data/ext/datadog_profiling_native_extension/stack_recorder.c +13 -6
  12. data/ext/datadog_profiling_native_extension/stack_recorder.h +1 -0
  13. data/lib/datadog/appsec/configuration/settings.rb +5 -0
  14. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +0 -1
  15. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +1 -1
  16. data/lib/datadog/appsec/extensions.rb +1 -0
  17. data/lib/datadog/core/configuration/components.rb +6 -3
  18. data/lib/datadog/core/configuration/ext.rb +1 -0
  19. data/lib/datadog/core/configuration/option.rb +21 -14
  20. data/lib/datadog/core/configuration/options.rb +5 -1
  21. data/lib/datadog/core/configuration/settings.rb +68 -5
  22. data/lib/datadog/core/configuration.rb +3 -17
  23. data/lib/datadog/core/deprecations.rb +58 -0
  24. data/lib/datadog/core/environment/ext.rb +2 -0
  25. data/lib/datadog/core/environment/yjit.rb +5 -0
  26. data/lib/datadog/core/runtime/ext.rb +2 -0
  27. data/lib/datadog/core/runtime/metrics.rb +6 -0
  28. data/lib/datadog/core/telemetry/component.rb +107 -0
  29. data/lib/datadog/core/telemetry/event.rb +124 -31
  30. data/lib/datadog/core/telemetry/ext.rb +2 -0
  31. data/lib/datadog/core/telemetry/http/adapters/net.rb +1 -1
  32. data/lib/datadog/core/telemetry/metric.rb +167 -0
  33. data/lib/datadog/core/telemetry/metrics_collection.rb +81 -0
  34. data/lib/datadog/core/telemetry/metrics_manager.rb +81 -0
  35. data/lib/datadog/core/telemetry/request.rb +1 -1
  36. data/lib/datadog/core/telemetry/worker.rb +173 -0
  37. data/lib/datadog/core/utils/only_once_successful.rb +76 -0
  38. data/lib/datadog/core.rb +2 -19
  39. data/lib/datadog/opentelemetry/sdk/propagator.rb +5 -10
  40. data/lib/datadog/opentelemetry/sdk/span_processor.rb +5 -2
  41. data/lib/datadog/profiling/collectors/code_provenance.rb +18 -5
  42. data/lib/datadog/profiling/component.rb +18 -1
  43. data/lib/datadog/profiling/ext/dir_monkey_patches.rb +410 -0
  44. data/lib/datadog/profiling.rb +1 -0
  45. data/lib/datadog/tracing/configuration/ext.rb +7 -0
  46. data/lib/datadog/tracing/configuration/settings.rb +52 -3
  47. data/lib/datadog/tracing/contrib/action_cable/event.rb +1 -1
  48. data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +1 -1
  49. data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +1 -1
  50. data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +1 -1
  51. data/lib/datadog/tracing/contrib/action_mailer/event.rb +4 -6
  52. data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +9 -4
  53. data/lib/datadog/tracing/contrib/action_mailer/events/process.rb +3 -2
  54. data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +1 -5
  55. data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +1 -1
  56. data/lib/datadog/tracing/contrib/active_job/events/discard.rb +1 -1
  57. data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +1 -1
  58. data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +1 -1
  59. data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +1 -1
  60. data/lib/datadog/tracing/contrib/active_job/events/perform.rb +1 -1
  61. data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +1 -1
  62. data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +1 -1
  63. data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +1 -1
  64. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +1 -1
  65. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +1 -1
  66. data/lib/datadog/tracing/contrib/active_support/cache/event.rb +32 -0
  67. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +156 -0
  68. data/lib/datadog/tracing/contrib/active_support/cache/events.rb +34 -0
  69. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +45 -41
  70. data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +17 -40
  71. data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +4 -1
  72. data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +29 -6
  73. data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +16 -4
  74. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +33 -29
  75. data/lib/datadog/tracing/contrib/analytics.rb +5 -0
  76. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +5 -0
  77. data/lib/datadog/tracing/contrib/graphql/patcher.rb +8 -2
  78. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +166 -0
  79. data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +25 -0
  80. data/lib/datadog/tracing/contrib/kafka/consumer_event.rb +1 -1
  81. data/lib/datadog/tracing/contrib/kafka/consumer_group_event.rb +1 -1
  82. data/lib/datadog/tracing/contrib/kafka/event.rb +1 -1
  83. data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +3 -3
  84. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +3 -3
  85. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +3 -3
  86. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +3 -3
  87. data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +3 -3
  88. data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +3 -3
  89. data/lib/datadog/tracing/contrib/racecar/event.rb +2 -2
  90. data/lib/datadog/tracing/contrib/rails/ext.rb +9 -0
  91. data/lib/datadog/tracing/contrib/rails/patcher.rb +7 -0
  92. data/lib/datadog/tracing/contrib/rails/runner.rb +95 -0
  93. data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
  94. data/lib/datadog/tracing/distributed/b3_single.rb +3 -1
  95. data/lib/datadog/tracing/distributed/datadog.rb +2 -2
  96. data/lib/datadog/tracing/distributed/propagation.rb +39 -4
  97. data/lib/datadog/tracing/distributed/trace_context.rb +5 -3
  98. data/lib/datadog/tracing/metadata/ext.rb +1 -0
  99. data/lib/datadog/tracing/span_operation.rb +3 -2
  100. data/lib/datadog/tracing/trace_operation.rb +7 -3
  101. data/lib/datadog/tracing/trace_segment.rb +4 -1
  102. data/lib/datadog/tracing/tracer.rb +9 -2
  103. data/lib/datadog/tracing.rb +5 -1
  104. data/lib/datadog/version.rb +2 -2
  105. metadata +21 -8
  106. data/lib/datadog/core/telemetry/client.rb +0 -95
  107. data/lib/datadog/core/telemetry/heartbeat.rb +0 -33
@@ -122,9 +122,18 @@ module Datadog
122
122
  # @default `DD_TRACE_DEBUG` environment variable, otherwise `false`
123
123
  # @return [Boolean]
124
124
  option :debug do |o|
125
- o.env Datadog::Core::Configuration::Ext::Diagnostics::ENV_DEBUG_ENABLED
125
+ o.env [Datadog::Core::Configuration::Ext::Diagnostics::ENV_DEBUG_ENABLED,
126
+ Datadog::Core::Configuration::Ext::Diagnostics::ENV_OTEL_LOG_LEVEL]
126
127
  o.default false
127
128
  o.type :bool
129
+ o.env_parser do |value|
130
+ if value
131
+ value = value.strip.downcase
132
+ # Debug is enabled when DD_TRACE_DEBUG is true or 1 OR
133
+ # when OTEL_LOG_LEVEL is set to debug
134
+ ['true', '1', 'debug'].include?(value)
135
+ end
136
+ end
128
137
  o.after_set do |enabled|
129
138
  # Enable rich debug print statements.
130
139
  # We do not need to unnecessarily load 'pp' unless in debugging mode.
@@ -388,6 +397,22 @@ module Datadog
388
397
  end
389
398
  end
390
399
 
400
+ # The profiler gathers data by sending `SIGPROF` unix signals to Ruby application threads.
401
+ #
402
+ # We've discovered that this can trigger a bug in a number of Ruby APIs in the `Dir` class, as
403
+ # described in https://github.com/DataDog/dd-trace-rb/issues/3450 . This workaround prevents the issue
404
+ # from happening by monkey patching the affected APIs.
405
+ #
406
+ # (In the future, once a fix lands upstream, we'll disable this workaround for Rubies that don't need it)
407
+ #
408
+ # @default `DD_PROFILING_DIR_INTERRUPTION_WORKAROUND_ENABLED` environment variable as a boolean,
409
+ # otherwise `true`
410
+ option :dir_interruption_workaround_enabled do |o|
411
+ o.env 'DD_PROFILING_DIR_INTERRUPTION_WORKAROUND_ENABLED'
412
+ o.type :bool
413
+ o.default true
414
+ end
415
+
391
416
  # Configures how much wall-time overhead the profiler targets. The profiler will dynamically adjust the
392
417
  # interval between samples it takes so as to try and maintain the property that it spends no longer than
393
418
  # this amount of wall-clock time profiling. For example, with the default value of 2%, the profiler will
@@ -465,7 +490,7 @@ module Datadog
465
490
  o.type :string, nilable: true
466
491
 
467
492
  # NOTE: service also gets set as a side effect of tags. See the WORKAROUND note in #initialize for details.
468
- o.env Core::Environment::Ext::ENV_SERVICE
493
+ o.env [Core::Environment::Ext::ENV_SERVICE, Core::Environment::Ext::ENV_OTEL_SERVICE]
469
494
  o.default Core::Environment::Ext::FALLBACK_SERVICE_NAME
470
495
 
471
496
  # There's a few cases where we don't want to use the fallback service name, so this helper allows us to get a
@@ -500,14 +525,13 @@ module Datadog
500
525
  # @return [Hash<String,String>]
501
526
  option :tags do |o|
502
527
  o.type :hash, nilable: true
503
- o.env Core::Environment::Ext::ENV_TAGS
528
+ o.env [Core::Environment::Ext::ENV_TAGS, Core::Environment::Ext::ENV_OTEL_RESOURCE_ATTRIBUTES]
504
529
  o.env_parser do |env_value|
505
530
  values = if env_value.include?(',')
506
531
  env_value.split(',')
507
532
  else
508
533
  env_value.split(' ') # rubocop:disable Style/RedundantArgument
509
534
  end
510
-
511
535
  values.map! do |v|
512
536
  v.gsub!(/\A[\s,]*|[\s,]*\Z/, '')
513
537
 
@@ -517,7 +541,23 @@ module Datadog
517
541
  values.compact!
518
542
  values.each_with_object({}) do |tag, tags|
519
543
  key, value = tag.split(':', 2)
520
- tags[key] = value if value && !value.empty?
544
+ if value.nil?
545
+ # support tags/attributes delimited by the OpenTelemetry separator (`=`)
546
+ key, value = tag.split('=', 2)
547
+ end
548
+ next if value.nil? || value.empty?
549
+
550
+ # maps OpenTelemetry semantic attributes to Datadog tags
551
+ case key.downcase
552
+ when 'deployment.environment'
553
+ tags['env'] = value
554
+ when 'service.version'
555
+ tags['version'] = value
556
+ when 'service.name'
557
+ tags['service'] = value
558
+ else
559
+ tags[key] = value
560
+ end
521
561
  end
522
562
  end
523
563
  o.setter do |new_value, old_value|
@@ -623,6 +663,16 @@ module Datadog
623
663
  o.type :bool
624
664
  end
625
665
 
666
+ # Enable metrics collection for telemetry. Metrics collection only works when telemetry is enabled and
667
+ # metrics are enabled.
668
+ # @default `DD_TELEMETRY_METRICS_ENABLED` environment variable, otherwise `true`.
669
+ # @return [Boolean]
670
+ option :metrics_enabled do |o|
671
+ o.type :bool
672
+ o.env Core::Telemetry::Ext::ENV_METRICS_ENABLED
673
+ o.default true
674
+ end
675
+
626
676
  # The interval in seconds when telemetry must be sent.
627
677
  #
628
678
  # This method is used internally, for testing purposes only.
@@ -636,6 +686,19 @@ module Datadog
636
686
  o.default 60.0
637
687
  end
638
688
 
689
+ # The interval in seconds when telemetry metrics are aggregated.
690
+ # Should be a denominator of `heartbeat_interval_seconds`.
691
+ #
692
+ # This method is used internally, for testing purposes only.
693
+ # @default `DD_TELEMETRY_METRICS_AGGREGATION_INTERVAL` environment variable, otherwise `10`.
694
+ # @return [Float]
695
+ # @!visibility private
696
+ option :metrics_aggregation_interval_seconds do |o|
697
+ o.type :float
698
+ o.env Core::Telemetry::Ext::ENV_METRICS_AGGREGATION_INTERVAL
699
+ o.default 10.0
700
+ end
701
+
639
702
  # The install id of the application.
640
703
  #
641
704
  # This method is used internally, by library injection.
@@ -84,23 +84,16 @@ module Datadog
84
84
  configuration = self.configuration
85
85
  yield(configuration)
86
86
 
87
- built_components = false
88
-
89
- components = safely_synchronize do |write_components|
87
+ safely_synchronize do |write_components|
90
88
  write_components.call(
91
89
  if components?
92
90
  replace_components!(configuration, @components)
93
91
  else
94
- components = build_components(configuration)
95
- built_components = true
96
- components
92
+ build_components(configuration)
97
93
  end
98
94
  )
99
95
  end
100
96
 
101
- # Should only be called the first time components are built
102
- components.telemetry.started! if built_components
103
-
104
97
  configuration
105
98
  end
106
99
 
@@ -200,20 +193,13 @@ module Datadog
200
193
  current_components = COMPONENTS_READ_LOCK.synchronize { defined?(@components) && @components }
201
194
  return current_components if current_components || !allow_initialization
202
195
 
203
- built_components = false
204
-
205
- components = safely_synchronize do |write_components|
196
+ safely_synchronize do |write_components|
206
197
  if defined?(@components) && @components
207
198
  @components
208
199
  else
209
- built_components = true
210
200
  write_components.call(build_components(configuration))
211
201
  end
212
202
  end
213
-
214
- # Should only be called the first time components are built
215
- components&.telemetry&.started! if built_components
216
- components
217
203
  end
218
204
 
219
205
  private
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Core
5
+ # Contains behavior for handling deprecated functions in the codebase.
6
+ module Deprecations
7
+ # Records the occurrence of a deprecated operation in this library.
8
+ #
9
+ # Currently, these operations are logged to `Datadog.logger` at `warn` level.
10
+ #
11
+ # `disallowed_next_major` adds a message informing that the deprecated operation
12
+ # won't be allowed in the next major release.
13
+ #
14
+ # @yieldreturn [String] a String with the lazily evaluated deprecation message.
15
+ # @param [Boolean] disallowed_next_major whether this deprecation will be enforced in the next major release.
16
+ # @param [Object] key A unique key for the deprecation. Only the first message with the same key will be logged.
17
+ def log_deprecation(disallowed_next_major: true, key: nil)
18
+ return unless log_deprecation?(key)
19
+
20
+ Datadog.logger.warn do
21
+ message = yield
22
+ message += ' This will be enforced in the next major release.' if disallowed_next_major
23
+ message
24
+ end
25
+
26
+ # Track the deprecation being logged.
27
+ deprecation_logged!(key)
28
+
29
+ nil
30
+ end
31
+
32
+ private
33
+
34
+ # Determines whether a deprecation message should be logged.
35
+ #
36
+ # Internal use only.
37
+ def log_deprecation?(key)
38
+ return true if key.nil?
39
+
40
+ # Only allow a deprecation to be logged once.
41
+ !logged_deprecations.key?(key)
42
+ end
43
+
44
+ def deprecation_logged!(key)
45
+ return if key.nil?
46
+
47
+ logged_deprecations[key] += 1
48
+ end
49
+
50
+ # Tracks what deprecation warnings have already been logged
51
+ #
52
+ # Internal use only.
53
+ def logged_deprecations
54
+ @logged_deprecations ||= Hash.new(0)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -18,8 +18,10 @@ module Datadog
18
18
  ENV_API_KEY = 'DD_API_KEY'
19
19
  ENV_ENVIRONMENT = 'DD_ENV'
20
20
  ENV_SERVICE = 'DD_SERVICE'
21
+ ENV_OTEL_SERVICE = 'OTEL_SERVICE_NAME'
21
22
  ENV_SITE = 'DD_SITE'
22
23
  ENV_TAGS = 'DD_TAGS'
24
+ ENV_OTEL_RESOURCE_ATTRIBUTES = 'OTEL_RESOURCE_ATTRIBUTES'
23
25
  ENV_VERSION = 'DD_VERSION'
24
26
  FALLBACK_SERVICE_NAME =
25
27
  begin
@@ -47,6 +47,11 @@ module Datadog
47
47
  ::RubyVM::YJIT.runtime_stats[:object_shape_count]
48
48
  end
49
49
 
50
+ # Size of memory Rust allocated for metadata
51
+ def yjit_alloc_size
52
+ ::RubyVM::YJIT.runtime_stats[:yjit_alloc_size]
53
+ end
54
+
50
55
  def available?
51
56
  defined?(::RubyVM::YJIT) \
52
57
  && ::RubyVM::YJIT.enabled? \
@@ -13,6 +13,7 @@ module Datadog
13
13
  # @public_api
14
14
  module Metrics
15
15
  ENV_ENABLED = 'DD_RUNTIME_METRICS_ENABLED'
16
+ ENV_OTEL_METRICS_EXPORTER = 'OTEL_METRICS_EXPORTER'
16
17
 
17
18
  METRIC_CLASS_COUNT = 'runtime.ruby.class_count'
18
19
  METRIC_GC_PREFIX = 'runtime.ruby.gc'
@@ -29,6 +30,7 @@ module Datadog
29
30
  METRIC_YJIT_LIVE_PAGE_COUNT = 'runtime.ruby.yjit.live_page_count'
30
31
  METRIC_YJIT_OBJECT_SHAPE_COUNT = 'runtime.ruby.yjit.object_shape_count'
31
32
  METRIC_YJIT_OUTLINED_CODE_SIZE = 'runtime.ruby.yjit.outlined_code_size'
33
+ METRIC_YJIT_YJIT_ALLOC_SIZE = 'runtime.ruby.yjit.yjit_alloc_size'
32
34
 
33
35
  TAG_SERVICE = 'service'
34
36
  end
@@ -140,6 +140,7 @@ module Datadog
140
140
  gauge(metric_name, metric_value) if metric_value
141
141
  end
142
142
 
143
+ # rubocop:disable Metrics/MethodLength
143
144
  def flush_yjit_stats
144
145
  # Only on Ruby >= 3.2
145
146
  try_flush do
@@ -176,9 +177,14 @@ module Datadog
176
177
  Core::Runtime::Ext::Metrics::METRIC_YJIT_OUTLINED_CODE_SIZE,
177
178
  Core::Environment::YJIT.outlined_code_size
178
179
  )
180
+ gauge_if_not_nil(
181
+ Core::Runtime::Ext::Metrics::METRIC_YJIT_YJIT_ALLOC_SIZE,
182
+ Core::Environment::YJIT.yjit_alloc_size
183
+ )
179
184
  end
180
185
  end
181
186
  end
187
+ # rubocop:enable Metrics/MethodLength
182
188
  end
183
189
  end
184
190
  end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'emitter'
4
+ require_relative 'event'
5
+ require_relative 'metrics_manager'
6
+ require_relative 'worker'
7
+ require_relative '../utils/forking'
8
+
9
+ module Datadog
10
+ module Core
11
+ module Telemetry
12
+ # Telemetry entrypoint, coordinates sending telemetry events at various points in app lifecycle.
13
+ class Component
14
+ attr_reader :enabled
15
+
16
+ include Core::Utils::Forking
17
+
18
+ # @param enabled [Boolean] Determines whether telemetry events should be sent to the API
19
+ # @param metrics_enabled [Boolean] Determines whether telemetry metrics should be sent to the API
20
+ # @param heartbeat_interval_seconds [Float] How frequently heartbeats will be reported, in seconds.
21
+ # @param metrics_aggregation_interval_seconds [Float] How frequently metrics will be aggregated, in seconds.
22
+ # @param [Boolean] dependency_collection Whether to send the `app-dependencies-loaded` event
23
+ def initialize(
24
+ heartbeat_interval_seconds:,
25
+ metrics_aggregation_interval_seconds:,
26
+ dependency_collection:,
27
+ enabled: true,
28
+ metrics_enabled: true
29
+ )
30
+ @enabled = enabled
31
+ @stopped = false
32
+
33
+ @metrics_manager = MetricsManager.new(
34
+ enabled: enabled && metrics_enabled,
35
+ aggregation_interval: metrics_aggregation_interval_seconds
36
+ )
37
+
38
+ @worker = Telemetry::Worker.new(
39
+ enabled: @enabled,
40
+ heartbeat_interval_seconds: heartbeat_interval_seconds,
41
+ metrics_aggregation_interval_seconds: metrics_aggregation_interval_seconds,
42
+ emitter: Emitter.new,
43
+ metrics_manager: @metrics_manager,
44
+ dependency_collection: dependency_collection
45
+ )
46
+ @worker.start
47
+ end
48
+
49
+ def disable!
50
+ @enabled = false
51
+ @worker.enabled = false
52
+ end
53
+
54
+ def stop!
55
+ return if @stopped
56
+
57
+ @worker.stop(true)
58
+ @stopped = true
59
+ end
60
+
61
+ def emit_closing!
62
+ return if !@enabled || forked?
63
+
64
+ @worker.enqueue(Event::AppClosing.new)
65
+ end
66
+
67
+ def integrations_change!
68
+ return if !@enabled || forked?
69
+
70
+ @worker.enqueue(Event::AppIntegrationsChange.new)
71
+ end
72
+
73
+ # Report configuration changes caused by Remote Configuration.
74
+ def client_configuration_change!(changes)
75
+ return if !@enabled || forked?
76
+
77
+ @worker.enqueue(Event::AppClientConfigurationChange.new(changes, 'remote_config'))
78
+ end
79
+
80
+ # Increments a count metric.
81
+ def inc(namespace, metric_name, value, tags: {}, common: true)
82
+ @metrics_manager.inc(namespace, metric_name, value, tags: tags, common: common)
83
+ end
84
+
85
+ # Decremenets a count metric.
86
+ def dec(namespace, metric_name, value, tags: {}, common: true)
87
+ @metrics_manager.dec(namespace, metric_name, value, tags: tags, common: common)
88
+ end
89
+
90
+ # Tracks gauge metric.
91
+ def gauge(namespace, metric_name, value, tags: {}, common: true)
92
+ @metrics_manager.gauge(namespace, metric_name, value, tags: tags, common: common)
93
+ end
94
+
95
+ # Tracks rate metric.
96
+ def rate(namespace, metric_name, value, tags: {}, common: true)
97
+ @metrics_manager.rate(namespace, metric_name, value, tags: tags, common: common)
98
+ end
99
+
100
+ # Tracks distribution metric.
101
+ def distribution(namespace, metric_name, value, tags: {}, common: true)
102
+ @metrics_manager.distribution(namespace, metric_name, value, tags: tags, common: common)
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -3,7 +3,16 @@
3
3
  module Datadog
4
4
  module Core
5
5
  module Telemetry
6
+ # Collection of telemetry events
6
7
  class Event
8
+ extend Core::Utils::Forking
9
+
10
+ # returns sequence that increments every time the configuration changes
11
+ def self.configuration_sequence
12
+ after_fork! { @sequence = Datadog::Core::Utils::Sequence.new(1) }
13
+ @sequence ||= Datadog::Core::Utils::Sequence.new(1)
14
+ end
15
+
7
16
  # Base class for all Telemetry V2 events.
8
17
  class Base
9
18
  # The type of the event.
@@ -12,8 +21,7 @@ module Datadog
12
21
  def type; end
13
22
 
14
23
  # The JSON payload for the event.
15
- # @param seq_id [Integer] The sequence ID for the event.
16
- def payload(seq_id)
24
+ def payload
17
25
  {}
18
26
  end
19
27
  end
@@ -24,8 +32,7 @@ module Datadog
24
32
  'app-started'
25
33
  end
26
34
 
27
- def payload(seq_id)
28
- @seq_id = seq_id
35
+ def payload
29
36
  {
30
37
  products: products,
31
38
  configuration: configuration,
@@ -38,6 +45,7 @@ module Datadog
38
45
  private
39
46
 
40
47
  def products
48
+ # @type var products: Hash[Symbol, Hash[Symbol, Object]]
41
49
  products = {
42
50
  appsec: {
43
51
  enabled: Datadog::AppSec.enabled?,
@@ -79,16 +87,19 @@ module Datadog
79
87
  ].freeze
80
88
 
81
89
  # rubocop:disable Metrics/AbcSize
90
+ # rubocop:disable Metrics/MethodLength
82
91
  def configuration
83
92
  config = Datadog.configuration
93
+ seq_id = Event.configuration_sequence.next
84
94
 
85
95
  list = [
86
- conf_value('DD_AGENT_HOST', config.agent.host),
87
- conf_value('DD_AGENT_TRANSPORT', agent_transport(config)),
88
- conf_value('DD_TRACE_SAMPLE_RATE', to_value(config.tracing.sampling.default_rate)),
96
+ conf_value('DD_AGENT_HOST', config.agent.host, seq_id),
97
+ conf_value('DD_AGENT_TRANSPORT', agent_transport(config), seq_id),
98
+ conf_value('DD_TRACE_SAMPLE_RATE', to_value(config.tracing.sampling.default_rate), seq_id),
89
99
  conf_value(
90
100
  'DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED',
91
- config.tracing.contrib.global_default_service_name.enabled
101
+ config.tracing.contrib.global_default_service_name.enabled,
102
+ seq_id
92
103
  ),
93
104
  ]
94
105
 
@@ -97,29 +108,45 @@ module Datadog
97
108
  peer_service_mapping = config.tracing.contrib.peer_service_mapping
98
109
  peer_service_mapping_str = peer_service_mapping.map { |key, value| "#{key}:#{value}" }.join(',')
99
110
  end
100
- list << conf_value('DD_TRACE_PEER_SERVICE_MAPPING', peer_service_mapping_str)
111
+ list << conf_value('DD_TRACE_PEER_SERVICE_MAPPING', peer_service_mapping_str, seq_id)
101
112
 
102
113
  # Whitelist of configuration options to send in additional payload object
103
114
  TARGET_OPTIONS.each do |option|
104
115
  split_option = option.split('.')
105
- list << conf_value(option, to_value(config.dig(*split_option)))
116
+ list << conf_value(option, to_value(config.dig(*split_option)), seq_id)
106
117
  end
107
118
 
108
119
  # Add some more custom additional payload values here
109
120
  list.push(
110
- conf_value('tracing.auto_instrument.enabled', !defined?(Datadog::AutoInstrument::LOADED).nil?),
111
- conf_value('tracing.writer_options.buffer_size', to_value(config.tracing.writer_options[:buffer_size])),
112
- conf_value('tracing.writer_options.flush_interval', to_value(config.tracing.writer_options[:flush_interval])),
113
- conf_value('tracing.opentelemetry.enabled', !defined?(Datadog::OpenTelemetry::LOADED).nil?),
121
+ conf_value('tracing.auto_instrument.enabled', !defined?(Datadog::AutoInstrument::LOADED).nil?, seq_id),
122
+ conf_value(
123
+ 'tracing.writer_options.buffer_size',
124
+ to_value(config.tracing.writer_options[:buffer_size]),
125
+ seq_id
126
+ ),
127
+ conf_value(
128
+ 'tracing.writer_options.flush_interval',
129
+ to_value(config.tracing.writer_options[:flush_interval]),
130
+ seq_id
131
+ ),
132
+ conf_value(
133
+ 'tracing.opentelemetry.enabled',
134
+ !defined?(Datadog::OpenTelemetry::LOADED).nil?,
135
+ seq_id
136
+ ),
114
137
  )
115
- list << conf_value('logger.instance', config.logger.instance.class.to_s) if config.logger.instance
116
- list << conf_value('appsec.enabled', config.dig('appsec', 'enabled')) if config.respond_to?('appsec')
117
- list << conf_value('ci.enabled', config.dig('ci', 'enabled')) if config.respond_to?('ci')
138
+ list << conf_value('logger.instance', config.logger.instance.class.to_s, seq_id) if config.logger.instance
139
+ if config.respond_to?('appsec')
140
+ list << conf_value('appsec.enabled', config.dig('appsec', 'enabled'), seq_id)
141
+ list << conf_value('appsec.sca_enabled', config.dig('appsec', 'sca_enabled'), seq_id)
142
+ end
143
+ list << conf_value('ci.enabled', config.dig('ci', 'enabled'), seq_id) if config.respond_to?('ci')
118
144
 
119
145
  list.reject! { |entry| entry[:value].nil? }
120
146
  list
121
147
  end
122
148
  # rubocop:enable Metrics/AbcSize
149
+ # rubocop:enable Metrics/MethodLength
123
150
 
124
151
  def agent_transport(config)
125
152
  adapter = Core::Configuration::AgentSettingsResolver.call(config).adapter
@@ -130,12 +157,12 @@ module Datadog
130
157
  end
131
158
  end
132
159
 
133
- def conf_value(name, value, origin = 'code')
160
+ def conf_value(name, value, seq_id, origin = 'code')
134
161
  {
135
162
  name: name,
136
163
  value: value,
137
164
  origin: origin,
138
- seq_id: @seq_id,
165
+ seq_id: seq_id,
139
166
  }
140
167
  end
141
168
 
@@ -165,7 +192,7 @@ module Datadog
165
192
  'app-dependencies-loaded'
166
193
  end
167
194
 
168
- def payload(seq_id)
195
+ def payload
169
196
  { dependencies: dependencies }
170
197
  end
171
198
 
@@ -188,7 +215,7 @@ module Datadog
188
215
  'app-integrations-change'
189
216
  end
190
217
 
191
- def payload(seq_id)
218
+ def payload
192
219
  { integrations: integrations }
193
220
  end
194
221
 
@@ -241,16 +268,33 @@ module Datadog
241
268
  @origin = origin
242
269
  end
243
270
 
244
- def payload(seq_id)
245
- {
246
- configuration: @changes.map do |name, value|
247
- {
248
- name: name,
249
- value: value,
250
- origin: @origin,
251
- }
252
- end
253
- }
271
+ def payload
272
+ { configuration: configuration }
273
+ end
274
+
275
+ def configuration
276
+ config = Datadog.configuration
277
+ seq_id = Event.configuration_sequence.next
278
+
279
+ res = @changes.map do |name, value|
280
+ {
281
+ name: name,
282
+ value: value,
283
+ origin: @origin,
284
+ seq_id: seq_id,
285
+ }
286
+ end
287
+
288
+ unless config.dig('appsec', 'sca_enabled').nil?
289
+ res << {
290
+ name: 'appsec.sca_enabled',
291
+ value: config.appsec.sca_enabled,
292
+ origin: 'code',
293
+ seq_id: seq_id,
294
+ }
295
+ end
296
+
297
+ res
254
298
  end
255
299
  end
256
300
 
@@ -267,6 +311,55 @@ module Datadog
267
311
  'app-closing'
268
312
  end
269
313
  end
314
+
315
+ # Telemetry class for the 'generate-metrics' event
316
+ class GenerateMetrics < Base
317
+ def type
318
+ 'generate-metrics'
319
+ end
320
+
321
+ def initialize(namespace, metric_series)
322
+ super()
323
+ @namespace = namespace
324
+ @metric_series = metric_series
325
+ end
326
+
327
+ def payload
328
+ {
329
+ namespace: @namespace,
330
+ series: @metric_series.map(&:to_h)
331
+ }
332
+ end
333
+ end
334
+
335
+ # Telemetry class for the 'distributions' event
336
+ class Distributions < GenerateMetrics
337
+ def type
338
+ 'distributions'
339
+ end
340
+ end
341
+
342
+ # Telemetry class for the 'message-batch' event
343
+ class MessageBatch
344
+ attr_reader :events
345
+
346
+ def type
347
+ 'message-batch'
348
+ end
349
+
350
+ def initialize(events)
351
+ @events = events
352
+ end
353
+
354
+ def payload
355
+ @events.map do |event|
356
+ {
357
+ request_type: event.type,
358
+ payload: event.payload,
359
+ }
360
+ end
361
+ end
362
+ end
270
363
  end
271
364
  end
272
365
  end
@@ -5,7 +5,9 @@ module Datadog
5
5
  module Telemetry
6
6
  module Ext
7
7
  ENV_ENABLED = 'DD_INSTRUMENTATION_TELEMETRY_ENABLED'
8
+ ENV_METRICS_ENABLED = 'DD_TELEMETRY_METRICS_ENABLED'
8
9
  ENV_HEARTBEAT_INTERVAL = 'DD_TELEMETRY_HEARTBEAT_INTERVAL'
10
+ ENV_METRICS_AGGREGATION_INTERVAL = 'DD_TELEMETRY_METRICS_AGGREGATION_INTERVAL'
9
11
  ENV_DEPENDENCY_COLLECTION = 'DD_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED'
10
12
  ENV_INSTALL_ID = 'DD_INSTRUMENTATION_INSTALL_ID'
11
13
  ENV_INSTALL_TYPE = 'DD_INSTRUMENTATION_INSTALL_TYPE'
@@ -15,7 +15,7 @@ module Datadog
15
15
  :timeout,
16
16
  :ssl
17
17
 
18
- DEFAULT_TIMEOUT = 30
18
+ DEFAULT_TIMEOUT = 2
19
19
 
20
20
  def initialize(hostname:, port: nil, timeout: DEFAULT_TIMEOUT, ssl: true)
21
21
  @hostname = hostname