dalli 4.3.1 → 4.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c21c31c46fc4381658892703d01baf8611392f5c1f72b9473013d2e53bc23254
4
- data.tar.gz: 1fd1a3ea06cc4bab1ebc1192e62ede8318521e7867a84b3dd09096364560979f
3
+ metadata.gz: 7eda4c85eb715e06ef3d8b34ea8e33a3cde89f19379a758f105363457451a034
4
+ data.tar.gz: 36ae8b603f8f778edbbf3bed9b7504ff1a440382bf5520423f49c39961f04a55
5
5
  SHA512:
6
- metadata.gz: 9c79888857cb9c9edc9a1f86447e630b54f52040305806ffe92d0966d326e78607e06387c6bbbcac8b96b380737389da2bcf98a9f93ef91e487e2a2152e7aad7
7
- data.tar.gz: f1783996f1d49db8985b755e78c3df6cee25776504504aa1ce303d665fc4798d3b09b8136d97e23dc2a3de8243bca68e7db2e00dbd2942c05e2f918d8efd8d1a
6
+ metadata.gz: b9a37ecfc73734a141979a34f2e155baa40cea5b22b016c192514c9d5847335d949ee642620c4508cc2ec8a2ceeb4dcec381715e633893623c42454975999d1a
7
+ data.tar.gz: 2a5f38c78c371e0710354a2b915a074512a87225f33fca95c9088ded76cad0dfc22e454fc9f64bddd40d8b0c0a6ab65bb108f467cd5b2b2c39d651285665f845
data/CHANGELOG.md CHANGED
@@ -1,6 +1,21 @@
1
1
  Dalli Changelog
2
2
  =====================
3
3
 
4
+ 4.3.2
5
+ ==========
6
+
7
+ OpenTelemetry:
8
+
9
+ - Migrate to stable OTel semantic conventions
10
+ - `db.system` renamed to `db.system.name`
11
+ - `db.operation` renamed to `db.operation.name`
12
+ - `server.address` now contains hostname only; `server.port` is a separate integer attribute
13
+ - `get_with_metadata` and `fetch_with_lock` now include `server.address`/`server.port`
14
+ - Add `db.query.text` span attribute with configurable modes
15
+ - `:otel_db_statement` option: `:include`, `:obfuscate`, or `nil` (default: omitted)
16
+ - Add `peer.service` span attribute
17
+ - `:otel_peer_service` option for logical service naming
18
+
4
19
  4.3.1
5
20
  ==========
6
21
 
data/lib/dalli/client.rb CHANGED
@@ -50,6 +50,10 @@ module Dalli
50
50
  # useful for injecting a FIPS compliant hash object.
51
51
  # - :protocol - one of either :binary or :meta, defaulting to :binary. This sets the protocol that Dalli uses
52
52
  # to communicate with memcached.
53
+ # - :otel_db_statement - controls the +db.query.text+ span attribute when OpenTelemetry is loaded.
54
+ # +:include+ logs the full operation and key(s), +:obfuscate+ replaces keys with "?",
55
+ # +nil+ (default) omits the attribute entirely.
56
+ # - :otel_peer_service - when set, adds a +peer.service+ span attribute with this value for logical service naming.
53
57
  #
54
58
  def initialize(servers = nil, options = {})
55
59
  @normalized_servers = ::Dalli::ServersArgNormalizer.normalize_servers(servers)
@@ -134,8 +138,8 @@ module Dalli
134
138
  key = key.to_s
135
139
  key = @key_manager.validate_key(key)
136
140
 
137
- Instrumentation.trace('get_with_metadata', { 'db.operation' => 'get_with_metadata' }) do
138
- server = ring.server_for_key(key)
141
+ server = ring.server_for_key(key)
142
+ Instrumentation.trace('get_with_metadata', trace_attrs('get_with_metadata', key, server)) do
139
143
  server.request(:meta_get, key, options)
140
144
  end
141
145
  rescue NetworkError => e
@@ -237,7 +241,8 @@ module Dalli
237
241
  key = key.to_s
238
242
  key = @key_manager.validate_key(key)
239
243
 
240
- Instrumentation.trace('fetch_with_lock', { 'db.operation' => 'fetch_with_lock' }) do
244
+ server = ring.server_for_key(key)
245
+ Instrumentation.trace('fetch_with_lock', trace_attrs('fetch_with_lock', key, server)) do
241
246
  fetch_with_lock_request(key, ttl, lock_ttl, recache_threshold, req_options, &block)
242
247
  end
243
248
  rescue NetworkError => e
