Module: Datadog::Tracing::Contrib::Configuration::CachingResolver

Included in:
ActiveRecord::Configuration::Resolver
Defined in:
lib/datadog/tracing/contrib/configuration/resolver.rb

Overview

The CachingResolver is a mixin that provides caching functionality to the Resolver class. This is useful when Resolver#resolve values that are expensive to compute. This is a size-limited, FIFO cache.

Examples:

class MyResolver < Datadog::Tracing::Contrib::Configuration::Resolver
  prepend Datadog::Tracing::Contrib::Configuration::CachingResolver
  # ...
end

Instance Method Summary collapse

Instance Method Details

#add(matcher, value) ⇒ Object

Adds a new matcher, associating with it a value.

This value is returned when #resolve is called with a matching value for this matcher. When multiple matchers would match, #resolve returns the latest added one.

The matcher can be transformed internally by the #parse_matcher method before being stored.

The value can also be retrieved by calling #get with the same matcher added by this method.

Parameters:

  • matcher (Object) —

    integration-specific matcher

  • value (Object) —

    arbitrary value to be associated with matcher



125
126
127
128
# File 'lib/datadog/tracing/contrib/configuration/resolver.rb', line 125

def add(matcher, value)
  reset_cache # Bust the cache when a new matcher is added
  super
end

#initialize(*args, cache_limit: 200) ⇒ Object

Parameters:

  • cache_limit (Integer) (defaults to: 200) —

    maximum number of entries to cache



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/datadog/tracing/contrib/configuration/resolver.rb', line 94

def initialize(*args, cache_limit: 200)
  super(*args)

  @cache_limit = cache_limit
  # Workaround for Ruby VM < 3.2.8, < 3.3.8 and < 3.4.3 (see https://bugs.ruby-lang.org/issues/21170)
  # We initialize the hash with 10 dummy entries + clear it to force Ruby to use an
  # "st_table" representation for the Hash, not an "ar_table" (since Ruby will not
  # shrink a Hash using an "st_table" back to an "ar_table")
  @cache = Hash[*1..20]
  @cache.clear
  # Workaround for the segfault from https://github.com/DataDog/dd-trace-rb/issues/5718#issuecomment-4421844775.
  # It crashes on a simple {Hash} lookup, {Hash#key?}, called from `@cache.fetch(value)`.
  # Using an identity-based {Hash} avoids {Hash#key?} calls.
  # We should attempt to remove this workaround when we only support Ruby 4+,
  # as large change around the crash site was done in that version (https://github.com/ruby/ruby/pull/14039/changes#diff-884a5a8a369ef1b4c7597e00aa65974cec8c5f54f25f03ad5d24848f64892869R1743),
  # where `RClass.cc_table` (the NULL dereferenced pointer) became a GC-managed object,
  @cache.compare_by_identity
end

#reset_cache ⇒ Object

Clears the internal cache.



131
132
133
# File 'lib/datadog/tracing/contrib/configuration/resolver.rb', line 131

def reset_cache
  @cache.clear
end

#resolve(value) ⇒ Object

Matches an arbitrary value against the configured matchers previously set with #add.

If multiple matchers would match, returns the latest one.

Parameters:

  • value (Object) —

    integration-specific value

Returns:

  • (Object) —

    matching value configured at #add, or nil if none match



114
115
116
117
118
119
120
121
122
# File 'lib/datadog/tracing/contrib/configuration/resolver.rb', line 114

def resolve(value)
  @cache.fetch(value) do
    if @cache.size >= @cache_limit
      @cache.shift # Remove the oldest entry if cache is full
    end

    @cache[value] = super
  end
end