datadog 2.2.0 → 2.4.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 +87 -2
- data/ext/datadog_profiling_loader/datadog_profiling_loader.c +9 -1
- data/ext/datadog_profiling_loader/extconf.rb +14 -26
- data/ext/datadog_profiling_native_extension/clock_id.h +1 -0
- data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +1 -2
- data/ext/datadog_profiling_native_extension/clock_id_noop.c +1 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +257 -69
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +53 -28
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +34 -4
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +4 -0
- data/ext/datadog_profiling_native_extension/collectors_stack.c +136 -81
- data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +661 -48
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +10 -1
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +83 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +53 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +91 -69
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +50 -0
- data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +75 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.c +54 -12
- data/ext/datadog_profiling_native_extension/heap_recorder.h +3 -1
- data/ext/datadog_profiling_native_extension/helpers.h +6 -17
- data/ext/datadog_profiling_native_extension/http_transport.c +41 -9
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +0 -86
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +2 -23
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +61 -172
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +116 -139
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +20 -11
- data/ext/datadog_profiling_native_extension/profiling.c +1 -3
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +0 -33
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +1 -26
- data/ext/datadog_profiling_native_extension/setup_signal_handler.h +1 -0
- data/ext/datadog_profiling_native_extension/stack_recorder.c +14 -2
- data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -0
- data/ext/datadog_profiling_native_extension/time_helpers.c +0 -15
- data/ext/datadog_profiling_native_extension/time_helpers.h +36 -6
- data/ext/{datadog_profiling_native_extension → libdatadog_api}/crashtracker.c +37 -22
- data/ext/libdatadog_api/datadog_ruby_common.c +83 -0
- data/ext/libdatadog_api/datadog_ruby_common.h +53 -0
- data/ext/libdatadog_api/extconf.rb +108 -0
- data/ext/libdatadog_api/macos_development.md +26 -0
- data/ext/libdatadog_extconf_helpers.rb +130 -0
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +2184 -108
- data/lib/datadog/appsec/assets/waf_rules/strict.json +1430 -2
- data/lib/datadog/appsec/component.rb +29 -8
- data/lib/datadog/appsec/configuration/settings.rb +2 -2
- data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +1 -0
- data/lib/datadog/appsec/contrib/devise/patcher/rememberable_patch.rb +21 -0
- data/lib/datadog/appsec/contrib/devise/patcher.rb +12 -2
- data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +35 -0
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +109 -0
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +71 -0
- data/lib/datadog/appsec/contrib/graphql/integration.rb +54 -0
- data/lib/datadog/appsec/contrib/graphql/patcher.rb +37 -0
- data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +59 -0
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +3 -6
- data/lib/datadog/appsec/event.rb +1 -1
- data/lib/datadog/appsec/processor/actions.rb +1 -1
- data/lib/datadog/appsec/processor/rule_loader.rb +3 -1
- data/lib/datadog/appsec/processor/rule_merger.rb +33 -15
- data/lib/datadog/appsec/processor.rb +36 -37
- data/lib/datadog/appsec/rate_limiter.rb +25 -40
- data/lib/datadog/appsec/remote.rb +7 -3
- data/lib/datadog/appsec/response.rb +15 -1
- data/lib/datadog/appsec.rb +3 -2
- data/lib/datadog/core/configuration/components.rb +18 -15
- data/lib/datadog/core/configuration/settings.rb +135 -9
- data/lib/datadog/core/crashtracking/agent_base_url.rb +21 -0
- data/lib/datadog/core/crashtracking/component.rb +111 -0
- data/lib/datadog/core/crashtracking/tag_builder.rb +39 -0
- data/lib/datadog/core/diagnostics/environment_logger.rb +8 -11
- data/lib/datadog/core/environment/execution.rb +5 -5
- data/lib/datadog/core/metrics/client.rb +7 -0
- data/lib/datadog/core/rate_limiter.rb +183 -0
- data/lib/datadog/core/remote/client/capabilities.rb +4 -3
- data/lib/datadog/core/remote/component.rb +4 -2
- data/lib/datadog/core/remote/negotiation.rb +4 -4
- data/lib/datadog/core/remote/tie.rb +2 -0
- data/lib/datadog/core/runtime/metrics.rb +1 -1
- data/lib/datadog/core/telemetry/component.rb +51 -2
- data/lib/datadog/core/telemetry/emitter.rb +9 -11
- data/lib/datadog/core/telemetry/event.rb +37 -1
- data/lib/datadog/core/telemetry/ext.rb +1 -0
- data/lib/datadog/core/telemetry/http/adapters/net.rb +10 -12
- data/lib/datadog/core/telemetry/http/ext.rb +3 -0
- data/lib/datadog/core/telemetry/http/transport.rb +38 -9
- data/lib/datadog/core/telemetry/logger.rb +51 -0
- data/lib/datadog/core/telemetry/logging.rb +71 -0
- data/lib/datadog/core/telemetry/request.rb +13 -1
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +102 -0
- data/lib/datadog/core/utils/time.rb +12 -0
- data/lib/datadog/di/code_tracker.rb +168 -0
- data/lib/datadog/di/configuration/settings.rb +163 -0
- data/lib/datadog/di/configuration.rb +11 -0
- data/lib/datadog/di/error.rb +31 -0
- data/lib/datadog/di/extensions.rb +16 -0
- data/lib/datadog/di/probe.rb +133 -0
- data/lib/datadog/di/probe_builder.rb +41 -0
- data/lib/datadog/di/redactor.rb +188 -0
- data/lib/datadog/di/serializer.rb +193 -0
- data/lib/datadog/di.rb +14 -0
- data/lib/datadog/kit/appsec/events.rb +2 -4
- data/lib/datadog/opentelemetry/sdk/propagator.rb +2 -0
- data/lib/datadog/opentelemetry/sdk/span_processor.rb +10 -0
- data/lib/datadog/opentelemetry/sdk/trace/span.rb +23 -0
- data/lib/datadog/profiling/collectors/code_provenance.rb +7 -7
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +28 -26
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +11 -13
- data/lib/datadog/profiling/collectors/info.rb +15 -6
- data/lib/datadog/profiling/collectors/thread_context.rb +30 -2
- data/lib/datadog/profiling/component.rb +89 -95
- data/lib/datadog/profiling/exporter.rb +3 -3
- data/lib/datadog/profiling/ext/dir_monkey_patches.rb +3 -3
- data/lib/datadog/profiling/ext.rb +21 -21
- data/lib/datadog/profiling/flush.rb +1 -1
- data/lib/datadog/profiling/http_transport.rb +14 -7
- data/lib/datadog/profiling/load_native_extension.rb +5 -5
- data/lib/datadog/profiling/preload.rb +1 -1
- data/lib/datadog/profiling/profiler.rb +5 -8
- data/lib/datadog/profiling/scheduler.rb +33 -25
- data/lib/datadog/profiling/stack_recorder.rb +3 -0
- data/lib/datadog/profiling/tag_builder.rb +2 -2
- data/lib/datadog/profiling/tasks/exec.rb +5 -5
- data/lib/datadog/profiling/tasks/setup.rb +16 -35
- data/lib/datadog/profiling.rb +4 -5
- data/lib/datadog/single_step_instrument.rb +12 -0
- data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +8 -12
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +5 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +78 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +33 -0
- data/lib/datadog/tracing/contrib/action_pack/patcher.rb +2 -0
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +4 -0
- data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +3 -1
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +4 -1
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +5 -1
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +5 -0
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
- data/lib/datadog/tracing/contrib/ext.rb +14 -0
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +9 -0
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +19 -0
- data/lib/datadog/tracing/contrib/graphql/patcher.rb +9 -12
- data/lib/datadog/tracing/contrib/graphql/trace_patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/graphql/tracing_patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +14 -10
- data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +10 -4
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +18 -15
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -5
- data/lib/datadog/tracing/contrib/httpclient/patcher.rb +1 -14
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +5 -0
- data/lib/datadog/tracing/contrib/httprb/patcher.rb +1 -14
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +15 -0
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +2 -0
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +17 -13
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +13 -6
- data/lib/datadog/tracing/contrib/patcher.rb +2 -1
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +4 -1
- data/lib/datadog/tracing/contrib/presto/patcher.rb +1 -13
- data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +28 -0
- data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +5 -1
- data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +22 -10
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +27 -0
- data/lib/datadog/tracing/contrib/redis/tags.rb +4 -0
- data/lib/datadog/tracing/contrib/sinatra/tracer.rb +4 -0
- data/lib/datadog/tracing/contrib/stripe/request.rb +3 -2
- data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +4 -1
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +14 -16
- data/lib/datadog/tracing/distributed/propagation.rb +7 -0
- data/lib/datadog/tracing/metadata/errors.rb +9 -1
- data/lib/datadog/tracing/metadata/ext.rb +6 -0
- data/lib/datadog/tracing/pipeline/span_filter.rb +2 -2
- data/lib/datadog/tracing/remote.rb +5 -2
- data/lib/datadog/tracing/sampling/matcher.rb +6 -1
- data/lib/datadog/tracing/sampling/rate_sampler.rb +1 -1
- data/lib/datadog/tracing/sampling/rule.rb +2 -0
- data/lib/datadog/tracing/sampling/rule_sampler.rb +9 -5
- data/lib/datadog/tracing/sampling/span/ext.rb +1 -1
- data/lib/datadog/tracing/sampling/span/rule.rb +2 -2
- data/lib/datadog/tracing/span.rb +9 -2
- data/lib/datadog/tracing/span_event.rb +41 -0
- data/lib/datadog/tracing/span_operation.rb +6 -2
- data/lib/datadog/tracing/trace_operation.rb +26 -2
- data/lib/datadog/tracing/tracer.rb +14 -12
- data/lib/datadog/tracing/transport/http/client.rb +1 -0
- data/lib/datadog/tracing/transport/io/client.rb +1 -0
- data/lib/datadog/tracing/transport/serializable_trace.rb +3 -0
- data/lib/datadog/tracing/workers/trace_writer.rb +1 -1
- data/lib/datadog/tracing/workers.rb +1 -1
- data/lib/datadog/version.rb +1 -1
- metadata +46 -11
- data/lib/datadog/profiling/crashtracker.rb +0 -91
- data/lib/datadog/profiling/ext/forking.rb +0 -98
- data/lib/datadog/tracing/sampling/rate_limiter.rb +0 -185
@@ -0,0 +1,193 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "redactor"
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module DI
|
7
|
+
# Serializes captured snapshot to primitive types, which are subsequently
|
8
|
+
# serialized to JSON and sent to the backend.
|
9
|
+
#
|
10
|
+
# This class performs actual removal of sensitive values from the
|
11
|
+
# snapshots. It uses Redactor to determine which values are sensitive
|
12
|
+
# and need to be removed.
|
13
|
+
#
|
14
|
+
# Serializer normally ought not to invoke user (application) code,
|
15
|
+
# to guarantee predictable performance. However, objects like ActiveRecord
|
16
|
+
# models cannot be usefully serialized into primitive types without
|
17
|
+
# custom logic (for example, the attributes are more than 3 levels
|
18
|
+
# down from the top-level object which is the default capture depth,
|
19
|
+
# thus they won't be captured at all). To accommodate complex objects,
|
20
|
+
# there is an extension mechanism implemented permitting registration
|
21
|
+
# of serializer callbacks for arbitrary types. Applications and libraries
|
22
|
+
# definining such serializer callbacks should be very careful to
|
23
|
+
# have predictable performance and avoid exceptions and infinite loops
|
24
|
+
# and other such issues.
|
25
|
+
#
|
26
|
+
# All serialization methods take the names of the variables being
|
27
|
+
# serialized in order to be able to redact values.
|
28
|
+
#
|
29
|
+
# @api private
|
30
|
+
class Serializer
|
31
|
+
def initialize(settings, redactor)
|
32
|
+
@settings = settings
|
33
|
+
@redactor = redactor
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_reader :settings
|
37
|
+
attr_reader :redactor
|
38
|
+
|
39
|
+
# Serializes positional and keyword arguments to a method,
|
40
|
+
# as obtained by a method probe.
|
41
|
+
#
|
42
|
+
# UI supports a single argument list only and does not distinguish
|
43
|
+
# between positional and keyword arguments. We convert positional
|
44
|
+
# arguments to keyword arguments ("arg1", "arg2", ...) and ensure
|
45
|
+
# the positional arguments are listed first.
|
46
|
+
def serialize_args(args, kwargs)
|
47
|
+
counter = 0
|
48
|
+
combined = args.each_with_object({}) do |value, c|
|
49
|
+
counter += 1
|
50
|
+
# Conversion to symbol is needed here to put args ahead of
|
51
|
+
# kwargs when they are merged below.
|
52
|
+
c[:"arg#{counter}"] = value
|
53
|
+
end.update(kwargs)
|
54
|
+
serialize_vars(combined)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Serializes variables captured by a line probe.
|
58
|
+
#
|
59
|
+
# These are normally local variables that exist on a particular line
|
60
|
+
# of executed code.
|
61
|
+
def serialize_vars(vars)
|
62
|
+
vars.each_with_object({}) do |(k, v), agg|
|
63
|
+
agg[k] = serialize_value(v, name: k)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Serializes a single named value.
|
68
|
+
#
|
69
|
+
# The name is needed to perform sensitive data redaction.
|
70
|
+
#
|
71
|
+
# In some cases, the value being serialized does not have a name
|
72
|
+
# (for example, it is the return value of a method).
|
73
|
+
# In this case +name+ can be nil.
|
74
|
+
#
|
75
|
+
# Returns a data structure comprised of only values of basic types
|
76
|
+
# (integers, strings, arrays, hashes).
|
77
|
+
#
|
78
|
+
# Respects string length, collection size and traversal depth limits.
|
79
|
+
def serialize_value(value, name: nil, depth: settings.dynamic_instrumentation.max_capture_depth)
|
80
|
+
if redactor.redact_type?(value)
|
81
|
+
return {type: class_name(value.class), notCapturedReason: "redactedType"}
|
82
|
+
end
|
83
|
+
|
84
|
+
if name && redactor.redact_identifier?(name)
|
85
|
+
return {type: class_name(value.class), notCapturedReason: "redactedIdent"}
|
86
|
+
end
|
87
|
+
|
88
|
+
serialized = {type: class_name(value.class)}
|
89
|
+
case value
|
90
|
+
when NilClass
|
91
|
+
serialized.update(isNull: true)
|
92
|
+
when Integer, Float, TrueClass, FalseClass
|
93
|
+
serialized.update(value: value.to_s)
|
94
|
+
when String, Symbol
|
95
|
+
value = value.to_s
|
96
|
+
max = settings.dynamic_instrumentation.max_capture_string_length
|
97
|
+
if value.length > max
|
98
|
+
serialized.update(truncated: true, size: value.length)
|
99
|
+
value = value[0...max]
|
100
|
+
end
|
101
|
+
serialized.update(value: value)
|
102
|
+
when Array
|
103
|
+
if depth < 0
|
104
|
+
serialized.update(notCapturedReason: "depth")
|
105
|
+
else
|
106
|
+
max = settings.dynamic_instrumentation.max_capture_collection_size
|
107
|
+
if max != 0 && value.length > max
|
108
|
+
serialized.update(notCapturedReason: "collectionSize", size: value.length)
|
109
|
+
# same steep failure with array slices.
|
110
|
+
# https://github.com/soutaro/steep/issues/1219
|
111
|
+
value = value[0...max] || []
|
112
|
+
end
|
113
|
+
entries = value.map do |elt|
|
114
|
+
serialize_value(elt, depth: depth - 1)
|
115
|
+
end
|
116
|
+
serialized.update(elements: entries)
|
117
|
+
end
|
118
|
+
when Hash
|
119
|
+
if depth < 0
|
120
|
+
serialized.update(notCapturedReason: "depth")
|
121
|
+
else
|
122
|
+
max = settings.dynamic_instrumentation.max_capture_collection_size
|
123
|
+
cur = 0
|
124
|
+
entries = []
|
125
|
+
value.each do |k, v|
|
126
|
+
if max != 0 && cur >= max
|
127
|
+
serialized.update(notCapturedReason: "collectionSize", size: value.length)
|
128
|
+
break
|
129
|
+
end
|
130
|
+
cur += 1
|
131
|
+
entries << [serialize_value(k, depth: depth - 1), serialize_value(v, name: k, depth: depth - 1)]
|
132
|
+
end
|
133
|
+
serialized.update(entries: entries)
|
134
|
+
end
|
135
|
+
else
|
136
|
+
if depth < 0
|
137
|
+
serialized.update(notCapturedReason: "depth")
|
138
|
+
else
|
139
|
+
fields = {}
|
140
|
+
max = settings.dynamic_instrumentation.max_capture_attribute_count
|
141
|
+
cur = 0
|
142
|
+
|
143
|
+
# MRI and JRuby 9.4.5+ preserve instance variable definition
|
144
|
+
# order when calling #instance_variables. Previous JRuby versions
|
145
|
+
# did not preserve order and returned the variables in arbitrary
|
146
|
+
# order.
|
147
|
+
#
|
148
|
+
# The arbitrary order is problematic because 1) when there are
|
149
|
+
# fewer instance variables than capture limit, the order in which
|
150
|
+
# the variables are shown in UI will change from one capture to
|
151
|
+
# the next and generally will be arbitrary to the user, and
|
152
|
+
# 2) when there are more instance variables than capture limit,
|
153
|
+
# *which* variables are captured will also change meaning user
|
154
|
+
# looking at the UI may have "new" instance variables appear and
|
155
|
+
# existing ones disappear as they are looking at multiple captures.
|
156
|
+
#
|
157
|
+
# For consistency, we should have some kind of stable order of
|
158
|
+
# instance variables on all supported Ruby runtimes, so that the UI
|
159
|
+
# stays consistent. Given that initial implementation of Ruby DI
|
160
|
+
# does not support JRuby, we don't handle JRuby's lack of ordering
|
161
|
+
# of #instance_variables here, but if JRuby is supported in the
|
162
|
+
# future this may need to be addressed.
|
163
|
+
ivars = value.instance_variables
|
164
|
+
|
165
|
+
ivars.each do |ivar|
|
166
|
+
if cur >= max
|
167
|
+
serialized.update(notCapturedReason: "fieldCount", fields: fields)
|
168
|
+
break
|
169
|
+
end
|
170
|
+
cur += 1
|
171
|
+
fields[ivar] = serialize_value(value.instance_variable_get(ivar), name: ivar, depth: depth - 1)
|
172
|
+
end
|
173
|
+
serialized.update(fields: fields)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
serialized
|
177
|
+
end
|
178
|
+
|
179
|
+
private
|
180
|
+
|
181
|
+
# Returns the name for the specified class object.
|
182
|
+
#
|
183
|
+
# Ruby can have nameless classes, e.g. Class.new is a class object
|
184
|
+
# with no name. We return a placeholder for such nameless classes.
|
185
|
+
def class_name(cls)
|
186
|
+
# We could call `cls.to_s` to get the "standard" Ruby inspection of
|
187
|
+
# the class, but it is likely that user code can override #to_s
|
188
|
+
# and we don't want to invoke user code.
|
189
|
+
cls.name || "[Unnamed class]"
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
data/lib/datadog/di.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'di/configuration'
|
4
|
+
require_relative 'di/extensions'
|
5
|
+
|
6
|
+
module Datadog
|
7
|
+
# Namespace for Datadog dynamic instrumentation.
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
module DI
|
11
|
+
# Expose DI to global shared objects
|
12
|
+
Extensions.activate!
|
13
|
+
end
|
14
|
+
end
|
@@ -53,13 +53,11 @@ module Datadog
|
|
53
53
|
# @param user_exists [bool] Whether the user id that did a login attempt exists.
|
54
54
|
# @param others [Hash<String || Symbol, String>] Additional free-form
|
55
55
|
# event information to attach to the trace.
|
56
|
-
def track_login_failure(trace = nil, span = nil,
|
56
|
+
def track_login_failure(trace = nil, span = nil, user_exists:, user_id: nil, **others)
|
57
57
|
set_trace_and_span_context('track_login_failure', trace, span) do |active_trace, active_span|
|
58
|
-
raise ArgumentError, 'user_id cannot be nil' if user_id.nil?
|
59
|
-
|
60
58
|
track(LOGIN_FAILURE_EVENT, active_trace, active_span, **others)
|
61
59
|
|
62
|
-
active_span.set_tag('appsec.events.users.login.failure.usr.id', user_id)
|
60
|
+
active_span.set_tag('appsec.events.users.login.failure.usr.id', user_id) if user_id
|
63
61
|
active_span.set_tag('appsec.events.users.login.failure.usr.exists', user_exists)
|
64
62
|
end
|
65
63
|
end
|
@@ -15,6 +15,7 @@ module Datadog
|
|
15
15
|
setter: ::OpenTelemetry::Context::Propagation.text_map_setter
|
16
16
|
)
|
17
17
|
unless setter == ::OpenTelemetry::Context::Propagation.text_map_setter
|
18
|
+
# PENDING: Not to report telemetry logs for now
|
18
19
|
Datadog.logger.error(
|
19
20
|
'Custom setter is not supported. Please inform the `datadog` team at ' \
|
20
21
|
' https://github.com/DataDog/dd-trace-rb of your use case so we can best support you. Using the default ' \
|
@@ -31,6 +32,7 @@ module Datadog
|
|
31
32
|
)
|
32
33
|
if getter != ::OpenTelemetry::Context::Propagation.text_map_getter &&
|
33
34
|
getter != ::OpenTelemetry::Common::Propagation.rack_env_getter
|
35
|
+
# PENDING: Not to report telemetry logs for now
|
34
36
|
Datadog.logger.error(
|
35
37
|
"Custom getter #{getter} is not supported. Please inform the `datadog` team at " \
|
36
38
|
' https://github.com/DataDog/dd-trace-rb of your use case so we can best support you. Using the default ' \
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative 'trace/span'
|
4
4
|
require_relative '../../tracing/span_link'
|
5
|
+
require_relative '../../tracing/span_event'
|
5
6
|
require_relative '../../tracing/trace_digest'
|
6
7
|
|
7
8
|
module Datadog
|
@@ -31,6 +32,15 @@ module Datadog
|
|
31
32
|
#
|
32
33
|
# @param [Span] span the {Span} that just ended.
|
33
34
|
def on_finish(span)
|
35
|
+
unless span.events.nil?
|
36
|
+
span.datadog_span.span_events = span.events.map do |event|
|
37
|
+
Datadog::Tracing::SpanEvent.new(
|
38
|
+
event.name,
|
39
|
+
attributes: event.attributes,
|
40
|
+
time_unix_nano: event.timestamp
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
34
44
|
span.datadog_span.finish(ns_to_time(span.end_timestamp))
|
35
45
|
end
|
36
46
|
|
@@ -15,6 +15,29 @@ module Datadog
|
|
15
15
|
res
|
16
16
|
end
|
17
17
|
|
18
|
+
# Record an exception during the execution of this span. Multiple exceptions
|
19
|
+
# can be recorded on a span.
|
20
|
+
#
|
21
|
+
# @param [Exception] exception The exception to recorded
|
22
|
+
# @param [optional Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}]
|
23
|
+
# attributes One or more key:value pairs, where the keys must be
|
24
|
+
# strings and the values may be (array of) string, boolean or numeric
|
25
|
+
# type.
|
26
|
+
#
|
27
|
+
# @return [void]
|
28
|
+
def record_exception(exception, attributes: nil)
|
29
|
+
res = super
|
30
|
+
if (span = datadog_span)
|
31
|
+
# Sets the exception attributes as span error tags. The values in the attribute hash MUST
|
32
|
+
# take precedence over the type, message and stacktrace inferred from the exception object
|
33
|
+
type = attributes&.[]('exception.type') || exception.class.to_s
|
34
|
+
message = attributes&.[]('exception.message') || exception.message
|
35
|
+
stacktrace = attributes&.[]('exception.stacktrace') || exception.full_message(highlight: false, order: :top)
|
36
|
+
span.set_error_tags([type, message, stacktrace])
|
37
|
+
end
|
38
|
+
res
|
39
|
+
end
|
40
|
+
|
18
41
|
# `alias` performed to match {OpenTelemetry::SDK::Trace::Span} aliasing upstream
|
19
42
|
alias []= set_attribute
|
20
43
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "set"
|
4
|
+
require "json"
|
5
5
|
|
6
6
|
module Datadog
|
7
7
|
module Profiling
|
@@ -14,7 +14,7 @@ module Datadog
|
|
14
14
|
#
|
15
15
|
# This class acts both as a collector (collecting data) as well as a recorder (records/serializes it)
|
16
16
|
class CodeProvenance
|
17
|
-
def initialize(standard_library_path: RbConfig::CONFIG.fetch(
|
17
|
+
def initialize(standard_library_path: RbConfig::CONFIG.fetch("rubylibdir"))
|
18
18
|
@libraries_by_name = {}
|
19
19
|
@libraries_by_path = {}
|
20
20
|
@seen_files = Set.new
|
@@ -22,8 +22,8 @@ module Datadog
|
|
22
22
|
|
23
23
|
record_library(
|
24
24
|
Library.new(
|
25
|
-
kind:
|
26
|
-
name:
|
25
|
+
kind: "standard library",
|
26
|
+
name: "stdlib",
|
27
27
|
version: RUBY_VERSION,
|
28
28
|
path: standard_library_path,
|
29
29
|
)
|
@@ -79,7 +79,7 @@ module Datadog
|
|
79
79
|
loaded_specs.each do |spec|
|
80
80
|
next if libraries_by_name.key?(spec.name)
|
81
81
|
|
82
|
-
record_library(Library.new(kind:
|
82
|
+
record_library(Library.new(kind: "library", name: spec.name, version: spec.version, path: spec.gem_dir))
|
83
83
|
recorded_library = true
|
84
84
|
end
|
85
85
|
|
@@ -119,7 +119,7 @@ module Datadog
|
|
119
119
|
end
|
120
120
|
|
121
121
|
def to_json(arg = nil)
|
122
|
-
{
|
122
|
+
{kind: @kind, name: @name, version: @version, paths: @paths}.to_json(arg)
|
123
123
|
end
|
124
124
|
|
125
125
|
def path
|
@@ -21,6 +21,8 @@ module Datadog
|
|
21
21
|
thread_context_collector:,
|
22
22
|
dynamic_sampling_rate_overhead_target_percentage:,
|
23
23
|
allocation_profiling_enabled:,
|
24
|
+
allocation_counting_enabled:,
|
25
|
+
gvl_profiling_enabled:,
|
24
26
|
# **NOTE**: This should only be used for testing; disabling the dynamic sampling rate will increase the
|
25
27
|
# profiler overhead!
|
26
28
|
dynamic_sampling_rate_enabled: true,
|
@@ -29,20 +31,22 @@ module Datadog
|
|
29
31
|
)
|
30
32
|
unless dynamic_sampling_rate_enabled
|
31
33
|
Datadog.logger.warn(
|
32
|
-
|
34
|
+
"Profiling dynamic sampling rate disabled. This should only be used for testing, and will increase overhead!"
|
33
35
|
)
|
34
36
|
end
|
35
37
|
|
36
38
|
self.class._native_initialize(
|
37
|
-
self,
|
38
|
-
thread_context_collector,
|
39
|
-
gc_profiling_enabled,
|
40
|
-
idle_sampling_helper,
|
41
|
-
no_signals_workaround_enabled,
|
42
|
-
dynamic_sampling_rate_enabled,
|
43
|
-
dynamic_sampling_rate_overhead_target_percentage,
|
44
|
-
allocation_profiling_enabled,
|
45
|
-
|
39
|
+
self_instance: self,
|
40
|
+
thread_context_collector: thread_context_collector,
|
41
|
+
gc_profiling_enabled: gc_profiling_enabled,
|
42
|
+
idle_sampling_helper: idle_sampling_helper,
|
43
|
+
no_signals_workaround_enabled: no_signals_workaround_enabled,
|
44
|
+
dynamic_sampling_rate_enabled: dynamic_sampling_rate_enabled,
|
45
|
+
dynamic_sampling_rate_overhead_target_percentage: dynamic_sampling_rate_overhead_target_percentage,
|
46
|
+
allocation_profiling_enabled: allocation_profiling_enabled,
|
47
|
+
allocation_counting_enabled: allocation_counting_enabled,
|
48
|
+
gvl_profiling_enabled: gvl_profiling_enabled,
|
49
|
+
skip_idle_samples_for_testing: skip_idle_samples_for_testing,
|
46
50
|
)
|
47
51
|
@worker_thread = nil
|
48
52
|
@failure_exception = nil
|
@@ -54,27 +58,25 @@ module Datadog
|
|
54
58
|
|
55
59
|
def start(on_failure_proc: nil)
|
56
60
|
@start_stop_mutex.synchronize do
|
57
|
-
return if @worker_thread
|
61
|
+
return if @worker_thread&.alive?
|
58
62
|
|
59
63
|
Datadog.logger.debug { "Starting thread for: #{self}" }
|
60
64
|
|
61
65
|
@idle_sampling_helper.start
|
62
66
|
|
63
67
|
@worker_thread = Thread.new do
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
on_failure_proc&.call
|
77
|
-
end
|
68
|
+
Thread.current.name = self.class.name
|
69
|
+
|
70
|
+
self.class._native_sampling_loop(self)
|
71
|
+
|
72
|
+
Datadog.logger.debug("CpuAndWallTimeWorker thread stopping cleanly")
|
73
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
74
|
+
@failure_exception = e
|
75
|
+
Datadog.logger.warn(
|
76
|
+
"CpuAndWallTimeWorker thread error. " \
|
77
|
+
"Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
|
78
|
+
)
|
79
|
+
on_failure_proc&.call
|
78
80
|
end
|
79
81
|
@worker_thread.name = self.class.name # Repeated from above to make sure thread gets named asap
|
80
82
|
@worker_thread.thread_variable_set(:fork_safe, true)
|
@@ -85,7 +87,7 @@ module Datadog
|
|
85
87
|
|
86
88
|
def stop
|
87
89
|
@start_stop_mutex.synchronize do
|
88
|
-
Datadog.logger.debug(
|
90
|
+
Datadog.logger.debug("Requesting CpuAndWallTimeWorker thread shut down")
|
89
91
|
|
90
92
|
@idle_sampling_helper.stop
|
91
93
|
|
@@ -21,7 +21,7 @@ module Datadog
|
|
21
21
|
|
22
22
|
def start
|
23
23
|
@start_stop_mutex.synchronize do
|
24
|
-
return if @worker_thread
|
24
|
+
return if @worker_thread&.alive?
|
25
25
|
|
26
26
|
Datadog.logger.debug { "Starting thread for: #{self}" }
|
27
27
|
|
@@ -30,19 +30,17 @@ module Datadog
|
|
30
30
|
self.class._native_reset(self)
|
31
31
|
|
32
32
|
@worker_thread = Thread.new do
|
33
|
-
|
34
|
-
Thread.current.name = self.class.name
|
33
|
+
Thread.current.name = self.class.name
|
35
34
|
|
36
|
-
|
35
|
+
self.class._native_idle_sampling_loop(self)
|
37
36
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
37
|
+
Datadog.logger.debug("IdleSamplingHelper thread stopping cleanly")
|
38
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
39
|
+
@failure_exception = e
|
40
|
+
Datadog.logger.warn(
|
41
|
+
"IdleSamplingHelper thread error. " \
|
42
|
+
"Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
|
43
|
+
)
|
46
44
|
end
|
47
45
|
@worker_thread.name = self.class.name # Repeated from above to make sure thread gets named asap
|
48
46
|
@worker_thread.thread_variable_set(:fork_safe, true)
|
@@ -53,7 +51,7 @@ module Datadog
|
|
53
51
|
|
54
52
|
def stop
|
55
53
|
@start_stop_mutex.synchronize do
|
56
|
-
Datadog.logger.debug(
|
54
|
+
Datadog.logger.debug("Requesting IdleSamplingHelper thread shut down")
|
57
55
|
|
58
56
|
return unless @worker_thread
|
59
57
|
|
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "set"
|
4
|
+
require "time"
|
5
|
+
require "libdatadog"
|
5
6
|
|
6
7
|
module Datadog
|
7
8
|
module Profiling
|
@@ -61,12 +62,20 @@ module Datadog
|
|
61
62
|
|
62
63
|
def collect_profiler_info(settings)
|
63
64
|
unless @profiler_info
|
64
|
-
lib_datadog_gem = ::Gem.loaded_specs[
|
65
|
+
lib_datadog_gem = ::Gem.loaded_specs["libdatadog"]
|
66
|
+
|
67
|
+
libdatadog_version =
|
68
|
+
if lib_datadog_gem
|
69
|
+
"#{lib_datadog_gem.version}-#{lib_datadog_gem.platform}"
|
70
|
+
else
|
71
|
+
# In some cases, Gem.loaded_specs may not be available, as in
|
72
|
+
# https://github.com/DataDog/dd-trace-rb/pull/1506; let's use the version directly
|
73
|
+
"#{Libdatadog::VERSION}-(unknown)"
|
74
|
+
end
|
75
|
+
|
65
76
|
@profiler_info = {
|
66
|
-
# TODO: If profiling is extracted and its version diverges from the datadog gem, this is inaccurate.
|
67
|
-
# Update if this ever occurs.
|
68
77
|
version: Datadog::Core::Environment::Identity.gem_datadog_version,
|
69
|
-
libdatadog:
|
78
|
+
libdatadog: libdatadog_version,
|
70
79
|
settings: collect_settings_recursively(settings.profiling),
|
71
80
|
}.freeze
|
72
81
|
end
|
@@ -20,6 +20,8 @@ module Datadog
|
|
20
20
|
tracer:,
|
21
21
|
endpoint_collection_enabled:,
|
22
22
|
timeline_enabled:,
|
23
|
+
waiting_for_gvl_threshold_ns:,
|
24
|
+
otel_context_enabled:,
|
23
25
|
allocation_type_enabled: true
|
24
26
|
)
|
25
27
|
tracer_context_key = safely_extract_context_key_from(tracer)
|
@@ -30,10 +32,34 @@ module Datadog
|
|
30
32
|
tracer_context_key,
|
31
33
|
endpoint_collection_enabled,
|
32
34
|
timeline_enabled,
|
35
|
+
waiting_for_gvl_threshold_ns,
|
36
|
+
otel_context_enabled,
|
33
37
|
allocation_type_enabled,
|
34
38
|
)
|
35
39
|
end
|
36
40
|
|
41
|
+
def self.for_testing(
|
42
|
+
recorder:,
|
43
|
+
max_frames: 400,
|
44
|
+
tracer: nil,
|
45
|
+
endpoint_collection_enabled: false,
|
46
|
+
timeline_enabled: false,
|
47
|
+
waiting_for_gvl_threshold_ns: 10_000_000,
|
48
|
+
otel_context_enabled: false,
|
49
|
+
**options
|
50
|
+
)
|
51
|
+
new(
|
52
|
+
recorder: recorder,
|
53
|
+
max_frames: max_frames,
|
54
|
+
tracer: tracer,
|
55
|
+
endpoint_collection_enabled: endpoint_collection_enabled,
|
56
|
+
timeline_enabled: timeline_enabled,
|
57
|
+
waiting_for_gvl_threshold_ns: waiting_for_gvl_threshold_ns,
|
58
|
+
otel_context_enabled: otel_context_enabled,
|
59
|
+
**options,
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
37
63
|
def inspect
|
38
64
|
# Compose Ruby's default inspect with our custom inspect for the native parts
|
39
65
|
result = super()
|
@@ -48,12 +74,14 @@ module Datadog
|
|
48
74
|
private
|
49
75
|
|
50
76
|
def safely_extract_context_key_from(tracer)
|
51
|
-
|
77
|
+
return unless tracer
|
78
|
+
|
79
|
+
provider = tracer.respond_to?(:provider) && tracer.provider
|
52
80
|
|
53
81
|
return unless provider
|
54
82
|
|
55
83
|
context = provider.instance_variable_get(:@context)
|
56
|
-
context
|
84
|
+
context&.instance_variable_get(:@key)
|
57
85
|
end
|
58
86
|
end
|
59
87
|
end
|