@@ -318,10 +323,7 @@ module Dalli
318
323
  def set_multi(hash, ttl = nil, req_options = nil)
319
324
  return if hash.empty?
320
325
 
321
- Instrumentation.trace('set_multi', {
322
- 'db.operation' => 'set_multi',
323
- 'db.memcached.key_count' => hash.size
324
- }) do
326
+ Instrumentation.trace('set_multi', multi_trace_attrs('set_multi', hash.size, hash.keys)) do
325
327
  pipelined_setter.process(hash, ttl_or_default(ttl), req_options)
326
328
  end
327
329
  end
@@ -378,10 +380,7 @@ module Dalli
378
380
  def delete_multi(keys)
379
381
  return if keys.empty?
380
382
 
381
- Instrumentation.trace('delete_multi', {
382
- 'db.operation' => 'delete_multi',
383
- 'db.memcached.key_count' => keys.size
384
- }) do
383
+ Instrumentation.trace('delete_multi', multi_trace_attrs('delete_multi', keys.size, keys)) do
385
384
  pipelined_deleter.process(keys)
386
385
  end
387
386
  end
@@ -522,10 +521,8 @@ module Dalli
522
521
  def record_hit_miss_metrics(span, key_count, hit_count)
523
522
  return unless span
524
523
 
525
- span.add_attributes({
526
- 'db.memcached.hit_count' => hit_count,
527
- 'db.memcached.miss_count' => key_count - hit_count
528
- })
524
+ span.add_attributes('db.memcached.hit_count' => hit_count,
525
+ 'db.memcached.miss_count' => key_count - hit_count)
529
526
  end
530
527
 
531
528
  def get_multi_yielding(keys)
@@ -550,7 +547,30 @@ module Dalli
550
547
  end
551
548
 
552
549
  def get_multi_attributes(keys)
553
- { 'db.operation' => 'get_multi', 'db.memcached.key_count' => keys.size }
550
+ multi_trace_attrs('get_multi', keys.size, keys)
551
+ end
552
+
553
+ def trace_attrs(operation, key, server)
554
+ attrs = { 'db.operation.name' => operation, 'server.address' => server.hostname }
555
+ attrs['server.port'] = server.port if server.socket_type == :tcp
556
+ attrs['peer.service'] = @options[:otel_peer_service] if @options[:otel_peer_service]
557
+ add_query_text(attrs, operation, key)
558
+ end
559
+
560
+ def multi_trace_attrs(operation, key_count, keys)
561
+ attrs = { 'db.operation.name' => operation, 'db.memcached.key_count' => key_count }
562
+ attrs['peer.service'] = @options[:otel_peer_service] if @options[:otel_peer_service]
563
+ add_query_text(attrs, operation, keys)
564
+ end
565
+
566
+ def add_query_text(attrs, operation, key_or_keys)
567
+ case @options[:otel_db_statement]
568
+ when :include
569
+ attrs['db.query.text'] = "#{operation} #{Array(key_or_keys).join(' ')}"
570
+ when :obfuscate
571
+ attrs['db.query.text'] = "#{operation} ?"
572
+ end
573
+ attrs
554
574
  end
555
575
 
556
576
  def check_positive!(amt)
@@ -618,10 +638,7 @@ module Dalli
618
638
  key = @key_manager.validate_key(key)
619
639
 
620
640
  server = ring.server_for_key(key)
621
- Instrumentation.trace(op.to_s, {
622
- 'db.operation' => op.to_s,
623
- 'server.address' => server.name
624
- }) do
641
+ Instrumentation.trace(op.to_s, trace_attrs(op.to_s, key, server)) do
625
642
  server.request(op, key, *args)
626
643
  end
627
644
  rescue RetryableNetworkError => e
@@ -8,25 +8,36 @@ module Dalli
8
8
  # When OpenTelemetry is loaded, Dalli automatically creates spans for cache operations.
9
9
  # When OpenTelemetry is not available, all tracing methods are no-ops with zero overhead.
10
10
  #
11
+ # Dalli 4.3.2 uses the stable OTel semantic conventions for database spans.
12
+ #
11
13
  # == Span Attributes
12
14
  #
13
15
  # All spans include the following default attributes:
14
- # - +db.system+ - Always "memcached"
16
+ # - +db.system.name+ - Always "memcached"
15
17
  #
16
18
  # Single-key operations (+get+, +set+, +delete+, +incr+, +decr+, etc.) add:
