ddtrace 1.0.0 → 1.1.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/.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'
|