datadog 2.32.0 → 2.34.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 (113) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -1
  3. data/ext/datadog_profiling_native_extension/clock_id.h +9 -1
  4. data/ext/datadog_profiling_native_extension/clock_id_from_mach.c +73 -0
  5. data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +1 -1
  6. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +20 -0
  7. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +5 -1
  8. data/ext/datadog_profiling_native_extension/extconf.rb +3 -0
  9. data/ext/datadog_profiling_native_extension/macos_sampler_thread.h +55 -0
  10. data/ext/datadog_profiling_native_extension/stack_recorder.c +3 -9
  11. data/ext/datadog_profiling_native_extension/time_helpers.h +1 -0
  12. data/ext/libdatadog_api/crashtracker.c +2 -0
  13. data/ext/libdatadog_extconf_helpers.rb +1 -1
  14. data/lib/datadog/ai_guard/autoload.rb +10 -0
  15. data/lib/datadog/ai_guard/component.rb +1 -1
  16. data/lib/datadog/ai_guard/contrib/auto_instrument.rb +24 -0
  17. data/lib/datadog/ai_guard/contrib/rack/integration.rb +42 -0
  18. data/lib/datadog/ai_guard/contrib/rack/patcher.rb +26 -0
  19. data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +83 -0
  20. data/lib/datadog/ai_guard/contrib/rails/integration.rb +41 -0
  21. data/lib/datadog/ai_guard/contrib/rails/patcher.rb +97 -0
  22. data/lib/datadog/ai_guard/evaluation.rb +1 -0
  23. data/lib/datadog/ai_guard/ext.rb +1 -0
  24. data/lib/datadog/ai_guard.rb +8 -0
  25. data/lib/datadog/appsec/component.rb +4 -1
  26. data/lib/datadog/appsec/compressed_json.rb +2 -2
  27. data/lib/datadog/appsec/contrib/aws_lambda/gateway/watcher.rb +75 -0
  28. data/lib/datadog/appsec/contrib/aws_lambda/integration.rb +39 -0
  29. data/lib/datadog/appsec/contrib/aws_lambda/patcher.rb +30 -0
  30. data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +111 -0
  31. data/lib/datadog/appsec/contrib/rack/ext.rb +1 -1
  32. data/lib/datadog/appsec.rb +1 -0
  33. data/lib/datadog/core/configuration/components.rb +8 -1
  34. data/lib/datadog/core/configuration/settings.rb +16 -1
  35. data/lib/datadog/core/configuration/supported_configurations.rb +12 -0
  36. data/lib/datadog/core/environment/ext.rb +5 -0
  37. data/lib/datadog/core/environment/identity.rb +15 -1
  38. data/lib/datadog/core/environment/process.rb +48 -27
  39. data/lib/datadog/core/environment/socket.rb +13 -0
  40. data/lib/datadog/core/remote/client/capabilities.rb +11 -2
  41. data/lib/datadog/core/remote/transport/http/config.rb +5 -5
  42. data/lib/datadog/core/telemetry/request.rb +0 -2
  43. data/lib/datadog/core/transport/response.rb +1 -1
  44. data/lib/datadog/core/utils/{base64.rb → base64_codec.rb} +3 -2
  45. data/lib/datadog/core/utils/hash.rb +0 -23
  46. data/lib/datadog/core/utils/spawn_monkey_patch.rb +46 -16
  47. data/lib/datadog/data_streams/pathway_context.rb +3 -3
  48. data/lib/datadog/di/code_tracker.rb +43 -22
  49. data/lib/datadog/di/contrib/active_record.rb +6 -2
  50. data/lib/datadog/di/instrumenter.rb +24 -4
  51. data/lib/datadog/di/probe_notification_builder.rb +1 -1
  52. data/lib/datadog/di/remote.rb +4 -4
  53. data/lib/datadog/di/serializer.rb +5 -5
  54. data/lib/datadog/di/utils.rb +42 -14
  55. data/lib/datadog/opentelemetry/configuration/settings.rb +65 -0
  56. data/lib/datadog/opentelemetry/ext.rb +9 -0
  57. data/lib/datadog/opentelemetry/logs.rb +98 -0
  58. data/lib/datadog/opentelemetry/metrics.rb +10 -37
  59. data/lib/datadog/opentelemetry/sdk/configurator.rb +40 -0
  60. data/lib/datadog/opentelemetry/sdk/id_generator.rb +16 -10
  61. data/lib/datadog/opentelemetry/sdk/logs_exporter.rb +37 -0
  62. data/lib/datadog/opentelemetry/signal_configuration.rb +53 -0
  63. data/lib/datadog/opentelemetry.rb +1 -0
  64. data/lib/datadog/profiling/component.rb +0 -1
  65. data/lib/datadog/profiling/stack_recorder.rb +0 -4
  66. data/lib/datadog/symbol_database/component.rb +409 -0
  67. data/lib/datadog/symbol_database/configuration.rb +2 -2
  68. data/lib/datadog/symbol_database/extractor.rb +45 -26
  69. data/lib/datadog/symbol_database/remote.rb +175 -0
  70. data/lib/datadog/symbol_database/scope.rb +16 -12
  71. data/lib/datadog/symbol_database/scope_batcher.rb +288 -0
  72. data/lib/datadog/symbol_database/service_version.rb +15 -6
  73. data/lib/datadog/symbol_database/symbol.rb +6 -3
  74. data/lib/datadog/symbol_database/uploader.rb +65 -8
  75. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +8 -0
  76. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +0 -4
  77. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +0 -4
  78. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +0 -4
  79. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +0 -5
  80. data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +0 -5
  81. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +0 -5
  82. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +0 -5
  83. data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +0 -8
  84. data/lib/datadog/tracing/contrib/excon/middleware.rb +0 -5
  85. data/lib/datadog/tracing/contrib/ext.rb +2 -3
  86. data/lib/datadog/tracing/contrib/faraday/middleware.rb +0 -5
  87. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +0 -5
  88. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +0 -5
  89. data/lib/datadog/tracing/contrib/http/instrumentation.rb +0 -5
  90. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +0 -5
  91. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +0 -5
  92. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +0 -5
  93. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +0 -5
  94. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +0 -5
  95. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +0 -5
  96. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +0 -5
  97. data/lib/datadog/tracing/contrib/racecar/event.rb +0 -5
  98. data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +6 -0
  99. data/lib/datadog/tracing/contrib/rack/ext.rb +27 -0
  100. data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +117 -1
  101. data/lib/datadog/tracing/contrib/redis/tags.rb +0 -5
  102. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +0 -5
  103. data/lib/datadog/tracing/contrib/sequel/utils.rb +0 -5
  104. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +0 -5
  105. data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +0 -13
  106. data/lib/datadog/tracing/distributed/trace_context.rb +0 -28
  107. data/lib/datadog/tracing/metadata/ext.rb +3 -0
  108. data/lib/datadog/tracing/span_operation.rb +13 -0
  109. data/lib/datadog/tracing/trace_operation.rb +22 -0
  110. data/lib/datadog/tracing/tracer.rb +7 -3
  111. data/lib/datadog/version.rb +1 -1
  112. metadata +27 -8
  113. data/ext/datadog_profiling_native_extension/clock_id_noop.c +0 -21
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../core/utils/only_once"
4
+ require_relative "../rack/request_middleware"
5
+ require_relative "../../../tracing/contrib"
6
+ require_relative "../../../tracing/contrib/rack/middlewares"
7
+
8
+ module Datadog
9
+ module AIGuard
10
+ module Contrib
11
+ module Rails
12
+ # Patcher for AI Guard on Rails. Inserts the AI Guard Rack middleware
13
+ # right after the Tracing Rack middleware so the request span is
14
+ # already active when AI Guard tags the client IP.
15
+ module Patcher
16
+ BEFORE_INITIALIZE_ONLY_ONCE_PER_APP = Hash.new { |h, key| h[key] = Datadog::Core::Utils::OnlyOnce.new }
17
+
18
+ module_function
19
+
20
+ def patched?
21
+ !!Patcher.instance_variable_get(:@patched)
22
+ end
23
+
24
+ def target_version
25
+ Integration.version
26
+ end
27
+
28
+ def patch
29
+ patch_before_initialize
30
+ Patcher.instance_variable_set(:@patched, true)
31
+ end
32
+
33
+ def patch_before_initialize
34
+ ::ActiveSupport.on_load(:before_initialize) do
35
+ Datadog::AIGuard::Contrib::Rails::Patcher.before_initialize(self)
36
+ end
37
+ end
38
+
39
+ def before_initialize(app)
40
+ BEFORE_INITIALIZE_ONLY_ONCE_PER_APP[app].run do
41
+ # Middleware must be added before the application is initialized.
42
+ # Otherwise the middleware stack will be frozen.
43
+ add_middleware(app) if Datadog.configuration.tracing[:rails][:middleware]
44
+ end
45
+ end
46
+
47
+ def add_middleware(app)
48
+ if include_middleware?(Datadog::Tracing::Contrib::Rack::TraceMiddleware, app)
49
+ app.middleware.insert_after(
50
+ Datadog::Tracing::Contrib::Rack::TraceMiddleware,
51
+ Datadog::AIGuard::Contrib::Rack::RequestMiddleware
52
+ )
53
+ else
54
+ app.middleware.insert_before(0, Datadog::AIGuard::Contrib::Rack::RequestMiddleware)
55
+ end
56
+ end
57
+
58
+ def include_middleware?(middleware, app)
59
+ found = false
60
+
61
+ # find tracer middleware reference in Rails::Configuration::MiddlewareStackProxy
62
+ app.middleware.instance_variable_get(:@operations).each do |operation|
63
+ args = case operation
64
+ when Array
65
+ # rails 5.2
66
+ _op, args = operation
67
+ args
68
+ when Proc
69
+ if operation.binding.local_variables.include?(:args)
70
+ # rails 6.0, 6.1
71
+ operation.binding.local_variable_get(:args)
72
+ else
73
+ # rails 7.0 uses ... to pass args
74
+ # steep:ignore:start
75
+ args_getter = Class.new do
76
+ def method_missing(_op, *args) # standard:disable Style/MissingRespondToMissing
77
+ args
78
+ end
79
+ end.new
80
+ # steep:ignore:end
81
+ operation.call(args_getter)
82
+ end
83
+ else
84
+ # unknown, pass through
85
+ []
86
+ end
87
+
88
+ found = true if args.include?(middleware)
89
+ end
90
+
91
+ found
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -16,6 +16,7 @@ module Datadog
16
16
  Tracing::Sampling::Ext::Decision::AI_GUARD
