Skip to content

Commit

Permalink
continuing decoupling with Tracing where possible
Browse files Browse the repository at this point in the history
  • Loading branch information
anmarchenko committed Sep 15, 2023
1 parent 0cf248e commit 4831625
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 38 deletions.
29 changes: 21 additions & 8 deletions lib/datadog/ci/configuration/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
module Datadog
module CI
module Configuration
# Adds CI behavior to Datadog trace settings
# Adds CI behavior to ddtrace settings
module Settings
InvalidIntegrationError = Class.new(StandardError)

def self.extended(base)
base = base.singleton_class unless base.is_a?(Class)
add_settings!(base)
Expand All @@ -24,16 +26,20 @@ def self.add_settings!(base)
define_method(:instrument) do |integration_name, options = {}, &block|
return unless enabled

registered_integration = Datadog::CI::Contrib::Integration.registry[integration_name]
return unless registered_integration
integration = fetch_integration(integration_name)
return unless integration.class.compatible?

return unless integration.default_configuration.enabled
integration.configure(:default, options, &block)

klass = registered_integration.klass
return unless klass.loaded? && klass.compatible?
return if integration.patcher.patched?
integration.patcher.patch
end

instance = klass.new
return if instance.patcher.patched?
define_method(:[]) do |integration_name, key = :default|
integration = fetch_integration(integration_name)

instance.patcher.patch
integration.resolve(key) unless integration.nil?
end

# TODO: Deprecate in the next major version, as `instrument` better describes this method's purpose
Expand All @@ -45,6 +51,13 @@ def self.add_settings!(base)
o.type :hash
o.default({})
end

define_method(:fetch_integration) do |name|
registered = Datadog::CI::Contrib::Integration.registry[name]
raise(InvalidIntegrationError, "'#{name}' is not a valid integration.") if registered.nil?

registered.integration
end
end
end
end
Expand Down
17 changes: 9 additions & 8 deletions lib/datadog/ci/contrib/integration.rb
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
# frozen_string_literal: true

require "datadog/tracing/contrib/configurable"
require "datadog/tracing/contrib/patchable"

module Datadog
module CI
module Contrib
# Base provides features that are shared across all integrations
module Integration
@registry = {}

RegisteredIntegration = Struct.new(:name, :klass, :options)
RegisteredIntegration = Struct.new(:name, :integration, :options)

def self.included(base)
base.extend(ClassMethods)

base.include(Datadog::Tracing::Contrib::Patchable)
base.include(Datadog::Tracing::Contrib::Configurable)
end

# Class-level methods for Integration
module ClassMethods
def register_as(name, options = {})
Integration.register(self, name, options)
end

def compatible?
true
end
end

def self.register(integration, name, options)
registry[name] = RegisteredIntegration.new(name, integration, options)
def self.register(klass, name, options)
registry[name] = RegisteredIntegration.new(name, klass.new, options)
end

def self.registry
Expand Down
9 changes: 5 additions & 4 deletions lib/datadog/ci/test.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# frozen_string_literal: true

require "datadog/tracing"
require "datadog/tracing/contrib/analytics"

require_relative "ext/app_types"
Expand All @@ -19,13 +20,13 @@ def self.trace(span_name, options = {})
}.merge(options[:span_options] || {})

if block_given?
Tracing.trace(span_name, **span_options) do |span, trace|
::Datadog::Tracing.trace(span_name, **span_options) do |span, trace|
set_tags!(trace, span, options)
yield(span, trace)
end
else
span = Tracing.trace(span_name, **span_options)
trace = Tracing.active_trace
span = ::Datadog::Tracing.trace(span_name, **span_options)
trace = ::Datadog::Tracing.active_trace
set_tags!(trace, span, options)
span
end
Expand All @@ -37,7 +38,7 @@ def self.set_tags!(trace, span, tags = {})

# Set default tags
trace.origin = Ext::Test::CONTEXT_ORIGIN if trace
Datadog::Tracing::Contrib::Analytics.set_measured(span)
::Datadog::Tracing::Contrib::Analytics.set_measured(span)
span.set_tag(Ext::Test::TAG_SPAN_KIND, Ext::AppTypes::TYPE_TEST)

# Set environment tags
Expand Down
44 changes: 29 additions & 15 deletions spec/datadog/ci/configuration/settings_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Dummy Integration
class FakeIntegration
def initialize(configuration)
@configuration = configuration
end

