diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md index 91b44d4372..9cfd888a20 100644 --- a/docs/GettingStarted.md +++ b/docs/GettingStarted.md @@ -2078,8 +2078,8 @@ end | `telemetry.enabled` | `DD_INSTRUMENTATION_TELEMETRY_ENABLED` | `false` | Allows you to enable sending telemetry data to Datadog. In a future release, we will be setting this to `true` by default, as documented [here](https://docs.datadoghq.com/tracing/configure_data_security/#telemetry-collection). | | **Tracing** | | | | | `tracing.analytics.enabled` | `DD_TRACE_ANALYTICS_ENABLED` | `nil` | Enables or disables trace analytics. See [Sampling](#sampling) for more details. | -| `tracing.distributed_tracing.propagation_extract_style` | `DD_PROPAGATION_STYLE_EXTRACT` | `['Datadog','B3','B3 single header']` | Distributed tracing header formats to extract. See [Distributed Tracing](#distributed-tracing) for more details. | -| `tracing.distributed_tracing.propagation_inject_style` | `DD_PROPAGATION_STYLE_INJECT` | `['Datadog']` | Distributed tracing header formats to inject. See [Distributed Tracing](#distributed-tracing) for more details. | +| `tracing.distributed_tracing.propagation_extract_style` | `DD_TRACE_PROPAGATION_STYLE_EXTRACT` | `['Datadog','b3multi','b3']` | Distributed tracing header formats to extract. See [Distributed Tracing](#distributed-tracing) for more details.| +| `tracing.distributed_tracing.propagation_inject_style` | `DD_TRACE_PROPAGATION_STYLE_INJECT` | `['Datadog']` | Distributed tracing header formats to inject. See [Distributed Tracing](#distributed-tracing) for more details. | | `tracing.enabled` | `DD_TRACE_ENABLED` | `true` | Enables or disables tracing. If set to `false` instrumentation will still run, but no traces are sent to the trace agent. | | `tracing.instrument(, )` | | | Activates instrumentation for a specific library. See [Integration instrumentation](#integration-instrumentation) for more details. | | `tracing.log_injection` | `DD_LOGS_INJECTION` | `true` | Injects [Trace Correlation](#trace-correlation) information into Rails logs if present. Supports the default logger (`ActiveSupport::TaggedLogging`), `lograge`, and `semantic_logger`. | diff --git a/docs/UpgradeGuide.md b/docs/UpgradeGuide.md index 837ef2af4c..6673ecf07e 100644 --- a/docs/UpgradeGuide.md +++ b/docs/UpgradeGuide.md @@ -694,7 +694,7 @@ end | Configuration | Changed | Many settings have been namespaced under specific categories | Update your configuration to these [new settings](#1.0-configuration-settings) where appropriate. | | Configuration | Removed | `Datadog.configure(client, options)` | Use `Datadog.configure_onto(client, options)` instead. | | Configuration | Removed | `DD_#{integration}_ANALYTICS_ENABLED` and `DD_#{integration}_ANALYTICS_SAMPLE_RATE` environment variables | Use `DD_TRACE_#{integration}_ANALYTICS_ENABLED` and `DD_TRACE_#{integration}_ANALYTICS_SAMPLE_RATE` instead. | -| Configuration | Removed | `DD_PROPAGATION_INJECT_STYLE` and `DD_PROPAGATION_EXTRACT_STYLE` environment variables | Use `DD_PROPAGATION_STYLE_INJECT` and `DD_PROPAGATION_STYLE_EXTRACT` instead. | +| Configuration | Removed | `DD_PROPAGATION_INJECT_STYLE` and `DD_PROPAGATION_EXTRACT_STYLE` environment variables | Use `DD_TRACE_PROPAGATION_STYLE_INJECT` and `DD_TRACE_PROPAGATION_STYLE_EXTRACT` instead. | | Integrations | Changed | `-` in HTTP header tag names are kept, and no longer replaced with `_` | For example: `http.response.headers.content_type` is changed to `http.response.headers.content-type`. | | Integrations | Changed | `Contrib::Configurable#default_configuration` moved to `Tracing::Contrib::Configurable#new_configuration` | Use `Tracing::Contrib::Configurable#new_configuration` instead. | | Integrations | Changed | `Datadog.configuration.registry` moved to `Datadog.registry` | Use `Datadog.registry` instead. | diff --git a/lib/datadog/core.rb b/lib/datadog/core.rb index 4177e4a321..0e41336a2b 100644 --- a/lib/datadog/core.rb +++ b/lib/datadog/core.rb @@ -1,4 +1,5 @@ -# typed: strict +# frozen_string_literal: true +# typed: true require_relative 'core/extensions' @@ -9,6 +10,25 @@ module Datadog # products. It is a dependency of each product. Contrast with Datadog::Kit # for higher-level features. module Core + class << self + # Records the occurrence of a deprecated operation in this library. + # + # Currently, these operations are logged to `Datadog.logger` at `warn` level. + # + # `disallowed_next_major` adds a message informing that the deprecated operation + # won't be allowed in the next major release. + # + # @yieldreturn [String] a String with the lazily evaluated deprecation message. + # @param [Boolean] disallowed_next_major whether this deprecation will be enforced in the next major release. + def log_deprecation(disallowed_next_major: true) + Datadog.logger.warn do + message = yield + message += ' This will be enforced in the next major release.' if disallowed_next_major + message + end + nil + end + end end extend Core::Extensions diff --git a/lib/datadog/core/configuration/settings.rb b/lib/datadog/core/configuration/settings.rb index c7a3b150f5..1e8c1be336 100644 --- a/lib/datadog/core/configuration/settings.rb +++ b/lib/datadog/core/configuration/settings.rb @@ -431,8 +431,8 @@ def initialize(*_) # # The supported formats are: # * `Datadog`: Datadog propagation format, described by [Distributed Tracing](https://docs.datadoghq.com/tracing/setup_overview/setup/ruby/#distributed-tracing). - # * `B3`: B3 Propagation using multiple headers, described by [openzipkin/b3-propagation](https://github.com/openzipkin/b3-propagation#multiple-headers). - # * `B3 single header`: B3 Propagation using a single header, described by [openzipkin/b3-propagation](https://github.com/openzipkin/b3-propagation#single-header). + # * `b3multi`: B3 Propagation using multiple headers, described by [openzipkin/b3-propagation](https://github.com/openzipkin/b3-propagation#multiple-headers). + # * `b3`: B3 Propagation using a single header, described by [openzipkin/b3-propagation](https://github.com/openzipkin/b3-propagation#single-header). # # @public_api settings :distributed_tracing do @@ -442,23 +442,40 @@ def initialize(*_) # The tracer will try to find distributed headers in the order they are present in the list provided to this option. # The first format to have valid data present will be used. # - # @default `DD_PROPAGATION_STYLE_EXTRACT` environment variable (comma-separated list), - # otherwise `['Datadog','B3','B3 single header']`. + # @default `DD_TRACE_PROPAGATION_STYLE_EXTRACT` environment variable (comma-separated list), + # otherwise `['Datadog','b3multi','b3']`. # @return [Array] option :propagation_extract_style do |o| o.default do + # DEV-2.0: Change default value to `tracecontext, Datadog`. # Look for all headers by default env_to_list( - Tracing::Configuration::Ext::Distributed::ENV_PROPAGATION_STYLE_EXTRACT, + [Tracing::Configuration::Ext::Distributed::ENV_PROPAGATION_STYLE_EXTRACT, + Tracing::Configuration::Ext::Distributed::ENV_PROPAGATION_STYLE_EXTRACT_OLD], [ Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG, - Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3, + Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_MULTI_HEADER, Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER ], comma_separated_only: true ) end + o.on_set do |styles| + # Modernize B3 options + # DEV-2.0: Can be removed with the removal of deprecated B3 constants. + styles.map! do |style| + case style + when Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3 + Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_MULTI_HEADER + when Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER_OLD + Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER + else + style + end + end + end + o.lazy end @@ -467,17 +484,34 @@ def initialize(*_) # # The tracer will inject data from all styles specified in this option. # - # @default `DD_PROPAGATION_STYLE_INJECT` environment variable (comma-separated list), otherwise `['Datadog']`. + # @default `DD_TRACE_PROPAGATION_STYLE_INJECT` environment variable (comma-separated list), otherwise `['Datadog']`. # @return [Array] option :propagation_inject_style do |o| o.default do + # DEV-2.0: Change default value to `tracecontext, Datadog`. env_to_list( - Tracing::Configuration::Ext::Distributed::ENV_PROPAGATION_STYLE_INJECT, + [Tracing::Configuration::Ext::Distributed::ENV_PROPAGATION_STYLE_INJECT, + Tracing::Configuration::Ext::Distributed::ENV_PROPAGATION_STYLE_INJECT_OLD], [Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG], comma_separated_only: true # Only inject Datadog headers by default ) end + o.on_set do |styles| + # Modernize B3 options + # DEV-2.0: Can be removed with the removal of deprecated B3 constants. + styles.map! do |style| + case style + when Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3 + Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_MULTI_HEADER + when Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER_OLD + Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER + else + style + end + end + end + o.lazy end end diff --git a/lib/datadog/core/environment/variable_helpers.rb b/lib/datadog/core/environment/variable_helpers.rb index 4e99e667af..1c36df49dc 100644 --- a/lib/datadog/core/environment/variable_helpers.rb +++ b/lib/datadog/core/environment/variable_helpers.rb @@ -9,18 +9,45 @@ module Environment module VariableHelpers extend self - def env_to_bool(var, default = nil) - var = decode_array(var) + # Reads an environment variable as a Boolean. + # + # @param [String] var environment variable + # @param [Array] var list of environment variables + # @param [Boolean] default the default value if the keys in `var` are not present in the environment + # @param [Boolean] deprecation_warning when `var` is a list, record a deprecation log when + # the first key in `var` is not used. + # @return [Boolean] if the environment value is the string `true` + # @return [default] if the environment value is not found + def env_to_bool(var, default = nil, deprecation_warning: true) + var = decode_array(var, deprecation_warning) var && ENV.key?(var) ? ENV[var].to_s.strip.downcase == 'true' : default end - def env_to_int(var, default = nil) - var = decode_array(var) + # Reads an environment variable as an Integer. + # + # @param [String] var environment variable + # @param [Array] var list of environment variables + # @param [Integer] default the default value if the keys in `var` are not present in the environment + # @param [Boolean] deprecation_warning when `var` is a list, record a deprecation log when + # the first key in `var` is not used. + # @return [Integer] if the environment value is a valid Integer + # @return [default] if the environment value is not found + def env_to_int(var, default = nil, deprecation_warning: true) + var = decode_array(var, deprecation_warning) var && ENV.key?(var) ? ENV[var].to_i : default end - def env_to_float(var, default = nil) - var = decode_array(var) + # Reads an environment variable as a Float. + # + # @param [String] var environment variable + # @param [Array] var list of environment variables + # @param [Float] default the default value if the keys in `var` are not present in the environment + # @param [Boolean] deprecation_warning when `var` is a list, record a deprecation log when + # the first key in `var` is not used. + # @return [Float] if the environment value is a valid Float + # @return [default] if the environment value is not found + def env_to_float(var, default = nil, deprecation_warning: true) + var = decode_array(var, deprecation_warning) var && ENV.key?(var) ? ENV[var].to_f : default end @@ -33,8 +60,16 @@ def env_to_float(var, default = nil) # either trailing or leading are trimmed. # # Empty entries, after trimmed, are also removed from the result. - def env_to_list(var, default = [], comma_separated_only:) - var = decode_array(var) + # + # @param [String] var environment variable + # @param [Array] var list of environment variables + # @param [Array] default the default value if the keys in `var` are not present in the environment + # @param [Boolean] deprecation_warning when `var` is a list, record a deprecation log when + # the first key in `var` is not used. + # @return [Array] if the environment value is a valid list + # @return [default] if the environment value is not found + def env_to_list(var, default = [], comma_separated_only:, deprecation_warning: true) + var = decode_array(var, deprecation_warning) if var && ENV.key?(var) value = ENV[var] @@ -59,8 +94,21 @@ def env_to_list(var, default = [], comma_separated_only:) private - def decode_array(var) - var.is_a?(Array) ? var.find { |env_var| ENV.key?(env_var) } : var + def decode_array(var, deprecation_warning) + if var.is_a?(Array) + var.find.with_index do |env_var, i| + found = ENV.key?(env_var) + + # Check if we are using a non-preferred environment variable + if deprecation_warning && found && i != 0 + Datadog::Core.log_deprecation { "#{env_var} environment variable is deprecated, use #{var.first} instead." } + end + + found + end + else + var + end end end end diff --git a/lib/datadog/tracing/configuration/ext.rb b/lib/datadog/tracing/configuration/ext.rb index c59bd33a14..3940527f83 100644 --- a/lib/datadog/tracing/configuration/ext.rb +++ b/lib/datadog/tracing/configuration/ext.rb @@ -18,11 +18,37 @@ module Correlation # @public_api module Distributed + # Custom Datadog format PROPAGATION_STYLE_DATADOG = 'Datadog'.freeze + + PROPAGATION_STYLE_B3_MULTI_HEADER = 'b3multi'.freeze + # @deprecated Use `b3multi` instead. PROPAGATION_STYLE_B3 = 'B3'.freeze - PROPAGATION_STYLE_B3_SINGLE_HEADER = 'B3 single header'.freeze - ENV_PROPAGATION_STYLE_INJECT = 'DD_PROPAGATION_STYLE_INJECT'.freeze - ENV_PROPAGATION_STYLE_EXTRACT = 'DD_PROPAGATION_STYLE_EXTRACT'.freeze + + PROPAGATION_STYLE_B3_SINGLE_HEADER = 'b3'.freeze + # @deprecated Use `b3` instead. + PROPAGATION_STYLE_B3_SINGLE_HEADER_OLD = 'B3 single header'.freeze + + # W3C Trace Context + PROPAGATION_STYLE_TRACE_CONTEXT = 'tracecontext'.freeze + + # Sets both extract and inject propagation style tho the provided value. + # Has lower precedence than `DD_TRACE_PROPAGATION_STYLE_INJECT` or + # `DD_TRACE_PROPAGATION_STYLE_EXTRACT`. + ENV_PROPAGATION_STYLE_EXTRACT = 'DD_TRACE_PROPAGATION_STYLE'.freeze + + ENV_PROPAGATION_STYLE_INJECT = 'DD_TRACE_PROPAGATION_STYLE_INJECT'.freeze + # @deprecated Use `DD_TRACE_PROPAGATION_STYLE_INJECT` instead. + ENV_PROPAGATION_STYLE_INJECT_OLD = 'DD_PROPAGATION_STYLE_INJECT'.freeze + + ENV_PROPAGATION_STYLE_EXTRACT = 'DD_TRACE_PROPAGATION_STYLE_EXTRACT'.freeze + # @deprecated Use `DD_TRACE_PROPAGATION_STYLE_EXTRACT` instead. + ENV_PROPAGATION_STYLE_EXTRACT_OLD = 'DD_PROPAGATION_STYLE_EXTRACT'.freeze + + # A no-op propagator. Compatible with OpenTelemetry's `none` propagator. + # @see https://opentelemetry.io/docs/concepts/sdk-configuration/general-sdk-configuration/#otel_propagators + PROPAGATION_STYLE_NONE = 'none'.freeze + ENV_X_DATADOG_TAGS_MAX_LENGTH = 'DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH'.freeze end diff --git a/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb b/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb index ce18b12a33..cbe2e3f1ff 100644 --- a/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +++ b/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb @@ -2,10 +2,11 @@ # typed: true require_relative 'fetcher' -require_relative '../../../distributed/b3' +require_relative '../../../distributed/b3_multi' require_relative '../../../distributed/b3_single' require_relative '../../../distributed/datadog' require_relative '../../../distributed/propagation' +require_relative '../../../distributed/trace_context' module Datadog module Tracing @@ -18,8 +19,8 @@ class Propagation < Tracing::Distributed::Propagation def initialize super( propagation_styles: { - Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3 => - Tracing::Distributed::B3.new(fetcher: Fetcher), + Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_MULTI_HEADER => + Tracing::Distributed::B3Multi.new(fetcher: Fetcher), Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER => Tracing::Distributed::B3Single.new(fetcher: Fetcher), Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG => diff --git a/lib/datadog/tracing/contrib/http/distributed/propagation.rb b/lib/datadog/tracing/contrib/http/distributed/propagation.rb index 96118148e5..cc086e6ed7 100644 --- a/lib/datadog/tracing/contrib/http/distributed/propagation.rb +++ b/lib/datadog/tracing/contrib/http/distributed/propagation.rb @@ -3,9 +3,10 @@ require_relative 'fetcher' require_relative '../../../distributed/propagation' -require_relative '../../../distributed/b3' +require_relative '../../../distributed/b3_multi' require_relative '../../../distributed/b3_single' require_relative '../../../distributed/datadog' +require_relative '../../../distributed/trace_context' module Datadog module Tracing @@ -17,8 +18,8 @@ class Propagation < Tracing::Distributed::Propagation def initialize super( propagation_styles: { - Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3 => - Tracing::Distributed::B3.new(fetcher: Fetcher), + Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_MULTI_HEADER => + Tracing::Distributed::B3Multi.new(fetcher: Fetcher), Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER => Tracing::Distributed::B3Single.new(fetcher: Fetcher), Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG => diff --git a/lib/datadog/tracing/distributed/b3.rb b/lib/datadog/tracing/distributed/b3_multi.rb similarity index 96% rename from lib/datadog/tracing/distributed/b3.rb rename to lib/datadog/tracing/distributed/b3_multi.rb index 52121cca9a..4e685ef52e 100644 --- a/lib/datadog/tracing/distributed/b3.rb +++ b/lib/datadog/tracing/distributed/b3_multi.rb @@ -7,9 +7,9 @@ module Datadog module Tracing module Distributed - # B3-style trace propagation. + # B3 multi header-style trace propagation. # @see https://github.com/openzipkin/b3-propagation#multiple-headers - class B3 + class B3Multi B3_TRACE_ID_KEY = 'x-b3-traceid' B3_SPAN_ID_KEY = 'x-b3-spanid' B3_SAMPLED_KEY = 'x-b3-sampled' diff --git a/spec/datadog/core/configuration/settings_spec.rb b/spec/datadog/core/configuration/settings_spec.rb index 678a79398a..4654bf326a 100644 --- a/spec/datadog/core/configuration/settings_spec.rb +++ b/spec/datadog/core/configuration/settings_spec.rb @@ -998,40 +998,72 @@ describe '#propagation_extract_style' do subject(:propagation_extract_style) { settings.tracing.distributed_tracing.propagation_extract_style } - context "when #{Datadog::Tracing::Configuration::Ext::Distributed::ENV_PROPAGATION_STYLE_EXTRACT}" do - around do |example| - ClimateControl.modify( - Datadog::Tracing::Configuration::Ext::Distributed::ENV_PROPAGATION_STYLE_EXTRACT => environment - ) do - example.run - end + around do |example| + ClimateControl.modify(var_name => var_value) do + example.run end + end + + context 'when DD_TRACE_PROPAGATION_STYLE_EXTRACT' do + let(:var_name) { 'DD_TRACE_PROPAGATION_STYLE_EXTRACT' } context 'is not defined' do - let(:environment) { nil } + let(:var_value) { nil } it do is_expected.to eq( [ Datadog::Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG, - Datadog::Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3, + Datadog::Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_MULTI_HEADER, + Datadog::Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER + ] + ) + end + end + + context 'is defined' do + let(:var_value) { 'b3multi,b3' } + + it do + is_expected.to eq( + [ + Datadog::Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_MULTI_HEADER, Datadog::Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER ] ) end end + context 'is set to deprecated style names' do + let(:var_value) { 'B3,B3 single header' } + + it 'translates to new names' do + is_expected.to eq( + [ + Datadog::Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_MULTI_HEADER, + Datadog::Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER + ] + ) + end + end + end + + context 'with deprecated DD_PROPAGATION_STYLE_EXTRACT' do + let(:var_name) { 'DD_PROPAGATION_STYLE_EXTRACT' } + context 'is defined' do - let(:environment) { 'B3,B3 single header' } + let(:var_value) { 'b3multi,b3' } it do is_expected.to eq( [ - Datadog::Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3, + Datadog::Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_MULTI_HEADER, Datadog::Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER ] ) end + + include_examples 'records deprecated action', 'DD_PROPAGATION_STYLE_EXTRACT environment variable is deprecated' end end end @@ -1039,32 +1071,64 @@ describe '#propagation_inject_style' do subject(:propagation_inject_style) { settings.tracing.distributed_tracing.propagation_inject_style } - context "when #{Datadog::Tracing::Configuration::Ext::Distributed::ENV_PROPAGATION_STYLE_INJECT}" do - around do |example| - ClimateControl.modify( - Datadog::Tracing::Configuration::Ext::Distributed::ENV_PROPAGATION_STYLE_INJECT => environment - ) do - example.run - end + around do |example| + ClimateControl.modify(var_name => var_value) do + example.run end + end + + context 'with DD_TRACE_PROPAGATION_STYLE_INJECT' do + let(:var_name) { 'DD_TRACE_PROPAGATION_STYLE_INJECT' } context 'is not defined' do - let(:environment) { nil } + let(:var_value) { nil } it { is_expected.to eq([Datadog::Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG]) } end context 'is defined' do - let(:environment) { 'Datadog,B3' } + let(:var_value) { 'Datadog,b3' } + + it do + is_expected.to eq( + [ + Datadog::Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG, + Datadog::Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER + ] + ) + end + end + + context 'is set to deprecated style names' do + let(:var_value) { 'B3,B3 single header' } + + it 'translates to new names' do + is_expected.to eq( + [ + Datadog::Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_MULTI_HEADER, + Datadog::Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER + ] + ) + end + end + end + + context 'with deprecated DD_PROPAGATION_STYLE_INJECT' do + let(:var_name) { 'DD_PROPAGATION_STYLE_INJECT' } + + context 'is defined' do + let(:var_value) { 'Datadog,b3' } it do is_expected.to eq( [ Datadog::Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG, - Datadog::Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3 + Datadog::Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_B3_SINGLE_HEADER ] ) end + + include_examples 'records deprecated action', 'DD_PROPAGATION_STYLE_INJECT environment variable is deprecated' end end end diff --git a/spec/datadog/core/environment/variable_helpers_spec.rb b/spec/datadog/core/environment/variable_helpers_spec.rb index 14cc3f6382..de7261ad15 100644 --- a/spec/datadog/core/environment/variable_helpers_spec.rb +++ b/spec/datadog/core/environment/variable_helpers_spec.rb @@ -6,18 +6,52 @@ RSpec.describe Datadog::Core::Environment::VariableHelpers do let(:variable_helpers) { Class.new { extend Datadog::Core::Environment::VariableHelpers } } + let(:env_key) { var } let(:var) { 'TEST_VAR' } + let(:options) { {} } shared_context 'env var' do around do |example| - ClimateControl.modify(var => env_value) do + ClimateControl.modify(env_key => env_value) do example.run end end end + shared_context 'with deprecated options' do + # rubocop:disable RSpec/NamedSubject + context 'with deprecated environment variables' do + let(:env_key) { 'key-deprecated' } + let(:var) { %w[key key-deprecated] } + let(:env_value) { 'value' } + + context 'and deprecation_warning option is true' do + let(:options) { { deprecation_warning: true } } + + it 'records to deprecation log' do + expect { subject }.to log_deprecation(include('key-deprecated')) + end + end + + context 'and deprecation_warning option is false' do + let(:options) { { deprecation_warning: false } } + + it 'does not record to deprecation log' do + expect { subject }.to_not log_deprecation + end + end + + context 'and deprecation_warning option the default' do + it 'records to deprecation log' do + expect { subject }.to log_deprecation(include('key-deprecated')) + end + end + end + # rubocop:enable RSpec/NamedSubject + end + describe '::env_to_bool' do - subject(:env_to_bool) { variable_helpers.env_to_bool(var) } + subject(:env_to_bool) { variable_helpers.env_to_bool(var, **options) } context 'when env var is not defined' do context 'and default is not defined' do @@ -62,11 +96,13 @@ it { is_expected.to be false } end end + + include_context 'with deprecated options' end end describe '::env_to_int' do - subject(:env_to_int) { variable_helpers.env_to_int(var) } + subject(:env_to_int) { variable_helpers.env_to_int(var, **options) } context 'when env var is not defined' do context 'and default is not defined' do @@ -108,11 +144,13 @@ it { is_expected.to eq 0 } end + + include_context 'with deprecated options' end end describe '::env_to_float' do - subject(:env_to_float) { variable_helpers.env_to_float(var) } + subject(:env_to_float) { variable_helpers.env_to_float(var, **options) } context 'when env var is not defined' do context 'and default is not defined' do @@ -154,11 +192,13 @@ it { is_expected.to eq 0.0 } end + + include_context 'with deprecated options' end end describe '::env_to_list' do - subject(:env_to_list) { variable_helpers.env_to_list(var, comma_separated_only: false) } + subject(:env_to_list) { variable_helpers.env_to_list(var, comma_separated_only: false, **options) } context 'when env var is not defined' do context 'and default is not defined' do @@ -234,12 +274,14 @@ context 'and comma_separated_only is set' do subject(:env_to_list) { variable_helpers.env_to_list(var, comma_separated_only: true) } - context 'B3 single header ' do - let(:env_value) { 'B3 single header ' } + context 'value with space' do + let(:env_value) { 'value with space' } - it { is_expected.to eq(['B3 single header']) } + it { is_expected.to eq(['value with space']) } end end + + include_context 'with deprecated options' end end end diff --git a/spec/datadog/core_spec.rb b/spec/datadog/core_spec.rb index 0218bdb6af..f9184ca809 100644 --- a/spec/datadog/core_spec.rb +++ b/spec/datadog/core_spec.rb @@ -4,6 +4,45 @@ require 'datadog/core' +RSpec.describe Datadog::Core do + describe '.log_deprecation' do + subject(:log_deprecation) { described_class.log_deprecation(**options) { message } } + let(:options) { {} } + let(:message) { 'Longer allowed.' } + + context 'by default' do + it 'warns with enforcement message' do + expect(Datadog.logger).to receive(:warn) do |&block| + expect(block.call).to eq('Longer allowed. This will be enforced in the next major release.') + end + log_deprecation + end + end + + context 'with disallowed_next_major true' do + let(:options) { { disallowed_next_major: true } } + + it 'warns with enforcement message' do + expect(Datadog.logger).to receive(:warn) do |&block| + expect(block.call).to eq('Longer allowed. This will be enforced in the next major release.') + end + log_deprecation + end + end + + context 'with disallowed_next_major false' do + let(:options) { { disallowed_next_major: false } } + + it 'warns with enforcement message' do + expect(Datadog.logger).to receive(:warn) do |&block| + expect(block.call).to eq('Longer allowed.') + end + log_deprecation + end + end + end +end + RSpec.describe Datadog do describe 'class' do subject(:datadog) { described_class } diff --git a/spec/datadog/tracing/contrib/grpc/distributed/propagation_spec.rb b/spec/datadog/tracing/contrib/grpc/distributed/propagation_spec.rb index 44dd9b35a2..1dd26251c8 100644 --- a/spec/datadog/tracing/contrib/grpc/distributed/propagation_spec.rb +++ b/spec/datadog/tracing/contrib/grpc/distributed/propagation_spec.rb @@ -4,7 +4,7 @@ require 'datadog/tracing/contrib/grpc/distributed/propagation' require_relative '../../../distributed/b3_single_spec' -require_relative '../../../distributed/b3_spec' +require_relative '../../../distributed/b3_multi_spec' require_relative '../../../distributed/datadog_spec' require_relative '../../../distributed/propagation_spec' @@ -36,9 +36,9 @@ end end - context 'for B3' do - it_behaves_like 'B3 distributed format' do - let(:b3) { Datadog::Tracing::Distributed::B3.new(fetcher: fetcher_class) } + context 'for B3 Multi' do + it_behaves_like 'B3 Multi distributed format' do + let(:b3) { Datadog::Tracing::Distributed::B3Multi.new(fetcher: fetcher_class) } let(:fetcher_class) { Datadog::Tracing::Contrib::GRPC::Distributed::Fetcher } end end diff --git a/spec/datadog/tracing/contrib/http/distributed/propagation_spec.rb b/spec/datadog/tracing/contrib/http/distributed/propagation_spec.rb index aa0ada36b9..6c587bf5be 100644 --- a/spec/datadog/tracing/contrib/http/distributed/propagation_spec.rb +++ b/spec/datadog/tracing/contrib/http/distributed/propagation_spec.rb @@ -4,7 +4,7 @@ require 'datadog/tracing/contrib/http/distributed/propagation' require_relative '../../../distributed/b3_single_spec' -require_relative '../../../distributed/b3_spec' +require_relative '../../../distributed/b3_multi_spec' require_relative '../../../distributed/datadog_spec' require_relative '../../../distributed/propagation_spec' @@ -15,9 +15,9 @@ subject(:propagation) { described_class.new } end - context 'for B3' do - it_behaves_like 'B3 distributed format' do - let(:b3) { Datadog::Tracing::Distributed::B3.new(fetcher: fetcher_class) } + context 'for B3 Multi' do + it_behaves_like 'B3 Multi distributed format' do + let(:b3) { Datadog::Tracing::Distributed::B3Multi.new(fetcher: fetcher_class) } let(:fetcher_class) { Datadog::Tracing::Contrib::HTTP::Distributed::Fetcher } end end diff --git a/spec/datadog/tracing/distributed/b3_spec.rb b/spec/datadog/tracing/distributed/b3_multi_spec.rb similarity index 94% rename from spec/datadog/tracing/distributed/b3_spec.rb rename to spec/datadog/tracing/distributed/b3_multi_spec.rb index 45231b78d2..5893dc29f5 100644 --- a/spec/datadog/tracing/distributed/b3_spec.rb +++ b/spec/datadog/tracing/distributed/b3_multi_spec.rb @@ -2,10 +2,10 @@ require 'spec_helper' -require 'datadog/tracing/distributed/b3' +require 'datadog/tracing/distributed/b3_multi' require 'datadog/tracing/trace_digest' -RSpec.shared_examples 'B3 distributed format' do +RSpec.shared_examples 'B3 Multi distributed format' do subject(:b3) { described_class.new(fetcher: fetcher_class) } let(:fetcher_class) { Datadog::Tracing::Distributed::Fetcher } @@ -147,6 +147,6 @@ end end -RSpec.describe Datadog::Tracing::Distributed::B3 do - it_behaves_like 'B3 distributed format' +RSpec.describe Datadog::Tracing::Distributed::B3Multi do + it_behaves_like 'B3 Multi distributed format' end diff --git a/spec/datadog/tracing/distributed/propagation_spec.rb b/spec/datadog/tracing/distributed/propagation_spec.rb index d2c7913f44..ceaa77af4f 100644 --- a/spec/datadog/tracing/distributed/propagation_spec.rb +++ b/spec/datadog/tracing/distributed/propagation_spec.rb @@ -10,8 +10,8 @@ let(:propagation_styles) do { 'Datadog' => Datadog::Tracing::Distributed::Datadog.new(fetcher: fetcher_class), - 'B3' => Datadog::Tracing::Distributed::B3.new(fetcher: fetcher_class), - 'B3 single header' => Datadog::Tracing::Distributed::B3Single.new(fetcher: fetcher_class), + 'b3multi' => Datadog::Tracing::Distributed::B3Multi.new(fetcher: fetcher_class), + 'b3' => Datadog::Tracing::Distributed::B3Single.new(fetcher: fetcher_class), } end let(:fetcher_class) { Datadog::Tracing::Distributed::Fetcher } @@ -205,7 +205,7 @@ end end - context 'B3 trace id and parent id' do + context 'B3 Multi trace id and parent id' do let(:data) do { prepare_key['x-b3-traceid'] => '00ef01', @@ -238,7 +238,7 @@ end end - context 'B3 single trace id and parent id' do + context 'B3 Single trace id and parent id' do let(:data) do { prepare_key['b3'] => '00ef01-011ef0' diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 3e440d9c41..7d6e94febc 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -24,6 +24,7 @@ require 'support/configuration_helpers' require 'support/container_helpers' +require 'support/core_helpers' require 'support/faux_transport' require 'support/faux_writer' require 'support/health_metric_helpers' @@ -59,6 +60,7 @@ RSpec.configure do |config| config.include ConfigurationHelpers config.include ContainerHelpers + config.include CoreHelpers config.include HealthMetricHelpers config.include HttpHelpers config.include LogHelpers diff --git a/spec/support/core_helpers.rb b/spec/support/core_helpers.rb new file mode 100644 index 0000000000..3d9bfde9ef --- /dev/null +++ b/spec/support/core_helpers.rb @@ -0,0 +1,52 @@ +# typed: false + +module CoreHelpers + # Asserts that a deprecated action is recorded by the `subject` execution. + RSpec.shared_examples 'records deprecated action' do |matcher = nil| + it 'records deprecated action in the deprecation log' do + expect { subject }.to log_deprecation(matcher) + end + end + + # Test matcher for this library's deprecated operation recorder. + # + # @example Matching the message + # expect { subject }.to log_deprecation(include('deprecated_option')) + # @example Matching any message + # expect { subject }.to log_deprecation + # @example Allowing no deprecation logging + # expect { subject }.to_not log_deprecation + # @example Negate message matching + # expect { subject }.to_not log_deprecation(include('no_longer_deprecated_option')) + RSpec::Matchers.define :log_deprecation do |message_matcher| + match(notify_expectation_failures: true) do |block| + expect(::Datadog::Core).to receive(:log_deprecation).with(no_args) do |&message_block| + expect(message_block.call).to match(message_matcher) if message_matcher + end + + block.call + + true + end + + match_when_negated(notify_expectation_failures: true) do |block| + if message_matcher + allow(::Datadog::Core).to receive(:log_deprecation).with(no_args) do |&message_block| + expect(message_block.call).to_not match(message_matcher) + end + else + expect(::Datadog::Core).to_not receive(:log_deprecation) + end + + block.call + + true + end + + supports_block_expectations + + def supports_value_expectations? + false + end + end +end