Module: Dalli::Instrumentation
- Defined in:
- lib/dalli/instrumentation.rb
Overview
Instrumentation support for Dalli. Provides hooks for distributed tracing via OpenTelemetry when the SDK is available.
When OpenTelemetry is loaded, Dalli automatically creates spans for cache operations. When OpenTelemetry is not available, all tracing methods are no-ops with zero overhead.
Dalli 5.0 uses the stable OTel semantic conventions for database spans.
Span Attributes
All spans include the following default attributes:
-
db.system.name- Always “memcached”
Single-key operations (get, set, delete, incr, decr, etc.) add:
-
db.operation.name- The operation name (e.g., “get”, “set”) -
server.address- The server hostname (e.g., “localhost”) -
server.port- The server port as an integer (e.g., 11211); omitted for Unix sockets
Multi-key operations (get_multi) add:
-
db.operation.name- “get_multi” -
db.memcached.key_count- Number of keys requested -
db.memcached.hit_count- Number of keys found in cache -
db.memcached.miss_count- Number of keys not found
Bulk write operations (set_multi, delete_multi) add:
-
db.operation.name- The operation name -
db.memcached.key_count- Number of keys in the operation
Optional Attributes
-
db.query.text- The operation and key(s), controlled by the:otel_db_statementclient option:-
:include- Full text (e.g., “get mykey”) -
:obfuscate- Obfuscated (e.g., “get ?”) -
nil(default) - Attribute omitted
-
-
peer.service- Logical service name, set via the:otel_peer_serviceclient option
Error Handling
When an exception occurs during a traced operation:
-
The exception is recorded on the span via
record_exception -
The span status is set to error with the exception message
-
The exception is re-raised to the caller
Constant Summary collapse
- DEFAULT_ATTRIBUTES =
Default attributes included on all memcached spans.
{ 'db.system.name' => 'memcached' }.freeze
Class Method Summary collapse
-
.enabled? ⇒ Boolean
Returns true if instrumentation is enabled (OpenTelemetry SDK is available).
-
.trace(name, attributes = {}) { ... } ⇒ Object
Wraps a block with a span if instrumentation is enabled.
-
.trace_with_result(name, attributes = {}) {|OpenTelemetry::Trace::Span, nil| ... } ⇒ Object
Like trace, but yields the span to allow adding attributes after execution.
-
.tracer ⇒ OpenTelemetry::Trace::Tracer?
Returns the OpenTelemetry tracer if available, nil otherwise.
Class Method Details
.enabled? ⇒ Boolean
Returns true if instrumentation is enabled (OpenTelemetry SDK is available).
75 76 77 |
# File 'lib/dalli/instrumentation.rb', line 75 def enabled? !tracer.nil? end |
.trace(name, attributes = {}) { ... } ⇒ Object
Wraps a block with a span if instrumentation is enabled.
Creates a client span with the given name and attributes merged with DEFAULT_ATTRIBUTES. The block is executed within the span context. If an exception occurs, it is recorded on the span before re-raising.
When tracing is disabled (OpenTelemetry not loaded), this method simply yields directly with zero overhead.
104 105 106 107 108 109 110 |
# File 'lib/dalli/instrumentation.rb', line 104 def trace(name, attributes = {}) return yield unless enabled? tracer.in_span(name, attributes: DEFAULT_ATTRIBUTES.merge(attributes), kind: :client) do |_span| yield end end |
.trace_with_result(name, attributes = {}) {|OpenTelemetry::Trace::Span, nil| ... } ⇒ Object
Like trace, but yields the span to allow adding attributes after execution.
This is useful for operations where metrics are only known after the operation completes, such as get_multi where hit/miss counts depend on the cache response.
When tracing is disabled, yields nil as the span argument.
136 137 138 139 140 |
# File 'lib/dalli/instrumentation.rb', line 136 def trace_with_result(name, attributes = {}, &) return yield(nil) unless enabled? tracer.in_span(name, attributes: DEFAULT_ATTRIBUTES.merge(attributes), kind: :client, &) end |
.tracer ⇒ OpenTelemetry::Trace::Tracer?
Returns the OpenTelemetry tracer if available, nil otherwise.
The tracer is cached after first lookup for performance. Uses the library name ‘dalli’ and current Dalli::VERSION.
rubocop:disable ThreadSafety/ClassInstanceVariable
65 66 67 68 69 |
# File 'lib/dalli/instrumentation.rb', line 65 def tracer return @tracer if defined?(@tracer) @tracer = (OpenTelemetry.tracer_provider.tracer('dalli', Dalli::VERSION) if defined?(OpenTelemetry)) end |