datadog 2.16.0 → 2.17.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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -1
  3. data/ext/datadog_profiling_native_extension/encoded_profile.c +22 -12
  4. data/ext/datadog_profiling_native_extension/encoded_profile.h +1 -0
  5. data/ext/datadog_profiling_native_extension/http_transport.c +45 -72
  6. data/ext/datadog_profiling_native_extension/stack_recorder.c +4 -5
  7. data/ext/libdatadog_api/crashtracker.c +10 -3
  8. data/ext/libdatadog_api/macos_development.md +3 -3
  9. data/ext/libdatadog_extconf_helpers.rb +1 -1
  10. data/lib/datadog/appsec/api_security/lru_cache.rb +49 -0
  11. data/lib/datadog/appsec/api_security.rb +9 -0
  12. data/lib/datadog/core/buffer/random.rb +18 -2
  13. data/lib/datadog/core/configuration/agent_settings_resolver.rb +5 -5
  14. data/lib/datadog/core/configuration/components.rb +29 -20
  15. data/lib/datadog/core/configuration/components_state.rb +23 -0
  16. data/lib/datadog/core/configuration/option.rb +18 -18
  17. data/lib/datadog/core/configuration/option_definition.rb +4 -4
  18. data/lib/datadog/core/configuration/options.rb +1 -1
  19. data/lib/datadog/core/configuration/settings.rb +10 -10
  20. data/lib/datadog/core/configuration.rb +16 -16
  21. data/lib/datadog/core/crashtracking/component.rb +2 -1
  22. data/lib/datadog/core/encoding.rb +1 -1
  23. data/lib/datadog/core/environment/cgroup.rb +10 -12
  24. data/lib/datadog/core/environment/container.rb +38 -40
  25. data/lib/datadog/core/environment/ext.rb +6 -6
  26. data/lib/datadog/core/environment/identity.rb +3 -3
  27. data/lib/datadog/core/environment/platform.rb +3 -3
  28. data/lib/datadog/core/error.rb +11 -9
  29. data/lib/datadog/core/logger.rb +2 -2
  30. data/lib/datadog/core/metrics/client.rb +12 -14
  31. data/lib/datadog/core/metrics/logging.rb +5 -5
  32. data/lib/datadog/core/rate_limiter.rb +4 -2
  33. data/lib/datadog/core/remote/client.rb +32 -31
  34. data/lib/datadog/core/remote/component.rb +3 -3
  35. data/lib/datadog/core/remote/configuration/digest.rb +7 -7
  36. data/lib/datadog/core/remote/configuration/path.rb +1 -1
  37. data/lib/datadog/core/remote/transport/http/client.rb +1 -1
  38. data/lib/datadog/core/remote/transport/http/config.rb +21 -5
  39. data/lib/datadog/core/remote/transport/http/negotiation.rb +1 -1
  40. data/lib/datadog/core/runtime/metrics.rb +3 -3
  41. data/lib/datadog/core/telemetry/component.rb +39 -24
  42. data/lib/datadog/core/telemetry/emitter.rb +7 -1
  43. data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +65 -0
  44. data/lib/datadog/core/telemetry/event/app_closing.rb +18 -0
  45. data/lib/datadog/core/telemetry/event/app_dependencies_loaded.rb +33 -0
  46. data/lib/datadog/core/telemetry/event/app_heartbeat.rb +18 -0
  47. data/lib/datadog/core/telemetry/event/app_integrations_change.rb +58 -0
  48. data/lib/datadog/core/telemetry/event/app_started.rb +179 -0
  49. data/lib/datadog/core/telemetry/event/base.rb +40 -0
  50. data/lib/datadog/core/telemetry/event/distributions.rb +18 -0
  51. data/lib/datadog/core/telemetry/event/generate_metrics.rb +43 -0
  52. data/lib/datadog/core/telemetry/event/log.rb +76 -0
  53. data/lib/datadog/core/telemetry/event/message_batch.rb +42 -0
  54. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +43 -0
  55. data/lib/datadog/core/telemetry/event.rb +17 -475
  56. data/lib/datadog/core/telemetry/logger.rb +1 -1
  57. data/lib/datadog/core/telemetry/metric.rb +3 -3
  58. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +2 -2
  59. data/lib/datadog/core/telemetry/transport/telemetry.rb +0 -1
  60. data/lib/datadog/core/telemetry/worker.rb +48 -27
  61. data/lib/datadog/core/transport/http/adapters/test.rb +2 -1
  62. data/lib/datadog/core/transport/http/builder.rb +13 -13
  63. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +6 -6
  64. data/lib/datadog/core/utils/duration.rb +32 -32
  65. data/lib/datadog/core/utils/forking.rb +2 -2
  66. data/lib/datadog/core/utils/network.rb +6 -6
  67. data/lib/datadog/core/utils/only_once_successful.rb +16 -5
  68. data/lib/datadog/core/utils/time.rb +10 -2
  69. data/lib/datadog/core/utils/truncation.rb +21 -0
  70. data/lib/datadog/core/vendor/multipart-post/multipart/post/composite_read_io.rb +1 -1
  71. data/lib/datadog/core/vendor/multipart-post/multipart/post/multipartable.rb +8 -8
  72. data/lib/datadog/core/vendor/multipart-post/multipart/post/parts.rb +7 -7
  73. data/lib/datadog/core/worker.rb +1 -1
  74. data/lib/datadog/core/workers/async.rb +9 -10
  75. data/lib/datadog/error_tracking/component.rb +2 -2
  76. data/lib/datadog/profiling/collectors/code_provenance.rb +1 -1
  77. data/lib/datadog/profiling/ext.rb +0 -1
  78. data/lib/datadog/profiling/flush.rb +1 -1
  79. data/lib/datadog/profiling/http_transport.rb +1 -6
  80. data/lib/datadog/profiling/scheduler.rb +8 -1
  81. data/lib/datadog/profiling/tag_builder.rb +1 -5
  82. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +4 -1
  83. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +33 -0
  84. data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +4 -0
  85. data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +2 -4
  86. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +10 -0
  87. data/lib/datadog/tracing/contrib/aws/parsed_context.rb +5 -1
  88. data/lib/datadog/tracing/contrib/http/instrumentation.rb +1 -5
  89. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +1 -5
  90. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +1 -5
  91. data/lib/datadog/tracing/contrib/patcher.rb +5 -2
  92. data/lib/datadog/tracing/contrib/support.rb +28 -0
  93. data/lib/datadog/tracing/metadata/errors.rb +4 -4
  94. data/lib/datadog/version.rb +1 -1
  95. metadata +23 -6
