Module: Datadog::Tracing::Contrib::ActiveSupport::Cache::Events::Cache

Includes:
Datadog::Tracing::Contrib::ActiveSupport::Cache::Event
Defined in:
lib/datadog/tracing/contrib/active_support/cache/events/cache.rb

Overview

Defines instrumentation for instantiation.active_record event

Constant Summary collapse

MAPPING =

DEV: Look for other uses of ‘ActiveSupport::Cache::Store#instrument`, to find other useful event keys.

{
  'cache_delete.active_support' => { resource: Ext::RESOURCE_CACHE_DELETE },
  'cache_read.active_support' => { resource: Ext::RESOURCE_CACHE_GET },
  'cache_read_multi.active_support' => { resource: Ext::RESOURCE_CACHE_MGET, multi_key: true },
  'cache_write.active_support' => { resource: Ext::RESOURCE_CACHE_SET },
  'cache_write_multi.active_support' => { resource: Ext::RESOURCE_CACHE_MSET, multi_key: true }
}.freeze

Class Method Summary collapse

Methods included from Datadog::Tracing::Contrib::ActiveSupport::Cache::Event

included

Class Method Details

.cache_backend(store) ⇒ Object

The name of the ‘store` is never saved by Rails. ActiveSupport looks up stores by converting a symbol into a ’require’ path, then “camelizing” it for a ‘const_get` call: “` require “active_support/cache/#store” ActiveSupport::Cache.const_get(store.to_s.camelize) “` We can reverse engineer the original symbol by converting the class name to snake case: e.g. ActiveSupport::Cache::RedisStore -> active_support/cache/redis_store In this case, `redis_store` is the store name.

Because there’s no API retrieve only the class name (only ‘RedisStore`, and not `ActiveSupport::Cache::RedisStore`) the easiest way to retrieve the store symbol is to convert the fully qualified name using the Rails-provided method `#underscore`, which is the reverse of `#camelize`, then extracting the last part of it.

Also, this method caches the store name, given this value will be retrieve multiple times and involves string manipulation.



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/datadog/tracing/contrib/active_support/cache/events/cache.rb', line 127

def cache_backend(store)
  # Cache the backend name to avoid the expensive string manipulation required to calculate it.
  # DEV: We can't store it directly in the `store` object because it is a frozen String.
  if (name = @cache_backend[store])
    return name
  end

  # DEV: #underscore is available through ActiveSupport, and is
  # DEV: the exact reverse operation to `#camelize`.
  # DEV: #demodulize is available through ActiveSupport, and is
  # DEV: used to remove the module ('*::') part of a constant name.
  name = ::ActiveSupport::Inflector.demodulize(store)
  name = ::ActiveSupport::Inflector.underscore(name)

  # Despite a given application only ever having 1-3 store types,
  # we limit the size of the `@cache_backend` just in case, because
  # the user can create custom Cache store classes themselves.
  @cache_backend[store] = name if @cache_backend.size < 50

  name
end

.event_nameObject



25
26
27
# File 'lib/datadog/tracing/contrib/active_support/cache/events/cache.rb', line 25

def event_name
  /\Acache_(?:delete|read|read_multi|write|write_multi)\.active_support\z/
end

.on_start(span, event, _id, payload) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/datadog/tracing/contrib/active_support/cache/events/cache.rb', line 64

def on_start(span, event, _id, payload)
  key = payload[:key]
  store = payload[:store]

  mapping = MAPPING.fetch(event)

  span.service = configuration[:cache_service]
  span.resource = mapping[:resource]

  span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
  span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_CACHE)

  if span.service != Datadog.configuration.service
    span.set_tag(Tracing::Contrib::Ext::Metadata::TAG_BASE_SERVICE, Datadog.configuration.service)
  end

  span.set_tag(Ext::TAG_CACHE_BACKEND, cache_backend(store))

  span.set_tag('EVENT', event)

  if Datadog.configuration.tracing[:active_support][:cache_key].enabled
    set_cache_key(span, key, mapping[:multi_key])
  end
rescue StandardError => e
  Datadog.logger.error(e.message)
  Datadog::Core::Telemetry::Logger.report(e)
end

.set_cache_key(span, key, multi_key) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/datadog/tracing/contrib/active_support/cache/events/cache.rb', line 92

def set_cache_key(span, key, multi_key)
  if multi_key
    keys = key.is_a?(Hash) ? key.keys : key # `write`s use Hashes, while `read`s use Arrays
    resolved_key = keys.map { |k| ::ActiveSupport::Cache.expand_cache_key(k) }
    cache_key = Core::Utils.truncate(resolved_key, Ext::QUANTIZE_CACHE_MAX_KEY_SIZE)
    span.set_tag(Ext::TAG_CACHE_KEY_MULTI, cache_key)
  else
    resolved_key = ::ActiveSupport::Cache.expand_cache_key(key)
    cache_key = Core::Utils.truncate(resolved_key, Ext::QUANTIZE_CACHE_MAX_KEY_SIZE)
    span.set_tag(Ext::TAG_CACHE_KEY, cache_key)
  end
end

.span_nameObject



29
30
31
# File 'lib/datadog/tracing/contrib/active_support/cache/events/cache.rb', line 29

def span_name
  Ext::SPAN_CACHE
end

.span_optionsObject



33
34
35
36
37
# File 'lib/datadog/tracing/contrib/active_support/cache/events/cache.rb', line 33

def span_options
  {
    type: Ext::SPAN_TYPE_CACHE
  }
end

.subscribe!Object

Acts as this module’s initializer.



20
21
22
23
# File 'lib/datadog/tracing/contrib/active_support/cache/events/cache.rb', line 20

def subscribe!
  @cache_backend = {}
  super
end

.trace?(event, _payload) ⇒ Boolean

Returns:

  • (Boolean)


48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/datadog/tracing/contrib/active_support/cache/events/cache.rb', line 48

def trace?(event, _payload)
  return false if !Tracing.enabled? || !configuration.enabled

  # DEV-3.0: Backwards compatibility code for the 2.x gem series.
  # DEV-3.0: See documentation at {Datadog::Tracing::Contrib::ActiveSupport::Cache::Instrumentation}
  # DEV-3.0: for the complete information about this backwards compatibility code.
  case event
  when 'cache_read.active_support'
    !ActiveSupport::Cache::Instrumentation.nested_read?
  when 'cache_read_multi.active_support'
    !ActiveSupport::Cache::Instrumentation.nested_multiread?
  else
    true
  end
end