Module: Honeycomb::Redis::Client

Defined in:
lib/honeycomb/integrations/redis.rb

Overview

Patches Redis::Client with Honeycomb instrumentation.

Circa versions 3.x and 4.x of their gem, the Redis class is backed by an underlying Redis::Client object. The methods used to send commands to the Redis server - namely Redis::Client#call, Redis::Client#call_loop, Redis::Client#call_pipeline, Redis::Client#call_pipelined, Redis::Client#call_with_timeout, and Redis::Client#call_without_timeout - all eventually wind up calling the Redis::Client#process method to do the “dirty work” of writing commands out to an underlying connection. So this gives us a single point of entry that’s ideal for introducing the Honeycomb span.

An alternative interface provided since at least version 3.0.0 is Redis::Distributed. Underneath, though, it maintains a collection of Redis objects, and each call is forwarded to one or more members of the collection. So patching Redis::Client still captures spans originating from Redis::Distributed. Typical commands (i.e., ones that aren’t “global” like ‘QUIT` or `FLUSHALL`) forward to just a single node anyway, so there’s not much use to wrapping everything up in a span for the Redis::Distributed method call.

Another alternative interface provided since v4.0.3 is Redis::Cluster, which you can configure the Redis class to use instead of Redis::Client. Again, though, Redis::Cluster maintains a collection of Redis::Client instances underneath. The tracing needs wind up being pretty much the same as Redis::Distributed, even though the actual architecture is significantly different.

An implementation detail of pub/sub commands since v2.0.0 (well below our supported version of the redis gem!) is Redis::SubscribedClient, but that still wraps an underlying Redis::Client or Redis::Cluster instance.

Instance Method Summary collapse

Instance Method Details

#process(commands) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/honeycomb/integrations/redis.rb', line 98

def process(commands)
  return super if ::Redis.honeycomb_client.nil?

  span = ::Redis.honeycomb_client.start_span(name: "redis")
  begin
    fields = Fields.new(self)
    fields.options = @options
    fields.command = commands
    span.add fields
    super
  rescue StandardError => e
    span.add_field "redis.error", e.class.name
    span.add_field "redis.error_detail", e.message
    raise
  ensure
    span.send
  end
end