@@ -75,10 +75,10 @@ module Datadog
75
75
  #
76
76
  # Versions < 5.0 are always single-threaded, but do not have the kwarg option.
77
77
  options = if dogstatsd_version >= Gem::Version.new('5.2')
78
- { single_thread: true }
79
- else
80
- {}
81
- end
78
+ {single_thread: true}
79
+ else
80
+ {}
81
+ end
82
82
 
83
83
  Datadog::Statsd.new(default_hostname, default_port, **options)
84
84
  end
@@ -99,7 +99,7 @@ module Datadog
99
99
  raise ArgumentError if value.nil?
100
100
 
101
101
  statsd.count(stat, value, metric_options(options))
102
- rescue StandardError => e
102
+ rescue => e
103
103
  logger.error(
104
104
  "Failed to send count stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
105
105
  )
@@ -113,7 +113,7 @@ module Datadog
113
113
  raise ArgumentError if value.nil?
114
114
 
115
115
  statsd.distribution(stat, value, metric_options(options))
116
- rescue StandardError => e
116
+ rescue => e
117
117
  logger.error(
118
118
  "Failed to send distribution stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
119
119
  )
@@ -126,7 +126,7 @@ module Datadog
126
126
  options = yield if block_given?
127
127
 
128
128
  statsd.increment(stat, metric_options(options))
129
- rescue StandardError => e
129
+ rescue => e
130
130
  logger.error(
131
131
  "Failed to send increment stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
132
132
  )
@@ -140,7 +140,7 @@ module Datadog
140
140
  raise ArgumentError if value.nil?
141
141
 
142
142
  statsd.gauge(stat, value, metric_options(options))
143
- rescue StandardError => e
143
+ rescue => e
144
144
  logger.error(
145
145
  "Failed to send gauge stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
146
146
  )