module Patcher
module_function

Expand Down Expand Up @@ -31,6 +35,13 @@ def self.auto_instrument?
def patcher
Patcher
end

def default_configuration
@configuration
end

def configure(name, options, &block)
end
end

RSpec.describe Datadog::CI::Configuration::Settings do
Expand Down Expand Up @@ -92,12 +103,15 @@ def patcher
let(:registry) { {} }
let(:integration_name) { :fake }

let(:integration_config) { double(enabled: true) }
let(:integration) { FakeIntegration.new(integration_config) }

subject(:instrument) { settings.ci.instrument(integration_name) }

before do
registry[integration_name] = instance_double(
Datadog::CI::Contrib::Integration::RegisteredIntegration,
klass: FakeIntegration
integration: integration
)

allow(Datadog::CI::Contrib::Integration).to receive(:registry).and_return(registry)
Expand All @@ -112,12 +126,10 @@ def patcher
let(:ci_enabled) { true }

context "when integration exists" do
context "when loaded and compatible" do
it "patches the integration" do
expect(FakeIntegration::Patcher).to receive(:patch)
it "patches the integration" do
expect(FakeIntegration::Patcher).to receive(:patch)

instrument
end
instrument
end

context "when called multiple times" do
Expand All @@ -129,8 +141,8 @@ def patcher
end
end

context "when not loaded" do
before { expect(FakeIntegration).to receive(:loaded?).and_return(false) }
context "when not compatible" do
before { expect(FakeIntegration).to receive(:compatible?).and_return(false) }

it "does not patch the integration" do
expect(FakeIntegration::Patcher).to_not receive(:patch)
Expand All @@ -139,22 +151,24 @@ def patcher
end
end

context "when loaded and not compatible" do
before { expect(FakeIntegration).to receive(:compatible?).and_return(false) }
context "when not enabled" do
before do
allow(integration_config).to receive(:enabled).and_return(false)
end

it "does not patch the integration" do
expect(FakeIntegration::Patcher).to_not receive(:patch)

instrument
end
end
end

context "when integration does not exist" do
let(:integration_name) { :not_exiting }
context "when integration does not exist" do
let(:integration_name) { :not_exiting }

it "does not patch the integration" do
expect { instrument }.to_not raise_error
end
it "does not patch the integration" do
expect { instrument }.to_not raise_error
end
end

Expand Down
2 changes: 1 addition & 1 deletion spec/datadog/ci/contrib/cucumber/integration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
RSpec.describe Datadog::CI::Contrib::Cucumber::Integration do
extend ConfigurationHelpers

let(:integration) { described_class.new(:cucumber) }
let(:integration) { described_class.new }

describe ".version" do
subject(:version) { described_class.version }
Expand Down
2 changes: 1 addition & 1 deletion spec/datadog/ci/contrib/minitest/integration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
RSpec.describe Datadog::CI::Contrib::Minitest::Integration do
extend ConfigurationHelpers

let(:integration) { described_class.new(:minitest) }
let(:integration) { described_class.new }

describe ".version" do
subject(:version) { described_class.version }
Expand Down
2 changes: 1 addition & 1 deletion spec/datadog/ci/contrib/rspec/integration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
RSpec.describe Datadog::CI::Contrib::RSpec::Integration do
extend ConfigurationHelpers

let(:integration) { described_class.new(:rspec) }
let(:integration) { described_class.new }

describe ".version" do
subject(:version) { described_class.version }
Expand Down
3 changes: 3 additions & 0 deletions spec/datadog/ci/contrib/support/mode_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
let(:components) { Datadog::Core::Configuration::Components.new(settings) }

before do
# TODO: this is a very hacky way that messes with Core's internals
allow_any_instance_of(Datadog::Core::Configuration).to receive(:configuration).and_return(settings)

allow(Datadog::Tracing)
.to receive(:tracer)
.and_return(components.tracer)
Expand Down
2 changes: 2 additions & 0 deletions spec/datadog/ci/contrib/support/tracer_helpers.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require "datadog/tracing"

module Contrib
# Contrib-specific tracer helpers.
# For contrib, we only allow one tracer to be active:
Expand Down
1 change: 1 addition & 0 deletions spec/support/tracer_helpers.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require "datadog/tracing"
require_relative "faux_writer"

module TracerHelpers
Expand Down

0 comments on commit 4831625

Please sign in to comment.