From 3acd7d5b58d5175aa160655508e23e33438fef0c Mon Sep 17 00:00:00 2001 From: David Elner Date: Thu, 2 Apr 2020 15:35:12 -0400 Subject: [PATCH 1/4] Added: Datadog::Configuration::Components --- lib/ddtrace/configuration.rb | 21 +++++++++++++++++++++ lib/ddtrace/configuration/components.rb | 12 ++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 lib/ddtrace/configuration/components.rb diff --git a/lib/ddtrace/configuration.rb b/lib/ddtrace/configuration.rb index 2e27f280d53..f16777e83aa 100644 --- a/lib/ddtrace/configuration.rb +++ b/lib/ddtrace/configuration.rb @@ -1,9 +1,14 @@ +require 'forwardable' + require 'ddtrace/configuration/pin_setup' require 'ddtrace/configuration/settings' +require 'ddtrace/configuration/components' module Datadog # Configuration provides a unique access point for configurations module Configuration + extend Forwardable + attr_writer :configuration def configuration @@ -13,6 +18,11 @@ def configuration def configure(target = configuration, opts = {}) if target.is_a?(Settings) yield(target) if block_given? + + # Rebuild immutable components from settings + rebuild_components!(target) + + target else PinSetup.new(target, opts).call end @@ -26,5 +36,16 @@ def tracer def runtime_metrics tracer.writer.runtime_metrics end + + protected + + def components + @components ||= Components.new(configuration) + end + + def rebuild_components!(configuration) + @components.teardown! if instance_variable_defined?(:@components) + @components = Components.new(configuration) + end end end diff --git a/lib/ddtrace/configuration/components.rb b/lib/ddtrace/configuration/components.rb new file mode 100644 index 00000000000..da77f33aa63 --- /dev/null +++ b/lib/ddtrace/configuration/components.rb @@ -0,0 +1,12 @@ +require 'ddtrace/tracer' + +module Datadog + module Configuration + # Global components for the trace library. + class Components + def initialize(settings); end + + def teardown!; end + end + end +end From a89a73ddcabc353566a766563876a0048093eab5 Mon Sep 17 00:00:00 2001 From: David Elner Date: Mon, 6 Apr 2020 16:13:04 -0400 Subject: [PATCH 2/4] Refactored: Extract #tracer and #runtime_metrics to Components --- lib/ddtrace/configuration.rb | 32 +- lib/ddtrace/configuration/components.rb | 74 +- lib/ddtrace/configuration/settings.rb | 152 ++-- lib/ddtrace/contrib/analytics.rb | 2 +- lib/ddtrace/opentracer/global_tracer.rb | 2 +- lib/ddtrace/tracer.rb | 35 +- spec/ddtrace/configuration/components_spec.rb | 124 +++ spec/ddtrace/configuration/settings_spec.rb | 716 +++++++++++++++--- spec/ddtrace/configuration_spec.rb | 93 +++ spec/ddtrace/contrib/analytics_examples.rb | 16 +- spec/ddtrace/integration_spec.rb | 94 +-- spec/ddtrace/span_spec.rb | 15 +- spec/ddtrace/tracer_spec.rb | 2 +- 13 files changed, 1086 insertions(+), 271 deletions(-) create mode 100644 spec/ddtrace/configuration/components_spec.rb diff --git a/lib/ddtrace/configuration.rb b/lib/ddtrace/configuration.rb index f16777e83aa..a1b5b4a984a 100644 --- a/lib/ddtrace/configuration.rb +++ b/lib/ddtrace/configuration.rb @@ -28,14 +28,10 @@ def configure(target = configuration, opts = {}) end end - # Helper methods - def tracer - configuration.tracer - end - - def runtime_metrics - tracer.writer.runtime_metrics - end + def_delegators \ + :components, + :runtime_metrics, + :tracer protected @@ -44,8 +40,24 @@ def components end def rebuild_components!(configuration) - @components.teardown! if instance_variable_defined?(:@components) - @components = Components.new(configuration) + # Build new components + new_components = Components.new(configuration) + + # Teardown old components if they exist + teardown_components!(@components, new_components) if instance_variable_defined?(:@components) + + # Activate new components + @components = new_components + end + + def teardown_components!(old, current) + # Shutdown the old tracer, unless it's still being used. + # (e.g. a custom tracer instance passed in.) + old.tracer.shutdown! unless old.tracer == current.tracer + + # Shutdown the old metrics, unless they are still being used. + # (e.g. custom Statsd instances.) + old.runtime_metrics.statsd.close unless old.runtime_metrics.statsd == current.runtime_metrics.statsd end end end diff --git a/lib/ddtrace/configuration/components.rb b/lib/ddtrace/configuration/components.rb index da77f33aa63..a604e51f0ff 100644 --- a/lib/ddtrace/configuration/components.rb +++ b/lib/ddtrace/configuration/components.rb @@ -3,10 +3,80 @@ module Datadog module Configuration # Global components for the trace library. + # rubocop:disable Metrics/LineLength class Components - def initialize(settings); end + def initialize(settings) + # Tracer + @tracer = build_tracer(settings) - def teardown!; end + # Runtime metrics + build_runtime_metrics(settings) + end + + attr_reader \ + :tracer + + def runtime_metrics + tracer.writer.runtime_metrics + end + + private + + def build_tracer(settings) + # If a custom tracer has been provided, use it instead. + # Ignore all other options (they should already be configured.) + return settings.tracer.instance unless settings.tracer.instance.nil? + + tracer = Tracer.new( + default_service: settings.service, + enabled: settings.tracer.enabled, + partial_flush: settings.tracer.partial_flush, + tags: build_tracer_tags(settings) + ) + + # TODO: We reconfigure the tracer here because it has way too many + # options it allows to mutate, and it's overwhelming to rewrite + # tracer initialization for now. Just reconfigure using the + # existing mutable #configure function. Remove when these components + # are extracted. + tracer.configure(build_tracer_options(settings)) + + tracer + end + + def build_tracer_tags(settings) + settings.tags.dup.tap do |tags| + tags['env'] = settings.env unless settings.env.nil? + tags['version'] = settings.version unless settings.version.nil? + end + end + + def build_tracer_options(settings) + settings = settings.tracer + + {}.tap do |opts| + opts[:hostname] = settings.hostname unless settings.hostname.nil? + opts[:min_spans_before_partial_flush] = settings.partial_flush.min_spans_threshold unless settings.partial_flush.min_spans_threshold.nil? + opts[:partial_flush] = settings.partial_flush.enabled unless settings.partial_flush.enabled.nil? + opts[:port] = settings.port unless settings.port.nil? + opts[:priority_sampling] = settings.priority_sampling unless settings.priority_sampling.nil? + opts[:sampler] = settings.sampler unless settings.sampler.nil? + opts[:transport_options] = settings.transport_options + opts[:writer] = settings.writer unless settings.writer.nil? + opts[:writer_options] = settings.writer_options if settings.writer.nil? + end + end + + def build_runtime_metrics(settings) + settings = settings.runtime_metrics + options = { enabled: settings.enabled } + options[:statsd] = settings.statsd unless settings.statsd.nil? + + # TODO: We reconfigure runtime metrics here because it is too deeply nested + # within the tracer/writer. Build a new runtime metrics instance when + # runtime metrics are extracted from tracer/writer. + runtime_metrics.configure(options) + end end end end diff --git a/lib/ddtrace/configuration/settings.rb b/lib/ddtrace/configuration/settings.rb index b448133c23f..6b96a1b040d 100644 --- a/lib/ddtrace/configuration/settings.rb +++ b/lib/ddtrace/configuration/settings.rb @@ -5,23 +5,32 @@ require 'ddtrace/ext/runtime' require 'ddtrace/ext/sampling' -require 'ddtrace/tracer' -require 'ddtrace/metrics' require 'ddtrace/diagnostics/health' +require 'ddtrace/logger' module Datadog module Configuration # Global configuration settings for the trace library. + # rubocop:disable Metrics/ClassLength class Settings include Base # # Configuration options # + settings :analytics do + option :enabled do |o| + o.default { env_to_bool(Ext::Analytics::ENV_TRACE_ANALYTICS_ENABLED, nil) } + o.lazy + end + end + option :analytics_enabled do |o| - # TODO: Raise deprecation warning - o.default { env_to_bool(Ext::Analytics::ENV_TRACE_ANALYTICS_ENABLED, nil) } - o.lazy + o.delegate_to { get_option(:analytics).enabled } + o.on_set do |value| + # TODO: Raise deprecation warning + get_option(:analytics).enabled = value + end end settings :diagnostics do @@ -63,7 +72,6 @@ class Settings option :env do |o| o.default { ENV.fetch(Ext::Environment::ENV_ENVIRONMENT, nil) } o.lazy - o.on_set { |value| get_option(:tracer).set_tags('env' => value) } end option :report_hostname do |o| @@ -71,19 +79,33 @@ class Settings o.lazy end + settings :runtime_metrics do + option :enabled do |o| + o.default { env_to_bool(Ext::Runtime::Metrics::ENV_ENABLED, false) } + o.lazy + end + + option :statsd + end + # Backwards compatibility for configuring runtime metrics e.g. `c.runtime_metrics enabled: true` def runtime_metrics(options = nil) - runtime_metrics = get_option(:tracer).writer.runtime_metrics - return runtime_metrics if options.nil? + settings = get_option(:runtime_metrics) + return settings if options.nil? + # If options were provided (old style) then raise warnings and apply them: # TODO: Raise deprecation warning - runtime_metrics.configure(options) + settings.enabled = options[:enabled] if options.key?(:enabled) + settings.statsd = options[:statsd] if options.key?(:statsd) + settings end option :runtime_metrics_enabled do |o| - # TODO: Raise deprecation warning - o.default { env_to_bool(Ext::Runtime::Metrics::ENV_ENABLED, false) } - o.lazy + o.delegate_to { get_option(:runtime_metrics).enabled } + o.on_set do |value| + # TODO: Raise deprecation warning + get_option(:runtime_metrics).enabled = value + end end settings :sampling do @@ -101,7 +123,6 @@ def runtime_metrics(options = nil) option :service do |o| o.default { ENV.fetch(Ext::Environment::ENV_SERVICE, nil) } o.lazy - o.on_set { |value| get_option(:tracer).default_service = value } end option :tags do |o| @@ -129,58 +150,79 @@ def runtime_metrics(options = nil) (old_value || {}).merge(string_tags) end - o.on_set { |value| get_option(:tracer).set_tags(value) } - o.lazy end - option :tracer do |o| - o.default { Tracer.new } - o.lazy + settings :tracer do + option :enabled, default: true + option :hostname # TODO: Deprecate + option :instance - # On reset, shut down the old tracer, - # then instantiate a new one. - o.resetter do |tracer| - tracer.shutdown! - Tracer.new - end - - # Backwards compatibility for configuring tracer e.g. `c.tracer debug: true` - o.helper :tracer do |options = nil| - tracer = options && options.key?(:instance) ? set_option(:tracer, options[:instance]) : get_option(:tracer) - - tracer.tap do |t| - unless options.nil? - t.configure(options) - - if options[:log] - # TODO: Raise deprecation warning - Datadog::Logger.log = options[:log] - end - - if options[:tags] - # TODO: Raise deprecation warning - t.set_tags(options[:tags]) - end - - if options[:env] - # TODO: Raise deprecation warning - t.set_tags(env: options[:env]) - end - - if options.key?(:debug) - # TODO: Raise deprecation warning - Datadog::Logger.debug_logging = options[:debug] - end - end - end + settings :partial_flush do + option :enabled, default: false + option :min_spans_threshold + end + + option :port # TODO: Deprecate + option :priority_sampling # TODO: Deprecate + option :sampler + option :transport_options, default: ->(_i) { {} }, lazy: true # TODO: Deprecate + option :writer # TODO: Deprecate + option :writer_options, default: ->(_i) { {} }, lazy: true # TODO: Deprecate + end + + # Backwards compatibility for configuring tracer e.g. `c.tracer debug: true` + def tracer(options = nil) + settings = get_option(:tracer) + return settings if options.nil? + + # If options were provided (old style) then raise warnings and apply them: + options = options.dup + + if options.key?(:log) + # TODO: Raise deprecation warning + Datadog::Logger.log = options.delete(:log) end + + if options.key?(:tags) + # TODO: Raise deprecation warning + set_option(:tags, options.delete(:tags)) + end + + if options.key?(:env) + # TODO: Raise deprecation warning + set_option(:env, options.delete(:env)) + end + + if options.key?(:debug) + # TODO: Raise deprecation warning + Datadog::Logger.debug_logging = options.delete(:debug) + end + + if options.key?(:partial_flush) + # TODO: Raise deprecation warning + settings.partial_flush.enabled = options.delete(:partial_flush) + end + + if options.key?(:min_spans_before_partial_flush) + # TODO: Raise deprecation warning + settings.partial_flush.min_spans_threshold = options.delete(:min_spans_before_partial_flush) + end + + # Forward remaining options to settings + options.each do |key, value| + setter = :"#{key}=" + settings.send(setter, value) if settings.respond_to?(setter) + end + end + + def tracer=(tracer) + get_option(:tracer).instance = tracer end option :version do |o| o.default { ENV.fetch(Ext::Environment::ENV_VERSION, nil) } o.lazy - o.on_set { |value| get_option(:tracer).set_tags('version' => value) } end end end diff --git a/lib/ddtrace/contrib/analytics.rb b/lib/ddtrace/contrib/analytics.rb index 05556f091bd..802fbb28ebb 100644 --- a/lib/ddtrace/contrib/analytics.rb +++ b/lib/ddtrace/contrib/analytics.rb @@ -9,7 +9,7 @@ module Analytics # Checks whether analytics should be enabled. # `flag` is a truthy/falsey value that represents a setting on the integration. def enabled?(flag = nil) - (Datadog.configuration.analytics_enabled && flag != false) || flag == true + (Datadog.configuration.analytics.enabled && flag != false) || flag == true end def set_sample_rate(span, sample_rate) diff --git a/lib/ddtrace/opentracer/global_tracer.rb b/lib/ddtrace/opentracer/global_tracer.rb index 083e19cbe1a..d6a3c9e306a 100644 --- a/lib/ddtrace/opentracer/global_tracer.rb +++ b/lib/ddtrace/opentracer/global_tracer.rb @@ -6,7 +6,7 @@ def global_tracer=(tracer) super.tap do if tracer.class <= Datadog::OpenTracer::Tracer # Update the Datadog global tracer, too. - Datadog.configuration.tracer = tracer.datadog_tracer + Datadog.configure { |c| c.tracer = tracer.datadog_tracer } end end end diff --git a/lib/ddtrace/tracer.rb b/lib/ddtrace/tracer.rb index bd03ba14a32..234fab24ff1 100644 --- a/lib/ddtrace/tracer.rb +++ b/lib/ddtrace/tracer.rb @@ -70,22 +70,23 @@ def call_context # * +enabled+: set if the tracer submits or not spans to the local agent. It's enabled # by default. def initialize(options = {}) - @enabled = options.fetch(:enabled, true) - @writer = options.fetch(:writer, Datadog::Writer.new) - @sampler = options.fetch(:sampler, Datadog::AllSampler.new) - - @provider = options.fetch(:context_provider, Datadog::DefaultContextProvider.new) - @provider ||= Datadog::DefaultContextProvider.new # @provider should never be nil - + # Configurable options @context_flush = if options[:partial_flush] Datadog::ContextFlush::Partial.new(options) else Datadog::ContextFlush::Finished.new end + @default_service = options[:default_service] + @enabled = options.fetch(:enabled, true) + @provider = options.fetch(:context_provider, Datadog::DefaultContextProvider.new) + @sampler = options.fetch(:sampler, Datadog::AllSampler.new) + @tags = options.fetch(:tags, {}) + @writer = options.fetch(:writer, Datadog::Writer.new) + + # Instance variables @mutex = Mutex.new - @tags = options.fetch(:tags, Datadog.configuration.tags) - @default_service = options.fetch(:default_service, Datadog.configuration.service) + @provider ||= Datadog::DefaultContextProvider.new # @provider should never be nil # Enable priority sampling by default activate_priority_sampling!(@sampler) @@ -114,11 +115,13 @@ def configure(options = {}) configure_writer(options) - @context_flush = if options[:partial_flush] - Datadog::ContextFlush::Partial.new(options) - else - Datadog::ContextFlush::Finished.new - end + if options.key?(:partial_flush) + @context_flush = if options[:partial_flush] + Datadog::ContextFlush::Partial.new(options) + else + Datadog::ContextFlush::Finished.new + end + end end # Set the information about the given service. A valid example is: @@ -355,10 +358,10 @@ def configure_writer(options = {}) sampler = options.fetch(:sampler, nil) priority_sampling = options.fetch(:priority_sampling, nil) writer = options.fetch(:writer, nil) - transport_options = options.fetch(:transport_options, {}) + transport_options = options.fetch(:transport_options, {}).dup # Compile writer options - writer_options = options.fetch(:writer_options, {}) + writer_options = options.fetch(:writer_options, {}).dup rebuild_writer = !writer_options.empty? # Re-build the sampler and writer if priority sampling is enabled, diff --git a/spec/ddtrace/configuration/components_spec.rb b/spec/ddtrace/configuration/components_spec.rb new file mode 100644 index 00000000000..7e4dcc15c50 --- /dev/null +++ b/spec/ddtrace/configuration/components_spec.rb @@ -0,0 +1,124 @@ +require 'spec_helper' + +require 'ddtrace/configuration/components' + +RSpec.describe Datadog::Configuration::Components do + describe '::new' do + subject(:components) { described_class.new(settings) } + let(:settings) { Datadog::Configuration::Settings.new } + + context 'given a tracer instance' do + let(:tracer) { instance_double(Datadog::Tracer, writer: writer) } + let(:writer) { instance_double(Datadog::Writer, runtime_metrics: runtime_metrics) } + let(:runtime_metrics) { instance_double(Datadog::Runtime::Metrics) } + + before do + settings.tracer = tracer + settings.service = 'my-service' + settings.tags = { 'custom-tag' => 'custom-value' } + + # NOTE: When given a tracer instance, it is expected to be fully configured. + # Do not expect the other settings to mutate the tracer instance. + expect(tracer).to_not receive(:configure) + expect(tracer).to_not receive(:set_tags) + allow(runtime_metrics).to receive(:configure) + end + + it 'uses the tracer instance' do + expect(components.tracer).to be(tracer) + end + end + + context 'given some tracer settings' do + before do + settings.service = 'my-service' + settings.env = 'test-env' + settings.tags = { 'custom-tag' => 'custom-value' } + settings.version = '0.1.0.alpha' + settings.tracer.enabled = false + settings.tracer.hostname = 'my-agent' + settings.tracer.port = 1234 + settings.tracer.partial_flush.enabled = true + settings.tracer.partial_flush.min_spans_threshold = 123 + end + + describe '#tracer' do + subject(:tracer) { components.tracer } + + it { expect(tracer.enabled).to be false } + it { expect(tracer.default_service).to eq('my-service') } + it { expect(tracer.context_flush).to be_a_kind_of(Datadog::ContextFlush::Partial) } + it { expect(tracer.context_flush.instance_variable_get(:@min_spans_for_partial)).to eq 123 } + it { expect(tracer.writer.transport.current_api.adapter.hostname).to eq 'my-agent' } + it { expect(tracer.writer.transport.current_api.adapter.port).to eq 1234 } + + it 'has tags applied' do + expect(tracer.tags).to include( + 'env' => 'test-env', + 'custom-tag' => 'custom-value', + 'version' => '0.1.0.alpha' + ) + end + end + + context 'including :writer' do + subject(:tracer) { components.tracer } + let(:writer) { Datadog::Writer.new } + + before do + settings.tracer.hostname = 'my-agent' + settings.tracer.port = 1234 + settings.tracer.writer = writer + end + + it { expect(tracer.writer).to be writer } + + # NOTE: Expect settings to NOT be retained because custom writer instances + # supersede these settings: declare settings in Writer::new instead. + it { expect(tracer.writer.transport.current_api.adapter.hostname).to_not eq 'my-agent' } + it { expect(tracer.writer.transport.current_api.adapter.port).to_not eq 1234 } + end + + context 'including :writer_options' do + subject(:tracer) { components.tracer } + + before do + settings.tracer.writer_options = { buffer_size: 1234 } + end + + it { expect(tracer.writer.instance_variable_get(:@buff_size)).to eq 1234 } + end + end + + context 'given some runtime metrics settings' do + context 'in the old style' do + context 'with #runtime_metrics_enabled=' do + before { settings.runtime_metrics_enabled = true } + it { expect(components.runtime_metrics.enabled?).to be true } + end + + context 'with #runtime_metrics' do + let(:statsd) { instance_double('statsd') } + before { settings.runtime_metrics enabled: true, statsd: statsd } + it { expect(components.runtime_metrics.enabled?).to be true } + it { expect(components.runtime_metrics.statsd).to be statsd } + end + end + + context 'in the new style' do + let(:statsd) { instance_double('statsd') } + + before do + settings.runtime_metrics.enabled = true + settings.runtime_metrics.statsd = statsd + end + + it { expect(components.runtime_metrics.enabled?).to be true } + it { expect(components.runtime_metrics.statsd).to be statsd } + end + end + + context 'given some health metrics settings' do + end + end +end diff --git a/spec/ddtrace/configuration/settings_spec.rb b/spec/ddtrace/configuration/settings_spec.rb index 7ee7e4c7b59..1683f3493ec 100644 --- a/spec/ddtrace/configuration/settings_spec.rb +++ b/spec/ddtrace/configuration/settings_spec.rb @@ -6,6 +6,137 @@ RSpec.describe Datadog::Configuration::Settings do subject(:settings) { described_class.new } + describe '#analytics' do + describe '#enabled' do + subject(:enabled) { settings.analytics.enabled } + + context "when #{Datadog::Ext::Analytics::ENV_TRACE_ANALYTICS_ENABLED}" do + around do |example| + ClimateControl.modify(Datadog::Ext::Analytics::ENV_TRACE_ANALYTICS_ENABLED => environment) do + example.run + end + end + + context 'is not defined' do + let(:environment) { nil } + it { is_expected.to be nil } + end + + context 'is defined' do + let(:environment) { 'true' } + it { is_expected.to be true } + end + end + end + + describe '#enabled=' do + it 'changes the #enabled setting' do + expect { settings.analytics.enabled = true } + .to change { settings.analytics.enabled } + .from(nil) + .to(true) + end + end + end + + describe '#analytics_enabled' do + subject(:analytics_enabled) { settings.analytics_enabled } + let(:value) { double } + + before { expect(settings.analytics).to receive(:enabled).and_return(value) } + + it 'retrieves the value from the new setting' do + is_expected.to be value + end + end + + describe '#analytics_enabled=' do + it 'changes the new #enabled setting' do + expect { settings.analytics_enabled = true } + .to change { settings.analytics.enabled } + .from(nil) + .to(true) + end + end + + describe '#diagnostics' do + describe '#health_metrics' do + # TODO + end + + describe '#health_metrics=' do + # TODO + end + end + + describe '#distributed_tracing' do + describe '#propagation_extract_style' do + subject(:propagation_extract_style) { settings.distributed_tracing.propagation_extract_style } + + context "when #{Datadog::Ext::DistributedTracing::PROPAGATION_EXTRACT_STYLE_ENV}" do + around do |example| + ClimateControl.modify(Datadog::Ext::DistributedTracing::PROPAGATION_EXTRACT_STYLE_ENV => environment) do + example.run + end + end + + context 'is not defined' do + let(:environment) { nil } + it do + is_expected.to eq( + [ + Datadog::Ext::DistributedTracing::PROPAGATION_STYLE_DATADOG, + Datadog::Ext::DistributedTracing::PROPAGATION_STYLE_B3, + Datadog::Ext::DistributedTracing::PROPAGATION_STYLE_B3_SINGLE_HEADER + ] + ) + end + end + + context 'is defined' do + let(:environment) { 'B3,B3 single header' } + it do + is_expected.to eq( + [ + Datadog::Ext::DistributedTracing::PROPAGATION_STYLE_B3, + Datadog::Ext::DistributedTracing::PROPAGATION_STYLE_B3_SINGLE_HEADER + ] + ) + end + end + end + end + + describe '#propagation_inject_style' do + subject(:propagation_inject_style) { settings.distributed_tracing.propagation_inject_style } + + context "when #{Datadog::Ext::DistributedTracing::PROPAGATION_INJECT_STYLE_ENV}" do + around do |example| + ClimateControl.modify(Datadog::Ext::DistributedTracing::PROPAGATION_INJECT_STYLE_ENV => environment) do + example.run + end + end + + context 'is not defined' do + let(:environment) { nil } + it { is_expected.to eq([Datadog::Ext::DistributedTracing::PROPAGATION_STYLE_DATADOG]) } + end + + context 'is defined' do + let(:environment) { 'Datadog,B3' } + it do + is_expected.to eq( + [ + Datadog::Ext::DistributedTracing::PROPAGATION_STYLE_DATADOG, + Datadog::Ext::DistributedTracing::PROPAGATION_STYLE_B3 + ] + ) + end + end + end + end + end + describe '#env' do subject(:env) { settings.env } context "when #{Datadog::Ext::Environment::ENV_ENVIRONMENT}" do @@ -33,9 +164,177 @@ context 'when given a value' do let(:env) { 'custom-env' } before { set_env } - it { expect(settings.env).to eq(env) } - it { expect(settings.tracer.tags).to include('env' => env) } + end + end + + describe '#report_hostname' do + subject(:report_hostname) { settings.report_hostname } + + context "when #{Datadog::Ext::NET::ENV_REPORT_HOSTNAME}" do + around do |example| + ClimateControl.modify(Datadog::Ext::NET::ENV_REPORT_HOSTNAME => environment) do + example.run + end + end + + context 'is not defined' do + let(:environment) { nil } + it { is_expected.to be false } + end + + context 'is defined' do + let(:environment) { 'true' } + it { is_expected.to be true } + end + end + end + + describe '#report_hostname=' do + it 'changes the #report_hostname setting' do + expect { settings.report_hostname = true } + .to change { settings.report_hostname } + .from(false) + .to(true) + end + end + + describe '#runtime_metrics' do + describe 'old style' do + context 'given nothing' do + subject(:runtime_metrics) { settings.runtime_metrics } + it 'returns the new settings object' do + is_expected.to be_a_kind_of(Datadog::Configuration::Base) + end + end + + context 'given :enabled' do + subject(:runtime_metrics) { settings.runtime_metrics enabled: true } + + it 'updates the new #enabled setting' do + expect { settings.runtime_metrics enabled: true } + .to change { settings.runtime_metrics.enabled } + .from(false) + .to(true) + end + end + + context 'given :statsd' do + subject(:runtime_metrics) { settings.runtime_metrics statsd: statsd } + let(:statsd) { double('statsd') } + + it 'updates the new #statsd setting' do + expect { settings.runtime_metrics statsd: statsd } + .to change { settings.runtime_metrics.statsd } + .from(nil) + .to(statsd) + end + end + end + + describe '#enabled' do + subject(:enabled) { settings.runtime_metrics.enabled } + + context "when #{Datadog::Ext::Runtime::Metrics::ENV_ENABLED}" do + around do |example| + ClimateControl.modify(Datadog::Ext::Runtime::Metrics::ENV_ENABLED => environment) do + example.run + end + end + + context 'is not defined' do + let(:environment) { nil } + it { is_expected.to be false } + end + + context 'is defined' do + let(:environment) { 'true' } + it { is_expected.to be true } + end + end + end + + describe '#enabled=' do + it 'changes the #enabled setting' do + expect { settings.runtime_metrics.enabled = true } + .to change { settings.runtime_metrics.enabled } + .from(false) + .to(true) + end + end + + describe '#statsd' do + subject(:statsd) { settings.runtime_metrics.statsd } + it { is_expected.to be nil } + end + + describe '#statsd=' do + let(:statsd) { double('statsd') } + + it 'changes the #statsd setting' do + expect { settings.runtime_metrics.statsd = statsd } + .to change { settings.runtime_metrics.statsd } + .from(nil) + .to(statsd) + end + end + end + + describe '#runtime_metrics_enabled' do + subject(:runtime_metrics_enabled) { settings.runtime_metrics_enabled } + let(:value) { double } + + before { expect(settings.runtime_metrics).to receive(:enabled).and_return(value) } + + it 'retrieves the value from the new setting' do + is_expected.to be value + end + end + + describe '#runtime_metrics_enabled=' do + it 'changes the new #enabled setting' do + expect { settings.runtime_metrics_enabled = true } + .to change { settings.runtime_metrics.enabled } + .from(false) + .to(true) + end + end + + describe '#sampling' do + describe '#rate_limit' do + subject(:rate_limit) { settings.sampling.rate_limit } + + context 'default' do + it { is_expected.to be 100 } + end + + context 'when ENV is provided' do + around do |example| + ClimateControl.modify(Datadog::Ext::Sampling::ENV_RATE_LIMIT => '20.0') do + example.run + end + end + + it { is_expected.to eq(20.0) } + end + end + + describe '#default_rate' do + subject(:default_rate) { settings.sampling.default_rate } + + context 'default' do + it { is_expected.to be nil } + end + + context 'when ENV is provided' do + around do |example| + ClimateControl.modify(Datadog::Ext::Sampling::ENV_SAMPLE_RATE => '0.5') do + example.run + end + end + + it { is_expected.to eq(0.5) } + end end end @@ -66,9 +365,7 @@ context 'when given a value' do let(:service) { 'custom-service' } before { set_service } - it { expect(settings.service).to eq(service) } - it { expect(settings.tracer.default_service).to eq(service) } end end @@ -177,17 +474,13 @@ context 'with Symbol keys' do let(:tags) { { :'custom-tag' => 'custom-value' } } before { set_tags } - it { expect(settings.tags).to eq('custom-tag' => 'custom-value') } - it { expect(settings.tracer.tags).to include('custom-tag' => 'custom-value') } end context 'with String keys' do let(:tags) { { 'custom-tag' => 'custom-value' } } before { set_tags } - it { expect(settings.tags).to eq(tags) } - it { expect(settings.tracer.tags).to include(tags) } end end @@ -203,164 +496,367 @@ end end - describe '#version' do - subject(:version) { settings.version } - context "when #{Datadog::Ext::Environment::ENV_VERSION}" do - around do |example| - ClimateControl.modify(Datadog::Ext::Environment::ENV_VERSION => version) do - example.run + describe '#tracer' do + context 'old style' do + context 'given :debug' do + subject(:configure) { settings.tracer(debug: debug) } + + shared_examples_for 'debug toggle' do + before { Datadog::Logger.debug_logging = !debug } + after { Datadog::Logger.debug_logging = false } + + it do + expect { configure }.to change { Datadog::Logger.debug_logging } + .from(!debug) + .to(debug) + end + end + + context 'as true' do + it_behaves_like 'debug toggle' do + let(:debug) { true } + end + end + + context 'as false' do + it_behaves_like 'debug toggle' do + let(:debug) { false } + end end end - context 'is not defined' do - let(:version) { nil } - it { is_expected.to be nil } + context 'given :env' do + let(:env) { 'my-env' } + + it 'updates the new #env setting' do + expect { settings.tracer env: env } + .to change { settings.env } + .from(nil) + .to(env) + end end - context 'is defined' do - let(:version) { 'version-value' } - it { is_expected.to eq(version) } + context 'given :log' do + let(:custom_log) { Logger.new(STDOUT, level: Logger::INFO) } + + before do + @original_log = Datadog::Logger.log + settings.tracer(log: custom_log) + end + + after do + Datadog::Logger.log = @original_log + end + + it 'uses the logger for logging' do + expect(Datadog::Logger.log).to eq(custom_log) + end + end + + describe 'given :min_spans_before_partial_flush' do + let(:value) { 1234 } + + it 'updates the new #min_spans_threshold setting' do + expect { settings.tracer min_spans_before_partial_flush: value } + .to change { settings.tracer.partial_flush.min_spans_threshold } + .from(nil) + .to(value) + end + end + + describe 'given :partial_flush' do + it 'updates the new #enabled setting' do + expect { settings.tracer partial_flush: true } + .to change { settings.tracer.partial_flush.enabled } + .from(false) + .to(true) + end + end + + context 'given :tags' do + let(:tags) { { 'custom-tag' => 'custom-value' } } + + it 'updates the new #tags setting' do + expect { settings.tracer tags: tags } + .to change { settings.tags } + .from({}) + .to(tags) + end + end + + context 'given :writer_options' do + before { settings.tracer(writer_options: { buffer_size: 1234 }) } + + it 'updates the new #writer_options setting' do + expect(settings.tracer.writer_options).to eq(buffer_size: 1234) + end + end + + context 'given some settings' do + let(:tracer) { Datadog::Tracer.new } + + before do + settings.tracer( + enabled: false, + hostname: 'tracer.host.com', + port: 1234, + env: :config_test, + tags: { foo: :bar }, + writer_options: { buffer_size: 1234 }, + instance: tracer + ) + end + + after do + Datadog::Logger.debug_logging = false + end + + it 'applies settings correctly' do + expect(settings.tracer.enabled).to be false + expect(settings.tracer.hostname).to eq('tracer.host.com') + expect(settings.tracer.port).to eq(1234) + expect(settings.env).to eq(:config_test) + expect(settings.tags['foo']).to eq(:bar) + end + end + + it 'acts on the tracer option' do + previous_state = settings.tracer.enabled + settings.tracer(enabled: !previous_state) + expect(settings.tracer.enabled).to eq(!previous_state) + settings.tracer(enabled: previous_state) + expect(settings.tracer.enabled).to eq(previous_state) end end - end - describe '#version=' do - subject(:set_version) { settings.version = version } + describe '#enabled' do + subject(:enabled) { settings.tracer.enabled } + it { is_expected.to be true } + end - context 'when given a value' do - let(:version) { '0.1.0.alpha' } - before { set_version } + describe '#enabled=' do + it 'updates the #enabled setting' do + expect { settings.tracer.enabled = false } + .to change { settings.tracer.enabled } + .from(true) + .to(false) + end + end - it { expect(settings.version).to eq(version) } - it { expect(settings.tracer.tags).to include('version' => version) } + describe '#hostname' do + subject(:hostname) { settings.tracer.hostname } + it { is_expected.to be nil } end - end - describe '#sampling' do - describe '#rate_limit' do - subject(:rate_limit) { settings.sampling.rate_limit } + describe '#hostname=' do + let(:hostname) { 'my-agent' } - context 'default' do - it { is_expected.to be 100 } + it 'updates the #hostname setting' do + expect { settings.tracer.hostname = hostname } + .to change { settings.tracer.hostname } + .from(nil) + .to(hostname) end + end - context 'when ENV is provided' do - around do |example| - ClimateControl.modify(Datadog::Ext::Sampling::ENV_RATE_LIMIT => '20.0') do - example.run - end - end + describe '#instance' do + subject(:instance) { settings.tracer.instance } + it { is_expected.to be nil } + end - it { is_expected.to eq(20.0) } + describe '#instance=' do + let(:tracer) { instance_double(Datadog::Tracer) } + + it 'updates the #instance setting' do + expect { settings.tracer.instance = tracer } + .to change { settings.tracer.instance } + .from(nil) + .to(tracer) end end - describe '#default_rate' do - subject(:default_rate) { settings.sampling.default_rate } + describe '#partial_flush' do + describe '#enabled' do + subject(:enabled) { settings.tracer.partial_flush.enabled } + it { is_expected.to be false } + end - context 'default' do + describe '#enabled=' do + it 'updates the #enabled setting' do + expect { settings.tracer.partial_flush.enabled = true } + .to change { settings.tracer.partial_flush.enabled } + .from(false) + .to(true) + end + end + + describe '#min_spans_threshold' do + subject(:min_spans_threshold) { settings.tracer.partial_flush.min_spans_threshold } it { is_expected.to be nil } end - context 'when ENV is provided' do - around do |example| - ClimateControl.modify(Datadog::Ext::Sampling::ENV_SAMPLE_RATE => '0.5') do - example.run - end - end + describe '#min_spans_threshold=' do + let(:value) { 1234 } - it { is_expected.to eq(0.5) } + it 'updates the #min_spans_before_partial_flush setting' do + expect { settings.tracer.partial_flush.min_spans_threshold = value } + .to change { settings.tracer.partial_flush.min_spans_threshold } + .from(nil) + .to(value) + end end end - end - describe '#tracer' do - context 'given :log' do - let(:custom_log) { Logger.new(STDOUT, level: Logger::INFO) } + describe '#port' do + subject(:port) { settings.tracer.port } + it { is_expected.to be nil } + end - before do - @original_log = Datadog::Logger.log - settings.tracer(log: custom_log) - end + describe '#port=' do + let(:port) { 1234 } - after do - Datadog::Logger.log = @original_log + it 'updates the #port setting' do + expect { settings.tracer.port = port } + .to change { settings.tracer.port } + .from(nil) + .to(port) end + end + + describe '#priority_sampling' do + subject(:priority_sampling) { settings.tracer.priority_sampling } + it { is_expected.to be nil } + end - it 'uses the logger for logging' do - expect(Datadog::Logger.log).to eq(custom_log) + describe '#priority_sampling=' do + it 'updates the #priority_sampling setting' do + expect { settings.tracer.priority_sampling = true } + .to change { settings.tracer.priority_sampling } + .from(nil) + .to(true) end end - context 'given :debug' do - subject(:configure) { settings.tracer(debug: debug) } + describe '#sampler' do + subject(:sampler) { settings.tracer.sampler } + it { is_expected.to be nil } + end - shared_examples_for 'debug toggle' do - before { Datadog::Logger.debug_logging = !debug } - after { Datadog::Logger.debug_logging = false } + describe '#sampler=' do + let(:sampler) { instance_double(Datadog::PrioritySampler) } - it do - expect { configure }.to change { Datadog::Logger.debug_logging } - .from(!debug) - .to(debug) - end + it 'updates the #sampler setting' do + expect { settings.tracer.sampler = sampler } + .to change { settings.tracer.sampler } + .from(nil) + .to(sampler) end + end + + describe '#transport_options' do + subject(:transport_options) { settings.tracer.transport_options } + it { is_expected.to eq({}) } - context 'as true' do - it_behaves_like 'debug toggle' do - let(:debug) { true } + context 'when modified' do + it 'does not modify the default by reference' do + settings.tracer.transport_options[:foo] = :bar + expect(settings.tracer.transport_options).to_not be_empty + expect(settings.tracer.options[:transport_options].default_value).to be_empty end end + end - context 'as false' do - it_behaves_like 'debug toggle' do - let(:debug) { false } - end + describe '#transport_options=' do + let(:options) { { hostname: 'my-agent' } } + + it 'updates the #transport_options setting' do + expect { settings.tracer.transport_options = options } + .to change { settings.tracer.transport_options } + .from({}) + .to(options) end end - context 'given some settings' do - let(:tracer) { Datadog::Tracer.new } + describe '#writer' do + subject(:writer) { settings.tracer.writer } + it { is_expected.to be nil } + end + + describe '#writer=' do + let(:writer) { instance_double(Datadog::Writer) } - before do - settings.tracer( - enabled: false, - hostname: 'tracer.host.com', - port: 1234, - env: :config_test, - tags: { foo: :bar }, - writer_options: { buffer_size: 1234 }, - instance: tracer - ) + it 'updates the #writer setting' do + expect { settings.tracer.writer = writer } + .to change { settings.tracer.writer } + .from(nil) + .to(writer) end + end + + describe '#writer_options' do + subject(:writer_options) { settings.tracer.writer_options } + it { is_expected.to eq({}) } - after do - Datadog::Logger.debug_logging = false + context 'when modified' do + it 'does not modify the default by reference' do + settings.tracer.writer_options[:foo] = :bar + expect(settings.tracer.writer_options).to_not be_empty + expect(settings.tracer.options[:writer_options].default_value).to be_empty + end end + end + + describe '#writer_options=' do + let(:options) { { priority_sampling: true } } - it 'applies settings correctly' do - expect(tracer.enabled).to be false - expect(tracer.writer.transport.current_api.adapter.hostname).to eq('tracer.host.com') - expect(tracer.writer.transport.current_api.adapter.port).to eq(1234) - expect(tracer.tags['env']).to eq(:config_test) - expect(tracer.tags['foo']).to eq(:bar) + it 'updates the #writer_options setting' do + expect { settings.tracer.writer_options = options } + .to change { settings.tracer.writer_options } + .from({}) + .to(options) end end + end - context 'given :writer_options' do - before { settings.tracer(writer_options: { buffer_size: 1234 }) } + describe '#tracer=' do + subject(:set_tracer) { settings.tracer = tracer } + let(:tracer) { instance_double(Datadog::Tracer) } - it 'applies settings correctly' do - expect(settings.tracer.writer.instance_variable_get(:@buff_size)).to eq(1234) + it 'sets the tracer instance' do + expect { set_tracer }.to change { settings.tracer.instance } + .from(nil) + .to(tracer) + end + end + + describe '#version' do + subject(:version) { settings.version } + context "when #{Datadog::Ext::Environment::ENV_VERSION}" do + around do |example| + ClimateControl.modify(Datadog::Ext::Environment::ENV_VERSION => version) do + example.run + end + end + + context 'is not defined' do + let(:version) { nil } + it { is_expected.to be nil } + end + + context 'is defined' do + let(:version) { 'version-value' } + it { is_expected.to eq(version) } end end + end + + describe '#version=' do + subject(:set_version) { settings.version = version } - it 'acts on the tracer option' do - previous_state = settings.tracer.enabled - settings.tracer(enabled: !previous_state) - expect(settings.tracer.enabled).to eq(!previous_state) - settings.tracer(enabled: previous_state) - expect(settings.tracer.enabled).to eq(previous_state) + context 'when given a value' do + let(:version) { '0.1.0.alpha' } + before { set_version } + it { expect(settings.version).to eq(version) } end end end diff --git a/spec/ddtrace/configuration_spec.rb b/spec/ddtrace/configuration_spec.rb index e34cf5f1103..4acb8d585bc 100644 --- a/spec/ddtrace/configuration_spec.rb +++ b/spec/ddtrace/configuration_spec.rb @@ -1,5 +1,6 @@ require 'spec_helper' +require 'datadog/statsd' require 'ddtrace/patcher' require 'ddtrace/configuration' @@ -9,6 +10,98 @@ describe '#configure' do subject(:configure) { test_class.configure } + + context 'when replacing a tracer' do + let(:old_tracer) { Datadog::Tracer.new } + let(:new_tracer) { Datadog::Tracer.new } + + before do + expect(old_tracer).to receive(:shutdown!) + + test_class.configure { |c| c.tracer = old_tracer } + test_class.configure { |c| c.tracer = new_tracer } + end + + it 'replaces the old tracer and shuts it down' do + expect(test_class.tracer).to be new_tracer + end + end + + context 'when reusing the same tracer' do + let(:tracer) { Datadog::Tracer.new } + + before do + expect(tracer).to_not receive(:shutdown!) + + test_class.configure { |c| c.tracer = tracer } + test_class.configure { |c| c.tracer = tracer } + end + + it 'replaces the old tracer and shuts it down' do + expect(test_class.tracer).to be tracer + end + end + + context 'when not changing the tracer' do + let(:tracer) { Datadog::Tracer.new } + + before do + expect(tracer).to_not receive(:shutdown!) + + test_class.configure { |c| c.tracer = tracer } + test_class.configure { |_c| } + end + + it 'replaces the old tracer and shuts it down' do + expect(test_class.tracer).to be tracer + end + end + + context 'when replacing metrics' do + let(:old_statsd) { instance_double(Datadog::Statsd) } + let(:new_statsd) { instance_double(Datadog::Statsd) } + + before do + expect(old_statsd).to receive(:close) + + test_class.configure { |c| c.runtime_metrics.statsd = old_statsd } + test_class.configure { |c| c.runtime_metrics.statsd = new_statsd } + end + + it 'replaces the old Statsd and closes it' do + expect(test_class.runtime_metrics.statsd).to be new_statsd + end + end + + context 'when reusing metrics' do + let(:statsd) { instance_double(Datadog::Statsd) } + + before do + expect(statsd).to_not receive(:close) + + test_class.configure { |c| c.runtime_metrics.statsd = statsd } + test_class.configure { |c| c.runtime_metrics.statsd = statsd } + end + + it 'replaces the old Statsd and closes it' do + expect(test_class.runtime_metrics.statsd).to be statsd + end + end + + context 'when not changing the metrics' do + let(:statsd) { instance_double(Datadog::Statsd) } + + before do + expect(statsd).to_not receive(:close) + + test_class.configure { |c| c.runtime_metrics.statsd = statsd } + test_class.configure { |_c| } + end + + it 'replaces the old Statsd and closes it' do + expect(test_class.runtime_metrics.statsd).to be statsd + end + end end end end diff --git a/spec/ddtrace/contrib/analytics_examples.rb b/spec/ddtrace/contrib/analytics_examples.rb index a76d03f1c9b..2d4efd93b2b 100644 --- a/spec/ddtrace/contrib/analytics_examples.rb +++ b/spec/ddtrace/contrib/analytics_examples.rb @@ -176,8 +176,8 @@ context 'is explicitly enabled' do around do |example| - Datadog.configuration.analytics_enabled = Datadog.configuration.analytics_enabled.tap do - Datadog.configuration.analytics_enabled = true + Datadog.configuration.analytics.enabled = Datadog.configuration.analytics.enabled.tap do + Datadog.configuration.analytics.enabled = true example.run end end @@ -187,8 +187,8 @@ context 'is explicitly disabled' do around do |example| - Datadog.configuration.analytics_enabled = Datadog.configuration.analytics_enabled.tap do - Datadog.configuration.analytics_enabled = false + Datadog.configuration.analytics.enabled = Datadog.configuration.analytics.enabled.tap do + Datadog.configuration.analytics.enabled = false example.run end end @@ -220,8 +220,8 @@ context 'is explicitly enabled' do around do |example| - Datadog.configuration.analytics_enabled = Datadog.configuration.analytics_enabled.tap do - Datadog.configuration.analytics_enabled = true + Datadog.configuration.analytics.enabled = Datadog.configuration.analytics.enabled.tap do + Datadog.configuration.analytics.enabled = true example.run end end @@ -231,8 +231,8 @@ context 'is explicitly disabled' do around do |example| - Datadog.configuration.analytics_enabled = Datadog.configuration.analytics_enabled.tap do - Datadog.configuration.analytics_enabled = false + Datadog.configuration.analytics.enabled = Datadog.configuration.analytics.enabled.tap do + Datadog.configuration.analytics.enabled = false example.run end end diff --git a/spec/ddtrace/integration_spec.rb b/spec/ddtrace/integration_spec.rb index c6cc32ce651..9b989e0702f 100644 --- a/spec/ddtrace/integration_spec.rb +++ b/spec/ddtrace/integration_spec.rb @@ -623,72 +623,58 @@ def agent_receives_span_step3(previous_success) end end - describe 'trace writer runtime metrics configuration' do + describe 'writer runtime metrics configuration' do let(:hostname) { double('example_hostname') } - let(:base_namespace) { 'original_example_namespace' } - let(:updated_namespace) { 'updated_example_namespace' } - let(:statsd_client) { Datadog::Statsd.new(hostname, 8125, tags: [], namespace: base_namespace) } - let(:statsd_client_updated) { Datadog::Statsd.new(hostname, 8125, tags: [], namespace: updated_namespace) } - let(:transport) { Datadog::Transport::HTTP.default } - - let(:writer_without_runtime) do - Datadog::Writer.new( - transport: transport, - priority_sampler: Datadog::PrioritySampler.new - ) - end + let(:statsd) { Datadog::Statsd.new(hostname, 8125) } - let(:writer_with_runtime) do - Datadog::Writer.new( - transport: transport, - priority_sampler: Datadog::PrioritySampler.new, - runtime_metrics: Datadog::Runtime::Metrics.new(statsd: statsd_client_updated) - ) - end + after { statsd.close } - after(:each) do - statsd_client.close - statsd_client_updated.close - end + context 'when tracer and runtime metrics are configured' do + context 'without a writer' do + before do + Datadog.configure do |c| + c.runtime_metrics statsd: statsd + c.tracer host: hostname + end + end - it 'should propogate runtime metrics configuration to the new writer when rebuilt' do - Datadog.configure do |c| - c.runtime_metrics_enabled - c.runtime_metrics statsd: statsd_client - c.tracer host: hostname + it { expect(Datadog.runtime_metrics.statsd).to be(statsd) } end - expect(Datadog.tracer.writer.runtime_metrics.statsd.namespace).to eq(base_namespace) - end + context 'with a writer' do + let(:writer_runtime_metrics) { Datadog::Runtime::Metrics.new } + let(:writer) do + Datadog::Writer.new( + transport: Datadog::Transport::HTTP.default, + priority_sampler: Datadog::PrioritySampler.new, + runtime_metrics: Datadog::Runtime::Metrics.new + ) + end - it 'should set runtime metrics configuration regardless of order' do - Datadog.configure do |c| - c.runtime_metrics_enabled - c.tracer host: hostname, writer: writer_without_runtime - c.runtime_metrics statsd: statsd_client - end + after { writer_runtime_metrics.statsd.close } - expect(Datadog.tracer.writer.runtime_metrics.statsd.namespace).to eq(base_namespace) - end + context '(writer first then runtime metrics)' do + before do + Datadog.configure do |c| + c.tracer host: hostname, writer: writer + c.runtime_metrics statsd: statsd + end + end - it 'should use new writer runtime metric configuration when available' do - Datadog.configure do |c| - c.runtime_metrics_enabled - c.runtime_metrics statsd: statsd_client - c.tracer host: hostname, writer: writer_with_runtime - end + it { expect(Datadog.runtime_metrics.statsd).to be(statsd) } + end - expect(Datadog.tracer.writer.runtime_metrics.statsd.namespace).to eq(updated_namespace) - end + context '(runtime metrics first then writer)' do + before do + Datadog.configure do |c| + c.runtime_metrics statsd: statsd + c.tracer host: hostname, writer: writer + end + end - it 'should prioritize default writer runtime metric configuration when any writer is configured' do - Datadog.configure do |c| - c.runtime_metrics_enabled - c.runtime_metrics statsd: statsd_client - c.tracer host: hostname, writer: writer_without_runtime + it { expect(Datadog.runtime_metrics.statsd).to be(statsd) } + end end - - expect(Datadog.tracer.writer.runtime_metrics.statsd.namespace).to eq(nil) end end end diff --git a/spec/ddtrace/span_spec.rb b/spec/ddtrace/span_spec.rb index bc34746c2c0..8b2af0590c7 100644 --- a/spec/ddtrace/span_spec.rb +++ b/spec/ddtrace/span_spec.rb @@ -52,20 +52,9 @@ it { is_expected.to eq service_value } end - context 'is only defined in the configuration' do - let(:env_service) { 'env-service' } - before { allow(Datadog.configuration).to receive(:service).and_return(env_service) } - it { is_expected.to eq env_service } - end - - context 'is not set anywhere' do + context 'is not set' do let(:default_service) { 'default-service' } - - before do - allow(Datadog.configuration).to receive(:service).and_return(nil) - allow(tracer).to receive(:default_service).and_return(default_service) - end - + before { allow(tracer).to receive(:default_service).and_return(default_service) } it { is_expected.to eq default_service } end end diff --git a/spec/ddtrace/tracer_spec.rb b/spec/ddtrace/tracer_spec.rb index a06784d62e9..9884234b322 100644 --- a/spec/ddtrace/tracer_spec.rb +++ b/spec/ddtrace/tracer_spec.rb @@ -26,7 +26,7 @@ before { allow(Datadog.configuration).to receive(:tags).and_return(env_tags) } context 'by default' do - it { is_expected.to be env_tags } + it { is_expected.to eq env_tags } end context 'when equivalent String and Symbols are added' do From 1038d11c8bdd35086789702e89f279733d7a0ee2 Mon Sep 17 00:00:00 2001 From: David Elner Date: Tue, 7 Apr 2020 16:06:02 -0400 Subject: [PATCH 3/4] Refactored: Extract #health_metrics to Components --- lib/ddtrace/buffer.rb | 12 ++--- lib/ddtrace/configuration.rb | 6 ++- lib/ddtrace/configuration/components.rb | 12 +++++ lib/ddtrace/configuration/settings.rb | 11 ++-- lib/ddtrace/context.rb | 4 +- lib/ddtrace/contrib/patcher.rb | 4 +- lib/ddtrace/diagnostics/health.rb | 6 --- lib/ddtrace/sampler.rb | 2 +- lib/ddtrace/span.rb | 2 +- lib/ddtrace/transport/statistics.rb | 4 +- spec/ddtrace/configuration/components_spec.rb | 9 ++++ spec/ddtrace/configuration/settings_spec.rb | 49 +++++++++++++++-- spec/ddtrace/configuration_spec.rb | 54 ++++++++++++++++--- spec/ddtrace/transport/http/client_spec.rb | 2 +- spec/ddtrace/transport/statistics_spec.rb | 14 ++--- spec/support/health_metric_helpers.rb | 2 +- 16 files changed, 147 insertions(+), 46 deletions(-) diff --git a/lib/ddtrace/buffer.rb b/lib/ddtrace/buffer.rb index 7313cc7d88b..3f85f040283 100644 --- a/lib/ddtrace/buffer.rb +++ b/lib/ddtrace/buffer.rb @@ -96,16 +96,16 @@ def measure_drop(trace) def measure_pop(traces) # Accepted - Diagnostics::Health.metrics.queue_accepted(@buffer_accepted) - Diagnostics::Health.metrics.queue_accepted_lengths(@buffer_accepted_lengths) + Datadog.health_metrics.queue_accepted(@buffer_accepted) + Datadog.health_metrics.queue_accepted_lengths(@buffer_accepted_lengths) # Dropped - Diagnostics::Health.metrics.queue_dropped(@buffer_dropped) + Datadog.health_metrics.queue_dropped(@buffer_dropped) # Queue gauges - Diagnostics::Health.metrics.queue_max_length(@max_size) - Diagnostics::Health.metrics.queue_spans(@buffer_spans) - Diagnostics::Health.metrics.queue_length(traces.length) + Datadog.health_metrics.queue_max_length(@max_size) + Datadog.health_metrics.queue_spans(@buffer_spans) + Datadog.health_metrics.queue_length(traces.length) # Reset aggregated metrics @buffer_accepted = 0 diff --git a/lib/ddtrace/configuration.rb b/lib/ddtrace/configuration.rb index a1b5b4a984a..10a66b98038 100644 --- a/lib/ddtrace/configuration.rb +++ b/lib/ddtrace/configuration.rb @@ -30,6 +30,7 @@ def configure(target = configuration, opts = {}) def_delegators \ :components, + :health_metrics, :runtime_metrics, :tracer @@ -57,7 +58,10 @@ def teardown_components!(old, current) # Shutdown the old metrics, unless they are still being used. # (e.g. custom Statsd instances.) - old.runtime_metrics.statsd.close unless old.runtime_metrics.statsd == current.runtime_metrics.statsd + old_statsd = [old.runtime_metrics.statsd, old.health_metrics.statsd].uniq + new_statsd = [current.runtime_metrics.statsd, current.health_metrics.statsd].uniq + unused_statsd = (old_statsd - (old_statsd & new_statsd)) + unused_statsd.each(&:close) end end end diff --git a/lib/ddtrace/configuration/components.rb b/lib/ddtrace/configuration/components.rb index a604e51f0ff..38af3be3527 100644 --- a/lib/ddtrace/configuration/components.rb +++ b/lib/ddtrace/configuration/components.rb @@ -11,9 +11,13 @@ def initialize(settings) # Runtime metrics build_runtime_metrics(settings) + + # Health metrics + @health_metrics = build_health_metrics(settings) end attr_reader \ + :health_metrics, :tracer def runtime_metrics @@ -77,6 +81,14 @@ def build_runtime_metrics(settings) # runtime metrics are extracted from tracer/writer. runtime_metrics.configure(options) end + + def build_health_metrics(settings) + settings = settings.diagnostics.health_metrics + options = { enabled: settings.enabled } + options[:statsd] = settings.statsd unless settings.statsd.nil? + + Datadog::Diagnostics::Health::Metrics.new(options) + end end end end diff --git a/lib/ddtrace/configuration/settings.rb b/lib/ddtrace/configuration/settings.rb index 6b96a1b040d..a1e7206993b 100644 --- a/lib/ddtrace/configuration/settings.rb +++ b/lib/ddtrace/configuration/settings.rb @@ -34,14 +34,13 @@ class Settings end settings :diagnostics do - option :health_metrics do |o| - o.default do - Datadog::Diagnostics::Health::Metrics.new( - enabled: env_to_bool(Datadog::Ext::Diagnostics::Health::Metrics::ENV_ENABLED, false) - ) + settings :health_metrics do + option :enabled do |o| + o.default { env_to_bool(Datadog::Ext::Diagnostics::Health::Metrics::ENV_ENABLED, false) } + o.lazy end - o.lazy + option :statsd end end diff --git a/lib/ddtrace/context.rb b/lib/ddtrace/context.rb index f89bdd9fda6..5616543f8d7 100644 --- a/lib/ddtrace/context.rb +++ b/lib/ddtrace/context.rb @@ -100,7 +100,7 @@ def add_span(span) # If overflow has already occurred, don't send this metric. # Prevents metrics spam if buffer repeatedly overflows for the same trace. unless @overflow - Diagnostics::Health.metrics.error_context_overflow(1, tags: ["max_length:#{@max_length}"]) + Datadog.health_metrics.error_context_overflow(1, tags: ["max_length:#{@max_length}"]) @overflow = true end @@ -131,7 +131,7 @@ def close_span(span) @trace.reject(&:finished?).group_by(&:name).each do |unfinished_span_name, unfinished_spans| Datadog::Logger.log.debug("unfinished span: #{unfinished_spans.first}") if Datadog::Logger.debug_logging - Diagnostics::Health.metrics.error_unfinished_spans( + Datadog.health_metrics.error_unfinished_spans( unfinished_spans.length, tags: ["name:#{unfinished_span_name}"] ) diff --git a/lib/ddtrace/contrib/patcher.rb b/lib/ddtrace/contrib/patcher.rb index 2872ec99586..d1bf02e559d 100644 --- a/lib/ddtrace/contrib/patcher.rb +++ b/lib/ddtrace/contrib/patcher.rb @@ -28,7 +28,7 @@ def patch begin super.tap do # Emit a metric - Diagnostics::Health.metrics.instrumentation_patched(1, tags: default_tags) + Datadog.health_metrics.instrumentation_patched(1, tags: default_tags) end rescue StandardError => e # Log the error @@ -38,7 +38,7 @@ def patch tags = default_tags tags << "error:#{e.class.name}" - Diagnostics::Health.metrics.error_instrumentation_patch(1, tags: tags) + Datadog.health_metrics.error_instrumentation_patch(1, tags: tags) end end end diff --git a/lib/ddtrace/diagnostics/health.rb b/lib/ddtrace/diagnostics/health.rb index ca12c0cbb1e..fe432d07c4a 100644 --- a/lib/ddtrace/diagnostics/health.rb +++ b/lib/ddtrace/diagnostics/health.rb @@ -26,12 +26,6 @@ class Metrics < ::Datadog::Metrics gauge :queue_spans, Ext::Diagnostics::Health::Metrics::METRIC_QUEUE_SPANS gauge :sampling_service_cache_length, Ext::Diagnostics::Health::Metrics::METRIC_SAMPLING_SERVICE_CACHE_LENGTH end - - module_function - - def metrics - Datadog.configuration.diagnostics.health_metrics - end end end end diff --git a/lib/ddtrace/sampler.rb b/lib/ddtrace/sampler.rb index e7a8800cd0d..cf825c4002e 100644 --- a/lib/ddtrace/sampler.rb +++ b/lib/ddtrace/sampler.rb @@ -176,7 +176,7 @@ def update(rate_by_service) update_all(rate_by_service) # Emit metric for service cache size - Diagnostics::Health.metrics.sampling_service_cache_length(length) + Datadog.health_metrics.sampling_service_cache_length(length) end private diff --git a/lib/ddtrace/span.rb b/lib/ddtrace/span.rb index e4428fdd405..2834ff7b7d0 100644 --- a/lib/ddtrace/span.rb +++ b/lib/ddtrace/span.rb @@ -180,7 +180,7 @@ def finish(finish_time = nil) @tracer.record(self) rescue StandardError => e Datadog::Logger.log.debug("error recording finished trace: #{e}") - Diagnostics::Health.metrics.error_span_finish(1, tags: ["error:#{e.class.name}"]) + Datadog.health_metrics.error_span_finish(1, tags: ["error:#{e.class.name}"]) end self end diff --git a/lib/ddtrace/transport/statistics.rb b/lib/ddtrace/transport/statistics.rb index d3397e37565..59ac3d76775 100644 --- a/lib/ddtrace/transport/statistics.rb +++ b/lib/ddtrace/transport/statistics.rb @@ -20,7 +20,7 @@ def update_stats_from_response!(response) end # Send health metrics - Diagnostics::Health.metrics.send_metrics( + Datadog.health_metrics.send_metrics( metrics_for_response(response).values ) end @@ -37,7 +37,7 @@ def update_stats_from_exception!(exception) stats.consecutive_errors += 1 # Send health metrics - Diagnostics::Health.metrics.send_metrics( + Datadog.health_metrics.send_metrics( metrics_for_exception(exception).values ) end diff --git a/spec/ddtrace/configuration/components_spec.rb b/spec/ddtrace/configuration/components_spec.rb index 7e4dcc15c50..bbc12211dc1 100644 --- a/spec/ddtrace/configuration/components_spec.rb +++ b/spec/ddtrace/configuration/components_spec.rb @@ -119,6 +119,15 @@ end context 'given some health metrics settings' do + let(:statsd) { instance_double('statsd') } + + before do + settings.diagnostics.health_metrics.enabled = true + settings.diagnostics.health_metrics.statsd = statsd + end + + it { expect(components.health_metrics.enabled?).to be true } + it { expect(components.health_metrics.statsd).to be statsd } end end end diff --git a/spec/ddtrace/configuration/settings_spec.rb b/spec/ddtrace/configuration/settings_spec.rb index 1683f3493ec..91fbeeb269d 100644 --- a/spec/ddtrace/configuration/settings_spec.rb +++ b/spec/ddtrace/configuration/settings_spec.rb @@ -61,11 +61,52 @@ describe '#diagnostics' do describe '#health_metrics' do - # TODO - end + describe '#enabled' do + subject(:enabled) { settings.diagnostics.health_metrics.enabled } + + context "when #{Datadog::Ext::Diagnostics::Health::Metrics::ENV_ENABLED}" do + around do |example| + ClimateControl.modify(Datadog::Ext::Diagnostics::Health::Metrics::ENV_ENABLED => environment) do + example.run + end + end - describe '#health_metrics=' do - # TODO + context 'is not defined' do + let(:environment) { nil } + it { is_expected.to be false } + end + + context 'is defined' do + let(:environment) { 'true' } + it { is_expected.to be true } + end + end + end + + describe '#enabled=' do + it 'changes the #enabled setting' do + expect { settings.diagnostics.health_metrics.enabled = true } + .to change { settings.diagnostics.health_metrics.enabled } + .from(false) + .to(true) + end + end + + describe '#statsd' do + subject(:statsd) { settings.diagnostics.health_metrics.statsd } + it { is_expected.to be nil } + end + + describe '#statsd=' do + let(:statsd) { double('statsd') } + + it 'changes the #statsd setting' do + expect { settings.diagnostics.health_metrics.statsd = statsd } + .to change { settings.diagnostics.health_metrics.statsd } + .from(nil) + .to(statsd) + end + end end end diff --git a/spec/ddtrace/configuration_spec.rb b/spec/ddtrace/configuration_spec.rb index 4acb8d585bc..8344c4d3199 100644 --- a/spec/ddtrace/configuration_spec.rb +++ b/spec/ddtrace/configuration_spec.rb @@ -62,14 +62,45 @@ let(:new_statsd) { instance_double(Datadog::Statsd) } before do - expect(old_statsd).to receive(:close) + expect(old_statsd).to receive(:close).once - test_class.configure { |c| c.runtime_metrics.statsd = old_statsd } - test_class.configure { |c| c.runtime_metrics.statsd = new_statsd } + test_class.configure do |c| + c.runtime_metrics.statsd = old_statsd + c.diagnostics.health_metrics.statsd = old_statsd + end + + test_class.configure do |c| + c.runtime_metrics.statsd = new_statsd + c.diagnostics.health_metrics.statsd = new_statsd + end + end + + it 'replaces the old Statsd and closes it' do + expect(test_class.runtime_metrics.statsd).to be new_statsd + expect(test_class.health_metrics.statsd).to be new_statsd + end + end + + context 'when replacing one of the metrics' do + let(:old_statsd) { instance_double(Datadog::Statsd) } + let(:new_statsd) { instance_double(Datadog::Statsd) } + + before do + expect(old_statsd).to_not receive(:close) + + test_class.configure do |c| + c.runtime_metrics.statsd = old_statsd + c.diagnostics.health_metrics.statsd = old_statsd + end + + test_class.configure do |c| + c.runtime_metrics.statsd = new_statsd + end end it 'replaces the old Statsd and closes it' do expect(test_class.runtime_metrics.statsd).to be new_statsd + expect(test_class.health_metrics.statsd).to be old_statsd end end @@ -79,8 +110,15 @@ before do expect(statsd).to_not receive(:close) - test_class.configure { |c| c.runtime_metrics.statsd = statsd } - test_class.configure { |c| c.runtime_metrics.statsd = statsd } + test_class.configure do |c| + c.runtime_metrics.statsd = statsd + c.diagnostics.health_metrics.statsd = statsd + end + + test_class.configure do |c| + c.runtime_metrics.statsd = statsd + c.diagnostics.health_metrics.statsd = statsd + end end it 'replaces the old Statsd and closes it' do @@ -94,7 +132,11 @@ before do expect(statsd).to_not receive(:close) - test_class.configure { |c| c.runtime_metrics.statsd = statsd } + test_class.configure do |c| + c.runtime_metrics.statsd = statsd + c.diagnostics.health_metrics.statsd = statsd + end + test_class.configure { |_c| } end diff --git a/spec/ddtrace/transport/http/client_spec.rb b/spec/ddtrace/transport/http/client_spec.rb index 57abdee1d60..29728a942e4 100644 --- a/spec/ddtrace/transport/http/client_spec.rb +++ b/spec/ddtrace/transport/http/client_spec.rb @@ -41,7 +41,7 @@ let(:response_class) { stub_const('TestResponse', Class.new { include Datadog::Transport::HTTP::Response }) } let(:response) { instance_double(response_class, code: double('status code')) } - before { allow(Datadog::Diagnostics::Health.metrics).to receive(:send_metrics) } + before { allow(Datadog.health_metrics).to receive(:send_metrics) } context 'given a block' do let(:handler) { double } diff --git a/spec/ddtrace/transport/statistics_spec.rb b/spec/ddtrace/transport/statistics_spec.rb index 18299d0d76e..78223a30b5a 100644 --- a/spec/ddtrace/transport/statistics_spec.rb +++ b/spec/ddtrace/transport/statistics_spec.rb @@ -18,7 +18,7 @@ subject(:update) { object.update_stats_from_response!(response) } let(:response) { instance_double(Datadog::Transport::Response) } - before { allow(Datadog::Diagnostics::Health.metrics).to receive(:send_metrics) } + before { allow(Datadog.health_metrics).to receive(:send_metrics) } context 'when the response' do context 'is OK' do @@ -35,7 +35,7 @@ expect(object.stats.internal_error).to eq(0) expect(object.stats.consecutive_errors).to eq(0) - expect(Datadog::Diagnostics::Health.metrics).to have_received(:send_metrics) do |metrics| + expect(Datadog.health_metrics).to have_received(:send_metrics) do |metrics| expect(metrics).to be_a_kind_of(Array) expect(metrics).to have(1).item expect(metrics).to include(kind_of(Datadog::Metrics::Metric)) @@ -64,7 +64,7 @@ expect(object.stats.internal_error).to eq(0) expect(object.stats.consecutive_errors).to eq(1) - expect(Datadog::Diagnostics::Health.metrics).to have_received(:send_metrics) do |metrics| + expect(Datadog.health_metrics).to have_received(:send_metrics) do |metrics| expect(metrics).to be_a_kind_of(Array) expect(metrics).to have(1).item expect(metrics).to include(kind_of(Datadog::Metrics::Metric)) @@ -93,7 +93,7 @@ expect(object.stats.internal_error).to eq(0) expect(object.stats.consecutive_errors).to eq(1) - expect(Datadog::Diagnostics::Health.metrics).to have_received(:send_metrics) do |metrics| + expect(Datadog.health_metrics).to have_received(:send_metrics) do |metrics| expect(metrics).to be_a_kind_of(Array) expect(metrics).to have(1).item expect(metrics).to include(kind_of(Datadog::Metrics::Metric)) @@ -122,7 +122,7 @@ expect(object.stats.internal_error).to eq(1) expect(object.stats.consecutive_errors).to eq(1) - expect(Datadog::Diagnostics::Health.metrics).to have_received(:send_metrics) do |metrics| + expect(Datadog.health_metrics).to have_received(:send_metrics) do |metrics| expect(metrics).to be_a_kind_of(Array) expect(metrics).to have(1).item expect(metrics).to include(kind_of(Datadog::Metrics::Metric)) @@ -226,7 +226,7 @@ subject(:update) { object.update_stats_from_exception!(exception) } let(:exception) { instance_double(StandardError) } - before { allow(Datadog::Diagnostics::Health.metrics).to receive(:send_metrics) } + before { allow(Datadog.health_metrics).to receive(:send_metrics) } it do update @@ -236,7 +236,7 @@ expect(object.stats.internal_error).to eq(1) expect(object.stats.consecutive_errors).to eq(1) - expect(Datadog::Diagnostics::Health.metrics).to have_received(:send_metrics) do |metrics| + expect(Datadog.health_metrics).to have_received(:send_metrics) do |metrics| expect(metrics).to be_a_kind_of(Array) expect(metrics).to have(1).item expect(metrics).to include(kind_of(Datadog::Metrics::Metric)) diff --git a/spec/support/health_metric_helpers.rb b/spec/support/health_metric_helpers.rb index 2cfb6272c7e..de2b0ad8c96 100644 --- a/spec/support/health_metric_helpers.rb +++ b/spec/support/health_metric_helpers.rb @@ -40,7 +40,7 @@ module HealthMetricHelpers shared_context 'health metrics' do include_context 'metrics' - let(:health_metrics) { Datadog::Diagnostics::Health.metrics } + let(:health_metrics) { Datadog.health_metrics } before { METRICS.each { |metric, _attrs| allow(health_metrics).to receive(metric) } } def have_received_lazy_health_metric(metric, *expected_args) From d4b6bf697215d7f981f716c60f58ac72f3a0a166 Mon Sep 17 00:00:00 2001 From: David Elner Date: Wed, 8 Apr 2020 18:16:01 -0400 Subject: [PATCH 4/4] Changed: Documentation to reflect new configuration styles. --- docs/DevelopmentGuide.md | 2 +- docs/GettingStarted.md | 41 ++++++++++++++++++++++------------------ 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/docs/DevelopmentGuide.md b/docs/DevelopmentGuide.md index c09d319df94..10534de556e 100644 --- a/docs/DevelopmentGuide.md +++ b/docs/DevelopmentGuide.md @@ -183,7 +183,7 @@ Then pass an adapter instance to the tracer configuration: ```ruby Datadog.configure do |c| - c.tracer transport_options: proc { |t| + c.tracer.transport_options = proc { |t| # By name t.adapter :custom diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md index cc9853041ef..1bcad1a7af7 100644 --- a/docs/GettingStarted.md +++ b/docs/GettingStarted.md @@ -1555,20 +1555,25 @@ To change the default behavior of the Datadog tracer, you can provide custom opt # config/initializers/datadog-tracer.rb Datadog.configure do |c| - c.tracer option_name: option_value, ... + c.tracer.enabled = true + c.tracer.hostname = 'my-agent' + c.tracer.port = 8126 + c.tracer.partial_flush.enabled = false + c.tracer.sampler = Datadog::AllSampler.new + + # OR for advanced use cases, you can specify your own tracer: + c.tracer.instance = Datadog::Tracer.new end ``` Available options are: - - `enabled`: defines if the `tracer` is enabled or not. If set to `false` the code could be still instrumented because of other settings, but no spans are sent to the local trace agent. - - `debug`: set to true to enable debug logging. + - `enabled`: defines if the `tracer` is enabled or not. If set to `false` instrumentation will still run, but no spans are sent to the trace agent. - `hostname`: set the hostname of the trace agent. + - `instance`: set to a custom `Datadog::Tracer` instance. If provided, other trace settings are ignored (you must configure it manually.) + - `partial_flush.enabled`: set to `true` to enable partial trace flushing (for long running traces.) Disabled by default. *Experimental.* - `port`: set the port the trace agent is listening on. - - `env`: set the environment. Rails users may set it to `Rails.env` to use their application settings. - - `tags`: set global tags that should be applied to all spans. Defaults to an empty hash - - `log`: defines a custom logger. - - `partial_flush`: set to `true` to enable partial trace flushing (for long running traces.) Disabled by default. *Experimental.* + - `sampler`: set to a custom `Datadog::Sampler` instance. If provided, the tracer will use this sampler to determine sampling behavior. #### Custom logging @@ -1580,13 +1585,12 @@ Additionally, it is possible to override the default logger and replace it by a ```ruby f = File.new("my-custom.log", "w+") # Log messages should go there -Datadog.configure do |c| - c.tracer log: Logger.new(f) # Overriding the default tracer -end - +Datadog::Logger.log = Logger.new(f) Datadog::Logger.log.info { "this is typically called by tracing code" } ``` +Additionally, you may activate debug logging with `Datadog::Logger.debug_logging = true`. + ### Environment and tags By default, the trace agent (not this library, but the program running in the background collecting data from various clients) uses the tags set in the agent config file, see our [environments tutorial](https://app.datadoghq.com/apm/docs/tutorials/environments) for details. @@ -1622,8 +1626,9 @@ Ultimately, tags can be set per span, but `env` should typically be the same for ```ruby # Sample rate is between 0 (nothing sampled) to 1 (everything sampled). sampler = Datadog::RateSampler.new(0.5) # sample 50% of the traces + Datadog.configure do |c| - c.tracer sampler: sampler + c.tracer.sampler = sampler end ``` @@ -2010,7 +2015,7 @@ The `Net` adapter submits traces using `Net::HTTP` over TCP. It is the default t ```ruby Datadog.configure do |c| - c.tracer transport_options: proc do |t| + c.tracer.transport_options = proc { |t| # Hostname, port, and additional options. :timeout is in seconds. t.adapter :net_http, '127.0.0.1', 8126, { timeout: 1 } } @@ -2025,7 +2030,7 @@ To use, first configure your trace agent to listen by Unix socket, then configur ```ruby Datadog.configure do |c| - c.tracer transport_options: proc { |t| + c.tracer.transport_options = proc { |t| # Provide filepath to trace agent Unix socket t.adapter :unix, '/tmp/ddagent/trace.sock' } @@ -2038,7 +2043,7 @@ The `Test` adapter is a no-op transport that can optionally buffer requests. For ```ruby Datadog.configure do |c| - c.tracer transport_options: proc { |t| + c.tracer.transport_options = proc { |t| # Set transport to no-op mode. Does not retain traces. t.adapter :test @@ -2055,7 +2060,7 @@ Custom adapters can be configured with: ```ruby Datadog.configure do |c| - c.tracer transport_options: proc { |t| + c.tracer.transport_options = proc { |t| # Initialize and pass an instance of the adapter custom_adapter = CustomAdapter.new t.adapter custom_adapter @@ -2086,12 +2091,12 @@ require 'ddtrace' Datadog.configure do |c| # To enable runtime metrics collection, set `true`. Defaults to `false` # You can also set DD_RUNTIME_METRICS_ENABLED=true to configure this. - c.runtime_metrics_enabled = true + c.runtime_metrics.enabled = true # Optionally, you can configure the Statsd instance used for sending runtime metrics. # Statsd is automatically configured with default settings if `dogstatsd-ruby` is available. # You can configure with host and port of Datadog agent; defaults to 'localhost:8125'. - c.runtime_metrics statsd: Datadog::Statsd.new + c.runtime_metrics.statsd = Datadog::Statsd.new end ```