class Datadog::Contrib::ActiveRecord::Configuration::Resolver

Converts Symbols, Strings, and Hashes to a normalized connection settings Hash.

When matching using a Hash, these are the valid fields: “` {

adapter: ...,
host: ...,
port: ...,
database: ...,
username: ...,
role: ...,

} “`

Partial matching is supported: not including certain fields or setting them to `nil` will cause them to matching all values for that field. For example: `database: nil` will match any database, given the remaining fields match.

Any fields not listed above are discarded.

When more than one configuration could be matched, the last one to match is selected, based on addition order (`#add`).

Public Class Methods

new(active_record_configuration = nil) click to toggle source
# File lib/ddtrace/contrib/active_record/configuration/resolver.rb, line 35
def initialize(active_record_configuration = nil)
  super()

  @active_record_configuration = active_record_configuration
end

Public Instance Methods

active_record_configuration() click to toggle source
# File lib/ddtrace/contrib/active_record/configuration/resolver.rb, line 41
def active_record_configuration
  @active_record_configuration || ::ActiveRecord::Base.configurations
end
add(matcher, value) click to toggle source
# File lib/ddtrace/contrib/active_record/configuration/resolver.rb, line 45
def add(matcher, value)
  parsed = parse_matcher(matcher)

  # In case of error parsing, don't store `nil` key
  # as it wouldn't be useful for matching configuration
  # hashes in `#resolve`.
  super(parsed, value) if parsed
end
resolve(db_config) click to toggle source
# File lib/ddtrace/contrib/active_record/configuration/resolver.rb, line 54
def resolve(db_config)
  active_record_config = resolve_connection_key(db_config).symbolize_keys

  hash = normalize_for_resolve(active_record_config)

  # Hashes in Ruby maintain insertion order
  _, config = @configurations.reverse_each.find do |matcher, _|
    matcher.none? do |key, value|
      value != hash[key]
    end
  end

  config
rescue => e
  Datadog.logger.error(
    "Failed to resolve ActiveRecord configuration key #{db_config.inspect}. " \
    "Cause: #{e.message} Source: #{Array(e.backtrace).first}"
  )

  nil
end

Protected Instance Methods

connection_resolver() click to toggle source
# File lib/ddtrace/contrib/active_record/configuration/resolver.rb, line 93
def connection_resolver
  @resolver ||= if defined?(::ActiveRecord::Base.configurations.resolve)
                  ::ActiveRecord::DatabaseConfigurations.new(active_record_configuration)
                elsif defined?(::ActiveRecord::ConnectionAdapters::ConnectionSpecification::Resolver)
                  ::ActiveRecord::ConnectionAdapters::ConnectionSpecification::Resolver.new(
                    active_record_configuration
                  )
                else
                  ::Datadog::Vendor::ActiveRecord::ConnectionAdapters::ConnectionSpecification::Resolver.new(
                    active_record_configuration
                  )
                end
end
normalize_for_config(active_record_config) click to toggle source

Extract only fields we'd like to match from the ActiveRecord configuration.

# File lib/ddtrace/contrib/active_record/configuration/resolver.rb, line 119
def normalize_for_config(active_record_config)
  {
    adapter: active_record_config[:adapter],
    host: active_record_config[:host],
    port: active_record_config[:port],
    database: active_record_config[:database],
    username: active_record_config[:username]
  }
end
Also aliased as: normalize_for_resolve
normalize_for_resolve(active_record_config)

Both resolvers perform the same operations for this implementation, but can be specialized

parse_matcher(matcher) click to toggle source
# File lib/ddtrace/contrib/active_record/configuration/resolver.rb, line 78
def parse_matcher(matcher)
  resolved_pattern = resolve_connection_key(matcher).symbolize_keys
  normalized = normalize_for_config(resolved_pattern)

  # Remove empty fields to allow for partial matching
  normalized.reject! { |_, v| v.nil? }

  normalized
rescue => e
  Datadog.logger.error(
    "Failed to resolve ActiveRecord configuration key #{matcher.inspect}. " \
    "Cause: #{e.message} Source: #{Array(e.backtrace).first}"
  )
end
resolve_connection_key(key) click to toggle source
# File lib/ddtrace/contrib/active_record/configuration/resolver.rb, line 107
def resolve_connection_key(key)
  result = connection_resolver.resolve(key)

  if result.respond_to?(:configuration_hash) # Rails >= 6.1
    result.configuration_hash
  else # Rails < 6.1
    result
  end
end