17
- # - +db.operation+ - The operation name (e.g., "get", "set")
18
- # - +server.address+ - The memcached server handling the request (e.g., "localhost:11211")
19
+ # - +db.operation.name+ - The operation name (e.g., "get", "set")
20
+ # - +server.address+ - The server hostname (e.g., "localhost")
21
+ # - +server.port+ - The server port as an integer (e.g., 11211); omitted for Unix sockets
19
22
  #
20
23
  # Multi-key operations (+get_multi+) add:
21
- # - +db.operation+ - "get_multi"
24
+ # - +db.operation.name+ - "get_multi"
22
25
  # - +db.memcached.key_count+ - Number of keys requested
23
26
  # - +db.memcached.hit_count+ - Number of keys found in cache
24
27
  # - +db.memcached.miss_count+ - Number of keys not found
25
28
  #
26
29
  # Bulk write operations (+set_multi+, +delete_multi+) add:
27
- # - +db.operation+ - The operation name
30
+ # - +db.operation.name+ - The operation name
28
31
  # - +db.memcached.key_count+ - Number of keys in the operation
29
32
  #
33
+ # == Optional Attributes
34
+ #
35
+ # - +db.query.text+ - The operation and key(s), controlled by the +:otel_db_statement+ client option:
36
+ # - +:include+ - Full text (e.g., "get mykey")
37
+ # - +:obfuscate+ - Obfuscated (e.g., "get ?")
38
+ # - +nil+ (default) - Attribute omitted
39
+ # - +peer.service+ - Logical service name, set via the +:otel_peer_service+ client option
40
+ #
30
41
  # == Error Handling
31
42
  #
32
43
  # When an exception occurs during a traced operation:
@@ -40,8 +51,8 @@ module Dalli
40
51
  ##
41
52
  module Instrumentation
42
53
  # Default attributes included on all memcached spans.
43
- # @return [Hash] frozen hash with 'db.system' => 'memcached'
44
- DEFAULT_ATTRIBUTES = { 'db.system' => 'memcached' }.freeze
54
+ # @return [Hash] frozen hash with 'db.system.name' => 'memcached'
55
+ DEFAULT_ATTRIBUTES = { 'db.system.name' => 'memcached' }.freeze
45
56
 
46
57
  class << self
47
58
  # Returns the OpenTelemetry tracer if available, nil otherwise.
@@ -75,15 +86,16 @@ module Dalli
75
86
  # @param name [String] the span name (e.g., 'get', 'set', 'delete')
76
87
  # @param attributes [Hash] span attributes to merge with defaults.
77
88
  # Common attributes include:
78
- # - 'db.operation' - the operation name
79
- # - 'server.address' - the target server
89
+ # - 'db.operation.name' - the operation name
90
+ # - 'server.address' - the server hostname
91
+ # - 'server.port' - the server port (integer)
80
92
  # - 'db.memcached.key_count' - number of keys (for multi operations)
81
93
  # @yield the cache operation to trace
82
94
  # @return [Object] the result of the block
83
95
  # @raise [StandardError] re-raises any exception from the block
84
96
  #
85
97
  # @example Tracing a set operation
86
- # trace('set', { 'db.operation' => 'set', 'server.address' => 'localhost:11211' }) do
98
+ # trace('set', { 'db.operation.name' => 'set', 'server.address' => 'localhost', 'server.port' => 11211 }) do
87
99
  # server.set(key, value, ttl)
88
100
  # end
89
101
  #
@@ -110,7 +122,7 @@ module Dalli
110
122
  # @raise [StandardError] re-raises any exception from the block
111
123
  #
112
124
  # @example Recording hit/miss metrics after get_multi
113
- # trace_with_result('get_multi', { 'db.operation' => 'get_multi' }) do |span|
125
+ # trace_with_result('get_multi', { 'db.operation.name' => 'get_multi' }) do |span|
114
126
  # results = fetch_from_cache(keys)
115
127
  # if span
116
128
  # span.set_attribute('db.memcached.hit_count', results.size)
data/lib/dalli/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dalli
4
- VERSION = '4.3.1'
4
+ VERSION = '4.3.2'
5
5
 
6
6
  MIN_SUPPORTED_MEMCACHED_VERSION = '1.4'
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dalli
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.3.1
4
+ version: 4.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter M. Goldstein
@@ -93,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
93
  - !ruby/object:Gem::Version
94
94
  version: '0'
95
95
  requirements: []
96
- rubygems_version: 4.0.4
96
+ rubygems_version: 4.0.6
97
97
  specification_version: 4
98
98
  summary: High performance memcached client for Ruby
99
99
  test_files: []