ddtrace 1.12.1 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +109 -9
- data/ext/ddtrace_profiling_native_extension/collectors_thread_context.c +97 -14
- data/ext/ddtrace_profiling_native_extension/extconf.rb +6 -0
- data/ext/ddtrace_profiling_native_extension/http_transport.c +19 -6
- data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +1 -1
- data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +41 -2
- data/ext/ddtrace_profiling_native_extension/private_vm_api_access.h +6 -0
- data/ext/ddtrace_profiling_native_extension/stack_recorder.c +6 -10
- data/ext/ddtrace_profiling_native_extension/time_helpers.c +40 -4
- data/ext/ddtrace_profiling_native_extension/time_helpers.h +14 -0
- data/lib/datadog/appsec/component.rb +9 -0
- data/lib/datadog/appsec/configuration/settings.rb +104 -195
- data/lib/datadog/appsec/configuration.rb +0 -79
- data/lib/datadog/appsec/contrib/auto_instrument.rb +2 -4
- data/lib/datadog/appsec/contrib/devise/event.rb +57 -0
- data/lib/datadog/appsec/contrib/devise/ext.rb +13 -0
- data/lib/datadog/appsec/contrib/devise/integration.rb +42 -0
- data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +76 -0
- data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +52 -0
- data/lib/datadog/appsec/contrib/devise/patcher.rb +45 -0
- data/lib/datadog/appsec/contrib/devise/resource.rb +35 -0
- data/lib/datadog/appsec/contrib/devise/tracking.rb +49 -0
- data/lib/datadog/appsec/contrib/rack/ext.rb +2 -1
- data/lib/datadog/appsec/contrib/rack/reactive/request.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/reactive/response.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +12 -7
- data/lib/datadog/appsec/contrib/rails/ext.rb +3 -2
- data/lib/datadog/appsec/contrib/rails/framework.rb +1 -3
- data/lib/datadog/appsec/contrib/rails/patcher.rb +8 -8
- data/lib/datadog/appsec/contrib/rails/reactive/action.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/ext.rb +2 -1
- data/lib/datadog/appsec/contrib/sinatra/framework.rb +1 -3
- data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +1 -1
- data/lib/datadog/appsec/event.rb +1 -1
- data/lib/datadog/appsec/extensions.rb +1 -130
- data/lib/datadog/appsec/monitor/reactive/set_user.rb +1 -1
- data/lib/datadog/appsec/processor.rb +1 -1
- data/lib/datadog/appsec/rate_limiter.rb +1 -1
- data/lib/datadog/appsec/remote.rb +1 -1
- data/lib/datadog/appsec.rb +1 -2
- data/lib/datadog/ci/configuration/settings.rb +6 -8
- data/lib/datadog/ci/contrib/cucumber/configuration/settings.rb +7 -5
- data/lib/datadog/ci/contrib/cucumber/ext.rb +10 -8
- data/lib/datadog/ci/contrib/minitest/configuration/settings.rb +35 -0
- data/lib/datadog/ci/contrib/minitest/ext.rb +21 -0
- data/lib/datadog/ci/contrib/minitest/integration.rb +49 -0
- data/lib/datadog/ci/contrib/minitest/patcher.rb +27 -0
- data/lib/datadog/ci/contrib/minitest/test_helper.rb +68 -0
- data/lib/datadog/ci/contrib/rspec/configuration/settings.rb +7 -5
- data/lib/datadog/ci/contrib/rspec/ext.rb +9 -7
- data/lib/datadog/ci.rb +1 -0
- data/lib/datadog/core/backport.rb +51 -0
- data/lib/datadog/core/configuration/base.rb +5 -5
- data/lib/datadog/core/configuration/components.rb +6 -1
- data/lib/datadog/core/configuration/ext.rb +7 -5
- data/lib/datadog/core/configuration/option.rb +269 -19
- data/lib/datadog/core/configuration/option_definition.rb +76 -11
- data/lib/datadog/core/configuration/options.rb +22 -10
- data/lib/datadog/core/configuration/settings.rb +116 -61
- data/lib/datadog/core/environment/ext.rb +13 -11
- data/lib/datadog/core/environment/yjit.rb +58 -0
- data/lib/datadog/core/git/ext.rb +24 -22
- data/lib/datadog/core/logging/ext.rb +3 -1
- data/lib/datadog/core/metrics/ext.rb +7 -5
- data/lib/datadog/core/remote/client/capabilities.rb +5 -0
- data/lib/datadog/core/remote/client.rb +3 -0
- data/lib/datadog/core/remote/component.rb +25 -34
- data/lib/datadog/core/remote/configuration/content.rb +28 -1
- data/lib/datadog/core/remote/configuration/repository.rb +3 -1
- data/lib/datadog/core/remote/ext.rb +1 -1
- data/lib/datadog/core/remote/negotiation.rb +17 -4
- data/lib/datadog/core/runtime/ext.rb +22 -12
- data/lib/datadog/core/runtime/metrics.rb +43 -0
- data/lib/datadog/core/telemetry/client.rb +12 -2
- data/lib/datadog/core/telemetry/emitter.rb +4 -2
- data/lib/datadog/core/telemetry/event.rb +19 -4
- data/lib/datadog/core/telemetry/ext.rb +4 -1
- data/lib/datadog/core/telemetry/heartbeat.rb +2 -4
- data/lib/datadog/core/telemetry/http/ext.rb +10 -8
- data/lib/datadog/core/telemetry/http/transport.rb +1 -0
- data/lib/datadog/core/telemetry/v2/app_client_configuration_change.rb +41 -0
- data/lib/datadog/core/telemetry/v2/request.rb +29 -0
- data/lib/datadog/core/transport/http/client.rb +1 -1
- data/lib/datadog/core/transport/http/config.rb +10 -0
- data/lib/datadog/core/utils/duration.rb +52 -0
- data/lib/datadog/core/utils/hash.rb +47 -0
- data/lib/datadog/core/utils/network.rb +1 -1
- data/lib/datadog/core/utils/safe_dup.rb +27 -20
- data/lib/datadog/core/utils.rb +1 -1
- data/lib/datadog/core/workers/async.rb +2 -2
- data/lib/datadog/kit/appsec/events.rb +139 -89
- data/lib/datadog/kit/identity.rb +80 -65
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +3 -0
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -0
- data/lib/datadog/profiling/collectors/thread_context.rb +9 -2
- data/lib/datadog/profiling/component.rb +41 -9
- data/lib/datadog/profiling/exporter.rb +5 -1
- data/lib/datadog/profiling/flush.rb +9 -2
- data/lib/datadog/profiling/http_transport.rb +4 -1
- data/lib/datadog/profiling/load_native_extension.rb +7 -1
- data/lib/datadog/profiling.rb +11 -1
- data/lib/datadog/tracing/component.rb +58 -6
- data/lib/datadog/tracing/configuration/dynamic/option.rb +71 -0
- data/lib/datadog/tracing/configuration/dynamic.rb +64 -0
- data/lib/datadog/tracing/configuration/ext.rb +35 -32
- data/lib/datadog/tracing/configuration/http.rb +74 -0
- data/lib/datadog/tracing/configuration/settings.rb +106 -92
- data/lib/datadog/tracing/contrib/action_cable/configuration/settings.rb +9 -6
- data/lib/datadog/tracing/contrib/action_cable/ext.rb +20 -18
- data/lib/datadog/tracing/contrib/action_mailer/configuration/settings.rb +9 -6
- data/lib/datadog/tracing/contrib/action_mailer/ext.rb +20 -18
- data/lib/datadog/tracing/contrib/action_pack/configuration/settings.rb +8 -6
- data/lib/datadog/tracing/contrib/action_pack/ext.rb +10 -8
- data/lib/datadog/tracing/contrib/action_view/configuration/settings.rb +9 -6
- data/lib/datadog/tracing/contrib/action_view/ext.rb +12 -10
- data/lib/datadog/tracing/contrib/active_job/configuration/settings.rb +13 -7
- data/lib/datadog/tracing/contrib/active_job/ext.rb +25 -23
- data/lib/datadog/tracing/contrib/active_job/log_injection.rb +1 -1
- data/lib/datadog/tracing/contrib/active_job/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/active_model_serializers/configuration/settings.rb +9 -6
- data/lib/datadog/tracing/contrib/active_model_serializers/ext.rb +12 -10
- data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +9 -7
- data/lib/datadog/tracing/contrib/active_record/events/sql.rb +0 -8
- data/lib/datadog/tracing/contrib/active_record/ext.rb +17 -15
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +0 -5
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +9 -7
- data/lib/datadog/tracing/contrib/active_support/ext.rb +18 -16
- data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +14 -7
- data/lib/datadog/tracing/contrib/aws/ext.rb +37 -24
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +9 -5
- data/lib/datadog/tracing/contrib/concurrent_ruby/configuration/settings.rb +3 -2
- data/lib/datadog/tracing/contrib/concurrent_ruby/ext.rb +4 -2
- data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +14 -7
- data/lib/datadog/tracing/contrib/dalli/ext.rb +19 -11
- data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +8 -6
- data/lib/datadog/tracing/contrib/delayed_job/configuration/settings.rb +13 -7
- data/lib/datadog/tracing/contrib/delayed_job/ext.rb +16 -14
- data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +14 -7
- data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +21 -15
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +8 -5
- data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +16 -9
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +43 -3
- data/lib/datadog/tracing/contrib/ethon/ext.rb +19 -11
- data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +0 -5
- data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +19 -10
- data/lib/datadog/tracing/contrib/excon/ext.rb +16 -8
- data/lib/datadog/tracing/contrib/excon/middleware.rb +20 -5
- data/lib/datadog/tracing/contrib/ext.rb +23 -1
- data/lib/datadog/tracing/contrib/extensions.rb +32 -0
- data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +20 -10
- data/lib/datadog/tracing/contrib/faraday/ext.rb +16 -8
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +16 -5
- data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +8 -6
- data/lib/datadog/tracing/contrib/grape/ext.rb +16 -14
- data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +8 -6
- data/lib/datadog/tracing/contrib/graphql/ext.rb +7 -5
- data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +19 -9
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +29 -20
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +21 -20
- data/lib/datadog/tracing/contrib/grpc/ext.rb +16 -13
- data/lib/datadog/tracing/contrib/grpc/formatting.rb +127 -0
- data/lib/datadog/tracing/contrib/hanami/configuration/settings.rb +3 -2
- data/lib/datadog/tracing/contrib/hanami/ext.rb +10 -8
- data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +4 -7
- data/lib/datadog/tracing/contrib/http/configuration/settings.rb +33 -11
- data/lib/datadog/tracing/contrib/http/ext.rb +16 -9
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +17 -5
- data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +33 -11
- data/lib/datadog/tracing/contrib/httpclient/ext.rb +17 -9
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +17 -5
- data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +33 -11
- data/lib/datadog/tracing/contrib/httprb/ext.rb +16 -9
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +17 -5
- data/lib/datadog/tracing/contrib/kafka/configuration/settings.rb +9 -6
- data/lib/datadog/tracing/contrib/kafka/ext.rb +42 -39
- data/lib/datadog/tracing/contrib/lograge/configuration/settings.rb +3 -2
- data/lib/datadog/tracing/contrib/lograge/ext.rb +3 -1
- data/lib/datadog/tracing/contrib/lograge/instrumentation.rb +1 -0
- data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +14 -7
- data/lib/datadog/tracing/contrib/mongodb/ext.rb +20 -16
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +9 -5
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +17 -14
- data/lib/datadog/tracing/contrib/mysql2/ext.rb +15 -10
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +9 -5
- data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +52 -0
- data/lib/datadog/tracing/contrib/opensearch/ext.rb +37 -0
- data/lib/datadog/tracing/contrib/opensearch/integration.rb +44 -0
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +128 -0
- data/lib/datadog/tracing/contrib/opensearch/quantize.rb +81 -0
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +17 -14
- data/lib/datadog/tracing/contrib/pg/ext.rb +22 -19
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +9 -5
- data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +14 -7
- data/lib/datadog/tracing/contrib/presto/ext.rb +25 -20
- data/lib/datadog/tracing/contrib/presto/instrumentation.rb +9 -5
- data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +12 -10
- data/lib/datadog/tracing/contrib/qless/configuration/settings.rb +12 -8
- data/lib/datadog/tracing/contrib/qless/ext.rb +14 -12
- data/lib/datadog/tracing/contrib/que/configuration/settings.rb +21 -12
- data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +9 -7
- data/lib/datadog/tracing/contrib/racecar/event.rb +0 -5
- data/lib/datadog/tracing/contrib/racecar/ext.rb +20 -18
- data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +16 -12
- data/lib/datadog/tracing/contrib/rack/ext.rb +18 -16
- data/lib/datadog/tracing/contrib/rack/header_collection.rb +3 -0
- data/lib/datadog/tracing/contrib/rack/header_tagging.rb +53 -0
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +8 -49
- data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +15 -11
- data/lib/datadog/tracing/contrib/rails/ext.rb +7 -5
- data/lib/datadog/tracing/contrib/rails/log_injection.rb +4 -10
- data/lib/datadog/tracing/contrib/rails/patcher.rb +10 -41
- data/lib/datadog/tracing/contrib/rails/railtie.rb +3 -3
- data/lib/datadog/tracing/contrib/rake/configuration/settings.rb +12 -9
- data/lib/datadog/tracing/contrib/rake/ext.rb +14 -12
- data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +17 -9
- data/lib/datadog/tracing/contrib/redis/ext.rb +22 -15
- data/lib/datadog/tracing/contrib/redis/tags.rb +9 -5
- data/lib/datadog/tracing/contrib/resque/configuration/settings.rb +13 -7
- data/lib/datadog/tracing/contrib/resque/ext.rb +9 -7
- data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +16 -9
- data/lib/datadog/tracing/contrib/rest_client/ext.rb +15 -8
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +20 -5
- data/lib/datadog/tracing/contrib/roda/configuration/settings.rb +9 -6
- data/lib/datadog/tracing/contrib/semantic_logger/configuration/settings.rb +3 -2
- data/lib/datadog/tracing/contrib/semantic_logger/ext.rb +3 -1
- data/lib/datadog/tracing/contrib/semantic_logger/instrumentation.rb +1 -0
- data/lib/datadog/tracing/contrib/sequel/configuration/settings.rb +9 -6
- data/lib/datadog/tracing/contrib/sequel/ext.rb +10 -8
- data/lib/datadog/tracing/contrib/sequel/utils.rb +2 -7
- data/lib/datadog/tracing/contrib/shoryuken/configuration/settings.rb +14 -8
- data/lib/datadog/tracing/contrib/shoryuken/ext.rb +14 -12
- data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +18 -11
- data/lib/datadog/tracing/contrib/sidekiq/ext.rb +32 -30
- data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +11 -9
- data/lib/datadog/tracing/contrib/sinatra/env.rb +0 -17
- data/lib/datadog/tracing/contrib/sinatra/ext.rb +21 -19
- data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +3 -14
- data/lib/datadog/tracing/contrib/sneakers/configuration/settings.rb +14 -8
- data/lib/datadog/tracing/contrib/sneakers/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sneakers/tracer.rb +1 -1
- data/lib/datadog/tracing/contrib/span_attribute_schema.rb +74 -10
- data/lib/datadog/tracing/contrib/stripe/configuration/settings.rb +9 -6
- data/lib/datadog/tracing/contrib/sucker_punch/configuration/settings.rb +9 -6
- data/lib/datadog/tracing/contrib/sucker_punch/ext.rb +15 -13
- data/lib/datadog/tracing/contrib/utils/database.rb +5 -3
- data/lib/datadog/tracing/correlation.rb +9 -12
- data/lib/datadog/tracing/diagnostics/ext.rb +21 -19
- data/lib/datadog/tracing/distributed/b3_multi.rb +2 -2
- data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
- data/lib/datadog/tracing/distributed/trace_context.rb +52 -17
- data/lib/datadog/tracing/metadata/ext.rb +9 -6
- data/lib/datadog/tracing/remote.rb +78 -0
- data/lib/datadog/tracing/sampling/rule_sampler.rb +29 -0
- data/lib/datadog/tracing/span_operation.rb +3 -15
- data/lib/datadog/tracing/trace_operation.rb +16 -3
- data/lib/datadog/tracing/trace_segment.rb +5 -2
- data/lib/datadog/tracing/tracer.rb +10 -1
- data/lib/ddtrace/transport/ext.rb +15 -9
- data/lib/ddtrace/transport/trace_formatter.rb +9 -0
- data/lib/ddtrace/version.rb +9 -12
- metadata +38 -10
- data/lib/datadog/tracing/contrib/sinatra/headers.rb +0 -35
|
@@ -1,27 +1,113 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative '../utils/safe_dup'
|
|
4
|
+
|
|
3
5
|
module Datadog
|
|
4
6
|
module Core
|
|
5
7
|
module Configuration
|
|
6
8
|
# Represents an instance of an integration configuration option
|
|
7
9
|
# @public_api
|
|
8
10
|
class Option
|
|
9
|
-
attr_reader
|
|
10
|
-
|
|
11
|
+
attr_reader :definition
|
|
12
|
+
|
|
13
|
+
# Option setting precedence.
|
|
14
|
+
module Precedence
|
|
15
|
+
# Represents an Option precedence level.
|
|
16
|
+
# Each precedence has a `numeric` value; higher values means higher precedence.
|
|
17
|
+
# `name` is for inspection purposes only.
|
|
18
|
+
Value = Struct.new(:numeric, :name) do
|
|
19
|
+
include Comparable
|
|
20
|
+
|
|
21
|
+
def <=>(other)
|
|
22
|
+
return nil unless other.is_a?(Value)
|
|
23
|
+
|
|
24
|
+
numeric <=> other.numeric
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Remote configuration provided through the Datadog app.
|
|
29
|
+
REMOTE_CONFIGURATION = Value.new(2, :remote_configuration).freeze
|
|
30
|
+
|
|
31
|
+
# Configuration provided in Ruby code, in this same process
|
|
32
|
+
# or via Environment variable
|
|
33
|
+
PROGRAMMATIC = Value.new(1, :programmatic).freeze
|
|
34
|
+
|
|
35
|
+
# Configuration that comes from default values
|
|
36
|
+
DEFAULT = Value.new(0, :default).freeze
|
|
37
|
+
|
|
38
|
+
# All precedences, sorted from highest to lowest
|
|
39
|
+
LIST = [REMOTE_CONFIGURATION, PROGRAMMATIC, DEFAULT].sort.reverse.freeze
|
|
40
|
+
end
|
|
11
41
|
|
|
12
42
|
def initialize(definition, context)
|
|
13
43
|
@definition = definition
|
|
14
44
|
@context = context
|
|
15
45
|
@value = nil
|
|
16
46
|
@is_set = false
|
|
47
|
+
|
|
48
|
+
# One value is stored per precedence, to allow unsetting a higher
|
|
49
|
+
# precedence value and falling back to a lower precedence one.
|
|
50
|
+
@value_per_precedence = Hash.new(UNSET)
|
|
51
|
+
|
|
52
|
+
# Lowest precedence, to allow for `#set` to always succeed for a brand new `Option` instance.
|
|
53
|
+
@precedence_set = Precedence::DEFAULT
|
|
17
54
|
end
|
|
18
55
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
56
|
+
# Overrides the current value for this option if the `precedence` is equal or higher than
|
|
57
|
+
# the previously set value.
|
|
58
|
+
# The first call to `#set` will always store the value regardless of precedence.
|
|
59
|
+
#
|
|
60
|
+
# @param value [Object] the new value to be associated with this option
|
|
61
|
+
# @param precedence [Precedence] from what precedence order this new value comes from
|
|
62
|
+
def set(value, precedence: Precedence::PROGRAMMATIC)
|
|
63
|
+
# Is there a higher precedence value set?
|
|
64
|
+
if @precedence_set > precedence
|
|
65
|
+
# This should be uncommon, as higher precedence values tend to
|
|
66
|
+
# happen later in the application lifecycle.
|
|
67
|
+
Datadog.logger.info do
|
|
68
|
+
"Option '#{definition.name}' not changed to '#{value}' (precedence: #{precedence.name}) because the higher " \
|
|
69
|
+
"precedence value '#{@value}' (precedence: #{@precedence_set.name}) was already set."
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# But if it happens, we have to store the lower precedence value `value`
|
|
73
|
+
# because it's possible to revert to it by `#unset`ting
|
|
74
|
+
# the existing, higher-precedence value.
|
|
75
|
+
# Effectively, we always store one value pre precedence.
|
|
76
|
+
@value_per_precedence[precedence] = value
|
|
77
|
+
|
|
78
|
+
return @value
|
|
24
79
|
end
|
|
80
|
+
|
|
81
|
+
internal_set(value, precedence)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def unset(precedence)
|
|
85
|
+
@value_per_precedence[precedence] = UNSET
|
|
86
|
+
|
|
87
|
+
# If we are unsetting the currently active value, we have to restore
|
|
88
|
+
# a lower precedence one...
|
|
89
|
+
if precedence == @precedence_set
|
|
90
|
+
# Find a lower precedence value that is already set.
|
|
91
|
+
Precedence::LIST.each do |p|
|
|
92
|
+
# DEV: This search can be optimized, but the list is small, and unset is
|
|
93
|
+
# DEV: only called from direct user interaction in the Datadog UI.
|
|
94
|
+
next unless p < precedence
|
|
95
|
+
|
|
96
|
+
# Look for value that is set.
|
|
97
|
+
# The hash `@value_per_precedence` has a custom default value of `UNSET`.
|
|
98
|
+
if (value = @value_per_precedence[p]) != UNSET
|
|
99
|
+
internal_set(value, p)
|
|
100
|
+
return nil
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# If no value is left to fall back on, reset this option
|
|
105
|
+
reset
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# ... otherwise, we are either unsetting a higher precedence value that is not
|
|
109
|
+
# yet set, thus there's nothing to do; or we are unsetting a lower precedence
|
|
110
|
+
# value, which also does not change the current value.
|
|
25
111
|
end
|
|
26
112
|
|
|
27
113
|
def get
|
|
@@ -30,32 +116,160 @@ module Datadog
|
|
|
30
116
|
elsif definition.delegate_to
|
|
31
117
|
context_eval(&definition.delegate_to)
|
|
32
118
|
else
|
|
33
|
-
|
|
119
|
+
set_value_from_env_or_default
|
|
34
120
|
end
|
|
35
121
|
end
|
|
36
122
|
|
|
37
123
|
def reset
|
|
38
|
-
@value =
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
124
|
+
@value = if definition.resetter
|
|
125
|
+
# Don't change @is_set to false; custom resetters are
|
|
126
|
+
# responsible for changing @value back to a good state.
|
|
127
|
+
# Setting @is_set = false would cause a default to be applied.
|
|
128
|
+
context_exec(@value, &definition.resetter)
|
|
129
|
+
else
|
|
130
|
+
@is_set = false
|
|
131
|
+
nil
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Reset back to the lowest precedence, to allow all `set`s to succeed right after a reset.
|
|
135
|
+
@precedence_set = Precedence::DEFAULT
|
|
136
|
+
# Reset all stored values
|
|
137
|
+
@value_per_precedence = Hash.new(UNSET)
|
|
47
138
|
end
|
|
48
139
|
|
|
49
140
|
def default_value
|
|
50
|
-
if definition.
|
|
141
|
+
if definition.default.instance_of?(Proc)
|
|
51
142
|
context_eval(&definition.default)
|
|
52
143
|
else
|
|
53
|
-
definition.default
|
|
144
|
+
definition.experimental_default_proc || Core::Utils::SafeDup.frozen_or_dup(definition.default)
|
|
54
145
|
end
|
|
55
146
|
end
|
|
56
147
|
|
|
148
|
+
def default_precedence?
|
|
149
|
+
precedence_set == Precedence::DEFAULT
|
|
150
|
+
end
|
|
151
|
+
|
|
57
152
|
private
|
|
58
153
|
|
|
154
|
+
def coerce_env_variable(value)
|
|
155
|
+
return context_exec(value, &@definition.env_parser) if @definition.env_parser
|
|
156
|
+
|
|
157
|
+
case @definition.type
|
|
158
|
+
when :hash
|
|
159
|
+
values = value.split(',') # By default we only want to support comma separated strings
|
|
160
|
+
|
|
161
|
+
values.map! do |v|
|
|
162
|
+
v.gsub!(/\A[\s,]*|[\s,]*\Z/, '')
|
|
163
|
+
|
|
164
|
+
v.empty? ? nil : v
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
values.compact!
|
|
168
|
+
values.each.with_object({}) do |v, hash|
|
|
169
|
+
pair = v.split(':', 2)
|
|
170
|
+
hash[pair[0]] = pair[1]
|
|
171
|
+
end
|
|
172
|
+
when :int
|
|
173
|
+
# DEV-2.0: Change to a more strict coercion method. Integer(value).
|
|
174
|
+
value.to_i
|
|
175
|
+
when :float
|
|
176
|
+
# DEV-2.0: Change to a more strict coercion method. Float(value).
|
|
177
|
+
value.to_f
|
|
178
|
+
when :array
|
|
179
|
+
values = value.split(',')
|
|
180
|
+
|
|
181
|
+
values.map! do |v|
|
|
182
|
+
v.gsub!(/\A[\s,]*|[\s,]*\Z/, '')
|
|
183
|
+
|
|
184
|
+
v.empty? ? nil : v
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
values.compact!
|
|
188
|
+
values
|
|
189
|
+
when :bool
|
|
190
|
+
string_value = value.strip
|
|
191
|
+
string_value = string_value.downcase
|
|
192
|
+
string_value == 'true' || string_value == '1' # rubocop:disable Style/MultipleComparison
|
|
193
|
+
when :string, NilClass
|
|
194
|
+
value
|
|
195
|
+
else
|
|
196
|
+
raise ArgumentError,
|
|
197
|
+
"The option #{@definition.name} is using an unsupported type option for env coercion `#{@definition.type}`"
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def validate_type(value)
|
|
202
|
+
return value if skip_validation?
|
|
203
|
+
|
|
204
|
+
raise_error = false
|
|
205
|
+
|
|
206
|
+
valid_type = validate(@definition.type, value)
|
|
207
|
+
|
|
208
|
+
unless valid_type
|
|
209
|
+
raise_error = if @definition.type_options[:nilable]
|
|
210
|
+
!value.is_a?(NilClass)
|
|
211
|
+
else
|
|
212
|
+
true
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
if raise_error
|
|
217
|
+
error_msg = if @definition.type_options[:nilable]
|
|
218
|
+
"The setting `#{@definition.name}` inside your app's `Datadog.configure` block expects a "\
|
|
219
|
+
"#{@definition.type} or `nil`, but a `#{value.class}` was provided (#{value.inspect})."\
|
|
220
|
+
else
|
|
221
|
+
"The setting `#{@definition.name}` inside your app's `Datadog.configure` block expects a "\
|
|
222
|
+
"#{@definition.type}, but a `#{value.class}` was provided (#{value.inspect})."\
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
error_msg = "#{error_msg} Please update your `configure` block. "\
|
|
226
|
+
'Alternatively, you can disable this validation using the '\
|
|
227
|
+
'`DD_EXPERIMENTAL_SKIP_CONFIGURATION_VALIDATION=true`environment variable. '\
|
|
228
|
+
'For help, please open an issue on <https://github.com/datadog/dd-trace-rb/issues/new/choose>.'
|
|
229
|
+
|
|
230
|
+
raise ArgumentError, error_msg
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
value
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def validate(type, value)
|
|
237
|
+
case type
|
|
238
|
+
when :string
|
|
239
|
+
value.is_a?(String)
|
|
240
|
+
when :int, :float
|
|
241
|
+
value.is_a?(Numeric)
|
|
242
|
+
when :array
|
|
243
|
+
value.is_a?(Array)
|
|
244
|
+
when :hash
|
|
245
|
+
value.is_a?(Hash)
|
|
246
|
+
when :bool
|
|
247
|
+
value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
|
248
|
+
when :proc
|
|
249
|
+
value.is_a?(Proc)
|
|
250
|
+
when :symbol
|
|
251
|
+
value.is_a?(Symbol)
|
|
252
|
+
when NilClass
|
|
253
|
+
true # No validation is performed when option is typeless
|
|
254
|
+
else
|
|
255
|
+
raise ArgumentError, "The option #{@definition.name} is using an unsupported type option `#{@definition.type}`"
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# Directly manipulates the current value and currently set precedence.
|
|
260
|
+
def internal_set(value, precedence)
|
|
261
|
+
old_value = @value
|
|
262
|
+
(@value = context_exec(validate_type(value), old_value, &definition.setter)).tap do |v|
|
|
263
|
+
@is_set = true
|
|
264
|
+
@precedence_set = precedence
|
|
265
|
+
# Store original value to ensure we can always safely call `#internal_set`
|
|
266
|
+
# when restoring a value from `@value_per_precedence`, and we are only running `definition.setter`
|
|
267
|
+
# on the original value, not on a valud that has already been processed by `definition.setter`.
|
|
268
|
+
@value_per_precedence[precedence] = value
|
|
269
|
+
context_exec(v, old_value, &definition.on_set) if definition.on_set
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
59
273
|
def context_exec(*args, &block)
|
|
60
274
|
@context.instance_exec(*args, &block)
|
|
61
275
|
end
|
|
@@ -63,6 +277,42 @@ module Datadog
|
|
|
63
277
|
def context_eval(&block)
|
|
64
278
|
@context.instance_eval(&block)
|
|
65
279
|
end
|
|
280
|
+
|
|
281
|
+
def set_value_from_env_or_default
|
|
282
|
+
value = nil
|
|
283
|
+
precedence = nil
|
|
284
|
+
|
|
285
|
+
if definition.env && ENV[definition.env]
|
|
286
|
+
value = coerce_env_variable(ENV[definition.env])
|
|
287
|
+
precedence = Precedence::PROGRAMMATIC
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
if value.nil? && definition.deprecated_env && ENV[definition.deprecated_env]
|
|
291
|
+
value = coerce_env_variable(ENV[definition.deprecated_env])
|
|
292
|
+
precedence = Precedence::PROGRAMMATIC
|
|
293
|
+
|
|
294
|
+
Datadog::Core.log_deprecation do
|
|
295
|
+
"#{definition.deprecated_env} environment variable is deprecated, use #{definition.env} instead."
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
option_value = value.nil? ? default_value : value
|
|
300
|
+
|
|
301
|
+
set(option_value, precedence: precedence || Precedence::DEFAULT)
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def skip_validation?
|
|
305
|
+
['true', '1'].include?(ENV.fetch('DD_EXPERIMENTAL_SKIP_CONFIGURATION_VALIDATION', '').strip)
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
# Used for testing
|
|
309
|
+
attr_reader :precedence_set
|
|
310
|
+
private :precedence_set
|
|
311
|
+
|
|
312
|
+
# Anchor object that represents a value that is not set.
|
|
313
|
+
# This is necessary because `nil` is a valid value to be set.
|
|
314
|
+
UNSET = Object.new
|
|
315
|
+
private_constant :UNSET
|
|
66
316
|
end
|
|
67
317
|
end
|
|
68
318
|
end
|
|
@@ -11,25 +11,37 @@ module Datadog
|
|
|
11
11
|
|
|
12
12
|
attr_reader \
|
|
13
13
|
:default,
|
|
14
|
+
# experimental_default_proc is used when we want to store a block as part of the option value.
|
|
15
|
+
# Since this new option is experimental and we might not need it in the near future, I gave it a name that is
|
|
16
|
+
# clear to the reader that they should not rely on it and that is subject to change.
|
|
17
|
+
# Currently is only use internally.
|
|
18
|
+
:experimental_default_proc,
|
|
19
|
+
:env,
|
|
20
|
+
:deprecated_env,
|
|
21
|
+
:env_parser,
|
|
14
22
|
:delegate_to,
|
|
15
23
|
:depends_on,
|
|
16
|
-
:lazy,
|
|
17
24
|
:name,
|
|
18
25
|
:on_set,
|
|
19
26
|
:resetter,
|
|
20
27
|
:setter,
|
|
21
|
-
:type
|
|
28
|
+
:type,
|
|
29
|
+
:type_options
|
|
22
30
|
|
|
23
31
|
def initialize(name, meta = {}, &block)
|
|
24
32
|
@default = meta[:default]
|
|
33
|
+
@experimental_default_proc = meta[:experimental_default_proc]
|
|
34
|
+
@env = meta[:env]
|
|
35
|
+
@deprecated_env = meta[:deprecated_env]
|
|
36
|
+
@env_parser = meta[:env_parser]
|
|
25
37
|
@delegate_to = meta[:delegate_to]
|
|
26
38
|
@depends_on = meta[:depends_on] || []
|
|
27
|
-
@lazy = meta[:lazy] || false
|
|
28
39
|
@name = name.to_sym
|
|
29
40
|
@on_set = meta[:on_set]
|
|
30
41
|
@resetter = meta[:resetter]
|
|
31
42
|
@setter = meta[:setter] || block || IDENTITY
|
|
32
43
|
@type = meta[:type]
|
|
44
|
+
@type_options = meta[:type_options]
|
|
33
45
|
end
|
|
34
46
|
|
|
35
47
|
# Creates a new Option, bound to the context provided.
|
|
@@ -40,36 +52,59 @@ module Datadog
|
|
|
40
52
|
# Acts as DSL for building OptionDefinitions
|
|
41
53
|
# @public_api
|
|
42
54
|
class Builder
|
|
55
|
+
class InvalidOptionError < StandardError; end
|
|
56
|
+
|
|
43
57
|
attr_reader \
|
|
44
58
|
:helpers
|
|
45
59
|
|
|
46
60
|
def initialize(name, options = {})
|
|
61
|
+
@env = nil
|
|
62
|
+
@deprecated_env = nil
|
|
63
|
+
@env_parser = nil
|
|
47
64
|
@default = nil
|
|
65
|
+
@experimental_default_proc = nil
|
|
48
66
|
@delegate_to = nil
|
|
49
67
|
@depends_on = []
|
|
50
68
|
@helpers = {}
|
|
51
|
-
@lazy = false
|
|
52
69
|
@name = name.to_sym
|
|
53
70
|
@on_set = nil
|
|
54
71
|
@resetter = nil
|
|
55
72
|
@setter = OptionDefinition::IDENTITY
|
|
56
73
|
@type = nil
|
|
57
|
-
|
|
74
|
+
@type_options = {}
|
|
58
75
|
# If options were supplied, apply them.
|
|
59
76
|
apply_options!(options)
|
|
60
77
|
|
|
61
78
|
# Apply block if given.
|
|
62
79
|
yield(self) if block_given?
|
|
80
|
+
|
|
81
|
+
validate_options!
|
|
63
82
|
end
|
|
64
83
|
|
|
65
84
|
def depends_on(*values)
|
|
66
85
|
@depends_on = values.flatten
|
|
67
86
|
end
|
|
68
87
|
|
|
88
|
+
def env(value)
|
|
89
|
+
@env = value
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def deprecated_env(value)
|
|
93
|
+
@deprecated_env = value
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def env_parser(&block)
|
|
97
|
+
@env_parser = block
|
|
98
|
+
end
|
|
99
|
+
|
|
69
100
|
def default(value = nil, &block)
|
|
70
101
|
@default = block || value
|
|
71
102
|
end
|
|
72
103
|
|
|
104
|
+
def experimental_default_proc(&block)
|
|
105
|
+
@experimental_default_proc = block
|
|
106
|
+
end
|
|
107
|
+
|
|
73
108
|
def delegate_to(&block)
|
|
74
109
|
@delegate_to = block
|
|
75
110
|
end
|
|
@@ -78,8 +113,14 @@ module Datadog
|
|
|
78
113
|
@helpers[name] = block
|
|
79
114
|
end
|
|
80
115
|
|
|
81
|
-
def lazy(
|
|
82
|
-
|
|
116
|
+
def lazy(_value = true)
|
|
117
|
+
Datadog::Core.log_deprecation do
|
|
118
|
+
'Defining an option as lazy is deprecated for removal. Options now always behave as lazy. '\
|
|
119
|
+
"Please remove all references to the lazy setting.\n"\
|
|
120
|
+
'Non-lazy options that were previously stored as blocks are no longer supported. '\
|
|
121
|
+
'If you used this feature, please let us know by opening an issue on: '\
|
|
122
|
+
'https://github.com/datadog/dd-trace-rb/issues/new so we can better understand and support your use case.'
|
|
123
|
+
end
|
|
83
124
|
end
|
|
84
125
|
|
|
85
126
|
def on_set(&block)
|
|
@@ -94,23 +135,32 @@ module Datadog
|
|
|
94
135
|
@setter = block
|
|
95
136
|
end
|
|
96
137
|
|
|
97
|
-
def type(value
|
|
138
|
+
def type(value, nilable: false)
|
|
98
139
|
@type = value
|
|
140
|
+
@type_options = { nilable: nilable }
|
|
141
|
+
|
|
142
|
+
value
|
|
99
143
|
end
|
|
100
144
|
|
|
101
145
|
# For applying options for OptionDefinition
|
|
146
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
102
147
|
def apply_options!(options = {})
|
|
103
148
|
return if options.nil? || options.empty?
|
|
104
149
|
|
|
105
150
|
default(options[:default]) if options.key?(:default)
|
|
151
|
+
experimental_default_proc(&options[:experimental_default_proc]) if options.key?(:experimental_default_proc)
|
|
152
|
+
env(options[:env]) if options.key?(:env)
|
|
153
|
+
deprecated_env(options[:deprecated_env]) if options.key?(:deprecated_env)
|
|
154
|
+
env_parser(&options[:env_parser]) if options.key?(:env_parser)
|
|
106
155
|
delegate_to(&options[:delegate_to]) if options.key?(:delegate_to)
|
|
107
156
|
depends_on(*options[:depends_on]) if options.key?(:depends_on)
|
|
108
157
|
lazy(options[:lazy]) if options.key?(:lazy)
|
|
109
158
|
on_set(&options[:on_set]) if options.key?(:on_set)
|
|
110
159
|
resetter(&options[:resetter]) if options.key?(:resetter)
|
|
111
160
|
setter(&options[:setter]) if options.key?(:setter)
|
|
112
|
-
type(
|
|
161
|
+
type(options[:type], **(options[:type_options] || {})) if options.key?(:type)
|
|
113
162
|
end
|
|
163
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
114
164
|
|
|
115
165
|
def to_definition
|
|
116
166
|
OptionDefinition.new(@name, meta)
|
|
@@ -119,15 +169,30 @@ module Datadog
|
|
|
119
169
|
def meta
|
|
120
170
|
{
|
|
121
171
|
default: @default,
|
|
172
|
+
experimental_default_proc: @experimental_default_proc,
|
|
173
|
+
env: @env,
|
|
174
|
+
deprecated_env: @deprecated_env,
|
|
175
|
+
env_parser: @env_parser,
|
|
122
176
|
delegate_to: @delegate_to,
|
|
123
177
|
depends_on: @depends_on,
|
|
124
|
-
lazy: @lazy,
|
|
125
178
|
on_set: @on_set,
|
|
126
179
|
resetter: @resetter,
|
|
127
180
|
setter: @setter,
|
|
128
|
-
type: @type
|
|
181
|
+
type: @type,
|
|
182
|
+
type_options: @type_options
|
|
129
183
|
}
|
|
130
184
|
end
|
|
185
|
+
|
|
186
|
+
private
|
|
187
|
+
|
|
188
|
+
def validate_options!
|
|
189
|
+
if !@default.nil? && @experimental_default_proc
|
|
190
|
+
raise InvalidOptionError,
|
|
191
|
+
'Using `default` and `experimental_default_proc` is not allowed. Please use one or the other.' \
|
|
192
|
+
'If you want to store a block as the default value use `experimental_default_proc`'\
|
|
193
|
+
' otherwise use `default`'
|
|
194
|
+
end
|
|
195
|
+
end
|
|
131
196
|
end
|
|
132
197
|
end
|
|
133
198
|
end
|
|
@@ -24,7 +24,9 @@ module Datadog
|
|
|
24
24
|
protected
|
|
25
25
|
|
|
26
26
|
def option(name, meta = {}, &block)
|
|
27
|
-
|
|
27
|
+
settings_name = defined?(@settings_name) && @settings_name
|
|
28
|
+
option_name = settings_name ? "#{settings_name}.#{name}" : name
|
|
29
|
+
builder = OptionDefinition::Builder.new(option_name, meta, &block)
|
|
28
30
|
options[name] = builder.to_definition.tap do
|
|
29
31
|
# Resolve and define helper functions
|
|
30
32
|
helpers = default_helpers(name)
|
|
@@ -65,14 +67,16 @@ module Datadog
|
|
|
65
67
|
@options ||= OptionSet.new
|
|
66
68
|
end
|
|
67
69
|
|
|
68
|
-
def set_option(name, value)
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
def set_option(name, value, precedence: Configuration::Option::Precedence::PROGRAMMATIC)
|
|
71
|
+
resolve_option(name).set(value, precedence: precedence)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def unset_option(name, precedence: Configuration::Option::Precedence::PROGRAMMATIC)
|
|
75
|
+
resolve_option(name).unset(precedence)
|
|
71
76
|
end
|
|
72
77
|
|
|
73
78
|
def get_option(name)
|
|
74
|
-
|
|
75
|
-
options[name].get
|
|
79
|
+
resolve_option(name).get
|
|
76
80
|
end
|
|
77
81
|
|
|
78
82
|
def reset_option(name)
|
|
@@ -84,6 +88,12 @@ module Datadog
|
|
|
84
88
|
self.class.options.key?(name)
|
|
85
89
|
end
|
|
86
90
|
|
|
91
|
+
# Is this option's value the default fallback value?
|
|
92
|
+
def using_default?(name)
|
|
93
|
+
get_option(name) # Resolve value check if environment variable overwrote the default
|
|
94
|
+
options[name].default_precedence?
|
|
95
|
+
end
|
|
96
|
+
|
|
87
97
|
def options_hash
|
|
88
98
|
self.class.options.merge(options).each_with_object({}) do |(key, _), hash|
|
|
89
99
|
hash[key] = get_option(key)
|
|
@@ -96,12 +106,14 @@ module Datadog
|
|
|
96
106
|
|
|
97
107
|
private
|
|
98
108
|
|
|
99
|
-
|
|
109
|
+
# Ensure option DSL is loaded
|
|
110
|
+
def resolve_option(name)
|
|
111
|
+
option = options[name]
|
|
112
|
+
return option if option
|
|
113
|
+
|
|
100
114
|
assert_valid_option!(name)
|
|
101
115
|
definition = self.class.options[name]
|
|
102
|
-
definition.build(self)
|
|
103
|
-
options[name] = option
|
|
104
|
-
end
|
|
116
|
+
options[name] = definition.build(self)
|
|
105
117
|
end
|
|
106
118
|
|
|
107
119
|
def assert_valid_option!(name)
|