@@ -159,7 +159,7 @@ module Datadog
159
159
  finished = Utils::Time.get_time
160
160
  distribution(stat, ((finished - start) * 1000), options)
161
161
  end
162
- rescue StandardError => e
162
+ rescue => e
163
163
  # TODO: Likely to be redundant, since `distribution` handles its own errors.
164
164
  logger.error(
165
165
  "Failed to send time stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
@@ -173,7 +173,7 @@ module Datadog
173
173
  end
174
174
 
175
175
  def close
176
- @statsd.close if @statsd && @statsd.respond_to?(:close)
176
+ @statsd.close if @statsd&.respond_to?(:close)
177
177
  end
178
178
 
179
179
  private
@@ -185,10 +185,8 @@ module Datadog
185
185
  defined?(Datadog::Statsd::VERSION) &&
186
186
  Datadog::Statsd::VERSION &&
187
187
  Gem::Version.new(Datadog::Statsd::VERSION)
188
- ) || (
189
- Gem.loaded_specs['dogstatsd-ruby'] &&
190
- Gem.loaded_specs['dogstatsd-ruby'].version
191
- )
188
+ ) ||
189
+ Gem.loaded_specs['dogstatsd-ruby']&.version
192
190
  end
193
191
 
194
192
  IGNORED_STATSD_ONLY_ONCE = Utils::OnlyOnce.new
@@ -17,25 +17,25 @@ module Datadog
17
17
  l.progname = nil
18
18
  l.formatter = proc do |_severity, datetime, _progname, msg|
19
19
  stat = JSON.parse(msg[3..-1]) # Trim off leading progname...
20
- "#{JSON.dump(timestamp: datetime.to_i, message: 'Metric sent.', metric: stat)}\n"
20
+ "#{JSON.dump(timestamp: datetime.to_i, message: "Metric sent.", metric: stat)}\n"
21
21
  end
22
22
  end
23
23
  end
24
24
 
25
25
  def count(stat, value, options = nil)
26
- logger.info({ stat: stat, type: :count, value: value, options: options }.to_json)
26
+ logger.info({stat: stat, type: :count, value: value, options: options}.to_json)
27
27
  end
28
28
 
29
29
  def distribution(stat, value, options = nil)
30
- logger.info({ stat: stat, type: :distribution, value: value, options: options }.to_json)
30
+ logger.info({stat: stat, type: :distribution, value: value, options: options}.to_json)
31
31
  end
32
32
 
33
33
  def increment(stat, options = nil)
34
- logger.info({ stat: stat, type: :increment, options: options }.to_json)
34
+ logger.info({stat: stat, type: :increment, options: options}.to_json)
35
35
  end
36
36
 
37
37
  def gauge(stat, value, options = nil)
38
- logger.info({ stat: stat, type: :gauge, value: value, options: options }.to_json)
38
+ logger.info({stat: stat, type: :gauge, value: value, options: options}.to_json)
39
39
  end
40
40
  end
41
41
  end
@@ -13,13 +13,15 @@ module Datadog
13
13
  # to be side-effect free.
14
14
  #
15
15
  # @return [Boolean] whether a resource conforms with the current limit
16
- def allow?(size = 1); end
16
+ def allow?(size = 1)
17
+ end
17
18
 
18
19
  # The effective rate limiting ratio based on
19
20
  # recent calls to `allow?`.
20
21
  #
21
22
  # @return [Float] recent allowance ratio
22
- def effective_rate; end
23
+ def effective_rate
24
+ end
23
25
  end
24
26
 
25
27
  # Implementation of the Token Bucket metering algorithm
@@ -11,6 +11,7 @@ module Datadog
11
11
  # Client communicates with the agent and sync remote configuration
12
12
  class Client
13
13
  class TransportError < StandardError; end
14
+
14
15
  class SyncError < StandardError; end
15
16
 
16
17
  attr_reader :transport, :repository, :id, :dispatcher, :logger
@@ -119,7 +120,7 @@ module Datadog
119
120
  end
120
121
  end
121
122
 
122
- def payload # rubocop:disable Metrics/MethodLength
123
+ def payload # standard:disable Metrics/MethodLength
123
124
  state = repository.state
124
125
 
