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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -1
- data/ext/datadog_profiling_native_extension/clock_id.h +9 -1
- data/ext/datadog_profiling_native_extension/clock_id_from_mach.c +73 -0
- data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +1 -1
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +20 -0
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +5 -1
- data/ext/datadog_profiling_native_extension/extconf.rb +3 -0
- data/ext/datadog_profiling_native_extension/macos_sampler_thread.h +55 -0
- data/ext/datadog_profiling_native_extension/stack_recorder.c +3 -9
- data/ext/datadog_profiling_native_extension/time_helpers.h +1 -0
- data/ext/libdatadog_api/crashtracker.c +2 -0
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/ai_guard/autoload.rb +10 -0
- data/lib/datadog/ai_guard/component.rb +1 -1
- data/lib/datadog/ai_guard/contrib/auto_instrument.rb +24 -0
- data/lib/datadog/ai_guard/contrib/rack/integration.rb +42 -0
- data/lib/datadog/ai_guard/contrib/rack/patcher.rb +26 -0
- data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +83 -0
- data/lib/datadog/ai_guard/contrib/rails/integration.rb +41 -0
- data/lib/datadog/ai_guard/contrib/rails/patcher.rb +97 -0
- data/lib/datadog/ai_guard/evaluation.rb +1 -0
- data/lib/datadog/ai_guard/ext.rb +1 -0
- data/lib/datadog/ai_guard.rb +8 -0
- data/lib/datadog/appsec/component.rb +4 -1
- data/lib/datadog/appsec/compressed_json.rb +2 -2
- data/lib/datadog/appsec/contrib/aws_lambda/gateway/watcher.rb +75 -0
- data/lib/datadog/appsec/contrib/aws_lambda/integration.rb +39 -0
- data/lib/datadog/appsec/contrib/aws_lambda/patcher.rb +30 -0
- data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +111 -0
- data/lib/datadog/appsec/contrib/rack/ext.rb +1 -1
- data/lib/datadog/appsec.rb +1 -0
- data/lib/datadog/core/configuration/components.rb +8 -1
- data/lib/datadog/core/configuration/settings.rb +16 -1
- data/lib/datadog/core/configuration/supported_configurations.rb +12 -0
- data/lib/datadog/core/environment/ext.rb +5 -0
- data/lib/datadog/core/environment/identity.rb +15 -1
- data/lib/datadog/core/environment/process.rb +48 -27
- data/lib/datadog/core/environment/socket.rb +13 -0
- data/lib/datadog/core/remote/client/capabilities.rb +11 -2
- data/lib/datadog/core/remote/transport/http/config.rb +5 -5
- data/lib/datadog/core/telemetry/request.rb +0 -2
- data/lib/datadog/core/transport/response.rb +1 -1
- data/lib/datadog/core/utils/{base64.rb → base64_codec.rb} +3 -2
- data/lib/datadog/core/utils/hash.rb +0 -23
- data/lib/datadog/core/utils/spawn_monkey_patch.rb +46 -16
- data/lib/datadog/data_streams/pathway_context.rb +3 -3
- data/lib/datadog/di/code_tracker.rb +43 -22
- data/lib/datadog/di/contrib/active_record.rb +6 -2
- data/lib/datadog/di/instrumenter.rb +24 -4
- data/lib/datadog/di/probe_notification_builder.rb +1 -1
- data/lib/datadog/di/remote.rb +4 -4
- data/lib/datadog/di/serializer.rb +5 -5
- data/lib/datadog/di/utils.rb +42 -14
- data/lib/datadog/opentelemetry/configuration/settings.rb +65 -0
- data/lib/datadog/opentelemetry/ext.rb +9 -0
- data/lib/datadog/opentelemetry/logs.rb +98 -0
- data/lib/datadog/opentelemetry/metrics.rb +10 -37
- data/lib/datadog/opentelemetry/sdk/configurator.rb +40 -0
- data/lib/datadog/opentelemetry/sdk/id_generator.rb +16 -10
- data/lib/datadog/opentelemetry/sdk/logs_exporter.rb +37 -0
- data/lib/datadog/opentelemetry/signal_configuration.rb +53 -0
- data/lib/datadog/opentelemetry.rb +1 -0
- data/lib/datadog/profiling/component.rb +0 -1
- data/lib/datadog/profiling/stack_recorder.rb +0 -4
- data/lib/datadog/symbol_database/component.rb +409 -0
- data/lib/datadog/symbol_database/configuration.rb +2 -2
- data/lib/datadog/symbol_database/extractor.rb +45 -26
- data/lib/datadog/symbol_database/remote.rb +175 -0
- data/lib/datadog/symbol_database/scope.rb +16 -12
- data/lib/datadog/symbol_database/scope_batcher.rb +288 -0
- data/lib/datadog/symbol_database/service_version.rb +15 -6
- data/lib/datadog/symbol_database/symbol.rb +6 -3
- data/lib/datadog/symbol_database/uploader.rb +65 -8
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +8 -0
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +0 -4
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +0 -4
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +0 -4
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +0 -5
- data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +0 -5
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +0 -5
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +0 -5
- data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +0 -8
- data/lib/datadog/tracing/contrib/excon/middleware.rb +0 -5
- data/lib/datadog/tracing/contrib/ext.rb +2 -3
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +0 -5
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +0 -5
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +0 -5
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +0 -5
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +0 -5
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +0 -5
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +0 -5
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +0 -5
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +0 -5
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +0 -5
- data/lib/datadog/tracing/contrib/presto/instrumentation.rb +0 -5
- data/lib/datadog/tracing/contrib/racecar/event.rb +0 -5
- data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +6 -0
- data/lib/datadog/tracing/contrib/rack/ext.rb +27 -0
- data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +117 -1
- data/lib/datadog/tracing/contrib/redis/tags.rb +0 -5
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +0 -5
- data/lib/datadog/tracing/contrib/sequel/utils.rb +0 -5
- data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +0 -5
- data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +0 -13
- data/lib/datadog/tracing/distributed/trace_context.rb +0 -28
- data/lib/datadog/tracing/metadata/ext.rb +3 -0
- data/lib/datadog/tracing/span_operation.rb +13 -0
- data/lib/datadog/tracing/trace_operation.rb +22 -0
- data/lib/datadog/tracing/tracer.rb +7 -3
- data/lib/datadog/version.rb +1 -1
- metadata +27 -8
- 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
|
data/lib/datadog/ai_guard/ext.rb
CHANGED
data/lib/datadog/ai_guard.rb
CHANGED
|
@@ -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
|
-
|
|
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/
|
|
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::
|
|
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
|
data/lib/datadog/appsec.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
|
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
|
|