17
17
  )
18
18
  trace.set_tag(Ext::EVENT_TAG, true)
19
+ trace.set_tag(Ext::SERVICE_ENTRY_EXECUTED_TAG, "1")
19
20
 
20
21
  if (last_message = messages.last)
21
22
  if last_message.tool_call
@@ -11,6 +11,7 @@ module Datadog
11
11
  REASON_TAG = "ai_guard.reason"
12
12
  BLOCKED_TAG = "ai_guard.blocked"
13
13
  EVENT_TAG = "ai_guard.event"
14
+ SERVICE_ENTRY_EXECUTED_TAG = "_dd.ai_guard.executed"
14
15
  METASTRUCT_TAG = "ai_guard"
15
16
  end
16
17
  end
@@ -3,6 +3,8 @@
3
3
  require_relative "core/configuration"
4
4
  require_relative "ai_guard/configuration"
5
5
 
6
+ require_relative "ai_guard/contrib/rack/integration"
7
+ require_relative "ai_guard/contrib/rails/integration"
6
8
  require_relative "ai_guard/contrib/ruby_llm/integration"
7
9
 
8
10
  module Datadog
@@ -50,6 +52,10 @@ module Datadog
50
52
  Datadog.send(:components).ai_guard&.logger
51
53
  end
52
54
 