125
126
  client_tracer_tags = [
@@ -134,10 +135,10 @@ module Datadog
134
135
  "ruby.runtime.engine.name:#{RUBY_ENGINE}",
135
136
  "ruby.runtime.engine.version:#{ruby_engine_version}",
136
137
  "ruby.rubygems.platform.local:#{Gem::Platform.local}",
137
- "ruby.gem.libddwaf.version:#{gem_spec('libddwaf').version}",
138
- "ruby.gem.libddwaf.platform:#{gem_spec('libddwaf').platform}",
139
- "ruby.gem.libdatadog.version:#{gem_spec('libdatadog').version}",
140
- "ruby.gem.libdatadog.platform:#{gem_spec('libdatadog').platform}",
138
+ "ruby.gem.libddwaf.version:#{gem_spec("libddwaf").version}",
139
+ "ruby.gem.libddwaf.platform:#{gem_spec("libddwaf").platform}",
140
+ "ruby.gem.libdatadog.version:#{gem_spec("libdatadog").version}",
141
+ "ruby.gem.libdatadog.platform:#{gem_spec("libdatadog").platform}",
141
142
  ]
142
143
 
143
144
  if (git_repository_url = Core::Environment::Git.git_repository_url)
@@ -202,37 +203,37 @@ module Datadog
202
203
  return @native_platform unless @native_platform.nil?
203
204
 
204
205
  os = if RUBY_ENGINE == 'jruby'
205
- os_name = java.lang.System.get_property('os.name')
206
+ os_name = java.lang.System.get_property('os.name')
206
207
 
207
- case os_name
208
- when /linux/i then 'linux'
209
- when /mac/i then 'darwin'
210
- else os_name
211
- end
212
- else
213
- Gem::Platform.local.os
214
- end
208
+ case os_name
209
+ when /linux/i then 'linux'
210
+ when /mac/i then 'darwin'
211
+ else os_name
212
+ end
213
+ else
214
+ Gem::Platform.local.os
215
+ end
215
216
 
216
217
  version = if os != 'linux'
217
- nil
218
- elsif RUBY_PLATFORM =~ /linux-(.+)$/
219
- # Old rubygems don't handle non-gnu linux correctly
220
- Regexp.last_match(1)
221
- else
222
- 'gnu'
223
- end
218
+ nil
219
+ elsif RUBY_PLATFORM =~ /linux-(.+)$/
220
+ # Old rubygems don't handle non-gnu linux correctly
221
+ Regexp.last_match(1)
222
+ else
223
+ 'gnu'
224
+ end
224
225
 
225
226
  cpu = if RUBY_ENGINE == 'jruby'
226
- os_arch = java.lang.System.get_property('os.arch')
227
-
228
- case os_arch
229
- when 'amd64' then 'x86_64'
230
- when 'aarch64' then os == 'darwin' ? 'arm64' : 'aarch64'
231
- else os_arch
232
- end
233
- else
234
- Gem::Platform.local.cpu
235
- end
227
+ os_arch = java.lang.System.get_property('os.arch')
228
+
229
+ case os_arch
230
+ when 'amd64' then 'x86_64'
231
+ when 'aarch64' then (os == 'darwin') ? 'arm64' : 'aarch64'
232
+ else os_arch
233
+ end
234
+ else
235
+ Gem::Platform.local.cpu
236
+ end
236
237
 
237
238
  @native_platform = [cpu, os, version].compact.join('-')
238
239
  end
@@ -42,7 +42,7 @@ module Datadog
42
42
  logger.error do
43
43
  "remote worker client sync error: #{e.message} location: #{Array(e.backtrace).first}. skipping sync"
44
44
  end
45
- rescue StandardError => e
45
+ rescue => e
46
46
  # In case of unexpected errors, reset the negotiation object
47
47
  # given external conditions have changed and the negotiation
48
48
  # negotiation object stores error logging state that should be reset.
@@ -50,8 +50,8 @@ module Datadog
50
50
 
51
51
  # Transient errors due to network or agent. Logged the error but not via telemetry
52
52
  logger.error do
53
- "remote worker error: #{e.class.name} #{e.message} location: #{Array(e.backtrace).first}. "\
54
- 'reseting client state'
53
+ "remote worker error: #{e.class.name} #{e.message} location: #{Array(e.backtrace).first}. " \
54
+ 'resetting client state'
55
55
  end
