ddtrace 0.28.0 → 0.29.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +8 -0
- data/Appraisals +57 -2
- data/CHANGELOG.md +41 -12
- data/Rakefile +3 -3
- data/ddtrace.gemspec +2 -1
- data/docs/DevelopmentGuide.md +1 -1
- data/docs/GettingStarted.md +6 -6
- data/lib/ddtrace.rb +7 -0
- data/lib/ddtrace/buffer.rb +60 -1
- data/lib/ddtrace/configuration/base.rb +82 -0
- data/lib/ddtrace/configuration/option.rb +28 -5
- data/lib/ddtrace/configuration/option_definition.rb +100 -0
- data/lib/ddtrace/configuration/options.rb +28 -14
- data/lib/ddtrace/configuration/settings.rb +77 -64
- data/lib/ddtrace/contrib/action_pack/configuration/settings.rb +9 -7
- data/lib/ddtrace/contrib/action_view/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/active_model_serializers/configuration/settings.rb +8 -14
- data/lib/ddtrace/contrib/active_model_serializers/event.rb +1 -1
- data/lib/ddtrace/contrib/active_record/configuration/settings.rb +11 -16
- data/lib/ddtrace/contrib/active_record/event.rb +1 -1
- data/lib/ddtrace/contrib/active_support/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/active_support/notifications/subscriber.rb +2 -2
- data/lib/ddtrace/contrib/active_support/notifications/subscription.rb +4 -1
- data/lib/ddtrace/contrib/aws/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/configuration/settings.rb +5 -11
- data/lib/ddtrace/contrib/dalli/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/dalli/instrumentation.rb +1 -18
- data/lib/ddtrace/contrib/delayed_job/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/elasticsearch/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/ethon/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/ethon/integration.rb +0 -4
- data/lib/ddtrace/contrib/excon/configuration/settings.rb +9 -7
- data/lib/ddtrace/contrib/excon/middleware.rb +1 -1
- data/lib/ddtrace/contrib/faraday/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/faraday/middleware.rb +1 -1
- data/lib/ddtrace/contrib/faraday/patcher.rb +8 -2
- data/lib/ddtrace/contrib/faraday/rack_builder.rb +18 -0
- data/lib/ddtrace/contrib/grape/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/grape/instrumentation.rb +2 -42
- data/lib/ddtrace/contrib/graphql/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/grpc/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/grpc/integration.rb +1 -3
- data/lib/ddtrace/contrib/http/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/http/instrumentation.rb +1 -23
- data/lib/ddtrace/contrib/mongodb/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/mysql2/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/mysql2/instrumentation.rb +1 -23
- data/lib/ddtrace/contrib/patchable.rb +1 -1
- data/lib/ddtrace/contrib/racecar/configuration/settings.rb +8 -14
- data/lib/ddtrace/contrib/racecar/event.rb +1 -1
- data/lib/ddtrace/contrib/rack/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/rack/request_queue.rb +7 -6
- data/lib/ddtrace/contrib/rails/configuration/settings.rb +30 -21
- data/lib/ddtrace/contrib/rake/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/rake/integration.rb +0 -4
- data/lib/ddtrace/contrib/redis/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/resque/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/rest_client/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/rest_client/integration.rb +0 -4
- data/lib/ddtrace/contrib/rest_client/request_patch.rb +1 -18
- data/lib/ddtrace/contrib/sequel/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/sequel/integration.rb +0 -4
- data/lib/ddtrace/contrib/shoryuken/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/sidekiq/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/sinatra/configuration/settings.rb +8 -6
- data/lib/ddtrace/contrib/sucker_punch/configuration/settings.rb +8 -6
- data/lib/ddtrace/diagnostics/health.rb +30 -0
- data/lib/ddtrace/distributed_tracing/headers/datadog.rb +1 -1
- data/lib/ddtrace/distributed_tracing/headers/headers.rb +2 -0
- data/lib/ddtrace/ext/diagnostics.rb +25 -0
- data/lib/ddtrace/ext/runtime.rb +1 -7
- data/lib/ddtrace/metrics.rb +89 -6
- data/lib/ddtrace/propagation/http_propagator.rb +2 -2
- data/lib/ddtrace/runtime/class_count.rb +3 -3
- data/lib/ddtrace/runtime/object_space.rb +19 -0
- data/lib/ddtrace/span.rb +1 -1
- data/lib/ddtrace/tracer.rb +5 -4
- data/lib/ddtrace/transport/http/client.rb +3 -4
- data/lib/ddtrace/transport/http/response.rb +4 -0
- data/lib/ddtrace/transport/http/statistics.rb +30 -0
- data/lib/ddtrace/transport/statistics.rb +28 -0
- data/lib/ddtrace/version.rb +3 -1
- data/lib/ddtrace/workers.rb +4 -2
- data/lib/ddtrace/writer.rb +3 -3
- metadata +74 -54
data/Rakefile
CHANGED
@@ -54,7 +54,7 @@ namespace :spec do
|
|
54
54
|
|
55
55
|
RSpec::Core::RakeTask.new(:contrib) do |t, args|
|
56
56
|
# rubocop:disable Metrics/LineLength
|
57
|
-
t.pattern = 'spec/**/contrib/{analytics,configurable,integration,patchable,patcher,registerable,registry,configuration/*}_spec.rb'
|
57
|
+
t.pattern = 'spec/**/contrib/{analytics,configurable,extensions,integration,patchable,patcher,registerable,registry,configuration/*}_spec.rb'
|
58
58
|
t.rspec_opts = args.to_a.join(' ')
|
59
59
|
end
|
60
60
|
|
@@ -189,8 +189,8 @@ end
|
|
189
189
|
|
190
190
|
desc 'CI task; it runs all tests for current version of Ruby'
|
191
191
|
task :ci do
|
192
|
-
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new(
|
193
|
-
raise NotImplementedError,
|
192
|
+
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new(Datadog::VERSION::MINIMUM_RUBY_VERSION)
|
193
|
+
raise NotImplementedError, "Ruby versions < #{Datadog::VERSION::MINIMUM_RUBY_VERSION} are not supported!"
|
194
194
|
elsif Gem::Version.new('2.0.0') <= Gem::Version.new(RUBY_VERSION) \
|
195
195
|
&& Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.1.0')
|
196
196
|
# Main library
|
data/ddtrace.gemspec
CHANGED
@@ -7,7 +7,7 @@ require 'ddtrace/version'
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
8
|
spec.name = 'ddtrace'
|
9
9
|
spec.version = Datadog::VERSION::STRING
|
10
|
-
spec.required_ruby_version =
|
10
|
+
spec.required_ruby_version = ">= #{Datadog::VERSION::MINIMUM_RUBY_VERSION}"
|
11
11
|
spec.authors = ['Datadog, Inc.']
|
12
12
|
spec.email = ['dev@datadoghq.com']
|
13
13
|
|
@@ -58,4 +58,5 @@ Gem::Specification.new do |spec|
|
|
58
58
|
spec.add_development_dependency 'redcarpet', '~> 3.4' if RUBY_PLATFORM != 'java'
|
59
59
|
spec.add_development_dependency 'pry', '~> 0.10.4'
|
60
60
|
spec.add_development_dependency 'pry-stack_explorer', '~> 0.4.9.2'
|
61
|
+
spec.add_development_dependency 'warning' if RUBY_VERSION >= '2.5.0'
|
61
62
|
end
|
data/docs/DevelopmentGuide.md
CHANGED
@@ -19,7 +19,7 @@ This guide covers some of the common how-tos and technical reference material fo
|
|
19
19
|
|
20
20
|
The trace library uses Docker Compose to create a Ruby environment to develop and test within, as well as containers for any dependencies that might be necessary for certain kinds of tests.
|
21
21
|
|
22
|
-
To start a development environment, choose a target Ruby version
|
22
|
+
To start a development environment, choose a target Ruby version then run the following:
|
23
23
|
|
24
24
|
```
|
25
25
|
# In the root directory of the project...
|
data/docs/GettingStarted.md
CHANGED
@@ -324,11 +324,11 @@ For a list of available integrations, and their configuration options, please re
|
|
324
324
|
|
325
325
|
| Name | Key | Versions Supported | How to configure | Gem source |
|
326
326
|
| ------------------------ | -------------------------- | ------------------------ | ----------------------------------- | ------------------------------------------------------------------------------ |
|
327
|
-
| Action View | `action_view` | `>= 3.2`
|
327
|
+
| Action View | `action_view` | `>= 3.2` | *[Link](#action-view)* | *[Link](https://github.com/rails/rails/tree/master/actionview)* |
|
328
328
|
| Active Model Serializers | `active_model_serializers` | `>= 0.9` | *[Link](#active-model-serializers)* | *[Link](https://github.com/rails-api/active_model_serializers)* |
|
329
|
-
| Action Pack | `action_pack` | `>= 3.2`
|
330
|
-
| Active Record | `active_record` | `>= 3.2`
|
331
|
-
| Active Support | `active_support` | `>= 3.2`
|
329
|
+
| Action Pack | `action_pack` | `>= 3.2` | *[Link](#action-pack)* | *[Link](https://github.com/rails/rails/tree/master/actionpack)* |
|
330
|
+
| Active Record | `active_record` | `>= 3.2` | *[Link](#active-record)* | *[Link](https://github.com/rails/rails/tree/master/activerecord)* |
|
331
|
+
| Active Support | `active_support` | `>= 3.2` | *[Link](#active-support)* | *[Link](https://github.com/rails/rails/tree/master/activesupport)* |
|
332
332
|
| AWS | `aws` | `>= 2.0` | *[Link](#aws)* | *[Link](https://github.com/aws/aws-sdk-ruby)* |
|
333
333
|
| Concurrent Ruby | `concurrent_ruby` | `>= 0.9` | *[Link](#concurrent-ruby)* | *[Link](https://github.com/ruby-concurrency/concurrent-ruby)* |
|
334
334
|
| Dalli | `dalli` | `>= 2.7` | *[Link](#dalli)* | *[Link](https://github.com/petergoldstein/dalli)* |
|
@@ -345,9 +345,9 @@ For a list of available integrations, and their configuration options, please re
|
|
345
345
|
| Net/HTTP | `http` | *(Any supported Ruby)* | *[Link](#nethttp)* | *[Link](https://ruby-doc.org/stdlib-2.4.0/libdoc/net/http/rdoc/Net/HTTP.html)* |
|
346
346
|
| Racecar | `racecar` | `>= 0.3.5` | *[Link](#racecar)* | *[Link](https://github.com/zendesk/racecar)* |
|
347
347
|
| Rack | `rack` | `>= 1.4.7` | *[Link](#rack)* | *[Link](https://github.com/rack/rack)* |
|
348
|
-
| Rails | `rails` | `>= 3.2`
|
348
|
+
| Rails | `rails` | `>= 3.2` | *[Link](#rails)* | *[Link](https://github.com/rails/rails)* |
|
349
349
|
| Rake | `rake` | `>= 12.0` | *[Link](#rake)* | *[Link](https://github.com/ruby/rake)* |
|
350
|
-
| Redis | `redis` | `>= 3.2
|
350
|
+
| Redis | `redis` | `>= 3.2` | *[Link](#redis)* | *[Link](https://github.com/redis/redis-rb)* |
|
351
351
|
| Resque | `resque` | `>= 1.0, < 2.0` | *[Link](#resque)* | *[Link](https://github.com/resque/resque)* |
|
352
352
|
| Rest Client | `rest-client` | `>= 1.8` | *[Link](#rest-client)* | *[Link](https://github.com/rest-client/rest-client)* |
|
353
353
|
| Sequel | `sequel` | `>= 3.41` | *[Link](#sequel)* | *[Link](https://github.com/jeremyevans/sequel)* |
|
data/lib/ddtrace.rb
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
require 'thread'
|
2
2
|
|
3
|
+
# During development, we load `ddtrace` by through `ddtrace.gemspec`,
|
4
|
+
# which in turn eager loads 'ddtrace/version'.
|
5
|
+
#
|
6
|
+
# Users load this gem by requiring this file.
|
7
|
+
# We need to ensure that any files loaded in our gemspec are also loaded here.
|
8
|
+
require 'ddtrace/version'
|
9
|
+
|
3
10
|
require 'ddtrace/pin'
|
4
11
|
require 'ddtrace/tracer'
|
5
12
|
require 'ddtrace/error'
|
data/lib/ddtrace/buffer.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'thread'
|
2
|
+
require 'ddtrace/diagnostics/health'
|
3
|
+
require 'ddtrace/runtime/object_space'
|
2
4
|
|
3
5
|
module Datadog
|
4
6
|
# Trace buffer that stores application traces. The buffer has a maximum size and when
|
@@ -11,6 +13,12 @@ module Datadog
|
|
11
13
|
@mutex = Mutex.new()
|
12
14
|
@traces = []
|
13
15
|
@closed = false
|
16
|
+
|
17
|
+
# Initialize metric values
|
18
|
+
@buffer_accepted = 0
|
19
|
+
@buffer_accepted_lengths = 0
|
20
|
+
@buffer_dropped = 0
|
21
|
+
@buffer_spans = 0
|
14
22
|
end
|
15
23
|
|
16
24
|
# Add a new ``trace`` in the local queue. This method doesn't block the execution
|
@@ -23,8 +31,13 @@ module Datadog
|
|
23
31
|
@traces << trace
|
24
32
|
else
|
25
33
|
# we should replace a random trace with the new one
|
26
|
-
|
34
|
+
replace_index = rand(len)
|
35
|
+
replaced_trace = @traces[replace_index]
|
36
|
+
@traces[replace_index] = trace
|
37
|
+
measure_drop(replaced_trace)
|
27
38
|
end
|
39
|
+
|
40
|
+
measure_accept(trace)
|
28
41
|
end
|
29
42
|
end
|
30
43
|
|
@@ -47,6 +60,9 @@ module Datadog
|
|
47
60
|
@mutex.synchronize do
|
48
61
|
traces = @traces
|
49
62
|
@traces = []
|
63
|
+
|
64
|
+
measure_pop(traces)
|
65
|
+
|
50
66
|
return traces
|
51
67
|
end
|
52
68
|
end
|
@@ -56,5 +72,48 @@ module Datadog
|
|
56
72
|
@closed = true
|
57
73
|
end
|
58
74
|
end
|
75
|
+
|
76
|
+
# Aggregate metrics:
|
77
|
+
# They reflect buffer activity since last #pop.
|
78
|
+
# These may not be as accurate or as granular, but they
|
79
|
+
# don't use as much network traffic as live stats.
|
80
|
+
|
81
|
+
def measure_accept(trace)
|
82
|
+
@buffer_spans += trace.length
|
83
|
+
@buffer_accepted += 1
|
84
|
+
@buffer_accepted_lengths += trace.length
|
85
|
+
rescue StandardError => e
|
86
|
+
Datadog::Tracer.log.debug("Failed to measure queue accept. Cause: #{e.message} Source: #{e.backtrace.first}")
|
87
|
+
end
|
88
|
+
|
89
|
+
def measure_drop(trace)
|
90
|
+
@buffer_dropped += 1
|
91
|
+
@buffer_spans -= trace.length
|
92
|
+
@buffer_accepted_lengths -= trace.length
|
93
|
+
rescue StandardError => e
|
94
|
+
Datadog::Tracer.log.debug("Failed to measure queue drop. Cause: #{e.message} Source: #{e.backtrace.first}")
|
95
|
+
end
|
96
|
+
|
97
|
+
def measure_pop(traces)
|
98
|
+
# Accepted
|
99
|
+
Diagnostics::Health.metrics.queue_accepted(@buffer_accepted)
|
100
|
+
Diagnostics::Health.metrics.queue_accepted_lengths(@buffer_accepted_lengths)
|
101
|
+
|
102
|
+
# Dropped
|
103
|
+
Diagnostics::Health.metrics.queue_dropped(@buffer_dropped)
|
104
|
+
|
105
|
+
# Queue gauges
|
106
|
+
Diagnostics::Health.metrics.queue_max_length(@max_size)
|
107
|
+
Diagnostics::Health.metrics.queue_spans(@buffer_spans)
|
108
|
+
Diagnostics::Health.metrics.queue_length(traces.length)
|
109
|
+
|
110
|
+
# Reset aggregated metrics
|
111
|
+
@buffer_accepted = 0
|
112
|
+
@buffer_accepted_lengths = 0
|
113
|
+
@buffer_dropped = 0
|
114
|
+
@buffer_spans = 0
|
115
|
+
rescue StandardError => e
|
116
|
+
Datadog::Tracer.log.debug("Failed to measure queue. Cause: #{e.message} Source: #{e.backtrace.first}")
|
117
|
+
end
|
59
118
|
end
|
60
119
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'ddtrace/environment'
|
2
|
+
require 'ddtrace/configuration/options'
|
3
|
+
|
4
|
+
module Datadog
|
5
|
+
module Configuration
|
6
|
+
# Basic configuration behavior
|
7
|
+
module Base
|
8
|
+
def self.included(base)
|
9
|
+
base.send(:extend, Datadog::Environment::Helpers)
|
10
|
+
base.send(:include, Options)
|
11
|
+
|
12
|
+
base.send(:extend, ClassMethods)
|
13
|
+
base.send(:include, InstanceMethods)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Class methods for configuration
|
17
|
+
module ClassMethods
|
18
|
+
protected
|
19
|
+
|
20
|
+
# Allows subgroupings of settings to be defined.
|
21
|
+
# e.g. `settings :foo { option :bar }` --> `config.foo.bar`
|
22
|
+
def settings(name, &block)
|
23
|
+
settings_class = new_settings_class(&block)
|
24
|
+
|
25
|
+
option(name) do |o|
|
26
|
+
o.default settings_class.new
|
27
|
+
o.resetter do |value|
|
28
|
+
value.reset! if value.respond_to?(:reset!)
|
29
|
+
value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def new_settings_class(&block)
|
37
|
+
Class.new { include Datadog::Configuration::Base }.tap do |klass|
|
38
|
+
klass.instance_eval(&block) if block_given?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Instance methods for configuration
|
44
|
+
module InstanceMethods
|
45
|
+
def initialize(options = {})
|
46
|
+
configure(options)
|
47
|
+
end
|
48
|
+
|
49
|
+
def configure(opts = {})
|
50
|
+
# Sort the options in preference of dependency order first
|
51
|
+
ordering = self.class.options.dependency_order
|
52
|
+
sorted_opts = opts.sort_by do |name, _value|
|
53
|
+
ordering.index(name) || (ordering.length + 1)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Ruby 2.0 doesn't support Array#to_h
|
57
|
+
sorted_opts = Hash[*sorted_opts.flatten]
|
58
|
+
|
59
|
+
# Apply options in sort order
|
60
|
+
sorted_opts.each do |name, value|
|
61
|
+
if respond_to?("#{name}=")
|
62
|
+
send("#{name}=", value)
|
63
|
+
elsif option_defined?(name)
|
64
|
+
set_option(name, value)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Apply any additional settings from block
|
69
|
+
yield(self) if block_given?
|
70
|
+
end
|
71
|
+
|
72
|
+
def to_h
|
73
|
+
options_hash
|
74
|
+
end
|
75
|
+
|
76
|
+
def reset!
|
77
|
+
reset_options!
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -13,19 +13,42 @@ module Datadog
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def set(value)
|
16
|
-
@value =
|
16
|
+
(@value = context_exec(value, &definition.setter)).tap do |v|
|
17
17
|
@is_set = true
|
18
|
+
context_exec(v, &definition.on_set) if definition.on_set
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
21
22
|
def get
|
22
|
-
|
23
|
-
|
23
|
+
if @is_set
|
24
|
+
@value
|
25
|
+
elsif definition.delegate_to
|
26
|
+
context_eval(&definition.delegate_to)
|
27
|
+
else
|
28
|
+
set(definition.default_value)
|
29
|
+
end
|
24
30
|
end
|
25
31
|
|
26
32
|
def reset
|
27
|
-
@
|
28
|
-
|
33
|
+
@value = if definition.resetter
|
34
|
+
# Don't change @is_set to false; custom resetters are
|
35
|
+
# responsible for changing @value back to a good state.
|
36
|
+
# Setting @is_set = false would cause a default to be applied.
|
37
|
+
context_exec(@value, &definition.resetter)
|
38
|
+
else
|
39
|
+
@is_set = false
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def context_exec(*args, &block)
|
47
|
+
@context.instance_exec(*args, &block)
|
48
|
+
end
|
49
|
+
|
50
|
+
def context_eval(&block)
|
51
|
+
@context.instance_eval(&block)
|
29
52
|
end
|
30
53
|
end
|
31
54
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'ddtrace/configuration/option'
|
2
|
+
|
1
3
|
module Datadog
|
2
4
|
module Configuration
|
3
5
|
# Represents a definition for an integration configuration option
|
@@ -6,22 +8,120 @@ module Datadog
|
|
6
8
|
|
7
9
|
attr_reader \
|
8
10
|
:default,
|
11
|
+
:delegate_to,
|
9
12
|
:depends_on,
|
10
13
|
:lazy,
|
11
14
|
:name,
|
15
|
+
:on_set,
|
16
|
+
:resetter,
|
12
17
|
:setter
|
13
18
|
|
14
19
|
def initialize(name, meta = {}, &block)
|
15
20
|
@default = meta[:default]
|
21
|
+
@delegate_to = meta[:delegate_to]
|
16
22
|
@depends_on = meta[:depends_on] || []
|
17
23
|
@lazy = meta[:lazy] || false
|
18
24
|
@name = name.to_sym
|
25
|
+
@on_set = meta[:on_set]
|
26
|
+
@resetter = meta[:resetter]
|
19
27
|
@setter = meta[:setter] || block || IDENTITY
|
20
28
|
end
|
21
29
|
|
22
30
|
def default_value
|
23
31
|
lazy ? @default.call : @default
|
24
32
|
end
|
33
|
+
|
34
|
+
# Creates a new Option, bound to the context provided.
|
35
|
+
def build(context)
|
36
|
+
Option.new(self, context)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Acts as DSL for building OptionDefinitions
|
40
|
+
class Builder
|
41
|
+
attr_reader \
|
42
|
+
:helpers
|
43
|
+
|
44
|
+
def initialize(name, options = {})
|
45
|
+
@default = nil
|
46
|
+
@delegate_to = nil
|
47
|
+
@depends_on = []
|
48
|
+
@helpers = {}
|
49
|
+
@lazy = false
|
50
|
+
@name = name.to_sym
|
51
|
+
@on_set = nil
|
52
|
+
@resetter = nil
|
53
|
+
@setter = OptionDefinition::IDENTITY
|
54
|
+
|
55
|
+
# If options were supplied, apply them.
|
56
|
+
apply_options!(options)
|
57
|
+
|
58
|
+
# Apply block if given.
|
59
|
+
yield(self) if block_given?
|
60
|
+
end
|
61
|
+
|
62
|
+
def depends_on(*values)
|
63
|
+
@depends_on = values.flatten
|
64
|
+
end
|
65
|
+
|
66
|
+
def default(value = nil, &block)
|
67
|
+
@default = block_given? ? block : value
|
68
|
+
end
|
69
|
+
|
70
|
+
def delegate_to(&block)
|
71
|
+
@delegate_to = block
|
72
|
+
end
|
73
|
+
|
74
|
+
def helper(name, *_args, &block)
|
75
|
+
@helpers[name] = block
|
76
|
+
end
|
77
|
+
|
78
|
+
# rubocop:disable Style/TrivialAccessors
|
79
|
+
# (Rubocop erroneously thinks #lazy == #lazy= )
|
80
|
+
def lazy(value = true)
|
81
|
+
@lazy = value
|
82
|
+
end
|
83
|
+
|
84
|
+
def on_set(&block)
|
85
|
+
@on_set = block
|
86
|
+
end
|
87
|
+
|
88
|
+
def resetter(&block)
|
89
|
+
@resetter = block
|
90
|
+
end
|
91
|
+
|
92
|
+
def setter(&block)
|
93
|
+
@setter = block
|
94
|
+
end
|
95
|
+
|
96
|
+
# For applying options for OptionDefinition
|
97
|
+
def apply_options!(options = {})
|
98
|
+
return if options.nil? || options.empty?
|
99
|
+
|
100
|
+
default(options[:default]) if options.key?(:default)
|
101
|
+
delegate_to(&options[:delegate_to]) if options.key?(:delegate_to)
|
102
|
+
depends_on(*options[:depends_on]) if options.key?(:depends_on)
|
103
|
+
lazy(options[:lazy]) if options.key?(:lazy)
|
104
|
+
on_set(&options[:on_set]) if options.key?(:on_set)
|
105
|
+
resetter(&options[:resetter]) if options.key?(:resetter)
|
106
|
+
setter(&options[:setter]) if options.key?(:setter)
|
107
|
+
end
|
108
|
+
|
109
|
+
def to_definition
|
110
|
+
OptionDefinition.new(@name, meta)
|
111
|
+
end
|
112
|
+
|
113
|
+
def meta
|
114
|
+
{
|
115
|
+
default: @default,
|
116
|
+
delegate_to: @delegate_to,
|
117
|
+
depends_on: @depends_on,
|
118
|
+
lazy: @lazy,
|
119
|
+
on_set: @on_set,
|
120
|
+
resetter: @resetter,
|
121
|
+
setter: @setter
|
122
|
+
}
|
123
|
+
end
|
124
|
+
end
|
25
125
|
end
|
26
126
|
end
|
27
127
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'ddtrace/configuration/option'
|
2
1
|
require 'ddtrace/configuration/option_set'
|
3
2
|
require 'ddtrace/configuration/option_definition'
|
4
3
|
require 'ddtrace/configuration/option_definition_set'
|
@@ -24,22 +23,33 @@ module Datadog
|
|
24
23
|
protected
|
25
24
|
|
26
25
|
def option(name, meta = {}, &block)
|
27
|
-
|
28
|
-
|
26
|
+
builder = OptionDefinition::Builder.new(name, meta, &block)
|
27
|
+
options[name] = builder.to_definition.tap do
|
28
|
+
# Resolve and define helper functions
|
29
|
+
helpers = default_helpers(name).merge(builder.helpers)
|
30
|
+
define_helpers(helpers)
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
32
34
|
private
|
33
35
|
|
34
|
-
def
|
35
|
-
option_name = name
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
def default_helpers(name)
|
37
|
+
option_name = name.to_sym
|
38
|
+
|
39
|
+
{
|
40
|
+
option_name.to_sym => proc do
|
41
|
+
get_option(option_name)
|
42
|
+
end,
|
43
|
+
"#{option_name}=".to_sym => proc do |value|
|
44
|
+
set_option(option_name, value)
|
45
|
+
end
|
46
|
+
}
|
47
|
+
end
|
40
48
|
|
41
|
-
|
42
|
-
|
49
|
+
def define_helpers(helpers)
|
50
|
+
helpers.each do |name, block|
|
51
|
+
next unless block.is_a?(Proc)
|
52
|
+
define_method(name, &block)
|
43
53
|
end
|
44
54
|
end
|
45
55
|
end
|
@@ -60,7 +70,11 @@ module Datadog
|
|
60
70
|
options[name].get
|
61
71
|
end
|
62
72
|
|
63
|
-
def
|
73
|
+
def option_defined?(name)
|
74
|
+
self.class.options.key?(name)
|
75
|
+
end
|
76
|
+
|
77
|
+
def options_hash
|
64
78
|
options.each_with_object({}) do |(key, _), hash|
|
65
79
|
hash[key] = get_option(key)
|
66
80
|
end
|
@@ -75,13 +89,13 @@ module Datadog
|
|
75
89
|
def add_option(name)
|
76
90
|
assert_valid_option!(name)
|
77
91
|
definition = self.class.options[name]
|
78
|
-
|
92
|
+
definition.build(self).tap do |option|
|
79
93
|
options[name] = option
|
80
94
|
end
|
81
95
|
end
|
82
96
|
|
83
97
|
def assert_valid_option!(name)
|
84
|
-
unless
|
98
|
+
unless option_defined?(name)
|
85
99
|
raise(InvalidOptionError, "#{self.class.name} doesn't define the option: #{name}")
|
86
100
|
end
|
87
101
|
end
|