55
+ def telemetry
56
+ Datadog.send(:components).ai_guard&.telemetry
57
+ end
58
+
53
59
  # Evaluates one or more messages using AI Guard API.
54
60
  #
55
61
  # Example:
@@ -171,3 +177,5 @@ module Datadog
171
177
  end
172
178
  end
173
179
  end
180
+
181
+ require_relative "ai_guard/autoload"
@@ -46,7 +46,10 @@ module Datadog
46
46
 
47
47
  security_engine = SecurityEngine::Engine.new(appsec_settings: settings.appsec, telemetry: telemetry)
48
48
  new(security_engine: security_engine)
49
- rescue => e
49
+ # NOTE: At this point we should capture all possible exceptions and
50
+ # gracefully fail component initialization, preventing propagation
51
+ # into the host application code.
52
+ rescue Exception => e # standard:disable Lint/RescueException
50
53
  Datadog.logger.warn("AppSec is disabled: #{e.class}: #{e.message}; there may be additional logged errors above")
51
54
 
52
55
  # Not reporting to telemetry here because some of the rescued exceptions
@@ -4,7 +4,7 @@ require 'json'
4
4
  require 'zlib'
5
5
  require 'stringio'
6
6
 
7
- require_relative '../core/utils/base64'
7
+ require_relative '../core/utils/base64_codec'
8
8
 
