ddtrace 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -16
- data/CHANGELOG.md +31 -2
- data/LICENSE-3rdparty.csv +3 -2
- data/README.md +2 -2
- data/ddtrace.gemspec +12 -3
- data/docs/GettingStarted.md +19 -2
- data/docs/ProfilingDevelopment.md +8 -8
- data/docs/UpgradeGuide.md +3 -3
- data/ext/ddtrace_profiling_loader/ddtrace_profiling_loader.c +118 -0
- data/ext/ddtrace_profiling_loader/extconf.rb +53 -0
- data/ext/ddtrace_profiling_native_extension/NativeExtensionDesign.md +31 -5
- data/ext/ddtrace_profiling_native_extension/clock_id_from_pthread.c +0 -8
- data/ext/ddtrace_profiling_native_extension/collectors_stack.c +278 -0
- data/ext/ddtrace_profiling_native_extension/extconf.rb +70 -100
- data/ext/ddtrace_profiling_native_extension/libddprof_helpers.h +13 -0
- data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +186 -0
- data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +579 -7
- data/ext/ddtrace_profiling_native_extension/private_vm_api_access.h +30 -0
- data/ext/ddtrace_profiling_native_extension/profiling.c +7 -0
- data/ext/ddtrace_profiling_native_extension/stack_recorder.c +139 -0
- data/ext/ddtrace_profiling_native_extension/stack_recorder.h +28 -0
- data/lib/datadog/appsec/autoload.rb +2 -2
- data/lib/datadog/appsec/configuration/settings.rb +19 -0
- data/lib/datadog/appsec/configuration.rb +8 -0
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +76 -33
- data/lib/datadog/appsec/contrib/rack/integration.rb +1 -0
- data/lib/datadog/appsec/contrib/rack/patcher.rb +0 -1
- data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +64 -0
- data/lib/datadog/appsec/contrib/rack/request.rb +6 -0
- data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +41 -0
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +60 -5
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +81 -0
- data/lib/datadog/appsec/contrib/rails/patcher.rb +34 -1
- data/lib/datadog/appsec/contrib/rails/reactive/action.rb +68 -0
- data/lib/datadog/appsec/contrib/rails/request.rb +33 -0
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +124 -0
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +69 -2
- data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +63 -0
- data/lib/datadog/appsec/event.rb +33 -18
- data/lib/datadog/appsec/extensions.rb +0 -3
- data/lib/datadog/appsec/processor.rb +45 -2
- data/lib/datadog/appsec/rate_limiter.rb +5 -0
- data/lib/datadog/appsec/reactive/operation.rb +0 -1
- data/lib/datadog/ci/ext/environment.rb +21 -7
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +1 -1
- data/lib/datadog/core/configuration/components.rb +22 -4
- data/lib/datadog/core/configuration/settings.rb +3 -3
- data/lib/datadog/core/configuration.rb +7 -5
- data/lib/datadog/core/environment/cgroup.rb +3 -1
- data/lib/datadog/core/environment/container.rb +2 -1
- data/lib/datadog/core/environment/variable_helpers.rb +26 -2
- data/lib/datadog/core/logging/ext.rb +11 -0
- data/lib/datadog/core/metrics/client.rb +15 -5
- data/lib/datadog/core/runtime/metrics.rb +1 -1
- data/lib/datadog/core/workers/async.rb +3 -1
- data/lib/datadog/core/workers/runtime_metrics.rb +0 -3
- data/lib/datadog/core.rb +6 -0
- data/lib/datadog/kit/enable_core_dumps.rb +50 -0
- data/lib/datadog/kit/identity.rb +63 -0
- data/lib/datadog/kit.rb +11 -0
- data/lib/datadog/opentracer/tracer.rb +0 -2
- data/lib/datadog/profiling/collectors/old_stack.rb +298 -0
- data/lib/datadog/profiling/collectors/stack.rb +6 -287
- data/lib/datadog/profiling/encoding/profile.rb +0 -1
- data/lib/datadog/profiling/ext.rb +1 -1
- data/lib/datadog/profiling/flush.rb +1 -1
- data/lib/datadog/profiling/load_native_extension.rb +22 -0
- data/lib/datadog/profiling/recorder.rb +1 -1
- data/lib/datadog/profiling/scheduler.rb +1 -1
- data/lib/datadog/profiling/stack_recorder.rb +33 -0
- data/lib/datadog/profiling/tag_builder.rb +48 -0
- data/lib/datadog/profiling/tasks/exec.rb +2 -2
- data/lib/datadog/profiling/tasks/setup.rb +6 -4
- data/lib/datadog/profiling.rb +29 -27
- data/lib/datadog/tracing/buffer.rb +9 -3
- data/lib/datadog/tracing/contrib/action_view/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +2 -2
- data/lib/datadog/tracing/contrib/active_record/utils.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/vendor/connection_specification.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +4 -2
- data/lib/datadog/tracing/contrib/concurrent_ruby/context_composite_executor_service.rb +10 -3
- data/lib/datadog/tracing/contrib/dalli/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/delayed_job/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/elasticsearch/integration.rb +9 -3
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +38 -2
- data/lib/datadog/tracing/contrib/ethon/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/extensions.rb +0 -2
- data/lib/datadog/tracing/contrib/faraday/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/grape/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/graphql/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/grpc/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/kafka/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/lograge/instrumentation.rb +2 -1
- data/lib/datadog/tracing/contrib/qless/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/que/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/racecar/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/rails/log_injection.rb +3 -16
- data/lib/datadog/tracing/contrib/rake/instrumentation.rb +2 -2
- data/lib/datadog/tracing/contrib/rake/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/redis/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/resque/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/rest_client/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/semantic_logger/instrumentation.rb +2 -1
- data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +20 -1
- data/lib/datadog/tracing/contrib/sinatra/framework.rb +11 -0
- data/lib/datadog/tracing/contrib/sinatra/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/sneakers/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/sucker_punch/patcher.rb +0 -1
- data/lib/datadog/tracing/event.rb +2 -1
- data/lib/datadog/tracing/sampling/priority_sampler.rb +4 -5
- data/lib/datadog/tracing/sampling/rule.rb +12 -6
- data/lib/datadog/tracing/sampling/rule_sampler.rb +3 -5
- data/lib/datadog/tracing/span_operation.rb +2 -3
- data/lib/datadog/tracing/trace_operation.rb +0 -1
- data/lib/ddtrace/transport/http/client.rb +2 -1
- data/lib/ddtrace/transport/http/response.rb +34 -4
- data/lib/ddtrace/transport/io/client.rb +3 -1
- data/lib/ddtrace/version.rb +1 -1
- data/lib/ddtrace.rb +1 -0
- metadata +43 -6
@@ -16,9 +16,40 @@ module Datadog
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
# Context manages a sequence of runs
|
20
|
+
class Context
|
21
|
+
attr_reader :time_ns, :time_ext_ns, :timeouts, :events
|
22
|
+
|
23
|
+
def initialize(processor)
|
24
|
+
@context = Datadog::AppSec::WAF::Context.new(processor.send(:handle))
|
25
|
+
@time_ns = 0.0
|
26
|
+
@time_ext_ns = 0.0
|
27
|
+
@timeouts = 0
|
28
|
+
@events = []
|
29
|
+
end
|
30
|
+
|
31
|
+
def run(*args)
|
32
|
+
start_ns = Core::Utils::Time.get_time(:nanosecond)
|
33
|
+
|
34
|
+
ret, res = @context.run(*args)
|
35
|
+
|
36
|
+
stop_ns = Core::Utils::Time.get_time(:nanosecond)
|
37
|
+
|
38
|
+
@time_ns += res.total_runtime
|
39
|
+
@time_ext_ns += (stop_ns - start_ns)
|
40
|
+
@timeouts += 1 if res.timeout
|
41
|
+
|
42
|
+
[ret, res]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
attr_reader :ruleset_info, :addresses
|
47
|
+
|
19
48
|
def initialize
|
20
49
|
@ruleset = nil
|
21
50
|
@handle = nil
|
51
|
+
@ruleset_info = nil
|
52
|
+
@addresses = nil
|
22
53
|
|
23
54
|
unless load_libddwaf && load_ruleset && create_waf_handle
|
24
55
|
Datadog.logger.warn { 'AppSec is disabled, see logged errors above' }
|
@@ -30,9 +61,13 @@ module Datadog
|
|
30
61
|
end
|
31
62
|
|
32
63
|
def new_context
|
33
|
-
|
64
|
+
Context.new(self)
|
34
65
|
end
|
35
66
|
|
67
|
+
protected
|
68
|
+
|
69
|
+
attr_reader :handle
|
70
|
+
|
36
71
|
private
|
37
72
|
|
38
73
|
def load_libddwaf
|
@@ -70,7 +105,13 @@ module Datadog
|
|
70
105
|
# TODO: this may need to be reset if the main Datadog logging level changes after initialization
|
71
106
|
Datadog::AppSec::WAF.logger = Datadog.logger if Datadog.logger.debug? && Datadog::AppSec.settings.waf_debug
|
72
107
|
|
73
|
-
|
108
|
+
obfuscator_config = {
|
109
|
+
key_regex: Datadog::AppSec.settings.obfuscator_key_regex,
|
110
|
+
value_regex: Datadog::AppSec.settings.obfuscator_value_regex,
|
111
|
+
}
|
112
|
+
@handle = Datadog::AppSec::WAF::Handle.new(@ruleset, obfuscator: obfuscator_config)
|
113
|
+
@ruleset_info = @handle.ruleset_info
|
114
|
+
@addresses = @handle.required_addresses
|
74
115
|
|
75
116
|
true
|
76
117
|
rescue StandardError => e
|
@@ -78,6 +119,8 @@ module Datadog
|
|
78
119
|
"libddwaf failed to initialize, error: #{e.inspect}"
|
79
120
|
end
|
80
121
|
|
122
|
+
@ruleset_info = e.ruleset_info if e.respond_to?(:ruleset_info)
|
123
|
+
|
81
124
|
false
|
82
125
|
end
|
83
126
|
|
@@ -379,49 +379,63 @@ module Datadog
|
|
379
379
|
committer_date: Time.at(fields[5].to_i).utc.to_datetime.iso8601
|
380
380
|
}
|
381
381
|
rescue => e
|
382
|
-
Datadog.logger.debug(
|
382
|
+
Datadog.logger.debug(
|
383
|
+
"Unable to read git commit users: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
|
384
|
+
)
|
383
385
|
nil
|
384
386
|
end
|
385
387
|
|
386
388
|
def git_repository_url
|
387
389
|
exec_git_command('git ls-remote --get-url')
|
388
390
|
rescue => e
|
389
|
-
Datadog.logger.debug(
|
391
|
+
Datadog.logger.debug(
|
392
|
+
"Unable to read git repository url: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
|
393
|
+
)
|
390
394
|
nil
|
391
395
|
end
|
392
396
|
|
393
397
|
def git_commit_message
|
394
398
|
exec_git_command('git show -s --format=%s')
|
395
399
|
rescue => e
|
396
|
-
Datadog.logger.debug(
|
400
|
+
Datadog.logger.debug(
|
401
|
+
"Unable to read git commit message: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
|
402
|
+
)
|
397
403
|
nil
|
398
404
|
end
|
399
405
|
|
400
406
|
def git_branch
|
401
407
|
exec_git_command('git rev-parse --abbrev-ref HEAD')
|
402
408
|
rescue => e
|
403
|
-
Datadog.logger.debug(
|
409
|
+
Datadog.logger.debug(
|
410
|
+
"Unable to read git branch: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
|
411
|
+
)
|
404
412
|
nil
|
405
413
|
end
|
406
414
|
|
407
415
|
def git_commit_sha
|
408
416
|
exec_git_command('git rev-parse HEAD')
|
409
417
|
rescue => e
|
410
|
-
Datadog.logger.debug(
|
418
|
+
Datadog.logger.debug(
|
419
|
+
"Unable to read git commit SHA: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
|
420
|
+
)
|
411
421
|
nil
|
412
422
|
end
|
413
423
|
|
414
424
|
def git_tag
|
415
425
|
exec_git_command('git tag --points-at HEAD')
|
416
426
|
rescue => e
|
417
|
-
Datadog.logger.debug(
|
427
|
+
Datadog.logger.debug(
|
428
|
+
"Unable to read git tag: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
|
429
|
+
)
|
418
430
|
nil
|
419
431
|
end
|
420
432
|
|
421
433
|
def git_base_directory
|
422
434
|
exec_git_command('git rev-parse --show-toplevel')
|
423
435
|
rescue => e
|
424
|
-
Datadog.logger.debug(
|
436
|
+
Datadog.logger.debug(
|
437
|
+
"Unable to read git base directory: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
|
438
|
+
)
|
425
439
|
nil
|
426
440
|
end
|
427
441
|
|
@@ -303,7 +303,7 @@ module Datadog
|
|
303
303
|
if logger
|
304
304
|
logger.debug do
|
305
305
|
'Could not extract configuration from transport_options proc. ' \
|
306
|
-
"Cause: #{e.message} Source: #{Array(e.backtrace).first}"
|
306
|
+
"Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
307
307
|
end
|
308
308
|
end
|
309
309
|
|
@@ -11,8 +11,6 @@ require 'datadog/tracing/tracer'
|
|
11
11
|
require 'datadog/tracing/flush'
|
12
12
|
require 'datadog/tracing/sync_writer'
|
13
13
|
|
14
|
-
require 'datadog/profiling'
|
15
|
-
|
16
14
|
module Datadog
|
17
15
|
module Core
|
18
16
|
module Configuration
|
@@ -181,7 +179,27 @@ module Datadog
|
|
181
179
|
end
|
182
180
|
|
183
181
|
def build_profiler(settings, agent_settings, tracer)
|
184
|
-
return unless
|
182
|
+
return unless settings.profiling.enabled
|
183
|
+
|
184
|
+
# Workaround for weird dependency direction: the Core::Configuration::Components class currently has a
|
185
|
+
# dependency on individual products, in this case the Profiler.
|
186
|
+
# (Note "currently": in the future we want to change this so core classes don't depend on specific products)
|
187
|
+
#
|
188
|
+
# If the current file included a `require 'datadog/profiler'` at its beginning, we would generate circular
|
189
|
+
# requires when used from profiling:
|
190
|
+
#
|
191
|
+
# datadog/profiling
|
192
|
+
# └─requires─> datadog/core
|
193
|
+
# └─requires─> datadog/core/configuration/components
|
194
|
+
# └─requires─> datadog/profiling # Loop!
|
195
|
+
#
|
196
|
+
# ...thus in #1998 we removed such a require.
|
197
|
+
#
|
198
|
+
# On the other hand, if datadog/core is loaded by a different product and no general `require 'ddtrace'` is
|
199
|
+
# done, then profiling may not be loaded, and thus to avoid this issue we do a require here (which is a
|
200
|
+
# no-op if profiling is already loaded).
|
201
|
+
require 'datadog/profiling'
|
202
|
+
return unless Profiling.supported?
|
185
203
|
|
186
204
|
unless defined?(Profiling::Tasks::Setup)
|
187
205
|
# In #1545 a user reported a NameError due to this constant being uninitialized
|
@@ -278,7 +296,7 @@ module Datadog
|
|
278
296
|
|
279
297
|
def build_profiler_collectors(settings, recorder, trace_identifiers_helper)
|
280
298
|
[
|
281
|
-
Profiling::Collectors::
|
299
|
+
Profiling::Collectors::OldStack.new(
|
282
300
|
recorder,
|
283
301
|
trace_identifiers_helper: trace_identifiers_helper,
|
284
302
|
max_frames: settings.profiling.advanced.max_frames
|
@@ -305,7 +305,7 @@ module Datadog
|
|
305
305
|
tags = {}
|
306
306
|
|
307
307
|
# Parse tags from environment
|
308
|
-
env_to_list(Core::Environment::Ext::ENV_TAGS).each do |tag|
|
308
|
+
env_to_list(Core::Environment::Ext::ENV_TAGS, comma_separated_only: false).each do |tag|
|
309
309
|
pair = tag.split(':')
|
310
310
|
tags[pair.first] = pair.last if pair.length == 2
|
311
311
|
end
|
@@ -412,7 +412,7 @@ module Datadog
|
|
412
412
|
Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG,
|
413
413
|
Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3,
|
414
414
|
Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER
|
415
|
-
]
|
415
|
+
], comma_separated_only: true
|
416
416
|
)
|
417
417
|
end
|
418
418
|
|
@@ -430,7 +430,7 @@ module Datadog
|
|
430
430
|
o.default do
|
431
431
|
env_to_list(
|
432
432
|
Tracing::Configuration::Ext::Distributed::ENV_PROPAGATION_STYLE_INJECT,
|
433
|
-
[Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG] # Only inject Datadog headers by default
|
433
|
+
[Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG], comma_separated_only: true # Only inject Datadog headers by default
|
434
434
|
)
|
435
435
|
end
|
436
436
|
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# typed: true
|
2
2
|
|
3
|
-
require 'forwardable'
|
4
3
|
require 'datadog/core/configuration/components'
|
5
4
|
require 'datadog/core/configuration/settings'
|
6
5
|
require 'datadog/core/logger'
|
@@ -11,7 +10,6 @@ module Datadog
|
|
11
10
|
# Configuration provides a unique access point for configurations
|
12
11
|
module Configuration # rubocop:disable Metrics/ModuleLength
|
13
12
|
include Kernel # Ensure that kernel methods are always available (https://sorbet.org/docs/error-reference#7003)
|
14
|
-
extend Forwardable
|
15
13
|
|
16
14
|
# Used to ensure that @components initialization/reconfiguration is performed one-at-a-time, by a single thread.
|
17
15
|
#
|
@@ -154,9 +152,13 @@ module Datadog
|
|
154
152
|
pin[option] if pin
|
155
153
|
end
|
156
154
|
|
157
|
-
|
158
|
-
|
159
|
-
|
155
|
+
# Internal {Datadog::Statsd} metrics collection.
|
156
|
+
#
|
157
|
+
# The list of metrics collected can be found in {Datadog::Core::Diagnostics::Ext::Health::Metrics}.
|
158
|
+
# @public_api
|
159
|
+
def health_metrics
|
160
|
+
components.health_metrics
|
161
|
+
end
|
160
162
|
|
161
163
|
def logger
|
162
164
|
# avoid initializing components if they didn't already exist
|
@@ -35,7 +35,9 @@ module Datadog
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
rescue StandardError => e
|
38
|
-
Datadog.logger.error(
|
38
|
+
Datadog.logger.error(
|
39
|
+
"Error while parsing cgroup. Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
|
40
|
+
)
|
39
41
|
end
|
40
42
|
end
|
41
43
|
end
|
@@ -81,7 +81,8 @@ module Datadog
|
|
81
81
|
end
|
82
82
|
rescue StandardError => e
|
83
83
|
Datadog.logger.error(
|
84
|
-
"Error while parsing container info. Cause: #{e.
|
84
|
+
"Error while parsing container info. Cause: #{e.class.name} #{e.message} " \
|
85
|
+
"Location: #{Array(e.backtrace).first}"
|
85
86
|
)
|
86
87
|
end
|
87
88
|
end
|
@@ -24,10 +24,34 @@ module Datadog
|
|
24
24
|
var && ENV.key?(var) ? ENV[var].to_f : default
|
25
25
|
end
|
26
26
|
|
27
|
-
|
27
|
+
# Parses comma- or space-separated lists.
|
28
|
+
#
|
29
|
+
# If a comma is present, then the list is considered comma-separated.
|
30
|
+
# Otherwise, it is considered space-separated.
|
31
|
+
#
|
32
|
+
# After the entries are separated, commas and whitespaces that are
|
33
|
+
# either trailing or leading are trimmed.
|
34
|
+
#
|
35
|
+
# Empty entries, after trimmed, are also removed from the result.
|
36
|
+
def env_to_list(var, default = [], comma_separated_only:)
|
28
37
|
var = decode_array(var)
|
29
38
|
if var && ENV.key?(var)
|
30
|
-
ENV[var]
|
39
|
+
value = ENV[var]
|
40
|
+
|
41
|
+
values = if value.include?(',') || comma_separated_only
|
42
|
+
value.split(',')
|
43
|
+
else
|
44
|
+
value.split(' ') # rubocop:disable Style/RedundantArgument
|
45
|
+
end
|
46
|
+
|
47
|
+
values.map! do |v|
|
48
|
+
v.gsub!(/\A[\s,]*|[\s,]*\Z/, '')
|
49
|
+
|
50
|
+
v.empty? ? nil : v
|
51
|
+
end
|
52
|
+
|
53
|
+
values.compact!
|
54
|
+
values
|
31
55
|
else
|
32
56
|
default
|
33
57
|
end
|
@@ -96,7 +96,9 @@ module Datadog
|
|
96
96
|
|
97
97
|
statsd.count(stat, value, metric_options(options))
|
98
98
|
rescue StandardError => e
|
99
|
-
Datadog.logger.error(
|
99
|
+
Datadog.logger.error(
|
100
|
+
"Failed to send count stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
101
|
+
)
|
100
102
|
end
|
101
103
|
|
102
104
|
def distribution(stat, value = nil, options = nil, &block)
|
@@ -107,7 +109,9 @@ module Datadog
|
|
107
109
|
|
108
110
|
statsd.distribution(stat, value, metric_options(options))
|
109
111
|
rescue StandardError => e
|
110
|
-
Datadog.logger.error(
|
112
|
+
Datadog.logger.error(
|
113
|
+
"Failed to send distribution stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
114
|
+
)
|
111
115
|
end
|
112
116
|
|
113
117
|
def increment(stat, options = nil)
|
@@ -117,7 +121,9 @@ module Datadog
|
|
117
121
|
|
118
122
|
statsd.increment(stat, metric_options(options))
|
119
123
|
rescue StandardError => e
|
120
|
-
Datadog.logger.error(
|
124
|
+
Datadog.logger.error(
|
125
|
+
"Failed to send increment stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
126
|
+
)
|
121
127
|
end
|
122
128
|
|
123
129
|
def gauge(stat, value = nil, options = nil, &block)
|
@@ -128,7 +134,9 @@ module Datadog
|
|
128
134
|
|
129
135
|
statsd.gauge(stat, value, metric_options(options))
|
130
136
|
rescue StandardError => e
|
131
|
-
Datadog.logger.error(
|
137
|
+
Datadog.logger.error(
|
138
|
+
"Failed to send gauge stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
139
|
+
)
|
132
140
|
end
|
133
141
|
|
134
142
|
def time(stat, options = nil)
|
@@ -144,7 +152,9 @@ module Datadog
|
|
144
152
|
distribution(stat, ((finished - start) * 1000), options)
|
145
153
|
end
|
146
154
|
rescue StandardError => e
|
147
|
-
Datadog.logger.error(
|
155
|
+
Datadog.logger.error(
|
156
|
+
"Failed to send time stat. Cause: #{e.class.name} #{e.message} Source: #{Array(e.backtrace).first}"
|
157
|
+
)
|
148
158
|
end
|
149
159
|
end
|
150
160
|
|
@@ -79,7 +79,7 @@ module Datadog
|
|
79
79
|
def try_flush
|
80
80
|
yield
|
81
81
|
rescue StandardError => e
|
82
|
-
Datadog.logger.error("Error while sending runtime metric. Cause: #{e.message}")
|
82
|
+
Datadog.logger.error("Error while sending runtime metric. Cause: #{e.class.name} #{e.message}")
|
83
83
|
end
|
84
84
|
|
85
85
|
def default_metric_options
|
@@ -138,7 +138,9 @@ module Datadog
|
|
138
138
|
# rubocop:disable Lint/RescueException
|
139
139
|
rescue Exception => e
|
140
140
|
@error = e
|
141
|
-
Datadog.logger.debug(
|
141
|
+
Datadog.logger.debug(
|
142
|
+
"Worker thread error. Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
|
143
|
+
)
|
142
144
|
raise
|
143
145
|
end
|
144
146
|
# rubocop:enable Lint/RescueException
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# typed: false
|
2
2
|
|
3
|
-
require 'forwardable'
|
4
|
-
|
5
3
|
require 'datadog/core/runtime/metrics'
|
6
4
|
|
7
5
|
require 'datadog/core/worker'
|
@@ -13,7 +11,6 @@ module Datadog
|
|
13
11
|
module Workers
|
14
12
|
# Emits runtime metrics asynchronously on a timed loop
|
15
13
|
class RuntimeMetrics < Worker
|
16
|
-
extend Forwardable
|
17
14
|
include Workers::Polling
|
18
15
|
|
19
16
|
# In seconds
|
data/lib/datadog/core.rb
CHANGED
@@ -59,6 +59,12 @@ require 'datadog/core/extensions'
|
|
59
59
|
# We must load core extensions to make certain global APIs
|
60
60
|
# accessible: both for Datadog features and the core itself.
|
61
61
|
module Datadog
|
62
|
+
# Common, lower level, internal code used (or usable) by two or more
|
63
|
+
# products. It is a dependency of each product. Contrast with Datadog::Kit
|
64
|
+
# for higher-level features.
|
65
|
+
module Core
|
66
|
+
end
|
67
|
+
|
62
68
|
extend Core::Extensions
|
63
69
|
|
64
70
|
# Add shutdown hook:
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# typed: ignore
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module Kit
|
5
|
+
# This helper is used to enable core dumps for the current Ruby app. This is useful when debugging native-level
|
6
|
+
# crashes.
|
7
|
+
#
|
8
|
+
# It can be enabled simply by adding `require 'datadog/kit/enable_core_dumps'` to start of the app.
|
9
|
+
module EnableCoreDumps
|
10
|
+
def self.call
|
11
|
+
current_size, maximum_size = Process.getrlimit(:CORE)
|
12
|
+
core_pattern =
|
13
|
+
begin
|
14
|
+
File.read('/proc/sys/kernel/core_pattern').strip
|
15
|
+
rescue
|
16
|
+
'(Could not open /proc/sys/kernel/core_pattern)'
|
17
|
+
end
|
18
|
+
|
19
|
+
if maximum_size <= 0
|
20
|
+
Kernel.warn("[DDTRACE] Could not enable core dumps on crash, maximum size is #{maximum_size} (disabled).")
|
21
|
+
return
|
22
|
+
elsif maximum_size == current_size
|
23
|
+
Kernel.warn('[DDTRACE] Core dumps already enabled, nothing to do!')
|
24
|
+
return
|
25
|
+
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
Process.setrlimit(:CORE, maximum_size)
|
29
|
+
rescue => e
|
30
|
+
Kernel.warn(
|
31
|
+
"[DDTRACE] Failed to enable core dumps. Cause: #{e.class.name} #{e.message} " \
|
32
|
+
"Location: #{Array(e.backtrace).first}"
|
33
|
+
)
|
34
|
+
return
|
35
|
+
end
|
36
|
+
|
37
|
+
if current_size == 0
|
38
|
+
Kernel.warn("[DDTRACE] Enabled core dumps. Maximum size: #{maximum_size} Output pattern: '#{core_pattern}'")
|
39
|
+
else
|
40
|
+
Kernel.warn(
|
41
|
+
"[DDTRACE] Raised core dump limit. Old size: #{current_size} " \
|
42
|
+
"Maximum size: #{maximum_size} Output pattern: '#{core_pattern}'"
|
43
|
+
)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
Datadog::Kit::EnableCoreDumps.call
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# typed: false
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module Kit
|
5
|
+
# Tracking identity via traces
|
6
|
+
module Identity
|
7
|
+
# Attach user information to the trace
|
8
|
+
#
|
9
|
+
# @param trace [TraceOperation] Trace to attach data to.
|
10
|
+
# @param id [String] Mandatory. Username or client id extracted
|
11
|
+
# from the access token or Authorization header in the inbound request
|
12
|
+
# from outside the system.
|
13
|
+
# @param email [String] Email of the authenticated user associated
|
14
|
+
# to the trace.
|
15
|
+
# @param name [String] User-friendly name. To be displayed in the
|
16
|
+
# UI if set.
|
17
|
+
# @param session_id [String] Session ID of the authenticated user.
|
18
|
+
# @param role [String] Actual/assumed role the client is making
|
19
|
+
# the request under extracted from token or application security
|
20
|
+
# context.
|
21
|
+
# @param scope [String] Scopes or granted authorities the client
|
22
|
+
# currently possesses extracted from token or application security
|
23
|
+
# context. The value would come from the scope associated with an OAuth
|
24
|
+
# 2.0 Access Token or an attribute value in a SAML 2.0 Assertion.
|
25
|
+
# @param others [Hash<String || Symbol, String>] Additional free-form
|
26
|
+
# user information to attach to the trace.
|
27
|
+
#
|
28
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
29
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
30
|
+
def self.set_user(trace, id:, email: nil, name: nil, session_id: nil, role: nil, scope: nil, **others)
|
31
|
+
raise ArgumentError, 'missing required key: :id' if id.nil?
|
32
|
+
|
33
|
+
# enforce types
|
34
|
+
|
35
|
+
raise TypeError, 'id must be a String' unless id.is_a?(String)
|
36
|
+
raise TypeError, 'email must be a String' unless email.nil? || email.is_a?(String)
|
37
|
+
raise TypeError, 'name must be a String' unless name.nil? || name.is_a?(String)
|
38
|
+
raise TypeError, 'session_id must be a String' unless session_id.nil? || session_id.is_a?(String)
|
39
|
+
raise TypeError, 'role must be a String' unless role.nil? || role.is_a?(String)
|
40
|
+
raise TypeError, 'scope must be a String' unless scope.nil? || scope.is_a?(String)
|
41
|
+
|
42
|
+
others.each do |k, v|
|
43
|
+
raise TypeError, "#{k.inspect} must be a String" unless v.nil? || v.is_a?(String)
|
44
|
+
end
|
45
|
+
|
46
|
+
# set tags once data is known consistent
|
47
|
+
|
48
|
+
trace.set_tag('usr.id', id)
|
49
|
+
trace.set_tag('usr.email', email) unless email.nil?
|
50
|
+
trace.set_tag('usr.name', name) unless name.nil?
|
51
|
+
trace.set_tag('usr.session_id', session_id) unless session_id.nil?
|
52
|
+
trace.set_tag('usr.role', role) unless role.nil?
|
53
|
+
trace.set_tag('usr.scope', scope) unless scope.nil?
|
54
|
+
|
55
|
+
others.each do |k, v|
|
56
|
+
trace.set_tag("usr.#{k}", v) unless v.nil?
|
57
|
+
end
|
58
|
+
end
|
59
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
60
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/datadog/kit.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# typed: false
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
# Datadog::Kit holds public-facing APIs for higher level user-facing
|
5
|
+
# features, these features not belonging to a specific product. Contrary to
|
6
|
+
# Datadog::Core, Kit depends on products.
|
7
|
+
module Kit
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'datadog/kit/identity'
|