datadog 2.8.0 → 2.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +36 -1
- data/ext/datadog_profiling_native_extension/clock_id.h +2 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +64 -54
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +1 -1
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +16 -16
- data/ext/datadog_profiling_native_extension/collectors_stack.c +7 -7
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +219 -122
- data/ext/datadog_profiling_native_extension/heap_recorder.h +1 -1
- data/ext/datadog_profiling_native_extension/http_transport.c +4 -4
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +3 -0
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +3 -1
- data/ext/datadog_profiling_native_extension/profiling.c +10 -8
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +8 -8
- data/ext/datadog_profiling_native_extension/stack_recorder.c +54 -54
- data/ext/datadog_profiling_native_extension/stack_recorder.h +1 -1
- data/ext/datadog_profiling_native_extension/time_helpers.h +1 -1
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +47 -0
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +31 -0
- data/ext/libdatadog_api/crashtracker.c +3 -0
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +355 -157
- data/lib/datadog/appsec/assets/waf_rules/strict.json +62 -32
- data/lib/datadog/appsec/context.rb +54 -0
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +7 -7
- data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +6 -6
- data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +4 -4
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +19 -28
- data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +5 -5
- data/lib/datadog/appsec/contrib/rack/gateway/response.rb +3 -3
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +64 -96
- data/lib/datadog/appsec/contrib/rack/reactive/request.rb +10 -10
- data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +5 -5
- data/lib/datadog/appsec/contrib/rack/reactive/response.rb +6 -6
- data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +10 -11
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +43 -49
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +21 -32
- data/lib/datadog/appsec/contrib/rails/patcher.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/reactive/action.rb +6 -6
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +41 -63
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +2 -2
- data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +5 -5
- data/lib/datadog/appsec/event.rb +6 -6
- data/lib/datadog/appsec/ext.rb +3 -1
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +22 -32
- data/lib/datadog/appsec/monitor/reactive/set_user.rb +5 -5
- data/lib/datadog/appsec/processor/rule_loader.rb +0 -3
- data/lib/datadog/appsec.rb +3 -3
- data/lib/datadog/auto_instrument.rb +3 -0
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +39 -11
- data/lib/datadog/core/configuration/components.rb +4 -2
- data/lib/datadog/core/configuration.rb +1 -1
- data/lib/datadog/{tracing → core}/contrib/rails/utils.rb +1 -3
- data/lib/datadog/core/crashtracking/component.rb +1 -3
- data/lib/datadog/core/telemetry/event.rb +87 -3
- data/lib/datadog/core/telemetry/logging.rb +2 -2
- data/lib/datadog/core/telemetry/metric.rb +22 -0
- data/lib/datadog/core/telemetry/worker.rb +33 -0
- data/lib/datadog/di/base.rb +115 -0
- data/lib/datadog/di/code_tracker.rb +7 -4
- data/lib/datadog/di/component.rb +17 -11
- data/lib/datadog/di/configuration/settings.rb +11 -1
- data/lib/datadog/di/contrib/railtie.rb +15 -0
- data/lib/datadog/di/contrib.rb +26 -0
- data/lib/datadog/di/error.rb +5 -0
- data/lib/datadog/di/instrumenter.rb +39 -18
- data/lib/datadog/di/{init.rb → preload.rb} +2 -4
- data/lib/datadog/di/probe_manager.rb +4 -4
- data/lib/datadog/di/probe_notification_builder.rb +16 -2
- data/lib/datadog/di/probe_notifier_worker.rb +5 -6
- data/lib/datadog/di/remote.rb +4 -4
- data/lib/datadog/di/transport.rb +2 -4
- data/lib/datadog/di.rb +5 -108
- data/lib/datadog/kit/appsec/events.rb +3 -3
- data/lib/datadog/kit/identity.rb +4 -4
- data/lib/datadog/profiling/component.rb +55 -53
- data/lib/datadog/profiling/http_transport.rb +1 -26
- data/lib/datadog/tracing/contrib/action_cable/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/action_mailer/integration.rb +6 -2
- data/lib/datadog/tracing/contrib/action_pack/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/action_view/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/active_job/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/active_record/integration.rb +6 -2
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +3 -1
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +3 -1
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +10 -0
- data/lib/datadog/tracing/contrib/active_support/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/auto_instrument.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/httprb/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/kafka/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/mongodb/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/opensearch/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/presto/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/rack/integration.rb +2 -2
- data/lib/datadog/tracing/contrib/rails/framework.rb +2 -2
- data/lib/datadog/tracing/contrib/rails/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/rest_client/integration.rb +3 -0
- data/lib/datadog/tracing/span.rb +12 -4
- data/lib/datadog/tracing/span_event.rb +123 -3
- data/lib/datadog/tracing/span_operation.rb +6 -0
- data/lib/datadog/tracing/transport/serializable_trace.rb +24 -6
- data/lib/datadog/version.rb +1 -1
- metadata +19 -10
- data/lib/datadog/appsec/reactive/operation.rb +0 -68
- data/lib/datadog/appsec/scope.rb +0 -58
- data/lib/datadog/core/crashtracking/agent_base_url.rb +0 -21
@@ -4,7 +4,7 @@ require_relative 'configuration/settings'
|
|
4
4
|
require_relative 'patcher'
|
5
5
|
require_relative '../integration'
|
6
6
|
require_relative '../rails/ext'
|
7
|
-
require_relative '
|
7
|
+
require_relative '../../../core/contrib/rails/utils'
|
8
8
|
|
9
9
|
module Datadog
|
10
10
|
module Tracing
|
@@ -18,6 +18,9 @@ module Datadog
|
|
18
18
|
|
19
19
|
# @public_api Changing the integration name or integration options can cause breaking changes
|
20
20
|
register_as :action_view, auto_patch: false
|
21
|
+
def self.gem_name
|
22
|
+
'actionview'
|
23
|
+
end
|
21
24
|
|
22
25
|
def self.version
|
23
26
|
# ActionView is its own gem in Rails 4.1+
|
@@ -41,7 +44,7 @@ module Datadog
|
|
41
44
|
# enabled by rails integration so should only auto instrument
|
42
45
|
# if detected that it is being used without rails
|
43
46
|
def auto_instrument?
|
44
|
-
!Contrib::Rails::Utils.railtie_supported?
|
47
|
+
!Core::Contrib::Rails::Utils.railtie_supported?
|
45
48
|
end
|
46
49
|
|
47
50
|
def new_configuration
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require_relative 'configuration/settings'
|
4
4
|
require_relative 'patcher'
|
5
5
|
require_relative '../integration'
|
6
|
-
require_relative '
|
6
|
+
require_relative '../../../core/contrib/rails/utils'
|
7
7
|
|
8
8
|
module Datadog
|
9
9
|
module Tracing
|
@@ -17,6 +17,9 @@ module Datadog
|
|
17
17
|
|
18
18
|
# @public_api Changing the integration name or integration options can cause breaking changes
|
19
19
|
register_as :active_job, auto_patch: false
|
20
|
+
def self.gem_name
|
21
|
+
'activejob'
|
22
|
+
end
|
20
23
|
|
21
24
|
def self.version
|
22
25
|
Gem.loaded_specs['activejob'] && Gem.loaded_specs['activejob'].version
|
@@ -33,7 +36,7 @@ module Datadog
|
|
33
36
|
# enabled by rails integration so should only auto instrument
|
34
37
|
# if detected that it is being used without rails
|
35
38
|
def auto_instrument?
|
36
|
-
!Contrib::Rails::Utils.railtie_supported?
|
39
|
+
!Core::Contrib::Rails::Utils.railtie_supported?
|
37
40
|
end
|
38
41
|
|
39
42
|
def new_configuration
|
@@ -7,7 +7,7 @@ require_relative 'patcher'
|
|
7
7
|
require_relative '../component'
|
8
8
|
require_relative '../integration'
|
9
9
|
require_relative '../rails/ext'
|
10
|
-
require_relative '
|
10
|
+
require_relative '../../../core/contrib/rails/utils'
|
11
11
|
|
12
12
|
module Datadog
|
13
13
|
module Tracing
|
@@ -22,6 +22,10 @@ module Datadog
|
|
22
22
|
# @public_api Changing the integration name or integration options can cause breaking changes
|
23
23
|
register_as :active_record, auto_patch: false
|
24
24
|
|
25
|
+
def self.gem_name
|
26
|
+
'activerecord'
|
27
|
+
end
|
28
|
+
|
25
29
|
def self.version
|
26
30
|
Gem.loaded_specs['activerecord'] && Gem.loaded_specs['activerecord'].version
|
27
31
|
end
|
@@ -37,7 +41,7 @@ module Datadog
|
|
37
41
|
# enabled by rails integration so should only auto instrument
|
38
42
|
# if detected that it is being used without rails
|
39
43
|
def auto_instrument?
|
40
|
-
!Contrib::Rails::Utils.railtie_supported?
|
44
|
+
!Core::Contrib::Rails::Utils.railtie_supported?
|
41
45
|
end
|
42
46
|
|
43
47
|
def new_configuration
|
@@ -81,7 +81,9 @@ module Datadog
|
|
81
81
|
|
82
82
|
span.set_tag('EVENT', event)
|
83
83
|
|
84
|
-
|
84
|
+
if Datadog.configuration.tracing[:active_support][:cache_key].enabled
|
85
|
+
set_cache_key(span, key, mapping[:multi_key])
|
86
|
+
end
|
85
87
|
rescue StandardError => e
|
86
88
|
Datadog.logger.error(e.message)
|
87
89
|
Datadog::Core::Telemetry::Logger.report(e)
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require_relative '../../../../core/utils'
|
4
4
|
require_relative '../../../metadata/ext'
|
5
5
|
require_relative '../ext'
|
6
|
+
require_relative 'event'
|
6
7
|
|
7
8
|
module Datadog
|
8
9
|
module Tracing
|
@@ -58,7 +59,8 @@ module Datadog
|
|
58
59
|
end
|
59
60
|
|
60
61
|
span.set_tag(Ext::TAG_CACHE_BACKEND, store) if store
|
61
|
-
|
62
|
+
|
63
|
+
set_cache_key(span, key, multi_key) if Datadog.configuration.tracing[:active_support][:cache_key].enabled
|
62
64
|
|
63
65
|
yield
|
64
66
|
end
|
@@ -39,6 +39,16 @@ module Datadog
|
|
39
39
|
)
|
40
40
|
end
|
41
41
|
end
|
42
|
+
|
43
|
+
# grouped "cache_key.*" settings
|
44
|
+
settings :cache_key do
|
45
|
+
# enable or disabling the inclusion of the cache_key in the span
|
46
|
+
option :enabled do |o|
|
47
|
+
# cache_key.enabled
|
48
|
+
o.type :bool
|
49
|
+
o.default true
|
50
|
+
end
|
51
|
+
end
|
42
52
|
end
|
43
53
|
end
|
44
54
|
end
|
@@ -5,7 +5,7 @@ require_relative 'configuration/settings'
|
|
5
5
|
require_relative 'patcher'
|
6
6
|
require_relative 'cache/redis'
|
7
7
|
require_relative '../rails/ext'
|
8
|
-
require_relative '
|
8
|
+
require_relative '../../../core/contrib/rails/utils'
|
9
9
|
|
10
10
|
module Datadog
|
11
11
|
module Tracing
|
@@ -19,6 +19,9 @@ module Datadog
|
|
19
19
|
|
20
20
|
# @public_api Changing the integration name or integration options can cause breaking changes
|
21
21
|
register_as :active_support, auto_patch: false
|
22
|
+
def self.gem_name
|
23
|
+
'activesupport'
|
24
|
+
end
|
22
25
|
|
23
26
|
def self.version
|
24
27
|
Gem.loaded_specs['activesupport'] && Gem.loaded_specs['activesupport'].version
|
@@ -35,7 +38,7 @@ module Datadog
|
|
35
38
|
# enabled by rails integration so should only auto instrument
|
36
39
|
# if detected that it is being used without rails
|
37
40
|
def auto_instrument?
|
38
|
-
!Contrib::Rails::Utils.railtie_supported?
|
41
|
+
!Core::Contrib::Rails::Utils.railtie_supported?
|
39
42
|
end
|
40
43
|
|
41
44
|
def new_configuration
|
@@ -9,10 +9,10 @@ module Datadog
|
|
9
9
|
module Contrib
|
10
10
|
# Auto-activate instrumentation
|
11
11
|
def self.auto_instrument!
|
12
|
-
require_relative 'rails/utils'
|
12
|
+
require_relative '../../core/contrib/rails/utils'
|
13
13
|
|
14
14
|
# Defer to Rails if this is a Rails application
|
15
|
-
if Datadog::
|
15
|
+
if Datadog::Core::Contrib::Rails::Utils.railtie_supported?
|
16
16
|
require_relative 'rails/auto_instrument_railtie'
|
17
17
|
else
|
18
18
|
AutoInstrument.patch_all!
|
@@ -16,6 +16,9 @@ module Datadog
|
|
16
16
|
|
17
17
|
# @public_api Changing the integration name or integration options can cause breaking changes
|
18
18
|
register_as :concurrent_ruby
|
19
|
+
def self.gem_name
|
20
|
+
'concurrent-ruby'
|
21
|
+
end
|
19
22
|
|
20
23
|
def self.version
|
21
24
|
Gem.loaded_specs['concurrent-ruby'] && Gem.loaded_specs['concurrent-ruby'].version
|
@@ -17,6 +17,9 @@ module Datadog
|
|
17
17
|
|
18
18
|
# @public_api Changing the integration name or integration options can cause breaking changes
|
19
19
|
register_as :httprb
|
20
|
+
def self.gem_name
|
21
|
+
'http'
|
22
|
+
end
|
20
23
|
|
21
24
|
def self.version
|
22
25
|
Gem.loaded_specs['http'] && Gem.loaded_specs['http'].version
|
@@ -16,6 +16,9 @@ module Datadog
|
|
16
16
|
|
17
17
|
# @public_api Changing the integration name or integration options can cause breaking changes
|
18
18
|
register_as :kafka, auto_patch: false
|
19
|
+
def self.gem_name
|
20
|
+
'ruby-kafka'
|
21
|
+
end
|
19
22
|
|
20
23
|
def self.version
|
21
24
|
Gem.loaded_specs['ruby-kafka'] && Gem.loaded_specs['ruby-kafka'].version
|
@@ -17,6 +17,9 @@ module Datadog
|
|
17
17
|
|
18
18
|
# @public_api Changing the integration name or integration options can cause breaking changes
|
19
19
|
register_as :mongo, auto_patch: true
|
20
|
+
def self.gem_name
|
21
|
+
'mongo'
|
22
|
+
end
|
20
23
|
|
21
24
|
def self.version
|
22
25
|
Gem.loaded_specs['mongo'] && Gem.loaded_specs['mongo'].version
|
@@ -16,6 +16,9 @@ module Datadog
|
|
16
16
|
|
17
17
|
# @public_api Changing the integration name or integration options can cause breaking changes
|
18
18
|
register_as :opensearch, auto_patch: true
|
19
|
+
def self.gem_name
|
20
|
+
'opensearch-ruby'
|
21
|
+
end
|
19
22
|
|
20
23
|
def self.version
|
21
24
|
Gem.loaded_specs['opensearch-ruby'] \
|
@@ -16,6 +16,9 @@ module Datadog
|
|
16
16
|
|
17
17
|
# @public_api Changing the integration name or integration options can cause breaking changes
|
18
18
|
register_as :presto
|
19
|
+
def self.gem_name
|
20
|
+
'presto-client'
|
21
|
+
end
|
19
22
|
|
20
23
|
def self.version
|
21
24
|
Gem.loaded_specs['presto-client'] && Gem.loaded_specs['presto-client'].version
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require_relative '../integration'
|
4
4
|
require_relative 'configuration/settings'
|
5
5
|
require_relative 'patcher'
|
6
|
-
require_relative '
|
6
|
+
require_relative '../../../core/contrib/rails/utils'
|
7
7
|
|
8
8
|
module Datadog
|
9
9
|
module Tracing
|
@@ -33,7 +33,7 @@ module Datadog
|
|
33
33
|
# enabled by rails integration so should only auto instrument
|
34
34
|
# if detected that it is being used without rails
|
35
35
|
def auto_instrument?
|
36
|
-
!Contrib::Rails::Utils.railtie_supported?
|
36
|
+
!Core::Contrib::Rails::Utils.railtie_supported?
|
37
37
|
end
|
38
38
|
|
39
39
|
def new_configuration
|
@@ -9,7 +9,7 @@ require_relative '../active_support/integration'
|
|
9
9
|
require_relative '../grape/endpoint'
|
10
10
|
require_relative '../lograge/integration'
|
11
11
|
require_relative 'ext'
|
12
|
-
require_relative 'utils'
|
12
|
+
require_relative '../../../core/contrib/rails/utils'
|
13
13
|
require_relative '../semantic_logger/integration'
|
14
14
|
|
15
15
|
module Datadog
|
@@ -41,7 +41,7 @@ module Datadog
|
|
41
41
|
# being executed, but here we know better, get it from Rails config.
|
42
42
|
# Don't set this if service has been explicitly provided by the user.
|
43
43
|
if datadog_config.service_without_fallback.nil?
|
44
|
-
datadog_config.service = rails_config[:service_name] || Utils.app_name
|
44
|
+
datadog_config.service = rails_config[:service_name] || Core::Contrib::Rails::Utils.app_name
|
45
45
|
end
|
46
46
|
|
47
47
|
activate_rack!(datadog_config, rails_config)
|
@@ -6,7 +6,7 @@ require_relative 'framework'
|
|
6
6
|
require_relative 'log_injection'
|
7
7
|
require_relative 'middlewares'
|
8
8
|
require_relative 'runner'
|
9
|
-
require_relative 'utils'
|
9
|
+
require_relative '../../../core/contrib/rails/utils'
|
10
10
|
require_relative '../semantic_logger/patcher'
|
11
11
|
|
12
12
|
module Datadog
|
@@ -16,6 +16,9 @@ module Datadog
|
|
16
16
|
|
17
17
|
# @public_api Changing the integration name or integration options can cause breaking changes
|
18
18
|
register_as :rest_client
|
19
|
+
def self.gem_name
|
20
|
+
'rest-client'
|
21
|
+
end
|
19
22
|
|
20
23
|
def self.version
|
21
24
|
Gem.loaded_specs['rest-client'] && Gem.loaded_specs['rest-client'].version
|
data/lib/datadog/tracing/span.rb
CHANGED
@@ -112,7 +112,10 @@ module Datadog
|
|
112
112
|
|
113
113
|
def duration
|
114
114
|
return @duration if @duration
|
115
|
-
|
115
|
+
|
116
|
+
start_time = @start_time
|
117
|
+
end_time = @end_time
|
118
|
+
end_time - start_time if start_time && end_time
|
116
119
|
end
|
117
120
|
|
118
121
|
def set_error(e)
|
@@ -135,6 +138,8 @@ module Datadog
|
|
135
138
|
# TODO: Change this to reflect attributes when serialization
|
136
139
|
# isn't handled by this method.
|
137
140
|
def to_hash
|
141
|
+
@meta['events'] = @events.map(&:to_hash).to_json unless @events.empty?
|
142
|
+
|
138
143
|
h = {
|
139
144
|
error: @status,
|
140
145
|
meta: @meta,
|
@@ -154,8 +159,6 @@ module Datadog
|
|
154
159
|
h[:duration] = duration_nano
|
155
160
|
end
|
156
161
|
|
157
|
-
h[:meta]['events'] = @events.map(&:to_hash).to_json unless @events.empty?
|
158
|
-
|
159
162
|
h
|
160
163
|
end
|
161
164
|
|
@@ -196,12 +199,17 @@ module Datadog
|
|
196
199
|
# Used for serialization
|
197
200
|
# @return [Integer] in nanoseconds since Epoch
|
198
201
|
def start_time_nano
|
199
|
-
|
202
|
+
return unless (start_time = @start_time)
|
203
|
+
|
204
|
+
start_time.to_i * 1000000000 + start_time.nsec
|
200
205
|
end
|
201
206
|
|
202
207
|
# Used for serialization
|
203
208
|
# @return [Integer] in nanoseconds since Epoch
|
204
209
|
def duration_nano
|
210
|
+
duration = self.duration
|
211
|
+
return unless duration
|
212
|
+
|
205
213
|
(duration * 1e9).to_i
|
206
214
|
end
|
207
215
|
|
@@ -19,23 +19,143 @@ module Datadog
|
|
19
19
|
# @return [Integer]
|
20
20
|
attr_reader :time_unix_nano
|
21
21
|
|
22
|
+
# TODO: Accept {Time} as the time_unix_nano parameter, possibly in addition to the current nano integer.
|
22
23
|
def initialize(
|
23
24
|
name,
|
24
25
|
attributes: nil,
|
25
26
|
time_unix_nano: nil
|
26
27
|
)
|
27
28
|
@name = name
|
28
|
-
|
29
|
+
|
30
|
+
@attributes = attributes.dup || {}
|
31
|
+
validate_attributes!(@attributes)
|
32
|
+
@attributes.transform_keys!(&:to_s)
|
33
|
+
|
29
34
|
# OpenTelemetry SDK stores span event timestamps in nanoseconds (not seconds).
|
30
35
|
# We will do the same here to avoid unnecessary conversions and inconsistencies.
|
31
36
|
@time_unix_nano = time_unix_nano || (Time.now.to_r * 1_000_000_000).to_i
|
32
37
|
end
|
33
38
|
|
39
|
+
# Converts the span event into a hash to be used by with the span tag serialization
|
40
|
+
# (`span.set_tag('events) = [event.to_hash]`). This serialization format has the drawback
|
41
|
+
# of being limiting span events to the size limit of a span tag.
|
42
|
+
# All Datadog agents support this format.
|
34
43
|
def to_hash
|
35
|
-
h = { name
|
36
|
-
h[
|
44
|
+
h = { 'name' => @name, 'time_unix_nano' => @time_unix_nano }
|
45
|
+
h['attributes'] = @attributes unless @attributes.empty?
|
46
|
+
h
|
47
|
+
end
|
48
|
+
|
49
|
+
# Converts the span event into a hash to be used by the MessagePack serialization as a
|
50
|
+
# top-level span field (span.span_events = [event.to_native_format]).
|
51
|
+
# This serialization format removes the serialization limitations of the `span.set_tag('events)` approach,
|
52
|
+
# but is only supported by newer version of the Datadog agent.
|
53
|
+
def to_native_format
|
54
|
+
h = { 'name' => @name, 'time_unix_nano' => @time_unix_nano }
|
55
|
+
|
56
|
+
attr = {}
|
57
|
+
@attributes.each do |key, value|
|
58
|
+
attr[key] = if value.is_a?(Array)
|
59
|
+
{ type: ARRAY_TYPE, array_value: value.map { |v| serialize_native_attribute(v) } }
|
60
|
+
else
|
61
|
+
serialize_native_attribute(value)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
h['attributes'] = attr unless @attributes.empty?
|
66
|
+
|
37
67
|
h
|
38
68
|
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
MIN_INT64_SIGNED = -2**63
|
73
|
+
MAX_INT64_SIGNED = 2 << 63 - 1
|
74
|
+
|
75
|
+
# Checks the attributes hash to ensure it only contains serializable values.
|
76
|
+
# Invalid values are removed from the hash.
|
77
|
+
def validate_attributes!(attributes)
|
78
|
+
attributes.select! do |key, value|
|
79
|
+
case value
|
80
|
+
when Array
|
81
|
+
next true if value.empty?
|
82
|
+
|
83
|
+
first = value.first
|
84
|
+
case first
|
85
|
+
when String, Integer, Float
|
86
|
+
first_type = first.class
|
87
|
+
if value.all? { |v| v.is_a?(first_type) }
|
88
|
+
value.all? { |v| validate_scalar_attribute!(key, v) }
|
89
|
+
else
|
90
|
+
Datadog.logger.warn("Attribute #{key} array must be homogenous: #{value}.")
|
91
|
+
false
|
92
|
+
end
|
93
|
+
when TrueClass, FalseClass
|
94
|
+
if value.all? { |v| v.is_a?(TrueClass) || v.is_a?(FalseClass) }
|
95
|
+
value.all? { |v| validate_scalar_attribute!(key, v) }
|
96
|
+
else
|
97
|
+
Datadog.logger.warn("Attribute #{key} array must be homogenous: #{value}.")
|
98
|
+
false
|
99
|
+
end
|
100
|
+
else
|
101
|
+
Datadog.logger.warn("Attribute #{key} must be a string, number, or boolean: #{value}.")
|
102
|
+
false
|
103
|
+
end
|
104
|
+
when String, Numeric, TrueClass, FalseClass
|
105
|
+
validate_scalar_attribute!(key, value)
|
106
|
+
else
|
107
|
+
Datadog.logger.warn("Attribute #{key} must be a string, number, boolean, or array: #{value}.")
|
108
|
+
false
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def validate_scalar_attribute!(key, value)
|
114
|
+
case value
|
115
|
+
when String, TrueClass, FalseClass
|
116
|
+
true
|
117
|
+
when Integer
|
118
|
+
# Cannot be larger than signed 64-bit integer
|
119
|
+
if value < MIN_INT64_SIGNED || value > MAX_INT64_SIGNED
|
120
|
+
Datadog.logger.warn("Attribute #{key} must be within the range of a signed 64-bit integer: #{value}.")
|
121
|
+
false
|
122
|
+
else
|
123
|
+
true
|
124
|
+
end
|
125
|
+
when Float
|
126
|
+
# Has to be finite
|
127
|
+
return true if value.finite?
|
128
|
+
|
129
|
+
Datadog.logger.warn("Attribute #{key} must be a finite number: #{value}.")
|
130
|
+
false
|
131
|
+
else
|
132
|
+
Datadog.logger.warn("Attribute #{key} must be a string, number, or boolean: #{value}.")
|
133
|
+
false
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
STRING_TYPE = 0
|
138
|
+
BOOLEAN_TYPE = 1
|
139
|
+
INTEGER_TYPE = 2
|
140
|
+
DOUBLE_TYPE = 3
|
141
|
+
ARRAY_TYPE = 4
|
142
|
+
|
143
|
+
# Serializes individual scalar attributes into the native format.
|
144
|
+
def serialize_native_attribute(value)
|
145
|
+
case value
|
146
|
+
when String
|
147
|
+
{ type: STRING_TYPE, string_value: value }
|
148
|
+
when TrueClass, FalseClass
|
149
|
+
{ type: BOOLEAN_TYPE, bool_value: value }
|
150
|
+
when Integer
|
151
|
+
{ type: INTEGER_TYPE, int_value: value }
|
152
|
+
when Float
|
153
|
+
{ type: DOUBLE_TYPE, double_value: value }
|
154
|
+
else
|
155
|
+
# This is technically unreachable due to the validation in #initialize.
|
156
|
+
raise ArgumentError, "Attribute must be a string, number, or boolean: #{value}."
|
157
|
+
end
|
158
|
+
end
|
39
159
|
end
|
40
160
|
end
|
41
161
|
end
|
@@ -11,6 +11,8 @@ require_relative 'event'
|
|
11
11
|
require_relative 'metadata'
|
12
12
|
require_relative 'metadata/ext'
|
13
13
|
require_relative 'span'
|
14
|
+
require_relative 'span_event'
|
15
|
+
require_relative 'span_link'
|
14
16
|
require_relative 'utils'
|
15
17
|
|
16
18
|
module Datadog
|
@@ -197,6 +199,9 @@ module Datadog
|
|
197
199
|
end
|
198
200
|
|
199
201
|
# Mark the span stopped at the current time
|
202
|
+
#
|
203
|
+
# steep:ignore:start
|
204
|
+
# Steep issue fixed in https://github.com/soutaro/steep/pull/1467
|
200
205
|
def stop(stop_time = nil)
|
201
206
|
# A span should not be stopped twice. Note that this is not thread-safe,
|
202
207
|
# stop is called from multiple threads, a given span might be stopped
|
@@ -219,6 +224,7 @@ module Datadog
|
|
219
224
|
|
220
225
|
self
|
221
226
|
end
|
227
|
+
# steep:ignore:end
|
222
228
|
|
223
229
|
# Return whether the duration is started or not
|
224
230
|
def started?
|
@@ -12,8 +12,11 @@ module Datadog
|
|
12
12
|
attr_reader \
|
13
13
|
:trace
|
14
14
|
|
15
|
-
|
15
|
+
# @param trace [Datadog::Trace] the trace to serialize
|
16
|
+
# @param native_events_supported [Boolean] whether the agent supports span events as a top-level field
|
17
|
+
def initialize(trace, native_events_supported = false)
|
16
18
|
@trace = trace
|
19
|
+
@native_events_supported = native_events_supported
|
17
20
|
end
|
18
21
|
|
19
22
|
# MessagePack serializer interface. Making this object
|
@@ -26,13 +29,13 @@ module Datadog
|
|
26
29
|
# @param packer [MessagePack::Packer] serialization buffer, can be +nil+ with JRuby
|
27
30
|
def to_msgpack(packer = nil)
|
28
31
|
# As of 1.3.3, JRuby implementation doesn't pass an existing packer
|
29
|
-
trace.spans.map { |s| SerializableSpan.new(s) }.to_msgpack(packer)
|
32
|
+
trace.spans.map { |s| SerializableSpan.new(s, @native_events_supported) }.to_msgpack(packer)
|
30
33
|
end
|
31
34
|
|
32
35
|
# JSON serializer interface.
|
33
36
|
# Used by older version of the transport.
|
34
37
|
def to_json(*args)
|
35
|
-
trace.spans.map { |s| SerializableSpan.new(s).to_hash }.to_json(*args)
|
38
|
+
trace.spans.map { |s| SerializableSpan.new(s, @native_events_supported).to_hash }.to_json(*args)
|
36
39
|
end
|
37
40
|
end
|
38
41
|
|
@@ -41,9 +44,12 @@ module Datadog
|
|
41
44
|
attr_reader \
|
42
45
|
:span
|
43
46
|
|
44
|
-
|
47
|
+
# @param span [Datadog::Span] the span to serialize
|
48
|
+
# @param native_events_supported [Boolean] whether the agent supports span events as a top-level field
|
49
|
+
def initialize(span, native_events_supported)
|
45
50
|
@span = span
|
46
51
|
@trace_id = Tracing::Utils::TraceId.to_low_order(span.trace_id)
|
52
|
+
@native_events_supported = native_events_supported
|
47
53
|
end
|
48
54
|
|
49
55
|
# MessagePack serializer interface. Making this object
|
@@ -55,11 +61,14 @@ module Datadog
|
|
55
61
|
#
|
56
62
|
# @param packer [MessagePack::Packer] serialization buffer, can be +nil+ with JRuby
|
57
63
|
# rubocop:disable Metrics/AbcSize
|
64
|
+
# rubocop:disable Metrics/MethodLength
|
58
65
|
def to_msgpack(packer = nil)
|
59
66
|
packer ||= MessagePack::Packer.new
|
60
67
|
|
61
68
|
number_of_elements_to_write = 11
|
62
69
|
|
70
|
+
number_of_elements_to_write += 1 if span.events.any? && @native_events_supported
|
71
|
+
|
63
72
|
if span.stopped?
|
64
73
|
packer.write_map_header(number_of_elements_to_write + 2) # Set header with how many elements in the map
|
65
74
|
|
@@ -72,8 +81,16 @@ module Datadog
|
|
72
81
|
packer.write_map_header(number_of_elements_to_write) # Set header with how many elements in the map
|
73
82
|
end
|
74
83
|
|
75
|
-
|
76
|
-
|
84
|
+
if span.events.any?
|
85
|
+
if @native_events_supported
|
86
|
+
# Use top-level field for native events
|
87
|
+
packer.write('span_events')
|
88
|
+
packer.write(span.events.map(&:to_native_format))
|
89
|
+
else
|
90
|
+
# Serialize span events as meta tags
|
91
|
+
span.set_tag('events', span.events.map(&:to_hash).to_json)
|
92
|
+
end
|
93
|
+
end
|
77
94
|
|
78
95
|
# DEV: We use strings as keys here, instead of symbols, as
|
79
96
|
# DEV: MessagePack will ultimately convert them to strings.
|
@@ -103,6 +120,7 @@ module Datadog
|
|
103
120
|
packer
|
104
121
|
end
|
105
122
|
# rubocop:enable Metrics/AbcSize
|
123
|
+
# rubocop:enable Metrics/MethodLength
|
106
124
|
|
107
125
|
# JSON serializer interface.
|
108
126
|
# Used by older version of the transport.
|