56
56
 
57
57
  # client state is unknown, state might be corrupted
@@ -29,13 +29,13 @@ module Datadog
29
29
  class << self
30
30
  def hexdigest(type, data)
31
31
  d = case type
32
- when :sha256
33
- ::Digest::SHA256.new
34
- when :sha512
35
- ::Digest::SHA512.new
36
- else
37
- raise InvalidHashTypeError, type
38
- end
32
+ when :sha256
33
+ ::Digest::SHA256.new
34
+ when :sha512
35
+ ::Digest::SHA512.new
36
+ else
37
+ raise InvalidHashTypeError, type
38
+ end
39
39
 
40
40
  while (buf = data.read(DIGEST_CHUNK))
41
41
  d.update(buf)
@@ -30,7 +30,7 @@ module Datadog
30
30
 
31
31
  raise ParseError, "could not parse: #{path.inspect}" if m.nil?
32
32
 
33
- org_id = m['org_id'] ? m['org_id'].to_i : nil
33
+ org_id = m['org_id']&.to_i
34
34
 
35
35
  source = m['source']
36
36
  raise ParseError, 'missing source value' unless source
@@ -28,7 +28,7 @@ module Datadog
28
28
 
29
29
  # Get responses from API
30
30
  yield(api, env)
31
- rescue StandardError => e
31
+ rescue => e
32
32
  message =
33
33
  "Internal error during #{self.class.name} request. Cause: #{e.class.name} #{e.message} " \
34
34
  "Location: #{Array(e.backtrace).first}"
@@ -5,6 +5,7 @@ require 'json'
5
5
  require_relative '../config'
6
6
  require_relative 'client'
7
7
  require_relative '../../../utils/base64'
8
+ require_relative '../../../utils/truncation'
8
9
  require_relative '../../../transport/http/response'
9
10
  require_relative '../../../transport/http/api/endpoint'
10
11
 
@@ -20,9 +21,11 @@ module Datadog
20
21
  include Datadog::Core::Transport::HTTP::Response
21
22
  include Core::Remote::Transport::Config::Response
22
23
 
23
- def initialize(http_response, options = {}) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
24
+ def initialize(http_response, options = {}) # standard:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
24
25
  super(http_response)
25
26
 
27
+ raise AgentErrorResponse.new(http_response.code, http_response.payload) if http_response.code != 200
28
+
26
29
  begin
27
30
  payload = JSON.parse(http_response.payload, symbolize_names: true)
28
31
  rescue JSON::ParserError => e
@@ -130,8 +133,21 @@ module Datadog
130
133
  end
131
134
  end
132
135
 
136
+ # Base class for Remote Configuration Config errors
137
+ class ConfigError < StandardError
138
+ end
139
+
140
+ # When the agent returned an error response to our request
141
+ class AgentErrorResponse < ConfigError
142
+ def initialize(code, body)
143
+ truncated_body = Core::Utils::Truncation.truncate_in_middle(body, 700, 300)
144
+ message = "Agent returned an error response: #{code}: #{truncated_body}"
145
+ super(message)
146
+ end
147
+ end
148
+
133
149
  # When an expected value type is incorrect
134
- class TypeError < StandardError
150
+ class TypeError < ConfigError
135
151
  def initialize(type, value)
136
152
  message = "not a #{type}: #{value.inspect}"
137
153
 
@@ -140,7 +156,7 @@ module Datadog
140
156
  end
141
157
 
142
158
  # When value decoding fails
143
- class DecodeError < StandardError
159
+ class DecodeError < ConfigError
144
160
  def initialize(key, value)
145
161
  message = "could not decode key #{key.inspect}: #{value.inspect}"
146
162
 
@@ -149,7 +165,7 @@ module Datadog
149
165
  end
150
166
 
151
167
  # When value parsing fails
152
- class ParseError < StandardError
168
+ class ParseError < ConfigError
153
169
  def initialize(key, value)
154
170
  message = "could not parse key #{key.inspect}: #{value.inspect}"
155
171
 
@@ -215,7 +231,7 @@ module Datadog
215
231
  env.body = env.request.parcel.data