9
9
  module Datadog
10
10
  module AppSec
@@ -27,7 +27,7 @@ module Datadog
27
27
  end
28
28
 
29
29
  private_class_method def self.compress_and_encode(payload)
30
- Core::Utils::Base64.strict_encode64(
30
+ Core::Utils::Base64Codec.strict_encode64(
31
31
  Zlib.gzip(payload, level: Zlib::BEST_SPEED, strategy: Zlib::DEFAULT_STRATEGY)
32
32
  )
33
33
  rescue Zlib::Error, TypeError => e
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../waf_addresses'
4
+ require_relative '../../../event'
5
+ require_relative '../../../trace_keeper'
6
+ require_relative '../../../security_event'
7
+ require_relative '../../../instrumentation/gateway'
8
+
9
+ module Datadog
10
+ module AppSec
11
+ module Contrib
12
+ module AwsLambda
13
+ module Gateway
14
+ module Watcher
15
+ class << self
16
+ def watch
17
+ gateway = Instrumentation.gateway
18
+
19
+ watch_request(gateway)
20
+ watch_response(gateway)
21
+ end
22
+
23
+ def watch_request(gateway = Instrumentation.gateway)
24
+ gateway.watch('aws_lambda.request.start') do |stack, payload|
25
+ context = payload.context
26
+ next stack.call(payload) unless context
27
+
28
+ persistent_data = WAFAddresses.from_request(payload.data)
29
+ result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
30
+
31
+ if result.match? || !result.attributes.empty?
32
+ context.events.push(
33
+ AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
34
+ )
35
+ end
36
+
37
+ if result.match?
38
+ AppSec::Event.tag(context, result)
39
+ TraceKeeper.keep!(context.trace) if result.keep?
40
+ AppSec::ActionsHandler.handle(result.actions)
41
+ end
42
+
43
+ stack.call(payload)
44
+ end
45
+ end
46
+
47
+ def watch_response(gateway = Instrumentation.gateway)
48
+ gateway.watch('aws_lambda.response.start') do |stack, payload|
49
+ context = payload.context
50
+ next stack.call(payload) unless context
51
+
52
+ persistent_data = WAFAddresses.from_response(payload.data)
53
+ result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
54
+
55
+ if result.match?
56
+ AppSec::Event.tag(context, result)
57
+ TraceKeeper.keep!(context.trace) if result.keep?
58
+
59
+ context.events.push(
60
+ AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
61
+ )
62
+
63
+ AppSec::ActionsHandler.handle(result.actions)
64
+ end
65
+
66
+ stack.call(payload)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'patcher'
4
+ require_relative '../integration'
5
+
6
+ module Datadog
7
+ module AppSec
8
+ module Contrib
9
+ module AwsLambda
10
+ class Integration
11
+ include Datadog::AppSec::Contrib::Integration
12
+
13
+ register_as :aws_lambda, auto_patch: false
14
+
15
+ # NOTE: AWS Lambda is a runtime environment, not an installable gem
16
+ def self.version
17
+ nil
18
+ end
19
+
20
+ def self.loaded?
21
+ true
22
+ end
23
+
24
+ def self.compatible?
25
+ super
26
+ end
27
+
28
+ def self.auto_instrument?
29
+ false
30
+ end
31
+
32
+ def patcher
33
+ Patcher
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../monitor'
4
+ require_relative 'gateway/watcher'
5
+
6
+ module Datadog
7
+ module AppSec
8
+ module Contrib
9
+ module AwsLambda
10
+ module Patcher
11
+ module_function
12
+
13
+ def patched?
14
+ Patcher.instance_variable_get(:@patched)
15
+ end
16
+
17
+ def target_version
18
+ Integration.version
19
+ end
20
+
21
+ def patch
22
+ Monitor::Gateway::Watcher.watch
23
+ Gateway::Watcher.watch
24
+ Patcher.instance_variable_set(:@patched, true)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+
5
+ require_relative '../../utils/http/media_type'
6
+ require_relative '../../utils/http/body'
7
+ require_relative '../../../core/utils/base64_codec'
8
+ require_relative '../../../core/header_collection'
9
+ require_relative '../../../tracing/client_ip'
10
+
11
+ module Datadog
12
+ module AppSec
13
+ module Contrib
14
+ module AwsLambda
15
+ # Extracts WAF input addresses from normalized AWS Lambda API Gateway event payloads.
16
+ # @api private
17
+ module WAFAddresses
18
+ module_function
19
+
20
+ def from_request(payload)
21
+ return {} if payload.nil? || payload.empty?
22
+
23
+ headers = parse_headers(payload)
24
+ data = {
25
+ 'server.request.cookies' => parse_cookies(payload, headers),
26
+ 'server.request.query' => payload['query'],
27
+ 'server.request.uri.raw' => build_fullpath(payload),
28
+ 'server.request.headers' => headers,
29
+ 'server.request.headers.no_cookies' => headers.dup.tap { |h| h.delete('cookie') },
30
+ 'http.client_ip' => extract_client_ip(payload['source_ip'], headers),
31
+ 'server.request.method' => payload['method'],
32
+ 'server.request.body' => parse_body(payload, headers),
33
+ 'server.request.path_params' => payload['path_params']
34
+ }
35
+
36
+ data.compact!
37
+ data
38
+ end
39
+
40
+ def from_response(payload)
41
+ return {} if payload.nil? || payload.empty?
42
+
43
+ headers = parse_headers(payload)
44
+ data = {
45
+ 'server.response.status' => payload['status_code']&.to_s,
46
+ 'server.response.headers' => headers,
47
+ 'server.response.headers.no_cookies' => headers.dup.tap { |h| h.delete('set-cookie') }
48
+ }
49
+
50
+ data.compact!
51
+ data
52
+ end
53
+
54
+ def parse_headers(payload)
55
+ (payload['headers'] || {}).each_with_object({}) do |(key, value), hash|
56
+ hash[key.downcase] = value
57
+ end
58
+ end
59
+
60
+ def parse_cookies(payload, headers)
61
+ raw_pairs = payload['cookies'] || headers['cookie']&.split(';')
62
+ return unless raw_pairs
63
+
64
+ raw_pairs.each_with_object({}) do |pair, hash|
65
+ name, value = pair.strip.split('=', 2)
66
+ hash[name] = value if name
67
+ end
68
+ end
69
+
70
+ def build_fullpath(payload)
71
+ path = payload['path']
72
+ return unless path
73
+
74
+ query_string = build_query_string(payload)
75
+ query_string ? "#{path}?#{query_string}" : path
76
+ end
77
+
78
+ def build_query_string(payload)
79
+ query_string = payload['query_string']
80
+ return query_string if query_string && !query_string.empty?
81
+
82
+ query = payload['query']
83
+ return if query.nil? || query.empty?
84
+
85
+ URI.encode_www_form(query)
86
+ end
87
+
88
+ def extract_client_ip(remote_ip, headers)
89
+ header_collection = Datadog::Core::HeaderCollection.from_hash(headers)
90
+ Datadog::Tracing::ClientIp.extract_client_ip(header_collection, remote_ip)
91
+ end
92
+
93
+ def parse_body(payload, headers)
94
+ body = payload['body']
95
+ return unless body
96
+
97
+ body = Core::Utils::Base64Codec.strict_decode64(body) if payload['base64_encoded']
98
+
99
+ content_type = headers['content-type']
100
+ return unless content_type
101
+
102
+ media_type = AppSec::Utils::HTTP::MediaType.parse(content_type)
103
+ return unless media_type
104
+
105
+ AppSec::Utils::HTTP::Body.parse(body, media_type: media_type)
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -13,7 +13,7 @@ module Datadog
13
13
  'cloudfront-viewer-ja3-fingerprint',
14
14
  'content-type',
15
15
  'user-agent',
16
- 'x-amzn-trace-Id',
16
+ 'x-amzn-trace-id',
17
17
  'x-appgw-trace-id',
18
18
  'x-cloud-trace-context',
19
19
  'x-sigsci-requestid',
@@ -63,5 +63,6 @@ require_relative 'appsec/contrib/graphql/integration'
63
63
  require_relative 'appsec/contrib/faraday/integration'
64
64
  require_relative 'appsec/contrib/excon/integration'
65
65
  require_relative 'appsec/contrib/rest_client/integration'
66
+ require_relative 'appsec/contrib/aws_lambda/integration'
66
67
 
67
68
  require_relative 'appsec/autoload'
@@ -19,6 +19,8 @@ require_relative '../../profiling/component'
19
19
  require_relative '../../appsec/component'
20
20
  require_relative '../../ai_guard/component'
21
21
  require_relative '../../di/component'
22
+ require_relative '../../symbol_database'
23
+ require_relative '../../symbol_database/component'
22
24
  require_relative '../../open_feature/component'
23
25
  require_relative '../../error_tracking/component'
24
26
  require_relative '../crashtracking/component'
@@ -120,6 +122,7 @@ module Datadog
120
122
  :ai_guard,
121
123
  :agent_info,
122
124
  :data_streams,
125
+ :symbol_database,
123
126
  :open_feature
124
127
 
125
128
  def initialize(settings)
@@ -133,7 +136,7 @@ module Datadog
133
136
  self.class::PATCH_ONLY_ONCE.run do
134
137
  Utils::AtForkMonkeyPatch.apply!
135
138
  Utils::SpawnMonkeyPatch.apply!(
136
- lineage_envs_provider: Core::Environment::Identity.method(:runtime_propagation_envs),
139
+ env_provider: Core::Environment::Identity.method(:runtime_propagation_envs),
137
140
  )
138
141
 
139
142
  # Register callback that calls Components.after_fork
@@ -171,6 +174,7 @@ module Datadog
171
174
  @ai_guard = Datadog::AIGuard::Component.build(settings, logger: @logger, telemetry: telemetry)
172
175
  @open_feature = OpenFeature::Component.build(settings, agent_settings, logger: @logger, telemetry: telemetry)
173
176
  @dynamic_instrumentation = Datadog::DI::Component.build(settings, agent_settings, @logger, telemetry: telemetry)
177
+ @symbol_database = Datadog::SymbolDatabase::Component.build(settings, agent_settings, @logger, telemetry: telemetry)
174
178
  @error_tracking = Datadog::ErrorTracking::Component.build(settings, @tracer, @logger)
175
179
  @data_streams = self.class.build_data_streams(settings, agent_settings, @logger, @agent_info)
176
180
  @environment_logger_extra[:dynamic_instrumentation_enabled] = !!@dynamic_instrumentation
@@ -241,6 +245,9 @@ module Datadog
241
245
  # Shutdown DI after remote, since remote config triggers DI operations.
242
246
  dynamic_instrumentation&.shutdown!
243
247
 
248
+ # Shutdown Symbol Database
249
+ symbol_database&.shutdown!
250
+
244
251
  # Shutdown OpenFeature component
245
252
  open_feature&.shutdown!
246
253
 
@@ -6,6 +6,7 @@ require_relative 'base'
6
6
  require_relative 'ext'
7
7
  require_relative '../environment/execution'
8
8
  require_relative '../environment/ext'
9
+ require_relative '../environment/process'
9
10
  require_relative '../runtime/ext'
10
11
  require_relative '../telemetry/ext'
11
12
  require_relative '../remote/ext'
@@ -171,6 +172,16 @@ module Datadog
171
172
  o.env Core::Environment::Ext::ENV_ENVIRONMENT
172
173
  end
173
174
 
175
+ # Override the hostname reported by this process.
176
+ # When `report_hostname` is enabled, sets the hostname on traces and
177
+ # the `host.name` resource attribute in OpenTelemetry.
178
+ # @default `DD_HOSTNAME` environment variable, otherwise `nil`
179
+ # @return [String,nil]
180
+ option :hostname do |o|
181
+ o.type :string, nilable: true
182
+ o.env Core::Environment::Ext::ENV_HOSTNAME
183
+ end
184
+
174
185
  # Configuration for container environments. For internal use only.
175
186
  # @!visibility private
176
187
  settings :container do
@@ -682,12 +693,16 @@ module Datadog
682
693
  o.env Core::Environment::Ext::ENV_SERVICE
683
694
  o.default Core::Environment::Ext::FALLBACK_SERVICE_NAME
684
695
 
696
+ o.after_set do |service_name|
697
+ Core::Environment::Process.set_service(service_name, user_configured: !using_default?(:service))
698
+ end
699
+
685
700
  # There's a few cases where we don't want to use the fallback service name, so this helper allows us to get a
686
701
  # nil instead so that one can do
687
702
  # nice_service_name = Datadog.configuration.service_without_fallback || nice_service_name_default
688
703
  o.helper(:service_without_fallback) do
689
704
  service_name = service
690
- service_name unless service_name.equal?(Core::Environment::Ext::FALLBACK_SERVICE_NAME)
705
+ service_name unless using_default?(:service)
691
706
  end
692
707
  end
693
708
 
@@ -61,6 +61,7 @@ module Datadog
61
61
  "DD_GIT_COMMIT_SHA",
62
62
  "DD_GIT_REPOSITORY_URL",
63
63
  "DD_HEALTH_METRICS_ENABLED",
64
+ "DD_HOSTNAME",
64
65
  "DD_INJECTION_ENABLED",
65
66
  "DD_INJECT_FORCE",
66
67
  "DD_INSTRUMENTATION_INSTALL_ID",
@@ -69,6 +70,7 @@ module Datadog
69
70
  "DD_INSTRUMENTATION_TELEMETRY_ENABLED",
70
71
  "DD_INTERNAL_FORCE_SYMBOL_DATABASE_UPLOAD",
71
72
  "DD_LOGS_INJECTION",
73
+ "DD_LOGS_OTEL_ENABLED",
72
74
  "DD_METRICS_OTEL_ENABLED",
73
75
  "DD_METRIC_AGENT_PORT",
74
76
  "DD_PROFILING_ALLOCATION_ENABLED",
@@ -228,6 +230,7 @@ module Datadog
228
230
  "DD_TRACE_HTTP_ENABLED",
229
231
  "DD_TRACE_HTTP_ERROR_STATUS_CODES",
230
232
  "DD_TRACE_HTTP_SERVER_ERROR_STATUSES",
233
+ "DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED",
231
234
  "DD_TRACE_KAFKA_ANALYTICS_ENABLED",
232
235
  "DD_TRACE_KAFKA_ANALYTICS_SAMPLE_RATE",
233
236
  "DD_TRACE_KAFKA_ENABLED",
@@ -348,8 +351,16 @@ module Datadog
348
351
  "DD_TRACE_WATERDROP_ENABLED",
349
352
  "DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH",
350
353
  "DD_VERSION",
354
+ "OTEL_BLRP_EXPORT_TIMEOUT",
355
+ "OTEL_BLRP_MAX_EXPORT_BATCH_SIZE",
356
+ "OTEL_BLRP_MAX_QUEUE_SIZE",
357
+ "OTEL_BLRP_SCHEDULE_DELAY",
351
358
  "OTEL_EXPORTER_OTLP_ENDPOINT",
352
359
  "OTEL_EXPORTER_OTLP_HEADERS",
360
+ "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT",
361
+ "OTEL_EXPORTER_OTLP_LOGS_HEADERS",
362
+ "OTEL_EXPORTER_OTLP_LOGS_PROTOCOL",
363
+ "OTEL_EXPORTER_OTLP_LOGS_TIMEOUT",
353
364
  "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT",
354
365
  "OTEL_EXPORTER_OTLP_METRICS_HEADERS",
355
366
  "OTEL_EXPORTER_OTLP_METRICS_PROTOCOL",
@@ -357,6 +368,7 @@ module Datadog
357
368
  "OTEL_EXPORTER_OTLP_METRICS_TIMEOUT",
358
369
  "OTEL_EXPORTER_OTLP_PROTOCOL",
359
370
  "OTEL_EXPORTER_OTLP_TIMEOUT",
371
+ "OTEL_LOGS_EXPORTER",
360
372
  "OTEL_LOG_LEVEL",
361
373
  "OTEL_METRICS_EXPORTER",
362
374
  "OTEL_METRIC_EXPORT_INTERVAL",
@@ -18,6 +18,7 @@ module Datadog
18
18
  ENV_API_KEY = 'DD_API_KEY'
19
19
  ENV_ENVIRONMENT = 'DD_ENV'
20
20
  ENV_EXTERNAL_ENV = 'DD_EXTERNAL_ENV'
21
+ ENV_HOSTNAME = 'DD_HOSTNAME'
21
22
  ENV_SERVICE = 'DD_SERVICE'
22
23
  ENV_SITE = 'DD_SITE'
23
24
  ENV_TAGS = 'DD_TAGS'
@@ -44,6 +45,10 @@ module Datadog
44
45
  TAG_RAILS_APPLICATION = "rails.application"
45
46
  TAG_PROCESS_TAGS = "_dd.tags.process"
46
47
  TAG_SERVICE = 'service'
48
+ # Service name was automatically populated by this library
49
+ TAG_SVC_AUTO = 'svc.auto'
50
+ # Service name was explicitly configured by the library user
51
+ TAG_SVC_USER = 'svc.user'
47
52
  TAG_VERSION = 'version'
48
53
 
49
54
  GEM_DATADOG_VERSION = Datadog::VERSION::STRING
@@ -76,7 +76,21 @@ module Datadog
76
76
  Core::Environment::Ext::GEM_DATADOG_VERSION
77
77
  end
78
78
 
79
- # Returns tracer version, comforming to https://semver.org/spec/v2.0.0.html
79
+ # Returns the tracer version in SemVer-2 form (https://semver.org/spec/v2.0.0.html).
80
+ #
81
+ # Converts the RubyGems-style version returned by {.gem_datadog_version}
82
+ # (dot-separated prerelease/build segments, e.g. "2.34.0.dev") into the
83
+ # SemVer-2 form expected by cross-language Datadog consumers (hyphen-separated
84
+ # prerelease, "+" build metadata, e.g. "2.34.0-dev").
85
+ #
86
+ # Called by reporters that emit a tracer version on the wire and must match
87
+ # the format used by other-language tracers:
88
+ # - process discovery memfd (`Core::ProcessDiscovery.get_metadata` → `tracer_version`)
89
+ # - telemetry payloads (`Core::Telemetry::Request#application`)
90
+ # - remote configuration client identification (`Core::Remote::Client#tracer_version`)
91
+ #
92
+ # Use {.gem_datadog_version} (not this method) when a RubyGems-style string is
93
+ # required (e.g. gem-internal contexts, gemspec interop).
80
94
  def gem_datadog_version_semver2
81
95
  major, minor, patch, rest = gem_datadog_version.split('.', 4)
82
96