Module: Datadog::Tracing::Contrib::ActiveSupport::Cache::Instrumentation

Defined in:
lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb

Overview

DEV-3.0: Backwards compatibility code for the 2.x gem series. DEV-3.0: DEV-3.0: ‘ActiveSupport::Cache` is now instrumented by subscribing to ActiveSupport::Notifications events. DEV-3.0: The implementation is located at Events::Cache. DEV-3.0: The events emitted provide richer introspection points (e.g. events for cache misses on `#fetch`) while DEV-3.0: also ensuring we are using Rails’ public API for improved compatibility. DEV-3.0: DEV-3.0: But a few operations holds us back: DEV-3.0: 1. ‘ActiveSupport::Cache::Store#fetch`: DEV-3.0: This method does not have an event that can produce an equivalent span to today’s 2.x implementation. DEV-3.0: In 2.x, ‘#fetch` produces two separate, nested spans: one for the `#read` operation and DEV-3.0: another for the `#write` operation that is called internally by `#fetch` when the cache key needs DEV-3.0: to be populated on a cache miss. DEV-3.0: But the ActiveSupport events emitted by `#fetch` provide two sibling events for the`#read` and DEV-3.0: `#write` operations. DEV-3.0: Moving from nested spans to sibling spans would be a breaking change. One notable difference is DEV-3.0: that if the nested `#write` operation fails 2.x, the `#read` span is marked as an error. This would DEV-3.0: not be the case with sibling spans, and would be a very visible change. DEV-3.0: 2. `ActiveSupport::Cache::Store#read_multi` & `ActiveSupport::Cache::Store#fetch_multi`: DEV-3.0: ActiveSupport events were introduced in ActiveSupport 5.2.0 for these methods. DEV-3.0: DEV-3.0: At the end of the day, moving to ActiveSupport events is the better approach, but we have to retain DEV-3.0: this last few monkey patches (and all the supporting code) to avoid a breaking change for now.

Defines the deprecate monkey-patch instrumentation for ‘ActiveSupport::Cache::Store#fetch`

Defined Under Namespace

Modules: Fetch, FetchMulti, InstanceMethods, ReadMulti, Store

Class Method Summary collapse

Class Method Details

.enabled?Boolean

Returns:

  • (Boolean)


97
98
99
# File 'lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb', line 97

def enabled?
  Tracing.enabled? && Datadog.configuration.tracing[:active_support][:enabled]
end

.nested_multiread?Boolean

In most of the cases, ‘#fetch()` and `#read()` calls are nested. Instrument both does not add any value. This method checks if these two operations are nested.

DEV-3.0: We should not have these checks in the 3.x series because ActiveSupport events provide more DEV-3.0: legible nested spans. While using ActiveSupport events, the nested spans actually provide meaningful DEV-3.0: information.

Returns:

  • (Boolean)


80
81
82
83
# File 'lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb', line 80

def nested_multiread?
  current_span = Tracing.active_span
  current_span && current_span.name == Ext::SPAN_CACHE && current_span.resource == Ext::RESOURCE_CACHE_MGET
end

.nested_read?Boolean

In most of the cases, ‘#fetch()` and `#read()` calls are nested. Instrument both does not add any value. This method checks if these two operations are nested.

DEV-3.0: We should not have these checks in the 3.x series because ActiveSupport events provide more DEV-3.0: legible nested spans. While using ActiveSupport events, the nested spans actually provide meaningful DEV-3.0: information.

Returns:

  • (Boolean)


74
75
76
77
# File 'lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb', line 74

def nested_read?
  current_span = Tracing.active_span
  current_span && current_span.name == Ext::SPAN_CACHE && current_span.resource == Ext::RESOURCE_CACHE_GET
end

.set_cache_key(span, single_key, multi_key) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
# File 'lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb', line 85

def set_cache_key(span, single_key, multi_key)
  if multi_key
    resolved_key = multi_key.map { |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_MULTI, cache_key)
  else
    resolved_key = ::ActiveSupport::Cache.expand_cache_key(single_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

.trace(action, store, key: nil, multi_key: nil) ⇒ Object

Parameters:

  • action (String)

    type of cache operation. Will be set as the span resource.

  • key (Object) (defaults to: nil)

    redis cache key. Used for actions with a single key locator.

  • multi_key (Array<Object>) (defaults to: nil)

    list of redis cache keys. Used for actions with a multiple key locators.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb', line 43

def trace(action, store, key: nil, multi_key: nil)
  return yield unless enabled?

  # create a new ``Span`` and add it to the tracing context
  Tracing.trace(
    Ext::SPAN_CACHE,
    type: Ext::SPAN_TYPE_CACHE,
    service: Datadog.configuration.tracing[:active_support][:cache_service],
    resource: action
  ) do |span|
    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, store) if store
    set_cache_key(span, key, multi_key)

    yield
  end
end