216
232
 
217
233
  # Query for response
218
- http_response = super(env, &block)
234
+ http_response = super
219
235
 
220
236
  response_options = {}
221
237
 
@@ -79,7 +79,7 @@ module Datadog
79
79
 
80
80
  def call(env, &block)
81
81
  # Query for response
82
- http_response = super(env, &block)
82
+ http_response = super
83
83
 
84
84
  # Process the response
85
85
  body = JSON.parse(http_response.payload, symbolize_names: true) if http_response.ok?
@@ -96,7 +96,7 @@ module Datadog
96
96
 
97
97
  def try_flush
98
98
  yield
99
- rescue StandardError => e
99
+ rescue => e
100
100
  Datadog.logger.warn("Error while sending runtime metric. Cause: #{e.class.name} #{e.message}")
101
101
  end
102
102
 
@@ -147,7 +147,7 @@ module Datadog
147
147
  gauge(metric_name, metric_value) if metric_value
148
148
  end
149
149
 
150
- # rubocop:disable Metrics/MethodLength
150
+ # standard:disable Metrics/MethodLength
151
151
  def flush_yjit_stats
152
152
  # Only on Ruby >= 3.2
153
153
  try_flush do
@@ -195,7 +195,7 @@ module Datadog
195
195
  end
196
196
  end
197
197
  end
198
- # rubocop:enable Metrics/MethodLength
198
+ # standard:enable Metrics/MethodLength
199
199
  end
200
200
  end
201
201
  end
@@ -16,6 +16,8 @@ module Datadog
16
16
  module Telemetry
17
17
  # Telemetry entrypoint, coordinates sending telemetry events at various points in app lifecycle.
18
18
  # Note: Telemetry does not spawn its worker thread in fork processes, thus no telemetry is sent in forked processes.
19
+ #
20
+ # @api private
19
21
  class Component
20
22
  attr_reader :enabled, :logger, :transport, :worker
21
23
 
@@ -40,7 +42,7 @@ module Datadog
40
42
  end
41
43
 
42
44
  # @param enabled [Boolean] Determines whether telemetry events should be sent to the API
