From 365e34434934e793bb5ecb04679b875b1e7bebac Mon Sep 17 00:00:00 2001 From: David Elner Date: Thu, 30 May 2024 15:20:07 -0400 Subject: [PATCH] Added: Core::Deprecations and limiting function --- lib/datadog/core.rb | 21 +----- lib/datadog/core/deprecations.rb | 58 ++++++++++++++++ sig/datadog/core.rbs | 1 + sig/datadog/core/deprecations.rbs | 22 +++++++ spec/datadog/core/deprecations_spec.rb | 91 ++++++++++++++++++++++++++ spec/datadog/core_spec.rb | 37 +---------- 6 files changed, 175 insertions(+), 55 deletions(-) create mode 100644 lib/datadog/core/deprecations.rb create mode 100644 sig/datadog/core/deprecations.rbs create mode 100644 spec/datadog/core/deprecations_spec.rb diff --git a/lib/datadog/core.rb b/lib/datadog/core.rb index 2f56cb785a7..86264868513 100644 --- a/lib/datadog/core.rb +++ b/lib/datadog/core.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require_relative 'core/deprecations' require_relative 'core/extensions' # We must load core extensions to make certain global APIs @@ -9,25 +10,7 @@ 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 + extend Core::Deprecations end extend Core::Extensions diff --git a/lib/datadog/core/deprecations.rb b/lib/datadog/core/deprecations.rb new file mode 100644 index 00000000000..01d134eac16 --- /dev/null +++ b/lib/datadog/core/deprecations.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +module Datadog + module Core + # Contains behavior for handling deprecated functions in the codebase. + module Deprecations + # 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. + # @param [Object] key A unique key for the deprecation. Only the first message with the same key will be logged. + def log_deprecation(disallowed_next_major: true, key: nil) + return unless log_deprecation?(key) + + Datadog.logger.warn do + message = yield + message += ' This will be enforced in the next major release.' if disallowed_next_major + message + end + + # Track the deprecation being logged. + deprecation_logged!(key) + + nil + end + + private + + # Determines whether a deprecation message should be logged. + # + # Internal use only. + def log_deprecation?(key) + return true if key.nil? + + # Only allow a deprecation to be logged once. + !logged_deprecations.key?(key) + end + + def deprecation_logged!(key) + return if key.nil? + + logged_deprecations[key] += 1 + end + + # Tracks what deprecation warnings have already been logged + # + # Internal use only. + def logged_deprecations + @logged_deprecations ||= Hash.new(0) + end + end + end +end diff --git a/sig/datadog/core.rbs b/sig/datadog/core.rbs index 410f4f2cd29..8f99173d43f 100644 --- a/sig/datadog/core.rbs +++ b/sig/datadog/core.rbs @@ -2,6 +2,7 @@ module Datadog module Core end + extend Core::Deprecations extend Core::Configuration extend Tracing::Contrib::Extensions::Helpers end diff --git a/sig/datadog/core/deprecations.rbs b/sig/datadog/core/deprecations.rbs new file mode 100644 index 00000000000..b3c42daa071 --- /dev/null +++ b/sig/datadog/core/deprecations.rbs @@ -0,0 +1,22 @@ +module Datadog + module Core + module Deprecations + interface _Hashing + def hash: () -> ::Integer + def eql?: (untyped) -> bool + def nil?: () -> bool + end + + type key = _Hashing + + @logged_deprecations: ::Hash[key, ::Integer] + def log_deprecation: (?disallowed_next_major: bool, ?key: key?) { () -> String } -> void + + private + def log_deprecation?: (key key) -> bool + + def deprecation_logged!: (key key) -> void + def logged_deprecations: () -> ::Hash[key, ::Integer] + end + end +end diff --git a/spec/datadog/core/deprecations_spec.rb b/spec/datadog/core/deprecations_spec.rb new file mode 100644 index 00000000000..e084a3e8f8f --- /dev/null +++ b/spec/datadog/core/deprecations_spec.rb @@ -0,0 +1,91 @@ +require 'spec_helper' + +require 'datadog/core/deprecations' + +RSpec.describe Datadog::Core::Deprecations do + context 'when extended' do + subject(:test_class) { Class.new { extend Datadog::Core::Deprecations } } + + describe '.log_deprecation' do + subject(:log_deprecation) { call_log_deprecation } + + let(:options) { {} } + let(:message) { 'Longer allowed.' } + + def call_log_deprecation + test_class.log_deprecation(**options) { message } + end + + 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 + + it 'does not limit messages' do + expect(Datadog.logger).to receive(:warn).twice + 2.times { call_log_deprecation } + end + end + + context 'with disallowed_next_major:' do + let(:options) { { disallowed_next_major: disallowed_next_major } } + + context 'true' do + let(: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 'false' do + let(: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 + + context 'with key:' do + let(:options) { { key: key } } + + context 'nil' do + let(:key) { nil } + + it 'does not limit messages' do + expect(Datadog.logger).to receive(:warn).twice + 2.times { call_log_deprecation } + end + end + + context 'Symbol' do + let(:key) { :deprecated_setting } + + it 'limits messages' do + expect(Datadog.logger).to receive(:warn).once + 2.times { call_log_deprecation } + end + end + + context 'String' do + let(:key) { 'deprecated_setting' } + + it 'limits messages' do + expect(Datadog.logger).to receive(:warn).once + 2.times { call_log_deprecation } + end + end + end + end + end +end diff --git a/spec/datadog/core_spec.rb b/spec/datadog/core_spec.rb index a979921dd06..194de852de8 100644 --- a/spec/datadog/core_spec.rb +++ b/spec/datadog/core_spec.rb @@ -3,42 +3,7 @@ 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 + it { expect(described_class).to be_a_kind_of(Datadog::Core::Deprecations) } end RSpec.describe Datadog do