datadog 2.1.0 → 2.3.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 +101 -1
- data/ext/datadog_profiling_loader/extconf.rb +15 -15
- 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 +132 -44
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +49 -26
- 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 +90 -37
- data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +81 -19
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +1 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +110 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +57 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +69 -62
- data/ext/datadog_profiling_native_extension/heap_recorder.c +34 -6
- 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 +3 -3
- 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 -126
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +64 -138
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +17 -11
- data/ext/datadog_profiling_native_extension/profiling.c +0 -2
- 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.c +1 -1
- data/ext/datadog_profiling_native_extension/setup_signal_handler.h +1 -0
- data/ext/datadog_profiling_native_extension/stack_recorder.c +27 -8
- 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 +20 -7
- data/ext/libdatadog_api/datadog_ruby_common.c +110 -0
- data/ext/libdatadog_api/datadog_ruby_common.h +57 -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/contrib/graphql/appsec_trace.rb +49 -0
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +73 -0
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +68 -0
- data/lib/datadog/appsec/contrib/graphql/integration.rb +41 -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 +1 -1
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +1 -1
- data/lib/datadog/appsec/extensions.rb +1 -0
- data/lib/datadog/appsec/processor/actions.rb +1 -1
- data/lib/datadog/appsec/response.rb +15 -1
- data/lib/datadog/appsec.rb +1 -0
- data/lib/datadog/core/configuration/components.rb +17 -12
- data/lib/datadog/core/configuration/settings.rb +93 -7
- data/lib/datadog/core/configuration.rb +3 -17
- 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/deprecations.rb +58 -0
- data/lib/datadog/core/diagnostics/environment_logger.rb +8 -11
- data/lib/datadog/core/environment/yjit.rb +5 -0
- data/lib/datadog/core/runtime/ext.rb +1 -0
- data/lib/datadog/core/runtime/metrics.rb +6 -0
- data/lib/datadog/core/telemetry/component.rb +154 -0
- data/lib/datadog/core/telemetry/emitter.rb +9 -11
- data/lib/datadog/core/telemetry/event.rb +132 -26
- data/lib/datadog/core/telemetry/ext.rb +3 -0
- data/lib/datadog/core/telemetry/http/adapters/net.rb +11 -13
- 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/logging.rb +35 -0
- data/lib/datadog/core/telemetry/metric.rb +167 -0
- data/lib/datadog/core/telemetry/metrics_collection.rb +81 -0
- data/lib/datadog/core/telemetry/metrics_manager.rb +81 -0
- data/lib/datadog/core/telemetry/request.rb +1 -1
- data/lib/datadog/core/telemetry/worker.rb +173 -0
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +102 -0
- data/lib/datadog/core/utils/only_once_successful.rb +76 -0
- data/lib/datadog/core.rb +2 -19
- data/lib/datadog/kit/appsec/events.rb +2 -4
- data/lib/datadog/opentelemetry/sdk/propagator.rb +5 -10
- data/lib/datadog/opentelemetry/sdk/span_processor.rb +15 -2
- data/lib/datadog/opentelemetry/sdk/trace/span.rb +23 -0
- data/lib/datadog/profiling/collectors/code_provenance.rb +24 -11
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +17 -17
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +11 -13
- data/lib/datadog/profiling/collectors/info.rb +3 -3
- data/lib/datadog/profiling/collectors/thread_context.rb +4 -2
- data/lib/datadog/profiling/component.rb +85 -90
- data/lib/datadog/profiling/exporter.rb +3 -3
- data/lib/datadog/profiling/ext/dir_monkey_patches.rb +410 -0
- data/lib/datadog/profiling/ext.rb +21 -21
- data/lib/datadog/profiling/flush.rb +1 -1
- data/lib/datadog/profiling/http_transport.rb +8 -6
- 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 +31 -25
- 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 +5 -5
- data/lib/datadog/tracing/contrib/action_cable/event.rb +1 -1
- data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +1 -1
- data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +1 -1
- data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +1 -1
- data/lib/datadog/tracing/contrib/action_mailer/event.rb +4 -6
- data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +9 -4
- data/lib/datadog/tracing/contrib/action_mailer/events/process.rb +3 -2
- data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +1 -5
- 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/events/instantiation.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +2 -1
- data/lib/datadog/tracing/contrib/active_support/cache/event.rb +32 -0
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +156 -0
- data/lib/datadog/tracing/contrib/active_support/cache/events.rb +34 -0
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +45 -41
- data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +17 -40
- data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +4 -1
- data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +29 -6
- data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +16 -4
- data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +33 -29
- data/lib/datadog/tracing/contrib/analytics.rb +5 -0
- data/lib/datadog/tracing/contrib/ext.rb +14 -0
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/graphql/patcher.rb +8 -2
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +166 -0
- data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +28 -0
- data/lib/datadog/tracing/contrib/kafka/consumer_event.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/consumer_group_event.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/event.rb +1 -1
- data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +3 -3
- data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +3 -3
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +16 -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/pg/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +4 -1
- 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/racecar/event.rb +2 -2
- data/lib/datadog/tracing/contrib/rails/ext.rb +9 -0
- data/lib/datadog/tracing/contrib/rails/patcher.rb +7 -0
- data/lib/datadog/tracing/contrib/rails/runner.rb +95 -0
- 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/b3_multi.rb +1 -1
- data/lib/datadog/tracing/distributed/b3_single.rb +3 -1
- data/lib/datadog/tracing/distributed/datadog.rb +2 -2
- data/lib/datadog/tracing/distributed/propagation.rb +9 -2
- data/lib/datadog/tracing/distributed/trace_context.rb +3 -2
- data/lib/datadog/tracing/metadata/errors.rb +9 -1
- data/lib/datadog/tracing/metadata/ext.rb +4 -0
- data/lib/datadog/tracing/pipeline/span_filter.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 +9 -4
- data/lib/datadog/tracing/trace_operation.rb +7 -3
- data/lib/datadog/tracing/trace_segment.rb +4 -1
- data/lib/datadog/tracing/tracer.rb +9 -2
- data/lib/datadog/tracing/transport/serializable_trace.rb +3 -0
- data/lib/datadog/tracing.rb +5 -1
- data/lib/datadog/version.rb +2 -2
- metadata +43 -12
- data/lib/datadog/core/telemetry/client.rb +0 -95
- data/lib/datadog/core/telemetry/heartbeat.rb +0 -33
- data/lib/datadog/profiling/crashtracker.rb +0 -91
- data/lib/datadog/profiling/ext/forking.rb +0 -98
@@ -0,0 +1,156 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../ext'
|
4
|
+
require_relative '../event'
|
5
|
+
|
6
|
+
module Datadog
|
7
|
+
module Tracing
|
8
|
+
module Contrib
|
9
|
+
module ActiveSupport
|
10
|
+
module Cache
|
11
|
+
module Events
|
12
|
+
# Defines instrumentation for instantiation.active_record event
|
13
|
+
module Cache
|
14
|
+
include ActiveSupport::Cache::Event
|
15
|
+
|
16
|
+
module_function
|
17
|
+
|
18
|
+
# Acts as this module's initializer.
|
19
|
+
def subscribe!
|
20
|
+
@cache_backend = {}
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
def event_name
|
25
|
+
/\Acache_(?:delete|read|read_multi|write|write_multi)\.active_support\z/
|
26
|
+
end
|
27
|
+
|
28
|
+
def span_name
|
29
|
+
Ext::SPAN_CACHE
|
30
|
+
end
|
31
|
+
|
32
|
+
def span_options
|
33
|
+
{
|
34
|
+
type: Ext::SPAN_TYPE_CACHE
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
# DEV: Look for other uses of `ActiveSupport::Cache::Store#instrument`, to find other useful event keys.
|
39
|
+
MAPPING = {
|
40
|
+
'cache_delete.active_support' => { resource: Ext::RESOURCE_CACHE_DELETE },
|
41
|
+
'cache_read.active_support' => { resource: Ext::RESOURCE_CACHE_GET },
|
42
|
+
'cache_read_multi.active_support' => { resource: Ext::RESOURCE_CACHE_MGET, multi_key: true },
|
43
|
+
'cache_write.active_support' => { resource: Ext::RESOURCE_CACHE_SET },
|
44
|
+
'cache_write_multi.active_support' => { resource: Ext::RESOURCE_CACHE_MSET, multi_key: true }
|
45
|
+
}.freeze
|
46
|
+
|
47
|
+
def trace?(event, _payload)
|
48
|
+
return false if !Tracing.enabled? || !configuration.enabled
|
49
|
+
|
50
|
+
# DEV-3.0: Backwards compatibility code for the 2.x gem series.
|
51
|
+
# DEV-3.0: See documentation at {Datadog::Tracing::Contrib::ActiveSupport::Cache::Instrumentation}
|
52
|
+
# DEV-3.0: for the complete information about this backwards compatibility code.
|
53
|
+
case event
|
54
|
+
when 'cache_read.active_support'
|
55
|
+
!ActiveSupport::Cache::Instrumentation.nested_read?
|
56
|
+
when 'cache_read_multi.active_support'
|
57
|
+
!ActiveSupport::Cache::Instrumentation.nested_multiread?
|
58
|
+
else
|
59
|
+
true
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def on_start(span, event, _id, payload)
|
64
|
+
key = payload[:key]
|
65
|
+
store = payload[:store]
|
66
|
+
|
67
|
+
mapping = MAPPING[event]
|
68
|
+
|
69
|
+
span.service = configuration[:cache_service]
|
70
|
+
span.resource = mapping[:resource]
|
71
|
+
|
72
|
+
span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
|
73
|
+
span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_CACHE)
|
74
|
+
|
75
|
+
if span.service != Datadog.configuration.service
|
76
|
+
span.set_tag(Tracing::Contrib::Ext::Metadata::TAG_BASE_SERVICE, Datadog.configuration.service)
|
77
|
+
end
|
78
|
+
|
79
|
+
span.set_tag(Ext::TAG_CACHE_BACKEND, cache_backend(store))
|
80
|
+
|
81
|
+
span.set_tag('EVENT', event)
|
82
|
+
|
83
|
+
set_cache_key(span, key, mapping[:multi_key])
|
84
|
+
end
|
85
|
+
|
86
|
+
def set_cache_key(span, key, multi_key)
|
87
|
+
if multi_key
|
88
|
+
keys = key.is_a?(Hash) ? key.keys : key # `write`s use Hashes, while `read`s use Arrays
|
89
|
+
resolved_key = keys.map { |k| ::ActiveSupport::Cache.expand_cache_key(k) }
|
90
|
+
cache_key = Core::Utils.truncate(resolved_key, Ext::QUANTIZE_CACHE_MAX_KEY_SIZE)
|
91
|
+
span.set_tag(Ext::TAG_CACHE_KEY_MULTI, cache_key)
|
92
|
+
else
|
93
|
+
resolved_key = ::ActiveSupport::Cache.expand_cache_key(key)
|
94
|
+
cache_key = Core::Utils.truncate(resolved_key, Ext::QUANTIZE_CACHE_MAX_KEY_SIZE)
|
95
|
+
span.set_tag(Ext::TAG_CACHE_KEY, cache_key)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# The name of the `store` is never saved by Rails.
|
100
|
+
# ActiveSupport looks up stores by converting a symbol into a 'require' path,
|
101
|
+
# then "camelizing" it for a `const_get` call:
|
102
|
+
# ```
|
103
|
+
# require "active_support/cache/#{store}"
|
104
|
+
# ActiveSupport::Cache.const_get(store.to_s.camelize)
|
105
|
+
# ```
|
106
|
+
# @see https://github.com/rails/rails/blob/261975dbef77731d2c76f907f1076c5132ebc0e4/activesupport/lib/active_support/cache.rb#L139-L149
|
107
|
+
#
|
108
|
+
# We can reverse engineer
|
109
|
+
# the original symbol by converting the class name to snake case:
|
110
|
+
# e.g. ActiveSupport::Cache::RedisStore -> active_support/cache/redis_store
|
111
|
+
# In this case, `redis_store` is the store name.
|
112
|
+
#
|
113
|
+
# Because there's no API retrieve only the class name
|
114
|
+
# (only `RedisStore`, and not `ActiveSupport::Cache::RedisStore`)
|
115
|
+
# the easiest way to retrieve the store symbol is to convert the fully qualified
|
116
|
+
# name using the Rails-provided method `#underscore`, which is the reverse of `#camelize`,
|
117
|
+
# then extracting the last part of it.
|
118
|
+
#
|
119
|
+
# Also, this method caches the store name, given this value will be retrieve
|
120
|
+
# multiple times and involves string manipulation.
|
121
|
+
def cache_backend(store)
|
122
|
+
# Cache the backend name to avoid the expensive string manipulation required to calculate it.
|
123
|
+
# DEV: We can't store it directly in the `store` object because it is a frozen String.
|
124
|
+
if (name = @cache_backend[store])
|
125
|
+
return name
|
126
|
+
end
|
127
|
+
|
128
|
+
# DEV: #underscore is available through ActiveSupport, and is
|
129
|
+
# DEV: the exact reverse operation to `#camelize`.
|
130
|
+
# DEV: #demodulize is available through ActiveSupport, and is
|
131
|
+
# DEV: used to remove the module ('*::') part of a constant name.
|
132
|
+
name = ::ActiveSupport::Inflector.demodulize(store)
|
133
|
+
name = ::ActiveSupport::Inflector.underscore(name)
|
134
|
+
|
135
|
+
# Despite a given application only ever having 1-3 store types,
|
136
|
+
# we limit the size of the `@cache_backend` just in case, because
|
137
|
+
# the user can create custom Cache store classes themselves.
|
138
|
+
@cache_backend[store] = name if @cache_backend.size < 50
|
139
|
+
|
140
|
+
name
|
141
|
+
end
|
142
|
+
|
143
|
+
# DEV: There are two possibly interesting fields in the `on_finish` payload:
|
144
|
+
# | `:hit` | If this read is a hit |
|
145
|
+
# | `:super_operation` | `:fetch` if a read is done with [`fetch`][ActiveSupport::Cache::Store#fetch] |
|
146
|
+
# @see https://github.com/rails/rails/blob/b9d6759401c3d50a51e0a7650cb2331f4218d11f/guides/source/active_support_instrumentation.md?plain=1#L528-L529
|
147
|
+
# def on_finish(span, event, id, payload)
|
148
|
+
# super
|
149
|
+
# end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'events/cache'
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module Tracing
|
7
|
+
module Contrib
|
8
|
+
module ActiveSupport
|
9
|
+
module Cache
|
10
|
+
# Defines collection of instrumented ActiveSupport events
|
11
|
+
module Events
|
12
|
+
ALL = [
|
13
|
+
Events::Cache,
|
14
|
+
].freeze
|
15
|
+
|
16
|
+
module_function
|
17
|
+
|
18
|
+
def all
|
19
|
+
self::ALL
|
20
|
+
end
|
21
|
+
|
22
|
+
def subscriptions
|
23
|
+
all.collect(&:subscriptions).collect(&:to_a).flatten
|
24
|
+
end
|
25
|
+
|
26
|
+
def subscribe!
|
27
|
+
all.each(&:subscribe!)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -9,7 +9,31 @@ module Datadog
|
|
9
9
|
module Contrib
|
10
10
|
module ActiveSupport
|
11
11
|
module Cache
|
12
|
-
#
|
12
|
+
# DEV-3.0: Backwards compatibility code for the 2.x gem series.
|
13
|
+
# DEV-3.0:
|
14
|
+
# DEV-3.0: `ActiveSupport::Cache` is now instrumented by subscribing to ActiveSupport::Notifications events.
|
15
|
+
# DEV-3.0: The implementation is located at {Datadog::Tracing::Contrib::ActiveSupport::Cache::Events::Cache}.
|
16
|
+
# DEV-3.0: The events emitted provide richer introspection points (e.g. events for cache misses on `#fetch`) while
|
17
|
+
# DEV-3.0: also ensuring we are using Rails' public API for improved compatibility.
|
18
|
+
# DEV-3.0:
|
19
|
+
# DEV-3.0: But a few operations holds us back:
|
20
|
+
# DEV-3.0: 1. `ActiveSupport::Cache::Store#fetch`:
|
21
|
+
# DEV-3.0: This method does not have an event that can produce an equivalent span to today's 2.x implementation.
|
22
|
+
# DEV-3.0: In 2.x, `#fetch` produces two separate, *nested* spans: one for the `#read` operation and
|
23
|
+
# DEV-3.0: another for the `#write` operation that is called internally by `#fetch` when the cache key needs
|
24
|
+
# DEV-3.0: to be populated on a cache miss.
|
25
|
+
# DEV-3.0: But the ActiveSupport events emitted by `#fetch` provide two *sibling* events for the`#read` and
|
26
|
+
# DEV-3.0: `#write` operations.
|
27
|
+
# DEV-3.0: Moving from nested spans to sibling spans would be a breaking change. One notable difference is
|
28
|
+
# DEV-3.0: that if the nested `#write` operation fails 2.x, the `#read` span is marked as an error. This would
|
29
|
+
# DEV-3.0: not be the case with sibling spans, and would be a very visible change.
|
30
|
+
# DEV-3.0: 2. `ActiveSupport::Cache::Store#read_multi` & `ActiveSupport::Cache::Store#fetch_multi`:
|
31
|
+
# DEV-3.0: ActiveSupport events were introduced in ActiveSupport 5.2.0 for these methods.
|
32
|
+
# DEV-3.0:
|
33
|
+
# DEV-3.0: At the end of the day, moving to ActiveSupport events is the better approach, but we have to retain
|
34
|
+
# DEV-3.0: this last few monkey patches (and all the supporting code) to avoid a breaking change for now.
|
35
|
+
#
|
36
|
+
# Defines the deprecate monkey-patch instrumentation for `ActiveSupport::Cache::Store#fetch`
|
13
37
|
module Instrumentation
|
14
38
|
module_function
|
15
39
|
|
@@ -43,6 +67,10 @@ module Datadog
|
|
43
67
|
# In most of the cases, `#fetch()` and `#read()` calls are nested.
|
44
68
|
# Instrument both does not add any value.
|
45
69
|
# This method checks if these two operations are nested.
|
70
|
+
#
|
71
|
+
# DEV-3.0: We should not have these checks in the 3.x series because ActiveSupport events provide more
|
72
|
+
# DEV-3.0: legible nested spans. While using ActiveSupport events, the nested spans actually provide meaningful
|
73
|
+
# DEV-3.0: information.
|
46
74
|
def nested_read?
|
47
75
|
current_span = Tracing.active_span
|
48
76
|
current_span && current_span.name == Ext::SPAN_CACHE && current_span.resource == Ext::RESOURCE_CACHE_GET
|
@@ -107,29 +135,20 @@ module Datadog
|
|
107
135
|
end
|
108
136
|
end
|
109
137
|
|
110
|
-
# Defines instrumentation for ActiveSupport cache
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
def read(*args, &block)
|
115
|
-
return super if Instrumentation.nested_read?
|
116
|
-
|
117
|
-
Instrumentation.trace(Ext::RESOURCE_CACHE_GET, dd_store_name, key: args[0]) { super }
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
# Defines instrumentation for ActiveSupport cache reading of multiple keys
|
138
|
+
# Defines the the legacy monkey-patching instrumentation for ActiveSupport cache read_multi
|
139
|
+
# DEV-3.0: ActiveSupport::Notifications events were introduced in ActiveSupport 5.2.0 for this method.
|
140
|
+
# DEV-3.0: As long as we support ActiveSupport < 5.2.0, we have to keep this method.
|
122
141
|
module ReadMulti
|
123
142
|
include InstanceMethods
|
124
143
|
|
125
|
-
def read_multi(*keys, &block)
|
144
|
+
def read_multi(*keys, **options, &block)
|
126
145
|
return super if Instrumentation.nested_multiread?
|
127
146
|
|
128
147
|
Instrumentation.trace(Ext::RESOURCE_CACHE_MGET, dd_store_name, multi_key: keys) { super }
|
129
148
|
end
|
130
149
|
end
|
131
150
|
|
132
|
-
# Defines instrumentation for ActiveSupport cache
|
151
|
+
# Defines the the legacy monkey-patching instrumentation for ActiveSupport cache fetch
|
133
152
|
module Fetch
|
134
153
|
include InstanceMethods
|
135
154
|
|
@@ -140,11 +159,13 @@ module Datadog
|
|
140
159
|
end
|
141
160
|
end
|
142
161
|
|
143
|
-
# Defines instrumentation for ActiveSupport cache
|
162
|
+
# Defines the the legacy monkey-patching instrumentation for ActiveSupport cache fetch_multi
|
163
|
+
# DEV-3.0: ActiveSupport::Notifications events were introduced in ActiveSupport 5.2.0 for this method.
|
164
|
+
# DEV-3.0: As long as we support ActiveSupport < 5.2.0, we have to keep this method.
|
144
165
|
module FetchMulti
|
145
166
|
include InstanceMethods
|
146
167
|
|
147
|
-
def fetch_multi(*args, &block)
|
168
|
+
def fetch_multi(*args, **options, &block)
|
148
169
|
return super if Instrumentation.nested_multiread?
|
149
170
|
|
150
171
|
keys = args[-1].instance_of?(Hash) ? args[0..-2] : args
|
@@ -152,30 +173,13 @@ module Datadog
|
|
152
173
|
end
|
153
174
|
end
|
154
175
|
|
155
|
-
#
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
end
|
163
|
-
|
164
|
-
# Defines instrumentation for ActiveSupport cache writing of multiple keys
|
165
|
-
module WriteMulti
|
166
|
-
include InstanceMethods
|
167
|
-
|
168
|
-
def write_multi(hash, options = nil)
|
169
|
-
Instrumentation.trace(Ext::RESOURCE_CACHE_MSET, dd_store_name, multi_key: hash.keys) { super }
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
# Defines instrumentation for ActiveSupport cache deleting
|
174
|
-
module Delete
|
175
|
-
include InstanceMethods
|
176
|
-
|
177
|
-
def delete(*args, &block)
|
178
|
-
Instrumentation.trace(Ext::RESOURCE_CACHE_DELETE, dd_store_name, key: args[0]) { super }
|
176
|
+
# Backports the payload[:store] key present since Rails 6.1:
|
177
|
+
# https://github.com/rails/rails/commit/6fa747f2946ee244b2aab0cd8c3c064f05d950a5
|
178
|
+
module Store
|
179
|
+
def instrument(operation, key, options = nil)
|
180
|
+
polyfill_options = options&.dup || {}
|
181
|
+
polyfill_options[:store] = self.class.name
|
182
|
+
super(operation, key, polyfill_options)
|
179
183
|
end
|
180
184
|
end
|
181
185
|
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative '../../patcher'
|
4
4
|
require_relative 'instrumentation'
|
5
|
+
require_relative 'events'
|
5
6
|
|
6
7
|
module Datadog
|
7
8
|
module Tracing
|
@@ -19,54 +20,30 @@ module Datadog
|
|
19
20
|
end
|
20
21
|
|
21
22
|
def patch
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
23
|
+
Events.subscribe!
|
24
|
+
|
25
|
+
# Backfill the `:store` key in the ActiveSupport event payload for older Rails.
|
26
|
+
if Integration.version < Gem::Version.new('6.1.0')
|
27
|
+
::ActiveSupport::Cache::Store.prepend(Cache::Instrumentation::Store)
|
28
|
+
end
|
29
|
+
|
30
|
+
# DEV-3.0: Backwards compatibility code for the 2.x gem series.
|
31
|
+
# DEV-3.0: See documentation at {Datadog::Tracing::Contrib::ActiveSupport::Cache::Instrumentation}
|
32
|
+
# DEV-3.0: for the complete information about this backwards compatibility code.
|
33
|
+
patch_legacy_cache_store
|
29
34
|
end
|
30
35
|
|
31
36
|
# This method is overwritten by
|
32
37
|
# `datadog/tracing/contrib/active_support/cache/redis.rb`
|
33
38
|
# with more complex behavior.
|
34
39
|
def cache_store_class(meth)
|
35
|
-
::ActiveSupport::Cache::Store
|
36
|
-
end
|
37
|
-
|
38
|
-
def patch_cache_store_read
|
39
|
-
cache_store_class(:read).prepend(Cache::Instrumentation::Read)
|
40
|
-
end
|
41
|
-
|
42
|
-
def patch_cache_store_read_multi
|
43
|
-
cache_store_class(:read_multi).prepend(Cache::Instrumentation::ReadMulti)
|
44
|
-
end
|
45
|
-
|
46
|
-
def patch_cache_store_fetch
|
47
|
-
cache_store_class(:fetch).prepend(Cache::Instrumentation::Fetch)
|
48
|
-
end
|
49
|
-
|
50
|
-
def patch_cache_store_fetch_multi
|
51
|
-
klass = cache_store_class(:fetch_multi)
|
52
|
-
return unless klass.public_method_defined?(:fetch_multi)
|
53
|
-
|
54
|
-
klass.prepend(Cache::Instrumentation::FetchMulti)
|
55
|
-
end
|
56
|
-
|
57
|
-
def patch_cache_store_write
|
58
|
-
cache_store_class(:write).prepend(Cache::Instrumentation::Write)
|
59
|
-
end
|
60
|
-
|
61
|
-
def patch_cache_store_write_multi
|
62
|
-
klass = cache_store_class(:write_multi)
|
63
|
-
return unless klass.public_method_defined?(:write_multi)
|
64
|
-
|
65
|
-
klass.prepend(Cache::Instrumentation::WriteMulti)
|
40
|
+
[::ActiveSupport::Cache::Store]
|
66
41
|
end
|
67
42
|
|
68
|
-
def
|
69
|
-
cache_store_class(:
|
43
|
+
def patch_legacy_cache_store
|
44
|
+
cache_store_class(:read_multi).each { |clazz| clazz.prepend(Cache::Instrumentation::ReadMulti) }
|
45
|
+
cache_store_class(:fetch).each { |clazz| clazz.prepend(Cache::Instrumentation::Fetch) }
|
46
|
+
cache_store_class(:fetch_multi).each { |clazz| clazz.prepend(Cache::Instrumentation::FetchMulti) }
|
70
47
|
end
|
71
48
|
end
|
72
49
|
end
|
@@ -30,7 +30,10 @@ module Datadog
|
|
30
30
|
|
31
31
|
def cache_store_class(meth)
|
32
32
|
if patch_redis?(meth)
|
33
|
-
::ActiveSupport::Cache::RedisStore
|
33
|
+
[::ActiveSupport::Cache::RedisStore, ::ActiveSupport::Cache::Store]
|
34
|
+
elsif Gem.loaded_specs['redis'] && defined?(::ActiveSupport::Cache::RedisCacheStore) \
|
35
|
+
&& ::ActiveSupport::Cache::RedisCacheStore.instance_methods(false).include?(meth)
|
36
|
+
[::ActiveSupport::Cache::RedisCacheStore, ::ActiveSupport::Cache::Store]
|
34
37
|
else
|
35
38
|
super
|
36
39
|
end
|
@@ -26,21 +26,25 @@ module Datadog
|
|
26
26
|
super
|
27
27
|
end
|
28
28
|
|
29
|
-
def subscription(span_name = nil,
|
29
|
+
def subscription(span_name = nil, span_options = nil, on_start: nil, on_finish: nil, trace: nil)
|
30
30
|
super(
|
31
31
|
span_name || self.span_name,
|
32
|
-
|
33
|
-
|
32
|
+
span_options || self.span_options,
|
33
|
+
on_start: on_start,
|
34
|
+
on_finish: on_finish,
|
35
|
+
trace: trace
|
34
36
|
)
|
35
37
|
end
|
36
38
|
|
37
|
-
def subscribe(pattern = nil, span_name = nil,
|
39
|
+
def subscribe(pattern = nil, span_name = nil, span_options = nil)
|
38
40
|
if supported?
|
39
41
|
super(
|
40
42
|
pattern || event_name,
|
41
43
|
span_name || self.span_name,
|
42
|
-
|
43
|
-
|
44
|
+
span_options || self.span_options,
|
45
|
+
on_start: method(:on_start),
|
46
|
+
on_finish: method(:on_finish),
|
47
|
+
trace: method(:trace?)
|
44
48
|
)
|
45
49
|
end
|
46
50
|
end
|
@@ -62,6 +66,25 @@ module Datadog
|
|
62
66
|
payload[:exception_object] ||
|
63
67
|
payload[:exception] # Fallback for ActiveSupport < 5.0
|
64
68
|
end
|
69
|
+
|
70
|
+
def on_start(_span, _event, _id, _payload); end
|
71
|
+
|
72
|
+
def on_finish(span, _event, _id, payload)
|
73
|
+
record_exception(span, payload)
|
74
|
+
end
|
75
|
+
|
76
|
+
def trace?(_event, _payload)
|
77
|
+
true
|
78
|
+
end
|
79
|
+
|
80
|
+
def record_exception(span, payload)
|
81
|
+
if payload[:exception_object]
|
82
|
+
span.set_error(payload[:exception_object])
|
83
|
+
elsif payload[:exception]
|
84
|
+
# Fallback for ActiveSupport < 5.0
|
85
|
+
span.set_error(payload[:exception])
|
86
|
+
end
|
87
|
+
end
|
65
88
|
end
|
66
89
|
end
|
67
90
|
end
|
@@ -45,16 +45,28 @@ module Datadog
|
|
45
45
|
end
|
46
46
|
|
47
47
|
# Creates a subscription and immediately activates it.
|
48
|
-
def subscribe(pattern, span_name,
|
49
|
-
subscription(
|
48
|
+
def subscribe(pattern, span_name, span_options = {}, on_start: nil, on_finish: nil, trace: nil)
|
49
|
+
subscription(
|
50
|
+
span_name,
|
51
|
+
span_options,
|
52
|
+
on_start: on_start,
|
53
|
+
on_finish: on_finish,
|
54
|
+
trace: trace
|
55
|
+
).tap do |subscription|
|
50
56
|
subscription.subscribe(pattern)
|
51
57
|
end
|
52
58
|
end
|
53
59
|
|
54
60
|
# Creates a subscription without activating it.
|
55
61
|
# Subscription is added to the inheriting class' list of subscriptions.
|
56
|
-
def subscription(span_name,
|
57
|
-
Subscription.new(
|
62
|
+
def subscription(span_name, span_options = {}, on_start: nil, on_finish: nil, trace: nil)
|
63
|
+
Subscription.new(
|
64
|
+
span_name,
|
65
|
+
span_options,
|
66
|
+
on_start: on_start,
|
67
|
+
on_finish: on_finish,
|
68
|
+
trace: trace
|
69
|
+
).tap do |subscription|
|
58
70
|
subscriptions << subscription
|
59
71
|
end
|
60
72
|
end
|
@@ -9,31 +9,34 @@ module Datadog
|
|
9
9
|
class Subscription
|
10
10
|
attr_accessor \
|
11
11
|
:span_name,
|
12
|
-
:
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
:span_options
|
13
|
+
|
14
|
+
# @param span_name [String] the operation name for the span
|
15
|
+
# @param span_options [Hash] span_options to pass during span creation
|
16
|
+
# @param on_start [Proc] a block to run when the event is fired,
|
17
|
+
# might not include all required information in the `payload` argument.
|
18
|
+
# @param on_finish [Proc] a block to run when the event has finished processing,
|
19
|
+
# possibly including more information in the `payload` argument.
|
20
|
+
# @param trace [Proc] whether to trace the event. Defaults to returning `true`.
|
21
|
+
def initialize(span_name, span_options, on_start: nil, on_finish: nil, trace: nil)
|
22
|
+
raise ArgumentError, 'Must be given either on_start or on_finish' unless on_start || on_finish
|
16
23
|
|
17
24
|
@span_name = span_name
|
18
|
-
@
|
19
|
-
@
|
25
|
+
@span_options = span_options
|
26
|
+
@on_start = Handler.new(on_start)
|
27
|
+
@on_finish = Handler.new(on_finish)
|
28
|
+
@trace = trace
|
20
29
|
@callbacks = Callbacks.new
|
21
30
|
end
|
22
31
|
|
23
|
-
# ActiveSupport
|
24
|
-
def call(name, start, finish, id, payload)
|
25
|
-
start_span(name, id, payload, start)
|
26
|
-
finish_span(name, id, payload, finish)
|
27
|
-
end
|
28
|
-
|
29
|
-
# ActiveSupport 4+ calls this on start
|
32
|
+
# Called by ActiveSupport on event start
|
30
33
|
def start(name, id, payload)
|
31
|
-
start_span(name, id, payload)
|
34
|
+
start_span(name, id, payload) if @trace&.call(name, payload)
|
32
35
|
end
|
33
36
|
|
34
|
-
#
|
37
|
+
# Called by ActiveSupport on event finish
|
35
38
|
def finish(name, id, payload)
|
36
|
-
finish_span(name, id, payload)
|
39
|
+
finish_span(name, id, payload) if payload[:datadog_span]
|
37
40
|
end
|
38
41
|
|
39
42
|
def before_trace(&block)
|
@@ -69,7 +72,8 @@ module Datadog
|
|
69
72
|
protected
|
70
73
|
|
71
74
|
attr_reader \
|
72
|
-
:
|
75
|
+
:on_start,
|
76
|
+
:on_finish,
|
73
77
|
:callbacks
|
74
78
|
|
75
79
|
def start_span(name, id, payload, start = nil)
|
@@ -77,11 +81,15 @@ module Datadog
|
|
77
81
|
callbacks.run(name, :before_trace, id, payload, start)
|
78
82
|
|
79
83
|
# Start a trace
|
80
|
-
Tracing.trace(@span_name, **@
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
84
|
+
span = Tracing.trace(@span_name, **@span_options)
|
85
|
+
|
86
|
+
# Start span if time is provided
|
87
|
+
span.start(start) unless start.nil?
|
88
|
+
payload[:datadog_span] = span
|
89
|
+
|
90
|
+
on_start.run(span, name, id, payload)
|
91
|
+
|
92
|
+
span
|
85
93
|
end
|
86
94
|
|
87
95
|
def finish_span(name, id, payload, finish = nil)
|
@@ -90,7 +98,7 @@ module Datadog
|
|
90
98
|
return nil if span.nil?
|
91
99
|
|
92
100
|
# Run handler for event
|
93
|
-
|
101
|
+
on_finish.run(span, name, id, payload)
|
94
102
|
|
95
103
|
# Finish the span
|
96
104
|
span.finish(finish)
|
@@ -109,21 +117,17 @@ module Datadog
|
|
109
117
|
class Handler
|
110
118
|
attr_reader :block
|
111
119
|
|
112
|
-
def initialize(
|
120
|
+
def initialize(block)
|
113
121
|
@block = block
|
114
122
|
end
|
115
123
|
|
116
124
|
def run(span, name, id, payload)
|
117
|
-
|
125
|
+
@block.call(span, name, id, payload) if @block
|
118
126
|
rescue StandardError => e
|
119
127
|
Datadog.logger.debug(
|
120
128
|
"ActiveSupport::Notifications handler for '#{name}' failed: #{e.class.name} #{e.message}"
|
121
129
|
)
|
122
130
|
end
|
123
|
-
|
124
|
-
def run!(*args)
|
125
|
-
@block.call(*args)
|
126
|
-
end
|
127
131
|
end
|
128
132
|
|
129
133
|
# Wrapper for subscription callbacks
|
@@ -9,6 +9,11 @@ module Datadog
|
|
9
9
|
module Analytics
|
10
10
|
module_function
|
11
11
|
|
12
|
+
# Applies Analytics sampling rate, if applicable for this Contrib::Configuration.
|
13
|
+
def set_rate!(span, configuration)
|
14
|
+
set_sample_rate(span, configuration[:analytics_sample_rate]) if enabled?(configuration[:analytics_enabled])
|
15
|
+
end
|
16
|
+
|
12
17
|
# Checks whether analytics should be enabled.
|
13
18
|
# `flag` is a truthy/falsey value that represents a setting on the integration.
|
14
19
|
def enabled?(flag = nil)
|
@@ -7,7 +7,21 @@ module Datadog
|
|
7
7
|
module Ext
|
8
8
|
# @public_api
|
9
9
|
module DB
|
10
|
+
# Name of the database. This is *not* the database hostname.
|
11
|
+
#
|
12
|
+
# For databases which support such a concept, the default schema/database/namespace
|
13
|
+
# as configured in the connection string.
|
14
|
+
#
|
15
|
+
# If the tracer is already tracking changes to the default schema/database throughout the lifetime of
|
16
|
+
# the session (i.e. the client executes USE {NEW_SCHEMA} and now the default schema has changed from what
|
17
|
+
# was set upon connection initialization), then ideally this attribute reflects the “current” value.
|
18
|
+
# If the tracer is not already tracking changes then just leaving it to the default value set upon
|
19
|
+
# initialization is OK.
|
20
|
+
#
|
21
|
+
# This is the equivalent of OTel’s `db.namespace`
|
22
|
+
# @see https://opentelemetry.io/docs/specs/semconv/database/database-spans/#common-attributes
|
10
23
|
TAG_INSTANCE = 'db.instance'
|
24
|
+
|
11
25
|
TAG_USER = 'db.user'
|
12
26
|
TAG_SYSTEM = 'db.system'
|
13
27
|
TAG_STATEMENT = 'db.statement'
|