43
- def initialize( # rubocop: disable Metrics/MethodLength
45
+ def initialize( # standard:disable Metrics/MethodLength
44
46
  settings:,
45
47
  agent_settings:,
46
48
  logger:,
@@ -60,25 +62,25 @@ module Datadog
60
62
  return unless @enabled
61
63
 
62
64
  @transport = if settings.telemetry.agentless_enabled
63
- agent_settings = Core::Configuration::AgentlessSettingsResolver.call(
64
- settings,
65
- host_prefix: 'instrumentation-telemetry-intake',
66
- url_override: settings.telemetry.agentless_url_override,
67
- url_override_source: 'c.telemetry.agentless_url_override',
68
- logger: logger,
69
- )
70
- Telemetry::Transport::HTTP.agentless_telemetry(
71
- agent_settings: agent_settings,
72
- logger: logger,
73
- # api_key should have already validated to be
74
- # not nil by +build+ method above.
75
- api_key: settings.api_key,
76
- )
77
- else
78
- Telemetry::Transport::HTTP.agent_telemetry(
79
- agent_settings: agent_settings, logger: logger,
80
- )
81
- end
65
+ agent_settings = Core::Configuration::AgentlessSettingsResolver.call(
66
+ settings,
67
+ host_prefix: 'instrumentation-telemetry-intake',
68
+ url_override: settings.telemetry.agentless_url_override,
69
+ url_override_source: 'c.telemetry.agentless_url_override',
70
+ logger: logger,
71
+ )
72
+ Telemetry::Transport::HTTP.agentless_telemetry(
73
+ agent_settings: agent_settings,
74
+ logger: logger,
75
+ # api_key should have already validated to be
76
+ # not nil by +build+ method above.
77
+ api_key: settings.api_key,
78
+ )
79
+ else
80
+ Telemetry::Transport::HTTP.agent_telemetry(
81
+ agent_settings: agent_settings, logger: logger,
82
+ )
83
+ end
82
84
 
83
85
  @worker = Telemetry::Worker.new(
84
86
  enabled: @enabled,
@@ -94,8 +96,6 @@ module Datadog
94
96
  logger: logger,
95
97
  shutdown_timeout: settings.telemetry.shutdown_timeout_seconds,
96
98
  )
97
-
98
- @worker.start
99
99
  end
100
100
 
101
101
  def disable!
@@ -103,10 +103,25 @@ module Datadog
103
103
  @worker&.enabled = false
104
104
  end
105
105
 
106
- def stop!
106
+ def start(initial_event_is_change = false)
107
+ return if !@enabled
108
+
109
+ initial_event = if initial_event_is_change
110
+ Event::SynthAppClientConfigurationChange.new
111
+ else
112
+ Event::AppStarted.new
113
+ end
114
+
115
+ @worker.start(initial_event)
116
+ end
117
+
118
+ def shutdown!
107
119
  return if @stopped
108
120
 
109
- @worker&.stop(true)
121
+ if defined?(@worker)
122
+ @worker&.stop(true)
123
+ end
124
+
110
125
  @stopped = true
111
126
  end
112
127
 
@@ -34,7 +34,13 @@ module Datadog
34
34
  logger.debug { "Telemetry sent for event `#{event.type}` (response code: #{res.code})" }
35
35
  res
36
36
  rescue => e
37
- logger.debug { "Unable to send telemetry request for event `#{event.type rescue 'unknown'}`: #{e}" }
37
+ logger.debug {
38
+ "Unable to send telemetry request for event `#{begin
39
+ event.type
40
+ rescue
41
+ "unknown"
42
+ end}`: #{e}"
43
+ }
38
44
  Core::Transport::InternalErrorResponse.new(e)
39
45
  end
40
46
 
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Datadog
6
+ module Core
7
+ module Telemetry
8
+ module Event
9
+ # Telemetry class for the 'app-client-configuration-change' event
10
+ class AppClientConfigurationChange < Base
11
+ attr_reader :changes, :origin
12
+
13
+ def type
14
+ 'app-client-configuration-change'
15
+ end
16
+
17
+ def initialize(changes, origin)
18
+ super()
19
+ @changes = changes
20
+ @origin = origin
21
+ end
22
+
23
+ def payload
24
+ {configuration: configuration}
25
+ end
26
+
27
+ def configuration
28
+ config = Datadog.configuration
29
+ seq_id = Event.configuration_sequence.next
30
+
31
+ res = @changes.map do |name, value|
32
+ {
33
+ name: name,
34
+ value: value,
35
+ origin: @origin,
36
+ seq_id: seq_id,
37
+ }
38
+ end
39
+
40
+ unless config.dig('appsec', 'sca_enabled').nil?
41
+ res << {
42
+ name: 'appsec.sca_enabled',
43
+ value: config.appsec.sca_enabled,
44
+ origin: 'code',
45
+ seq_id: seq_id,
46
+ }
47
+ end
48
+
49
+ res
50
+ end
51
+
52
+ def ==(other)
53
+ other.is_a?(AppClientConfigurationChange) && other.changes == @changes && other.origin == @origin
54
+ end
55
+
56
+ alias_method :eql?, :==
57
+
58
+ def hash
59
+ [self.class, @changes, @origin].hash
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Datadog
6
+ module Core
7
+ module Telemetry
8
+ module Event
9
+ # Telemetry class for the 'app-closing' event
10
+ class AppClosing < Base
11
+ def type
12
+ 'app-closing'
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Datadog
6
+ module Core
7
+ module Telemetry
8
+ module Event
9
+ # Telemetry class for the 'app-dependencies-loaded' event
10
+ class AppDependenciesLoaded < Base
11
+ def type
12
+ 'app-dependencies-loaded'
13
+ end
14
+
15
+ def payload
16
+ {dependencies: dependencies}
17
+ end
18
+
19
+ private
20
+
21
+ def dependencies
22
+ Gem.loaded_specs.collect do |name, gem|
23
+ {
24
+ name: name,
25
+ version: gem.version.to_s,
26
+ }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Datadog
6
+ module Core
7
+ module Telemetry
8
+ module Event
9
+ # Telemetry class for the 'app-heartbeat' event
10
+ class AppHeartbeat < Base
11
+ def type
12
+ 'app-heartbeat'
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end