datadog 2.30.0 → 2.32.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 +44 -1
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +17 -7
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +11 -4
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +6 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +18 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +10 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +7 -4
- data/ext/datadog_profiling_native_extension/http_transport.c +10 -5
- data/ext/libdatadog_api/crashtracker.c +5 -8
- data/ext/libdatadog_api/datadog_ruby_common.c +18 -0
- data/ext/libdatadog_api/datadog_ruby_common.h +10 -0
- data/ext/libdatadog_api/di.c +127 -0
- data/ext/libdatadog_api/extconf.rb +9 -4
- data/ext/libdatadog_api/init.c +5 -2
- data/ext/libdatadog_extconf_helpers.rb +46 -1
- data/lib/datadog/ai_guard/component.rb +2 -0
- data/lib/datadog/ai_guard/configuration.rb +105 -2
- data/lib/datadog/ai_guard/contrib/ruby_llm/chat_instrumentation.rb +41 -3
- data/lib/datadog/ai_guard/evaluation/content_builder.rb +31 -0
- data/lib/datadog/ai_guard/evaluation/content_part.rb +36 -0
- data/lib/datadog/ai_guard/evaluation/no_op_result.rb +3 -1
- data/lib/datadog/ai_guard/evaluation/request.rb +14 -9
- data/lib/datadog/ai_guard/evaluation/result.rb +3 -1
- data/lib/datadog/ai_guard/evaluation.rb +37 -7
- data/lib/datadog/ai_guard/ext.rb +1 -0
- data/lib/datadog/ai_guard.rb +26 -8
- data/lib/datadog/appsec/autoload.rb +1 -1
- data/lib/datadog/appsec/component.rb +11 -7
- data/lib/datadog/appsec/configuration.rb +414 -1
- data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +2 -1
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +6 -7
- data/lib/datadog/appsec/instrumentation/gateway.rb +0 -13
- data/lib/datadog/appsec/metrics/telemetry.rb +13 -1
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +2 -0
- data/lib/datadog/appsec/security_engine/runner.rb +1 -1
- data/lib/datadog/appsec/trace_keeper.rb +18 -6
- data/lib/datadog/appsec/utils/http/media_type.rb +1 -2
- data/lib/datadog/appsec/utils/http/url_encoded.rb +3 -3
- data/lib/datadog/appsec.rb +5 -9
- data/lib/datadog/core/configuration/base.rb +17 -5
- data/lib/datadog/core/configuration/components.rb +22 -9
- data/lib/datadog/core/configuration/config_helper.rb +9 -0
- data/lib/datadog/core/configuration/option.rb +30 -5
- data/lib/datadog/core/configuration/option_definition.rb +38 -12
- data/lib/datadog/core/configuration/options.rb +40 -6
- data/lib/datadog/core/configuration/settings.rb +18 -0
- data/lib/datadog/core/configuration/supported_configurations.rb +3 -0
- data/lib/datadog/core/configuration.rb +1 -1
- data/lib/datadog/core/contrib/rails/railtie.rb +32 -0
- data/lib/datadog/core/contrib/rails/utils.rb +7 -3
- data/lib/datadog/core/crashtracking/component.rb +3 -3
- data/lib/datadog/core/diagnostics/environment_logger.rb +3 -1
- data/lib/datadog/core/environment/container.rb +2 -2
- data/lib/datadog/core/environment/ext.rb +1 -0
- data/lib/datadog/core/environment/identity.rb +25 -3
- data/lib/datadog/core/environment/process.rb +12 -0
- data/lib/datadog/core/feature_flags.rb +1 -1
- data/lib/datadog/core/metrics/client.rb +5 -5
- data/lib/datadog/core/remote/client.rb +1 -1
- data/lib/datadog/core/remote/component.rb +38 -21
- data/lib/datadog/core/runtime/metrics.rb +1 -1
- data/lib/datadog/core/telemetry/component.rb +3 -0
- data/lib/datadog/core/telemetry/emitter.rb +1 -1
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +2 -3
- data/lib/datadog/core/telemetry/event/app_extended_heartbeat.rb +32 -0
- data/lib/datadog/core/telemetry/event/app_started.rb +151 -169
- data/lib/datadog/core/telemetry/event.rb +1 -7
- data/lib/datadog/core/telemetry/ext.rb +1 -0
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +5 -0
- data/lib/datadog/core/telemetry/worker.rb +20 -0
- data/lib/datadog/core/transport/http.rb +2 -0
- data/lib/datadog/core/utils/only_once.rb +1 -1
- data/lib/datadog/core/utils/spawn_monkey_patch.rb +36 -0
- data/lib/datadog/core/utils.rb +1 -1
- data/lib/datadog/core/workers/async.rb +1 -1
- data/lib/datadog/core.rb +1 -2
- data/lib/datadog/data_streams/configuration.rb +40 -1
- data/lib/datadog/data_streams/pathway_context.rb +1 -1
- data/lib/datadog/data_streams/processor.rb +1 -1
- data/lib/datadog/data_streams.rb +1 -1
- data/lib/datadog/di/base.rb +8 -5
- data/lib/datadog/di/boot.rb +2 -4
- data/lib/datadog/di/code_tracker.rb +179 -1
- data/lib/datadog/di/component.rb +5 -1
- data/lib/datadog/di/configuration.rb +235 -2
- data/lib/datadog/di/instrumenter.rb +55 -29
- data/lib/datadog/di/probe_builder.rb +1 -1
- data/lib/datadog/di/probe_file_loader.rb +2 -2
- data/lib/datadog/di/probe_manager.rb +6 -6
- data/lib/datadog/di/probe_notification_builder.rb +110 -2
- data/lib/datadog/di/probe_notifier_worker.rb +2 -2
- data/lib/datadog/di/remote.rb +6 -6
- data/lib/datadog/di/transport/input.rb +3 -3
- data/lib/datadog/di.rb +81 -0
- data/lib/datadog/error_tracking/configuration.rb +55 -2
- data/lib/datadog/kit/enable_core_dumps.rb +1 -1
- data/lib/datadog/open_feature/component.rb +18 -1
- data/lib/datadog/open_feature/evaluation_engine.rb +2 -2
- data/lib/datadog/open_feature/hooks/flag_eval_hook.rb +49 -0
- data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +149 -0
- data/lib/datadog/open_feature/provider.rb +19 -1
- data/lib/datadog/open_feature/remote.rb +1 -1
- data/lib/datadog/open_feature/transport.rb +1 -1
- data/lib/datadog/opentelemetry/configuration/settings.rb +2 -0
- data/lib/datadog/opentelemetry/metrics.rb +3 -3
- data/lib/datadog/opentelemetry/sdk/configurator.rb +1 -1
- data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +1 -1
- data/lib/datadog/profiling/collectors/code_provenance.rb +36 -11
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +31 -2
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +8 -2
- data/lib/datadog/profiling/collectors/info.rb +16 -3
- data/lib/datadog/profiling/component.rb +12 -4
- data/lib/datadog/profiling/exporter.rb +37 -12
- data/lib/datadog/profiling/ext.rb +0 -2
- data/lib/datadog/profiling/flush.rb +21 -12
- data/lib/datadog/profiling/http_transport.rb +12 -1
- data/lib/datadog/profiling/load_native_extension.rb +2 -2
- data/lib/datadog/profiling/profiler.rb +13 -5
- data/lib/datadog/profiling/scheduler.rb +2 -2
- data/lib/datadog/profiling/tasks/exec.rb +8 -3
- data/lib/datadog/profiling/tasks/help.rb +1 -0
- data/lib/datadog/profiling/tasks/setup.rb +2 -2
- data/lib/datadog/profiling.rb +1 -2
- data/lib/datadog/single_step_instrument.rb +1 -1
- data/lib/datadog/symbol_database/configuration.rb +65 -0
- data/lib/datadog/symbol_database/extractor.rb +915 -0
- data/lib/datadog/symbol_database/file_hash.rb +46 -0
- data/lib/datadog/symbol_database/logger.rb +43 -0
- data/lib/datadog/symbol_database/scope.rb +98 -0
- data/lib/datadog/symbol_database/service_version.rb +57 -0
- data/lib/datadog/symbol_database/symbol.rb +66 -0
- data/lib/datadog/symbol_database/transport/http/endpoint.rb +28 -0
- data/lib/datadog/symbol_database/transport/http.rb +45 -0
- data/lib/datadog/symbol_database/transport.rb +54 -0
- data/lib/datadog/symbol_database/uploader.rb +166 -0
- data/lib/datadog/symbol_database.rb +49 -0
- data/lib/datadog/tracing/buffer.rb +3 -3
- data/lib/datadog/tracing/component.rb +11 -0
- data/lib/datadog/tracing/configuration/settings.rb +2 -1
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +5 -3
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +20 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +3 -1
- data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/discard.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/perform.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +1 -1
- data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +1 -1
- data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +2 -2
- data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/utils.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/component.rb +1 -1
- data/lib/datadog/tracing/contrib/configurable.rb +18 -3
- data/lib/datadog/tracing/contrib/configuration/resolver.rb +7 -4
- data/lib/datadog/tracing/contrib/dalli/quantize.rb +1 -1
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/excon/middleware.rb +2 -2
- data/lib/datadog/tracing/contrib/extensions.rb +9 -0
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +2 -2
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +5 -5
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +2 -2
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +2 -2
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +3 -3
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -2
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +2 -2
- data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +2 -2
- data/lib/datadog/tracing/contrib/karafka/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +3 -3
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/presto/instrumentation.rb +3 -3
- data/lib/datadog/tracing/contrib/rack/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/log_injection.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/rails/runner.rb +1 -1
- data/lib/datadog/tracing/contrib/rake/instrumentation.rb +2 -2
- data/lib/datadog/tracing/contrib/redis/quantize.rb +1 -1
- data/lib/datadog/tracing/contrib/redis/tags.rb +1 -1
- data/lib/datadog/tracing/contrib/sidekiq/utils.rb +1 -1
- data/lib/datadog/tracing/contrib/status_range_matcher.rb +4 -0
- data/lib/datadog/tracing/contrib/stripe/request.rb +1 -1
- data/lib/datadog/tracing/contrib.rb +8 -0
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +3 -1
- data/lib/datadog/tracing/distributed/baggage.rb +59 -5
- data/lib/datadog/tracing/distributed/datadog.rb +13 -11
- data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +1 -1
- data/lib/datadog/tracing/distributed/propagation.rb +2 -2
- data/lib/datadog/tracing/distributed/trace_context.rb +74 -32
- data/lib/datadog/tracing/event.rb +1 -1
- data/lib/datadog/tracing/metadata/tagging.rb +2 -2
- data/lib/datadog/tracing/pipeline.rb +1 -1
- data/lib/datadog/tracing/remote.rb +1 -1
- data/lib/datadog/tracing/sampling/ext.rb +2 -0
- data/lib/datadog/tracing/sampling/priority_sampler.rb +13 -0
- data/lib/datadog/tracing/sampling/rule.rb +1 -1
- data/lib/datadog/tracing/sampling/rule_sampler.rb +54 -25
- data/lib/datadog/tracing/sampling/span/rule_parser.rb +2 -2
- data/lib/datadog/tracing/span_operation.rb +4 -4
- data/lib/datadog/tracing/trace_operation.rb +53 -9
- data/lib/datadog/tracing/tracer.rb +29 -4
- data/lib/datadog/tracing/transport/io/client.rb +1 -1
- data/lib/datadog/tracing/transport/trace_formatter.rb +1 -1
- data/lib/datadog/tracing/workers.rb +2 -1
- data/lib/datadog/version.rb +1 -1
- metadata +27 -12
- data/lib/datadog/ai_guard/configuration/settings.rb +0 -113
- data/lib/datadog/appsec/configuration/settings.rb +0 -423
- data/lib/datadog/data_streams/configuration/settings.rb +0 -49
- data/lib/datadog/di/configuration/settings.rb +0 -243
- data/lib/datadog/error_tracking/configuration/settings.rb +0 -63
data/lib/datadog/di/remote.rb
CHANGED
|
@@ -88,11 +88,11 @@ module Datadog
|
|
|
88
88
|
# content as errored but with a somewhat different exception
|
|
89
89
|
# message.
|
|
90
90
|
# TODO assert content state (errored for this example)
|
|
91
|
-
content.errored("Error applying dynamic instrumentation configuration: #{exc.class
|
|
91
|
+
content.errored("Error applying dynamic instrumentation configuration: #{exc.class}: #{exc.message}")
|
|
92
92
|
rescue => exc
|
|
93
93
|
raise if component.settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
|
94
94
|
|
|
95
|
-
component.logger.debug { "di: unhandled exception adding #{probe.type} probe at #{probe.location} (#{probe.id}) in DI remote receiver: #{exc.class}: #{exc}" }
|
|
95
|
+
component.logger.debug { "di: unhandled exception adding #{probe.type} probe at #{probe.location} (#{probe.id}) in DI remote receiver: #{exc.class}: #{exc.message}" }
|
|
96
96
|
component.telemetry&.report(exc, description: "Unhandled exception adding probe in DI remote receiver")
|
|
97
97
|
|
|
98
98
|
# TODO test this path
|
|
@@ -106,7 +106,7 @@ module Datadog
|
|
|
106
106
|
# content as errored but with a somewhat different exception
|
|
107
107
|
# message.
|
|
108
108
|
# TODO assert content state (errored for this example)
|
|
109
|
-
content.errored("Error applying dynamic instrumentation configuration: #{exc.class
|
|
109
|
+
content.errored("Error applying dynamic instrumentation configuration: #{exc.class}: #{exc.message}")
|
|
110
110
|
end
|
|
111
111
|
|
|
112
112
|
# Important: even if processing fails for this probe config,
|
|
@@ -117,11 +117,11 @@ module Datadog
|
|
|
117
117
|
rescue => exc
|
|
118
118
|
raise if component.settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
|
119
119
|
|
|
120
|
-
component.logger.debug { "di: unhandled exception handling a probe in DI remote receiver: #{exc.class}: #{exc}" }
|
|
120
|
+
component.logger.debug { "di: unhandled exception handling a probe in DI remote receiver: #{exc.class}: #{exc.message}" }
|
|
121
121
|
component.telemetry&.report(exc, description: "Unhandled exception handling probe in DI remote receiver")
|
|
122
122
|
|
|
123
123
|
# TODO assert content state (errored for this example)
|
|
124
|
-
content.errored("Error applying dynamic instrumentation configuration: #{exc.class
|
|
124
|
+
content.errored("Error applying dynamic instrumentation configuration: #{exc.class}: #{exc.message}")
|
|
125
125
|
end
|
|
126
126
|
|
|
127
127
|
# This method does not mark +previous_content+ as succeeded or errored,
|
|
@@ -136,7 +136,7 @@ module Datadog
|
|
|
136
136
|
rescue => exc
|
|
137
137
|
raise if component.settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
|
138
138
|
|
|
139
|
-
component.logger.debug { "di: unhandled exception removing probes in DI remote receiver: #{exc.class}: #{exc}" }
|
|
139
|
+
component.logger.debug { "di: unhandled exception removing probes in DI remote receiver: #{exc.class}: #{exc.message}" }
|
|
140
140
|
component.telemetry&.report(exc, description: "Unhandled exception removing probes in DI remote receiver")
|
|
141
141
|
end
|
|
142
142
|
|
|
@@ -81,14 +81,14 @@ module Datadog
|
|
|
81
81
|
# Serialization failed for this snapshot - report via callback
|
|
82
82
|
# This catches JSON::GeneratorError, Encoding errors, TypeError, etc.
|
|
83
83
|
probe_id = snapshot.dig(:debugger, :snapshot, :probe, :id)
|
|
84
|
-
logger.debug { "di: JSON encoding failed for snapshot (probe #{probe_id}): #{exc.class}: #{exc}" }
|
|
84
|
+
logger.debug { "di: JSON encoding failed for snapshot (probe #{probe_id}): #{exc.class}: #{exc.message}" }
|
|
85
85
|
telemetry&.report(exc, description: "JSON encoding failed for snapshot")
|
|
86
86
|
|
|
87
87
|
if probe_id
|
|
88
88
|
begin
|
|
89
89
|
on_serialization_error.call(probe_id, exc)
|
|
90
90
|
rescue => callback_exc
|
|
91
|
-
logger.debug { "di: error in serialization error callback for probe #{probe_id}: #{callback_exc.class}: #{callback_exc}" }
|
|
91
|
+
logger.debug { "di: error in serialization error callback for probe #{probe_id}: #{callback_exc.class}: #{callback_exc.message}" }
|
|
92
92
|
telemetry&.report(callback_exc, description: "Error in serialization error callback")
|
|
93
93
|
end
|
|
94
94
|
end
|
|
@@ -110,7 +110,7 @@ module Datadog
|
|
|
110
110
|
begin
|
|
111
111
|
send_input_chunk(chunked_payload, serialized_tags)
|
|
112
112
|
rescue => exc
|
|
113
|
-
logger.debug { "di: failed to send snapshot chunk: #{exc.class}: #{exc} (at #{exc.backtrace.first})" }
|
|
113
|
+
logger.debug { "di: failed to send snapshot chunk: #{exc.class}: #{exc.message} (at #{exc.backtrace.first})" }
|
|
114
114
|
telemetry&.report(exc, description: "Error sending snapshot chunk")
|
|
115
115
|
end
|
|
116
116
|
end
|
data/lib/datadog/di.rb
CHANGED
|
@@ -11,11 +11,92 @@ module Datadog
|
|
|
11
11
|
module DI
|
|
12
12
|
INSTRUMENTED_COUNTERS_LOCK = Mutex.new
|
|
13
13
|
|
|
14
|
+
# Captured at load time from Exception itself (not a subclass).
|
|
15
|
+
# Used to bypass subclass overrides of backtrace_locations.
|
|
16
|
+
#
|
|
17
|
+
# This does NOT protect against monkeypatching Exception#backtrace_locations
|
|
18
|
+
# before dd-trace-rb loads — in that case we'd capture the monkeypatch.
|
|
19
|
+
# The practical threat model is customer subclasses overriding the method:
|
|
20
|
+
#
|
|
21
|
+
# class MyError < StandardError
|
|
22
|
+
# def backtrace_locations; []; end
|
|
23
|
+
# end
|
|
24
|
+
#
|
|
25
|
+
# The UnboundMethod bypasses subclass overrides: bind(exception).call
|
|
26
|
+
# always dispatches to the original Exception implementation.
|
|
27
|
+
#
|
|
28
|
+
# Note: if the subclass overrides #backtrace (not #backtrace_locations),
|
|
29
|
+
# MRI's setup_exception skips storing the VM backtrace entirely — both
|
|
30
|
+
# @bt and @bt_locations stay nil. In that case this UnboundMethod also
|
|
31
|
+
# returns nil. See EXCEPTION_BACKTRACE comment for details.
|
|
32
|
+
EXCEPTION_BACKTRACE_LOCATIONS = Exception.instance_method(:backtrace_locations)
|
|
33
|
+
|
|
34
|
+
# Same UnboundMethod trick for Exception#backtrace (Array<String>).
|
|
35
|
+
# Used as a fallback when backtrace_locations returns nil — which happens
|
|
36
|
+
# when someone calls Exception#set_backtrace with an Array<String>.
|
|
37
|
+
#
|
|
38
|
+
# set_backtrace accepts Array<String> or nil. When called with strings,
|
|
39
|
+
# it replaces the VM-level backtrace: backtrace returns the new strings,
|
|
40
|
+
# but backtrace_locations returns nil because the VM cannot reconstruct
|
|
41
|
+
# Location objects from formatted strings. This occurs in exception
|
|
42
|
+
# wrapping patterns where a library catches an exception, creates a new
|
|
43
|
+
# one, and copies the original's string backtrace onto it via
|
|
44
|
+
# set_backtrace before re-raising.
|
|
45
|
+
#
|
|
46
|
+
# Ruby 3.4+ also allows set_backtrace(Array<Location>), which preserves
|
|
47
|
+
# backtrace_locations — but older Rubies and most existing code use
|
|
48
|
+
# the string form.
|
|
49
|
+
#
|
|
50
|
+
# Like EXCEPTION_BACKTRACE_LOCATIONS, this UnboundMethod bypasses
|
|
51
|
+
# subclass overrides of #backtrace: bind(exception).call dispatches
|
|
52
|
+
# to Exception#backtrace regardless of what the subclass defines.
|
|
53
|
+
#
|
|
54
|
+
# However, when a subclass overrides #backtrace, MRI's setup_exception
|
|
55
|
+
# (eval.c) calls the override via rb_get_backtrace during raise. If it
|
|
56
|
+
# gets a non-nil result, it skips storing the VM backtrace in @bt and
|
|
57
|
+
# @bt_locations entirely. So the UnboundMethod bypasses the override
|
|
58
|
+
# at dispatch but reads nil from @bt because the data was never stored.
|
|
59
|
+
#
|
|
60
|
+
# This constant is used as a fallback when backtrace_locations returns
|
|
61
|
+
# nil. In the common set_backtrace-with-strings case, no subclass
|
|
62
|
+
# override is involved and the fallback works. The only unrecoverable
|
|
63
|
+
# case: a subclass overrides #backtrace, the exception is raised
|
|
64
|
+
# normally, and set_backtrace is never called. Both @bt and
|
|
65
|
+
# @bt_locations are nil — DI reports an empty stacktrace (type and
|
|
66
|
+
# message are still reported).
|
|
67
|
+
EXCEPTION_BACKTRACE = Exception.instance_method(:backtrace)
|
|
68
|
+
|
|
14
69
|
class << self
|
|
15
70
|
def enabled?
|
|
16
71
|
Datadog.configuration.dynamic_instrumentation.enabled
|
|
17
72
|
end
|
|
18
73
|
|
|
74
|
+
# Returns iseqs that correspond to loaded files (filtering out eval'd code).
|
|
75
|
+
#
|
|
76
|
+
# There are several types of iseqs returned by +all_iseqs+:
|
|
77
|
+
#
|
|
78
|
+
# 1. Eval'd code — these have a nil +absolute_path+ and are filtered out here.
|
|
79
|
+
# 2. Whole-file iseqs — have +absolute_path+ set and +first_lineno+ of 0.
|
|
80
|
+
# Only available for a subset of loaded files (the full-file iseq may be
|
|
81
|
+
# garbage collected after loading completes). Easiest to work with since
|
|
82
|
+
# we just match the file path to the probe specification.
|
|
83
|
+
# 3. Per-method iseqs — have +absolute_path+ set and +first_lineno+ > 0.
|
|
84
|
+
# Often the only iseqs available for third-party code. Require identifying
|
|
85
|
+
# the correct iseq containing the target line, which may involve examining
|
|
86
|
+
# the iseq's +trace_points+ since +define_method+ can create nested,
|
|
87
|
+
# non-contiguous line ranges.
|
|
88
|
+
#
|
|
89
|
+
# Note: the same line of code can appear in multiple iseqs (e.g. when
|
|
90
|
+
# +define_method+ is used inside a method). DI treats this as an error
|
|
91
|
+
# since a probe must resolve to exactly one code location.
|
|
92
|
+
#
|
|
93
|
+
# @return [Array<RubyVM::InstructionSequence>] iseqs with non-nil +absolute_path+
|
|
94
|
+
def file_iseqs
|
|
95
|
+
all_iseqs.select do |iseq|
|
|
96
|
+
iseq.absolute_path
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
19
100
|
# This method is called from DI Remote handler to issue DI operations
|
|
20
101
|
# to the probe manager (add or remove probes).
|
|
21
102
|
#
|
|
@@ -1,11 +1,64 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'ext'
|
|
4
|
+
|
|
3
5
|
module Datadog
|
|
4
6
|
module ErrorTracking
|
|
5
7
|
# Configuration for ErrorTracking
|
|
6
8
|
module Configuration
|
|
9
|
+
# Settings
|
|
10
|
+
module Settings
|
|
11
|
+
def self.extended(base)
|
|
12
|
+
base = base.singleton_class unless base.is_a?(Class)
|
|
13
|
+
add_settings!(base)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.add_settings!(base)
|
|
17
|
+
base.class_eval do
|
|
18
|
+
# Error Tracking specific configurations.
|
|
19
|
+
# @public_api
|
|
20
|
+
settings :error_tracking do
|
|
21
|
+
# Enable automatic reporting of handled errors and defines the scope
|
|
22
|
+
# for which to report errors: user code, gems, or both. Possible
|
|
23
|
+
# values are: all | user | third_party.
|
|
24
|
+
#
|
|
25
|
+
# @default 'DD_ERROR_TRACKING_HANDLED_ERRORS' environment variable, otherwise `nil`
|
|
26
|
+
# @return [String, nil]
|
|
27
|
+
option :handled_errors do |o|
|
|
28
|
+
o.type :string, nilable: true
|
|
29
|
+
o.default Ext::DEFAULT_HANDLED_ERRORS
|
|
30
|
+
o.env Ext::ENV_HANDLED_ERRORS
|
|
31
|
+
o.setter do |value|
|
|
32
|
+
next value if Ext::VALID_HANDLED_ERRORS.include?(value)
|
|
33
|
+
|
|
34
|
+
unless value.nil?
|
|
35
|
+
Datadog.logger.warn(
|
|
36
|
+
"Invalid handled errors scope: #{value}. " \
|
|
37
|
+
"Supported values are: #{Ext::VALID_HANDLED_ERRORS.join(" | ")}. " \
|
|
38
|
+
'Deactivating the feature.'
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
Ext::DEFAULT_HANDLED_ERRORS
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Enable automatic reporting of handled errors and specify what files should be
|
|
47
|
+
# instrumented. The value is a list of comma separated paths, filenames or gem names.
|
|
48
|
+
# The paths can be absolute, starting with '/' or relative to directory in which the program
|
|
49
|
+
# is launched, starting with './'.
|
|
50
|
+
#
|
|
51
|
+
# @default 'DD_ERROR_TRACKING_HANDLED_ERRORS_MODULES' environment variable, otherwise `nil`
|
|
52
|
+
# @return [String, nil]
|
|
53
|
+
option :handled_errors_include do |o|
|
|
54
|
+
o.type :array
|
|
55
|
+
o.default []
|
|
56
|
+
o.env Ext::ENV_HANDLED_ERRORS_INCLUDE
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
7
62
|
end
|
|
8
63
|
end
|
|
9
64
|
end
|
|
10
|
-
|
|
11
|
-
require_relative 'configuration/settings'
|
|
@@ -30,7 +30,7 @@ module Datadog
|
|
|
30
30
|
Process.setrlimit(:CORE, maximum_size)
|
|
31
31
|
rescue => e
|
|
32
32
|
Kernel.warn(
|
|
33
|
-
"[datadog] Failed to enable core dumps. Cause: #{e.class
|
|
33
|
+
"[datadog] Failed to enable core dumps. Cause: #{e.class}: #{e.message} " \
|
|
34
34
|
"Location: #{Array(e.backtrace).first}"
|
|
35
35
|
)
|
|
36
36
|
return
|
|
@@ -6,12 +6,13 @@ require_relative 'exposures/buffer'
|
|
|
6
6
|
require_relative 'exposures/worker'
|
|
7
7
|
require_relative 'exposures/deduplicator'
|
|
8
8
|
require_relative 'exposures/reporter'
|
|
9
|
+
require_relative 'metrics/flag_eval_metrics'
|
|
9
10
|
|
|
10
11
|
module Datadog
|
|
11
12
|
module OpenFeature
|
|
12
13
|
# This class is the entry point for the OpenFeature component
|
|
13
14
|
class Component
|
|
14
|
-
attr_reader :engine
|
|
15
|
+
attr_reader :engine, :flag_eval_hook
|
|
15
16
|
|
|
16
17
|
def self.build(settings, agent_settings, logger:, telemetry:)
|
|
17
18
|
return unless settings.respond_to?(:open_feature) && settings.open_feature.enabled
|
|
@@ -50,11 +51,27 @@ module Datadog
|
|
|
50
51
|
|
|
51
52
|
reporter = Exposures::Reporter.new(@worker, telemetry: telemetry, logger: logger)
|
|
52
53
|
@engine = EvaluationEngine.new(reporter, telemetry: telemetry, logger: logger)
|
|
54
|
+
|
|
55
|
+
@telemetry = telemetry
|
|
56
|
+
@logger = logger
|
|
57
|
+
@flag_eval_hook = create_flag_eval_hook
|
|
53
58
|
end
|
|
54
59
|
|
|
55
60
|
def shutdown!
|
|
56
61
|
@worker.graceful_shutdown
|
|
57
62
|
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
def create_flag_eval_hook
|
|
67
|
+
require_relative 'hooks/flag_eval_hook'
|
|
68
|
+
return unless Hooks::FlagEvalHook.available?
|
|
69
|
+
|
|
70
|
+
metrics = Metrics::FlagEvalMetrics.new(telemetry: @telemetry, logger: @logger)
|
|
71
|
+
Hooks::FlagEvalHook.new(metrics)
|
|
72
|
+
rescue LoadError
|
|
73
|
+
nil
|
|
74
|
+
end
|
|
58
75
|
end
|
|
59
76
|
end
|
|
60
77
|
end
|
|
@@ -42,7 +42,7 @@ module Datadog
|
|
|
42
42
|
@telemetry.report(e, description: 'OpenFeature: Failed to fetch flag value')
|
|
43
43
|
|
|
44
44
|
ResolutionDetails.build_error(
|
|
45
|
-
value: default_value, error_code: Ext::GENERAL, error_message: e.message
|
|
45
|
+
value: default_value, error_code: Ext::GENERAL, error_message: "#{e.class}: #{e.message}"
|
|
46
46
|
)
|
|
47
47
|
end
|
|
48
48
|
|
|
@@ -63,7 +63,7 @@ module Datadog
|
|
|
63
63
|
@logger.error("#{message}, #{e.class}: #{e.message}")
|
|
64
64
|
@telemetry.report(e, description: "#{message} (#{e.class})")
|
|
65
65
|
|
|
66
|
-
raise ReconfigurationError, e.message
|
|
66
|
+
raise ReconfigurationError, "#{e.class}: #{e.message}"
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
69
|
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datadog
|
|
4
|
+
module OpenFeature
|
|
5
|
+
module Hooks
|
|
6
|
+
# Records flag evaluation metrics via OpenTelemetry hook
|
|
7
|
+
#
|
|
8
|
+
# Compatible with OpenFeature SDK >= 0.5.0 which provides the Hooks::Hook module,
|
|
9
|
+
# but also works with older versions since the SDK uses respond_to?(:finally)
|
|
10
|
+
# to detect hook capabilities.
|
|
11
|
+
class FlagEvalHook
|
|
12
|
+
# Include the Hook module if available (SDK >= 0.5.0) for interface documentation
|
|
13
|
+
# and default implementations of other hook methods (before, after, error)
|
|
14
|
+
include ::OpenFeature::SDK::Hooks::Hook if defined?(::OpenFeature::SDK::Hooks::Hook)
|
|
15
|
+
|
|
16
|
+
# Returns true if the OpenFeature SDK supports hooks (>= 0.5.0)
|
|
17
|
+
def self.available?
|
|
18
|
+
!!defined?(::OpenFeature::SDK::Hooks::Hook)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def initialize(metrics)
|
|
22
|
+
@metrics = metrics
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def finally(hook_context:, evaluation_details:, **_opts)
|
|
26
|
+
metrics = @metrics
|
|
27
|
+
return unless metrics
|
|
28
|
+
|
|
29
|
+
metrics.record(
|
|
30
|
+
hook_context.flag_key,
|
|
31
|
+
variant: evaluation_details.variant,
|
|
32
|
+
reason: evaluation_details.reason,
|
|
33
|
+
error_code: evaluation_details.error_code,
|
|
34
|
+
allocation_key: extract_allocation_key(evaluation_details),
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def extract_allocation_key(evaluation_details)
|
|
41
|
+
metadata = evaluation_details.flag_metadata
|
|
42
|
+
return unless metadata.is_a?(Hash)
|
|
43
|
+
|
|
44
|
+
metadata['__dd_allocation_key']
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datadog
|
|
4
|
+
module OpenFeature
|
|
5
|
+
module Metrics
|
|
6
|
+
# Records flag evaluation metrics via OpenTelemetry
|
|
7
|
+
class FlagEvalMetrics
|
|
8
|
+
METER_NAME = 'ddtrace.openfeature'
|
|
9
|
+
METRIC_NAME = 'feature_flag.evaluations'
|
|
10
|
+
METRIC_UNIT = '{evaluation}'
|
|
11
|
+
METRIC_DESCRIPTION = 'Number of feature flag evaluations'
|
|
12
|
+
|
|
13
|
+
ATTR_FLAG_KEY = 'feature_flag.key'
|
|
14
|
+
ATTR_VARIANT = 'feature_flag.result.variant'
|
|
15
|
+
ATTR_REASON = 'feature_flag.result.reason'
|
|
16
|
+
ATTR_ALLOCATION_KEY = 'feature_flag.result.allocation_key'
|
|
17
|
+
ATTR_ERROR_TYPE = 'error.type'
|
|
18
|
+
|
|
19
|
+
DEFAULT_ERROR_TYPE = 'general'
|
|
20
|
+
|
|
21
|
+
ERROR_TYPE_MAP = {
|
|
22
|
+
'FLAG_NOT_FOUND' => 'flag_not_found',
|
|
23
|
+
'TYPE_MISMATCH' => 'type_mismatch',
|
|
24
|
+
'PARSE_ERROR' => 'parse_error',
|
|
25
|
+
'PROVIDER_NOT_READY' => 'provider_not_ready',
|
|
26
|
+
'TARGETING_KEY_MISSING' => 'targeting_key_missing',
|
|
27
|
+
'INVALID_CONTEXT' => 'invalid_context',
|
|
28
|
+
'PROVIDER_FATAL' => 'provider_fatal',
|
|
29
|
+
'GENERAL' => DEFAULT_ERROR_TYPE,
|
|
30
|
+
}.freeze
|
|
31
|
+
|
|
32
|
+
# Reasons that should not include allocation_key in metrics
|
|
33
|
+
EXCLUDE_ALLOCATION_KEY_REASONS = %w[error default disabled].freeze
|
|
34
|
+
|
|
35
|
+
def initialize(telemetry:, logger:)
|
|
36
|
+
@telemetry = telemetry
|
|
37
|
+
@logger = logger
|
|
38
|
+
@enabled = Datadog.configuration.opentelemetry.metrics.enabled
|
|
39
|
+
@counter = nil
|
|
40
|
+
@mutex = Mutex.new
|
|
41
|
+
|
|
42
|
+
unless @enabled
|
|
43
|
+
@logger.debug { 'OpenFeature: OTel metrics not enabled (DD_METRICS_OTEL_ENABLED=false), flag evaluation metrics disabled' }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def record(flag_key, variant:, reason:, error_code: nil, allocation_key: nil)
|
|
48
|
+
return unless @enabled
|
|
49
|
+
|
|
50
|
+
counter = get_or_create_counter
|
|
51
|
+
return unless counter
|
|
52
|
+
|
|
53
|
+
attributes = build_attributes(
|
|
54
|
+
flag_key,
|
|
55
|
+
variant: variant,
|
|
56
|
+
reason: reason,
|
|
57
|
+
error_code: error_code,
|
|
58
|
+
allocation_key: allocation_key,
|
|
59
|
+
)
|
|
60
|
+
counter.add(1, attributes: attributes)
|
|
61
|
+
rescue => e
|
|
62
|
+
@logger.debug { "OpenFeature: Failed to record evaluation metric: #{e.class}: #{e.message}" }
|
|
63
|
+
@telemetry.report(e, description: 'OpenFeature: Failed to record evaluation metric')
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
# Counter is created lazily because OTel SDK may not be initialized
|
|
69
|
+
# when the OpenFeature component is created.
|
|
70
|
+
def get_or_create_counter
|
|
71
|
+
@mutex.synchronize do
|
|
72
|
+
return @counter if @counter
|
|
73
|
+
|
|
74
|
+
meter_provider = get_or_initialize_meter_provider
|
|
75
|
+
return unless meter_provider
|
|
76
|
+
|
|
77
|
+
meter = meter_provider.meter(METER_NAME)
|
|
78
|
+
@counter = meter.create_counter(
|
|
79
|
+
METRIC_NAME,
|
|
80
|
+
unit: METRIC_UNIT,
|
|
81
|
+
description: METRIC_DESCRIPTION
|
|
82
|
+
)
|
|
83
|
+
end
|
|
84
|
+
rescue => e
|
|
85
|
+
@logger.debug { "OpenFeature: Failed to create metrics counter: #{e.class}: #{e.message}" }
|
|
86
|
+
nil
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Fetch an available OTel meter provider, initializing if needed.
|
|
90
|
+
# Returns the meter provider if available, nil otherwise.
|
|
91
|
+
def get_or_initialize_meter_provider
|
|
92
|
+
meter_provider = defined?(::OpenTelemetry) ? ::OpenTelemetry.meter_provider : nil
|
|
93
|
+
return meter_provider if sdk_meter_provider?(meter_provider)
|
|
94
|
+
|
|
95
|
+
@logger.debug { 'OpenFeature: Initializing OTel meter provider directly' }
|
|
96
|
+
require 'opentelemetry-metrics-sdk'
|
|
97
|
+
require 'datadog/opentelemetry/metrics'
|
|
98
|
+
Datadog::OpenTelemetry::Metrics.initialize!(Datadog.send(:components))
|
|
99
|
+
|
|
100
|
+
meter_provider = ::OpenTelemetry.meter_provider
|
|
101
|
+
sdk_meter_provider?(meter_provider) ? meter_provider : nil
|
|
102
|
+
rescue LoadError => e
|
|
103
|
+
@logger.debug { "OpenFeature: Failed to initialize OTel metrics: #{e.class}: #{e.message}" }
|
|
104
|
+
nil
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def sdk_meter_provider?(meter_provider)
|
|
108
|
+
return false if meter_provider.nil?
|
|
109
|
+
return false unless defined?(::OpenTelemetry::SDK::Metrics::MeterProvider)
|
|
110
|
+
|
|
111
|
+
meter_provider.is_a?(::OpenTelemetry::SDK::Metrics::MeterProvider)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def build_attributes(flag_key, variant:, reason:, error_code:, allocation_key:)
|
|
115
|
+
reason_downcase = normalize_reason(reason)
|
|
116
|
+
|
|
117
|
+
attrs = {
|
|
118
|
+
ATTR_FLAG_KEY => flag_key,
|
|
119
|
+
ATTR_VARIANT => variant.to_s,
|
|
120
|
+
ATTR_REASON => reason_downcase,
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if allocation_key && !allocation_key.empty? && !exclude_allocation_key?(reason_downcase)
|
|
124
|
+
attrs[ATTR_ALLOCATION_KEY] = allocation_key
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
if error_code
|
|
128
|
+
attrs[ATTR_ERROR_TYPE] = normalize_error_type(error_code)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
attrs
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def normalize_reason(reason)
|
|
135
|
+
reason = reason.to_s
|
|
136
|
+
reason.empty? ? 'unknown' : reason.downcase
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def normalize_error_type(error_code)
|
|
140
|
+
ERROR_TYPE_MAP.fetch(error_code.to_s, DEFAULT_ERROR_TYPE)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def exclude_allocation_key?(reason_downcase)
|
|
144
|
+
EXCLUDE_ALLOCATION_KEY_REASONS.include?(reason_downcase)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
@@ -7,6 +7,8 @@ module Datadog
|
|
|
7
7
|
module OpenFeature
|
|
8
8
|
# OpenFeature feature flagging provider backed by Datadog Remote Configuration.
|
|
9
9
|
#
|
|
10
|
+
# Requires openfeature-sdk >= 0.5.1 for flag evaluation metrics support.
|
|
11
|
+
#
|
|
10
12
|
# Implementation follows the OpenFeature contract of Provider SDK.
|
|
11
13
|
# For details see:
|
|
12
14
|
# - https://github.com/open-feature/ruby-sdk/blob/v0.4.1/README.md#develop-a-provider
|
|
@@ -67,6 +69,11 @@ module Datadog
|
|
|
67
69
|
# no-op
|
|
68
70
|
end
|
|
69
71
|
|
|
72
|
+
def hooks
|
|
73
|
+
hook = Datadog.send(:components).open_feature&.flag_eval_hook
|
|
74
|
+
[hook].compact
|
|
75
|
+
end
|
|
76
|
+
|
|
70
77
|
def fetch_boolean_value(flag_key:, default_value:, evaluation_context: nil)
|
|
71
78
|
evaluate(flag_key, default_value: default_value, expected_type: :boolean, evaluation_context: evaluation_context)
|
|
72
79
|
end
|
|
@@ -117,7 +124,7 @@ module Datadog
|
|
|
117
124
|
value: result.value,
|
|
118
125
|
variant: result.variant,
|
|
119
126
|
reason: result.reason,
|
|
120
|
-
flag_metadata: result
|
|
127
|
+
flag_metadata: build_flag_metadata(result),
|
|
121
128
|
)
|
|
122
129
|
rescue => e
|
|
123
130
|
::OpenFeature::SDK::Provider::ResolutionDetails.new(
|
|
@@ -128,6 +135,17 @@ module Datadog
|
|
|
128
135
|
)
|
|
129
136
|
end
|
|
130
137
|
|
|
138
|
+
def build_flag_metadata(result)
|
|
139
|
+
metadata = result.flag_metadata || {}
|
|
140
|
+
allocation_key = result.allocation_key
|
|
141
|
+
if allocation_key && !allocation_key.empty?
|
|
142
|
+
metadata = metadata.dup
|
|
143
|
+
metadata['__dd_allocation_key'] = allocation_key
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
metadata
|
|
147
|
+
end
|
|
148
|
+
|
|
131
149
|
def component_not_configured_default(value)
|
|
132
150
|
::OpenFeature::SDK::Provider::ResolutionDetails.new(
|
|
133
151
|
value: value,
|
|
@@ -41,7 +41,7 @@ module Datadog
|
|
|
41
41
|
engine.reconfigure!(read_content(content))
|
|
42
42
|
content.applied
|
|
43
43
|
rescue EvaluationEngine::ReconfigurationError => e
|
|
44
|
-
content.errored("Error applying OpenFeature configuration: #{e.message}")
|
|
44
|
+
content.errored("Error applying OpenFeature configuration: #{e.class}: #{e.message}")
|
|
45
45
|
end
|
|
46
46
|
when :delete
|
|
47
47
|
# NOTE: For now, we treat deletion as clearing the configuration
|
|
@@ -55,7 +55,7 @@ module Datadog
|
|
|
55
55
|
@api.call(env)
|
|
56
56
|
end
|
|
57
57
|
rescue => e
|
|
58
|
-
message = "Internal error during request. Cause: #{e.class
|
|
58
|
+
message = "Internal error during request. Cause: #{e.class}: #{e.message} " \
|
|
59
59
|
"Location: #{Array(e.backtrace).first}"
|
|
60
60
|
@logger.debug(message)
|
|
61
61
|
|
|
@@ -76,6 +76,7 @@ module Datadog
|
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
option :headers do |o|
|
|
79
|
+
o.skip_telemetry true
|
|
79
80
|
o.type :hash
|
|
80
81
|
o.env 'OTEL_EXPORTER_OTLP_HEADERS'
|
|
81
82
|
o.default { {} }
|
|
@@ -131,6 +132,7 @@ module Datadog
|
|
|
131
132
|
end
|
|
132
133
|
|
|
133
134
|
option :headers do |o|
|
|
135
|
+
o.skip_telemetry true
|
|
134
136
|
o.type :hash, nilable: true
|
|
135
137
|
o.env 'OTEL_EXPORTER_OTLP_METRICS_HEADERS'
|
|
136
138
|
o.default nil
|
|
@@ -11,7 +11,7 @@ module Datadog
|
|
|
11
11
|
new(components).configure_metrics_sdk
|
|
12
12
|
true
|
|
13
13
|
rescue => exc
|
|
14
|
-
components.logger.error("Failed to initialize OpenTelemetry metrics: #{exc.class}: #{exc}: #{exc.backtrace.join("\n")}")
|
|
14
|
+
components.logger.error("Failed to initialize OpenTelemetry metrics: #{exc.class}: #{exc.message}: #{exc.backtrace.join("\n")}")
|
|
15
15
|
false
|
|
16
16
|
end
|
|
17
17
|
|
|
@@ -67,7 +67,7 @@ module Datadog
|
|
|
67
67
|
|
|
68
68
|
configure_otlp_exporter(provider)
|
|
69
69
|
rescue => e
|
|
70
|
-
@logger.warn("Failed to configure OTLP metrics exporter: #{e.class}: #{e}")
|
|
70
|
+
@logger.warn("Failed to configure OTLP metrics exporter: #{e.class}: #{e.message}")
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
def default_metrics_endpoint
|
|
@@ -101,7 +101,7 @@ module Datadog
|
|
|
101
101
|
)
|
|
102
102
|
provider.add_metric_reader(reader)
|
|
103
103
|
rescue LoadError => e
|
|
104
|
-
@logger.warn("Could not load OTLP metrics exporter: #{e.class}: #{e}")
|
|
104
|
+
@logger.warn("Could not load OTLP metrics exporter: #{e.class}: #{e.message}")
|
|
105
105
|
end
|
|
106
106
|
|
|
107
107
|
# Returns metrics config value if explicitly set, otherwise falls back to exporter config or computed default value.
|
|
@@ -37,7 +37,7 @@ module Datadog
|
|
|
37
37
|
begin
|
|
38
38
|
require 'opentelemetry-metrics-sdk'
|
|
39
39
|
rescue LoadError => exc
|
|
40
|
-
components.logger.warn("Failed to load OpenTelemetry metrics gems: #{exc.class}: #{exc}")
|
|
40
|
+
components.logger.warn("Failed to load OpenTelemetry metrics gems: #{exc.class}: #{exc.message}")
|
|
41
41
|
return super
|
|
42
42
|
end
|
|
43
43
|
|
|
@@ -19,7 +19,7 @@ module Datadog
|
|
|
19
19
|
telemetry&.inc(TELEMETRY_NAMESPACE, metric_name, 1, tags: TELEMETRY_TAGS)
|
|
20
20
|
result
|
|
21
21
|
rescue => e
|
|
22
|
-
Datadog.logger.error("Failed to export OpenTelemetry Metrics: #{e.class}: #{e}")
|
|
22
|
+
Datadog.logger.error("Failed to export OpenTelemetry Metrics: #{e.class}: #{e.message}")
|
|
23
23
|
telemetry&.inc(TELEMETRY_NAMESPACE, METRIC_EXPORT_FAILURES, 1, tags: TELEMETRY_TAGS)
|
|
24
24
|
raise
|
|
25
25
|
end
|