datadog 2.1.0 → 2.2.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 +53 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +19 -1
- data/ext/datadog_profiling_native_extension/collectors_stack.c +41 -0
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +1 -1
- data/ext/datadog_profiling_native_extension/crashtracker.c +1 -1
- data/ext/datadog_profiling_native_extension/extconf.rb +6 -4
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +47 -1
- data/ext/datadog_profiling_native_extension/setup_signal_handler.c +1 -1
- data/ext/datadog_profiling_native_extension/stack_recorder.c +13 -6
- data/ext/datadog_profiling_native_extension/stack_recorder.h +1 -0
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +1 -1
- data/lib/datadog/appsec/extensions.rb +1 -0
- data/lib/datadog/core/configuration/components.rb +6 -3
- data/lib/datadog/core/configuration/settings.rb +39 -0
- data/lib/datadog/core/configuration.rb +3 -17
- data/lib/datadog/core/deprecations.rb +58 -0
- 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 +107 -0
- data/lib/datadog/core/telemetry/event.rb +100 -25
- data/lib/datadog/core/telemetry/ext.rb +2 -0
- data/lib/datadog/core/telemetry/http/adapters/net.rb +1 -1
- 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/only_once_successful.rb +76 -0
- data/lib/datadog/core.rb +2 -19
- data/lib/datadog/opentelemetry/sdk/propagator.rb +5 -10
- data/lib/datadog/opentelemetry/sdk/span_processor.rb +5 -2
- data/lib/datadog/profiling/collectors/code_provenance.rb +18 -5
- data/lib/datadog/profiling/component.rb +18 -1
- data/lib/datadog/profiling/ext/dir_monkey_patches.rb +410 -0
- data/lib/datadog/profiling.rb +1 -0
- 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 +1 -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/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 +25 -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/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/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/span_operation.rb +3 -2
- 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.rb +5 -1
- data/lib/datadog/version.rb +2 -2
- metadata +22 -9
- data/lib/datadog/core/telemetry/client.rb +0 -95
- data/lib/datadog/core/telemetry/heartbeat.rb +0 -33
@@ -4,6 +4,7 @@ require_relative '../analytics'
|
|
4
4
|
require_relative '../patcher'
|
5
5
|
require_relative 'tracing_patcher'
|
6
6
|
require_relative 'trace_patcher'
|
7
|
+
require_relative 'unified_trace_patcher'
|
7
8
|
|
8
9
|
module Datadog
|
9
10
|
module Tracing
|
@@ -23,10 +24,15 @@ module Datadog
|
|
23
24
|
if configuration[:with_deprecated_tracer]
|
24
25
|
TracingPatcher.patch!(schemas, trace_options)
|
25
26
|
elsif Integration.trace_supported?
|
26
|
-
|
27
|
+
if configuration[:with_unified_tracer]
|
28
|
+
UnifiedTracePatcher.patch!(schemas, trace_options)
|
29
|
+
else
|
30
|
+
TracePatcher.patch!(schemas, trace_options)
|
31
|
+
end
|
27
32
|
else
|
28
33
|
Datadog.logger.warn(
|
29
|
-
"GraphQL version (#{target_version}) does not support GraphQL::Tracing::DataDogTrace
|
34
|
+
"GraphQL version (#{target_version}) does not support GraphQL::Tracing::DataDogTrace"\
|
35
|
+
'or Datadog::Tracing::Contrib::GraphQL::UnifiedTrace.'\
|
30
36
|
'Falling back to GraphQL::Tracing::DataDogTracing.'
|
31
37
|
)
|
32
38
|
TracingPatcher.patch!(schemas, trace_options)
|
@@ -0,0 +1,166 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'graphql/tracing'
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module Tracing
|
7
|
+
module Contrib
|
8
|
+
module GraphQL
|
9
|
+
# These methods will be called by the GraphQL runtime to trace the execution of queries.
|
10
|
+
# This tracer differs from the upstream one as it follows the unified naming convention specification,
|
11
|
+
# which is required to use features such as API Catalog.
|
12
|
+
# DEV-3.0: This tracer should be the default one in the next major version.
|
13
|
+
module UnifiedTrace
|
14
|
+
# @param analytics_enabled [Boolean] Deprecated
|
15
|
+
# @param analytics_sample_rate [Float] Deprecated
|
16
|
+
# @param service [String|nil] The service name to be set on the spans
|
17
|
+
def initialize(*args, analytics_enabled: false, analytics_sample_rate: 1.0, service: nil, **kwargs)
|
18
|
+
@analytics_enabled = analytics_enabled
|
19
|
+
@analytics_sample_rate = analytics_sample_rate
|
20
|
+
|
21
|
+
@service_name = service
|
22
|
+
@has_prepare_span = respond_to?(:prepare_span)
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
def lex(*args, query_string:, **kwargs)
|
27
|
+
trace(proc { super }, 'lex', query_string, query_string: query_string)
|
28
|
+
end
|
29
|
+
|
30
|
+
def parse(*args, query_string:, **kwargs)
|
31
|
+
trace(proc { super }, 'parse', query_string, query_string: query_string) do |span|
|
32
|
+
span.set_tag('graphql.source', query_string)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def validate(*args, query:, validate:, **kwargs)
|
37
|
+
trace(proc { super }, 'validate', query.selected_operation_name, query: query, validate: validate) do |span|
|
38
|
+
span.set_tag('graphql.source', query.query_string)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def analyze_multiplex(*args, multiplex:, **kwargs)
|
43
|
+
trace(proc { super }, 'analyze_multiplex', multiplex_resource(multiplex), multiplex: multiplex)
|
44
|
+
end
|
45
|
+
|
46
|
+
def analyze_query(*args, query:, **kwargs)
|
47
|
+
trace(proc { super }, 'analyze', query.query_string, query: query)
|
48
|
+
end
|
49
|
+
|
50
|
+
def execute_multiplex(*args, multiplex:, **kwargs)
|
51
|
+
trace(proc { super }, 'execute_multiplex', multiplex_resource(multiplex), multiplex: multiplex) do |span|
|
52
|
+
span.set_tag('graphql.source', "Multiplex[#{multiplex.queries.map(&:query_string).join(', ')}]")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def execute_query(*args, query:, **kwargs)
|
57
|
+
trace(proc { super }, 'execute', query.selected_operation_name, query: query) do |span|
|
58
|
+
span.set_tag('graphql.source', query.query_string)
|
59
|
+
span.set_tag('graphql.operation.type', query.selected_operation.operation_type)
|
60
|
+
span.set_tag('graphql.operation.name', query.selected_operation_name) if query.selected_operation_name
|
61
|
+
query.variables.instance_variable_get(:@storage).each do |key, value|
|
62
|
+
span.set_tag("graphql.variables.#{key}", value)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def execute_query_lazy(*args, query:, multiplex:, **kwargs)
|
68
|
+
resource = if query
|
69
|
+
query.selected_operation_name || fallback_transaction_name(query.context)
|
70
|
+
else
|
71
|
+
multiplex_resource(multiplex)
|
72
|
+
end
|
73
|
+
trace(proc { super }, 'execute_lazy', resource, query: query, multiplex: multiplex)
|
74
|
+
end
|
75
|
+
|
76
|
+
def execute_field_span(callable, span_key, **kwargs)
|
77
|
+
# @platform_key_cache is initialized upstream, in ::GraphQL::Tracing::PlatformTrace
|
78
|
+
platform_key = @platform_key_cache[UnifiedTrace].platform_field_key_cache[kwargs[:field]]
|
79
|
+
|
80
|
+
if platform_key
|
81
|
+
trace(callable, span_key, platform_key, **kwargs) do |span|
|
82
|
+
kwargs[:arguments].each do |key, value|
|
83
|
+
span.set_tag("graphql.variables.#{key}", value)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
else
|
87
|
+
callable.call
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def execute_field(*args, **kwargs)
|
92
|
+
execute_field_span(proc { super }, 'resolve', **kwargs)
|
93
|
+
end
|
94
|
+
|
95
|
+
def execute_field_lazy(*args, **kwargs)
|
96
|
+
execute_field_span(proc { super }, 'resolve_lazy', **kwargs)
|
97
|
+
end
|
98
|
+
|
99
|
+
def authorized_span(callable, span_key, **kwargs)
|
100
|
+
platform_key = @platform_key_cache[UnifiedTrace].platform_authorized_key_cache[kwargs[:type]]
|
101
|
+
trace(callable, span_key, platform_key, **kwargs)
|
102
|
+
end
|
103
|
+
|
104
|
+
def authorized(*args, **kwargs)
|
105
|
+
authorized_span(proc { super }, 'authorized', **kwargs)
|
106
|
+
end
|
107
|
+
|
108
|
+
def authorized_lazy(*args, **kwargs)
|
109
|
+
authorized_span(proc { super }, 'authorized_lazy', **kwargs)
|
110
|
+
end
|
111
|
+
|
112
|
+
def resolve_type_span(callable, span_key, **kwargs)
|
113
|
+
platform_key = @platform_key_cache[UnifiedTrace].platform_resolve_type_key_cache[kwargs[:type]]
|
114
|
+
trace(callable, span_key, platform_key, **kwargs)
|
115
|
+
end
|
116
|
+
|
117
|
+
def resolve_type(*args, **kwargs)
|
118
|
+
resolve_type_span(proc { super }, 'resolve_type', **kwargs)
|
119
|
+
end
|
120
|
+
|
121
|
+
def resolve_type_lazy(*args, **kwargs)
|
122
|
+
resolve_type_span(proc { super }, 'resolve_type_lazy', **kwargs)
|
123
|
+
end
|
124
|
+
|
125
|
+
include ::GraphQL::Tracing::PlatformTrace
|
126
|
+
|
127
|
+
def platform_field_key(field, *args, **kwargs)
|
128
|
+
field.path
|
129
|
+
end
|
130
|
+
|
131
|
+
def platform_authorized_key(type, *args, **kwargs)
|
132
|
+
"#{type.graphql_name}.authorized"
|
133
|
+
end
|
134
|
+
|
135
|
+
def platform_resolve_type_key(type, *args, **kwargs)
|
136
|
+
"#{type.graphql_name}.resolve_type"
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
|
141
|
+
def trace(callable, trace_key, resource, **kwargs)
|
142
|
+
Tracing.trace("graphql.#{trace_key}", resource: resource, service: @service_name, type: 'graphql') do |span|
|
143
|
+
yield(span) if block_given?
|
144
|
+
|
145
|
+
prepare_span(trace_key, kwargs, span) if @has_prepare_span
|
146
|
+
|
147
|
+
callable.call
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def multiplex_resource(multiplex)
|
152
|
+
return nil unless multiplex
|
153
|
+
|
154
|
+
operations = multiplex.queries.map(&:selected_operation_name).compact.join(', ')
|
155
|
+
if operations.empty?
|
156
|
+
first_query = multiplex.queries.first
|
157
|
+
fallback_transaction_name(first_query && first_query.context)
|
158
|
+
else
|
159
|
+
operations
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module Tracing
|
5
|
+
module Contrib
|
6
|
+
module GraphQL
|
7
|
+
# Provides instrumentation for `graphql` through the GraphQL's tracing with methods defined in UnifiedTrace
|
8
|
+
module UnifiedTracePatcher
|
9
|
+
module_function
|
10
|
+
|
11
|
+
def patch!(schemas, options)
|
12
|
+
require_relative 'unified_trace'
|
13
|
+
if schemas.empty?
|
14
|
+
::GraphQL::Schema.trace_with(UnifiedTrace, **options)
|
15
|
+
else
|
16
|
+
schemas.each do |schema|
|
17
|
+
schema.trace_with(UnifiedTrace, **options)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -29,7 +29,7 @@ module Datadog
|
|
29
29
|
Datadog.configuration.tracing[:kafka]
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
32
|
+
def on_start(span, _event, _id, payload)
|
33
33
|
span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
|
34
34
|
span.set_tag(Contrib::Ext::Messaging::TAG_SYSTEM, Ext::TAG_MESSAGING_SYSTEM)
|
35
35
|
|
@@ -15,7 +15,9 @@ module Datadog
|
|
15
15
|
|
16
16
|
EVENT_NAME = 'request.connection.kafka'
|
17
17
|
|
18
|
-
|
18
|
+
module_function
|
19
|
+
|
20
|
+
def on_start(span, _event, _id, payload)
|
19
21
|
super
|
20
22
|
|
21
23
|
span.resource = payload[:api]
|
@@ -24,8 +26,6 @@ module Datadog
|
|
24
26
|
span.set_tag(Ext::TAG_RESPONSE_SIZE, payload[:response_size]) if payload.key?(:response_size)
|
25
27
|
end
|
26
28
|
|
27
|
-
module_function
|
28
|
-
|
29
29
|
def span_name
|
30
30
|
Ext::SPAN_CONNECTION_REQUEST
|
31
31
|
end
|
@@ -17,7 +17,9 @@ module Datadog
|
|
17
17
|
|
18
18
|
EVENT_NAME = 'process_batch.consumer.kafka'
|
19
19
|
|
20
|
-
|
20
|
+
module_function
|
21
|
+
|
22
|
+
def on_start(span, _event, _id, payload)
|
21
23
|
super
|
22
24
|
|
23
25
|
span.resource = payload[:topic]
|
@@ -31,8 +33,6 @@ module Datadog
|
|
31
33
|
span.set_tag(Ext::TAG_OFFSET_LAG, payload[:offset_lag]) if payload.key?(:offset_lag)
|
32
34
|
end
|
33
35
|
|
34
|
-
module_function
|
35
|
-
|
36
36
|
def span_name
|
37
37
|
Ext::SPAN_PROCESS_BATCH
|
38
38
|
end
|
@@ -17,7 +17,9 @@ module Datadog
|
|
17
17
|
|
18
18
|
EVENT_NAME = 'process_message.consumer.kafka'
|
19
19
|
|
20
|
-
|
20
|
+
module_function
|
21
|
+
|
22
|
+
def on_start(span, _event, _id, payload)
|
21
23
|
super
|
22
24
|
|
23
25
|
span.resource = payload[:topic]
|
@@ -29,8 +31,6 @@ module Datadog
|
|
29
31
|
span.set_tag(Ext::TAG_OFFSET_LAG, payload[:offset_lag]) if payload.key?(:offset_lag)
|
30
32
|
end
|
31
33
|
|
32
|
-
module_function
|
33
|
-
|
34
34
|
def span_name
|
35
35
|
Ext::SPAN_PROCESS_MESSAGE
|
36
36
|
end
|
@@ -19,7 +19,9 @@ module Datadog
|
|
19
19
|
|
20
20
|
EVENT_NAME = 'heartbeat.consumer.kafka'
|
21
21
|
|
22
|
-
|
22
|
+
module_function
|
23
|
+
|
24
|
+
def on_start(span, _event, _id, payload)
|
23
25
|
super
|
24
26
|
|
25
27
|
if payload.key?(:topic_partitions)
|
@@ -29,8 +31,6 @@ module Datadog
|
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
32
|
-
module_function
|
33
|
-
|
34
34
|
def span_name
|
35
35
|
Ext::SPAN_CONSUMER_HEARTBEAT
|
36
36
|
end
|
@@ -15,7 +15,9 @@ module Datadog
|
|
15
15
|
|
16
16
|
EVENT_NAME = 'send_messages.producer.kafka'
|
17
17
|
|
18
|
-
|
18
|
+
module_function
|
19
|
+
|
20
|
+
def on_start(span, _event, _id, payload)
|
19
21
|
super
|
20
22
|
|
21
23
|
span.set_tag(Ext::TAG_MESSAGE_COUNT, payload[:message_count]) if payload.key?(:message_count)
|
@@ -23,8 +25,6 @@ module Datadog
|
|
23
25
|
span.set_tag(Tracing::Metadata::Ext::TAG_KIND, Tracing::Metadata::Ext::SpanKind::TAG_PRODUCER)
|
24
26
|
end
|
25
27
|
|
26
|
-
module_function
|
27
|
-
|
28
28
|
def span_name
|
29
29
|
Ext::SPAN_SEND_MESSAGES
|
30
30
|
end
|
@@ -15,7 +15,9 @@ module Datadog
|
|
15
15
|
|
16
16
|
EVENT_NAME = 'deliver_messages.producer.kafka'
|
17
17
|
|
18
|
-
|
18
|
+
module_function
|
19
|
+
|
20
|
+
def on_start(span, _event, _id, payload)
|
19
21
|
super
|
20
22
|
|
21
23
|
span.set_tag(Ext::TAG_ATTEMPTS, payload[:attempts]) if payload.key?(:attempts)
|
@@ -26,8 +28,6 @@ module Datadog
|
|
26
28
|
span.set_tag(Tracing::Metadata::Ext::TAG_KIND, Tracing::Metadata::Ext::SpanKind::TAG_PRODUCER)
|
27
29
|
end
|
28
30
|
|
29
|
-
module_function
|
30
|
-
|
31
31
|
def span_name
|
32
32
|
Ext::SPAN_DELIVER_MESSAGES
|
33
33
|
end
|
@@ -19,7 +19,7 @@ module Datadog
|
|
19
19
|
# Class methods for Racecar events.
|
20
20
|
# Note, they share the same process method and before_trace method.
|
21
21
|
module ClassMethods
|
22
|
-
def subscription(*args)
|
22
|
+
def subscription(*args, **kwargs)
|
23
23
|
super.tap do |subscription|
|
24
24
|
subscription.before_trace { ensure_clean_context! }
|
25
25
|
end
|
@@ -33,7 +33,7 @@ module Datadog
|
|
33
33
|
Datadog.configuration.tracing[:racecar]
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
36
|
+
def on_start(span, event, _id, payload)
|
37
37
|
span.service = configuration[:service_name]
|
38
38
|
span.resource = payload[:consumer_class]
|
39
39
|
|
@@ -14,6 +14,15 @@ module Datadog
|
|
14
14
|
ENV_ANALYTICS_SAMPLE_RATE = 'DD_TRACE_RAILS_ANALYTICS_SAMPLE_RATE'
|
15
15
|
ENV_DISABLE = 'DISABLE_DATADOG_RAILS'
|
16
16
|
|
17
|
+
SPAN_RUNNER_FILE = 'rails.runner.file'
|
18
|
+
SPAN_RUNNER_INLINE = 'rails.runner.inline'
|
19
|
+
SPAN_RUNNER_STDIN = 'rails.runner.stdin'
|
20
|
+
TAG_COMPONENT = 'rails'
|
21
|
+
TAG_OPERATION_FILE = 'runner.file'
|
22
|
+
TAG_OPERATION_INLINE = 'runner.inline'
|
23
|
+
TAG_OPERATION_STDIN = 'runner.stdin'
|
24
|
+
TAG_RUNNER_SOURCE = 'source'
|
25
|
+
|
17
26
|
# @!visibility private
|
18
27
|
MINIMUM_VERSION = Gem::Version.new('4')
|
19
28
|
end
|
@@ -5,6 +5,7 @@ require_relative '../rack/middlewares'
|
|
5
5
|
require_relative 'framework'
|
6
6
|
require_relative 'log_injection'
|
7
7
|
require_relative 'middlewares'
|
8
|
+
require_relative 'runner'
|
8
9
|
require_relative 'utils'
|
9
10
|
require_relative '../semantic_logger/patcher'
|
10
11
|
|
@@ -28,6 +29,7 @@ module Datadog
|
|
28
29
|
def patch
|
29
30
|
patch_before_initialize
|
30
31
|
patch_after_initialize
|
32
|
+
patch_rails_runner
|
31
33
|
end
|
32
34
|
|
33
35
|
def patch_before_initialize
|
@@ -81,6 +83,11 @@ module Datadog
|
|
81
83
|
def setup_tracer
|
82
84
|
Contrib::Rails::Framework.setup
|
83
85
|
end
|
86
|
+
|
87
|
+
# Instruments the `bin/rails runner` command.
|
88
|
+
def patch_rails_runner
|
89
|
+
::Rails::Command.singleton_class.prepend(Command) if defined?(::Rails::Command)
|
90
|
+
end
|
84
91
|
end
|
85
92
|
end
|
86
93
|
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module Tracing
|
5
|
+
module Contrib
|
6
|
+
module Rails
|
7
|
+
# Instruments the `bin/rails runner` command.
|
8
|
+
# This command executes the provided code with the host Rails application loaded.
|
9
|
+
# The command can be either:
|
10
|
+
# * `-`: for code provided through the STDIN.
|
11
|
+
# * File path: for code provided through a local file.
|
12
|
+
# * `inline code`: for code provided directly as a command line argument.
|
13
|
+
# @see https://guides.rubyonrails.org/v6.1/command_line.html#bin-rails-runner
|
14
|
+
module Runner
|
15
|
+
# Limit the maximum size of the source code captured in the source tag.
|
16
|
+
MAX_TAG_VALUE_SIZE = 4096
|
17
|
+
private_constant :MAX_TAG_VALUE_SIZE
|
18
|
+
|
19
|
+
def runner(code_or_file = nil, *_command_argv)
|
20
|
+
if code_or_file == '-'
|
21
|
+
name = Ext::SPAN_RUNNER_STDIN
|
22
|
+
resource = nil
|
23
|
+
operation = Ext::TAG_OPERATION_STDIN
|
24
|
+
# The source is not yet available for STDIN, but it will be captured in `eval`.
|
25
|
+
elsif File.exist?(code_or_file)
|
26
|
+
name = Ext::SPAN_RUNNER_FILE
|
27
|
+
resource = code_or_file
|
28
|
+
operation = Ext::TAG_OPERATION_FILE
|
29
|
+
source = File.read(code_or_file)
|
30
|
+
else
|
31
|
+
name = Ext::SPAN_RUNNER_INLINE
|
32
|
+
resource = nil
|
33
|
+
operation = Ext::TAG_OPERATION_INLINE
|
34
|
+
source = code_or_file
|
35
|
+
end
|
36
|
+
|
37
|
+
Tracing.trace(
|
38
|
+
name,
|
39
|
+
service: Datadog.configuration.tracing[:rails][:service_name],
|
40
|
+
resource: resource,
|
41
|
+
tags: {
|
42
|
+
Tracing::Metadata::Ext::TAG_COMPONENT => Ext::TAG_COMPONENT,
|
43
|
+
Tracing::Metadata::Ext::TAG_OPERATION => operation,
|
44
|
+
}
|
45
|
+
) do |span|
|
46
|
+
if source
|
47
|
+
span.set_tag(
|
48
|
+
Ext::TAG_RUNNER_SOURCE,
|
49
|
+
Core::Utils.truncate(source, MAX_TAG_VALUE_SIZE)
|
50
|
+
)
|
51
|
+
end
|
52
|
+
Contrib::Analytics.set_rate!(span, Datadog.configuration.tracing[:rails])
|
53
|
+
|
54
|
+
super
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Capture the executed source code when provided from STDIN.
|
59
|
+
def eval(*args)
|
60
|
+
span = Datadog::Tracing.active_span
|
61
|
+
if span.name == Ext::SPAN_RUNNER_STDIN
|
62
|
+
source = args[0]
|
63
|
+
span.set_tag(
|
64
|
+
Ext::TAG_RUNNER_SOURCE,
|
65
|
+
Core::Utils.truncate(source, MAX_TAG_VALUE_SIZE)
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
super
|
70
|
+
end
|
71
|
+
|
72
|
+
ruby2_keywords :eval if respond_to?(:ruby2_keywords, true)
|
73
|
+
end
|
74
|
+
|
75
|
+
# The instrumentation target, {Rails::Command::RunnerCommand} is only loaded
|
76
|
+
# right before `bin/rails runner` is executed. This means there's not much
|
77
|
+
# opportunity to patch it ahead of time.
|
78
|
+
# To ensure we can patch it successfully, we patch it's caller, {Rails::Command}
|
79
|
+
# and promptly patch {Rails::Command::RunnerCommand} when it is loaded.
|
80
|
+
module Command
|
81
|
+
def find_by_namespace(*args)
|
82
|
+
ret = super
|
83
|
+
# Patch RunnerCommand if it is loaded and not already patched.
|
84
|
+
if defined?(::Rails::Command::RunnerCommand) && !(::Rails::Command::RunnerCommand < Runner)
|
85
|
+
::Rails::Command::RunnerCommand.prepend(Runner)
|
86
|
+
end
|
87
|
+
ret
|
88
|
+
end
|
89
|
+
|
90
|
+
ruby2_keywords :find_by_namespace if respond_to?(:ruby2_keywords, true)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -31,7 +31,7 @@ module Datadog
|
|
31
31
|
|
32
32
|
# DEV: We need these to be hex encoded
|
33
33
|
data[@trace_id_key] = format('%032x', digest.trace_id)
|
34
|
-
data[@span_id_key] = format('%016x', digest.span_id)
|
34
|
+
data[@span_id_key] = format('%016x', digest.span_id || 0) # # Fall back to zero (invalid) if not present
|
35
35
|
|
36
36
|
if digest.trace_sampling_priority
|
37
37
|
sampling_priority = Helpers.clamp_sampling_priority(
|
@@ -25,8 +25,10 @@ module Datadog
|
|
25
25
|
def inject!(digest, env)
|
26
26
|
return if digest.nil?
|
27
27
|
|
28
|
+
span_id = digest.span_id || 0 # Fall back to zero (invalid) if not present
|
29
|
+
|
28
30
|
# DEV: We need these to be hex encoded
|
29
|
-
value = "#{format('%032x', digest.trace_id)}-#{format('%016x',
|
31
|
+
value = "#{format('%032x', digest.trace_id)}-#{format('%016x', span_id)}"
|
30
32
|
|
31
33
|
if digest.trace_sampling_priority
|
32
34
|
sampling_priority = Helpers.clamp_sampling_priority(
|
@@ -42,7 +42,7 @@ module Datadog
|
|
42
42
|
|
43
43
|
data[@trace_id_key] = Tracing::Utils::TraceId.to_low_order(digest.trace_id).to_s
|
44
44
|
|
45
|
-
data[@parent_id_key] = digest.span_id.to_s
|
45
|
+
data[@parent_id_key] = digest.span_id.to_s if digest.span_id
|
46
46
|
data[@sampling_priority_key] = digest.trace_sampling_priority.to_s if digest.trace_sampling_priority
|
47
47
|
data[@origin_key] = digest.trace_origin.to_s if digest.trace_origin
|
48
48
|
|
@@ -109,7 +109,7 @@ module Datadog
|
|
109
109
|
|
110
110
|
return tags if high_order == 0
|
111
111
|
|
112
|
-
tags.merge(Tracing::Metadata::Ext::Distributed::TAG_TID => high_order
|
112
|
+
tags.merge(Tracing::Metadata::Ext::Distributed::TAG_TID => format('%016x', high_order))
|
113
113
|
end
|
114
114
|
|
115
115
|
# Side effect: Remove high order 64 bit hex-encoded `tid` tag from distributed tags
|
@@ -32,7 +32,9 @@ module Datadog
|
|
32
32
|
|
33
33
|
# inject! populates the env with span ID, trace ID and sampling priority
|
34
34
|
#
|
35
|
-
# This method will never raise errors
|
35
|
+
# This method will never raise errors.
|
36
|
+
# It can propagate partial data, if deemed useful, instead of failing.
|
37
|
+
# In case of unrecoverable errors, it will log them to `Datadog.logger`.
|
36
38
|
#
|
37
39
|
# DEV-2.0: inject! should work without arguments, injecting the active_trace's digest
|
38
40
|
# DEV-2.0: and returning a new Hash with the injected data.
|
@@ -45,7 +47,7 @@ module Datadog
|
|
45
47
|
# @param digest [TraceDigest]
|
46
48
|
# @param data [Hash]
|
47
49
|
# @return [Boolean] `true` if injected successfully, `false` if no propagation style is configured
|
48
|
-
# @return [nil] in case of
|
50
|
+
# @return [nil] in case of unrecoverable errors, see `Datadog.logger` output for details.
|
49
51
|
def inject!(digest, data)
|
50
52
|
if digest.nil?
|
51
53
|
::Datadog.logger.debug('Cannot inject distributed trace data: digest is nil.')
|
@@ -54,6 +56,11 @@ module Datadog
|
|
54
56
|
|
55
57
|
digest = digest.to_digest if digest.respond_to?(:to_digest)
|
56
58
|
|
59
|
+
if digest.trace_id.nil?
|
60
|
+
::Datadog.logger.debug('Cannot inject distributed trace data: digest.trace_id is nil.')
|
61
|
+
return nil
|
62
|
+
end
|
63
|
+
|
57
64
|
result = false
|
58
65
|
|
59
66
|
# Inject all configured propagation styles
|
@@ -107,7 +107,7 @@ module Datadog
|
|
107
107
|
def build_traceparent(digest)
|
108
108
|
build_traceparent_string(
|
109
109
|
digest.trace_id,
|
110
|
-
digest.span_id,
|
110
|
+
digest.span_id || 0, # Fall back to zero (invalid) if not present
|
111
111
|
build_trace_flags(digest)
|
112
112
|
)
|
113
113
|
end
|
@@ -198,7 +198,8 @@ module Datadog
|
|
198
198
|
|
199
199
|
def last_dd_parent_id(digest)
|
200
200
|
if !digest.span_remote
|
201
|
-
|
201
|
+
span_id = digest.span_id || 0 # Fall back to zero (invalid) if not present
|
202
|
+
"p:#{format('%016x', span_id)};"
|
202
203
|
elsif digest.trace_distributed_tags&.key?(Tracing::Metadata::Ext::Distributed::TAG_DD_PARENT_ID)
|
203
204
|
"p:#{digest.trace_distributed_tags[Tracing::Metadata::Ext::Distributed::TAG_DD_PARENT_ID]};"
|
204
205
|
else
|
@@ -48,7 +48,8 @@ module Datadog
|
|
48
48
|
tags: nil,
|
49
49
|
trace_id: nil,
|
50
50
|
type: nil,
|
51
|
-
links: nil
|
51
|
+
links: nil,
|
52
|
+
id: nil
|
52
53
|
)
|
53
54
|
# Ensure dynamically created strings are UTF-8 encoded.
|
54
55
|
#
|
@@ -60,7 +61,7 @@ module Datadog
|
|
60
61
|
self.type = type
|
61
62
|
self.resource = resource
|
62
63
|
|
63
|
-
@id = Tracing::Utils.next_id
|
64
|
+
@id = id.nil? ? Tracing::Utils.next_id : id
|
64
65
|
@parent_id = parent_id || 0
|
65
66
|
@trace_id = trace_id || Tracing::Utils::TraceId.next_id
|
66
67
|
|