module NewRelic::Agent::Instrumentation::Redis

This file is distributed under New Relic’s license terms. See github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.

Constants

INSTRUMENTATION_NAME

Public Instance Methods

call_pipeline_with_tracing(pipeline) { || ... } click to toggle source

Used for Redis 4.x and 3.x

# File lib/new_relic/agent/instrumentation/redis/instrumentation.rb, line 23
def call_pipeline_with_tracing(pipeline)
  operation = pipeline.is_a?(::Redis::Pipeline::Multi) ? Constants::MULTI_OPERATION : Constants::PIPELINE_OPERATION
  statement = ::NewRelic::Agent::Datastores::Redis.format_pipeline_commands(pipeline.commands)

  with_tracing(operation, statement: statement, database: _nr_db) { yield }
end
call_pipelined_with_tracing(pipeline) { || ... } click to toggle source

Used for Redis 5.x+

# File lib/new_relic/agent/instrumentation/redis/instrumentation.rb, line 31
def call_pipelined_with_tracing(pipeline)
  operation = pipeline.flatten.include?('MULTI') ? Constants::MULTI_OPERATION : Constants::PIPELINE_OPERATION
  statement = ::NewRelic::Agent::Datastores::Redis.format_pipeline_commands(pipeline)

  with_tracing(operation, statement: statement, database: _nr_db) { yield }
end
call_with_tracing(command) { || ... } click to toggle source
# File lib/new_relic/agent/instrumentation/redis/instrumentation.rb, line 15
def call_with_tracing(command, &block)
  operation = command[0]
  statement = ::NewRelic::Agent::Datastores::Redis.format_command(command)

  with_tracing(operation, statement: statement, database: _nr_db) { yield }
end
connect_with_tracing() { || ... } click to toggle source
# File lib/new_relic/agent/instrumentation/redis/instrumentation.rb, line 11
def connect_with_tracing
  with_tracing(Constants::CONNECT, database: _nr_db) { yield }
end

Private Instance Methods

_nr_db() click to toggle source
# File lib/new_relic/agent/instrumentation/redis/instrumentation.rb, line 91
def _nr_db
  # db is a method on the Redis client in versions < 5.x
  return db if respond_to?(:db)
  # db is accessible through the RedisClient::Config object in versions > 5.x
  return _nr_redis_client_config.db if _nr_redis_client_config.respond_to?(:db)
rescue StandardError => e
  NewRelic::Agent.logger.debug("Failed to determine configured Redis db value: #{e.class} - #{e.message}")
  nil
end
_nr_hostname() click to toggle source
# File lib/new_relic/agent/instrumentation/redis/instrumentation.rb, line 58
def _nr_hostname
  _nr_redis_client_config.path ? Constants::LOCALHOST : _nr_redis_client_config.host
rescue => e
  NewRelic::Agent.logger.debug("Failed to retrieve Redis host: #{e.class} - #{e.message}")
  Constants::UNKNOWN
end
_nr_port_path_or_id() click to toggle source
# File lib/new_relic/agent/instrumentation/redis/instrumentation.rb, line 65
def _nr_port_path_or_id
  _nr_redis_client_config.path || _nr_redis_client_config.port
rescue => e
  NewRelic::Agent.logger.debug("Failed to retrieve Redis port_path_or_id: #{e.class} - #{e.message}")
  Constants::UNKNOWN
end
_nr_redis_client_config() click to toggle source
# File lib/new_relic/agent/instrumentation/redis/instrumentation.rb, line 72
def _nr_redis_client_config
  @nr_config ||= begin
    # redis gem
    config = if defined?(::Redis::Client) && self.is_a?(::Redis::Client)
      self
    # redis-client gem v0.11+ (self is a RedisClient::Middlewares)
    elsif respond_to?(:client)
      # The following line needs else branch coverage
      client && client.config # rubocop:disable Style/SafeNavigation
    # redis-client gem <0.11 (self is a RedisClient::Middlewares)
    elsif defined?(::RedisClient)
      ::RedisClient.config if ::RedisClient.respond_to?(:config)
    end
    raise 'Unable to locate the underlying Redis client configuration.' unless config

    config
  end
end
with_tracing(operation, statement: nil, database: nil) { || ... } click to toggle source
# File lib/new_relic/agent/instrumentation/redis/instrumentation.rb, line 40
def with_tracing(operation, statement: nil, database: nil)
  NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)

  segment = NewRelic::Agent::Tracer.start_datastore_segment(
    product: Constants::PRODUCT_NAME,
    operation: operation,
    host: _nr_hostname,
    port_path_or_id: _nr_port_path_or_id,
    database_name: database
  )
  begin
    segment.notice_nosql_statement(statement) if statement
    NewRelic::Agent::Tracer.capture_segment_error(segment) { yield }
  ensure
    ::NewRelic::Agent::Transaction::Segment.finish(segment)
  end
end