Skip to content

Commit

Permalink
feat: redis metrics [wip]
Browse files Browse the repository at this point in the history
  • Loading branch information
zvkemp committed Jan 30, 2025
1 parent 50dc0c1 commit 97ee174
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 1 deletion.
18 changes: 18 additions & 0 deletions instrumentation/redis/Appraisals
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# frozen_string_literal: true

appraise 'redis-4.x-metrics-sdk' do
gem 'redis-client', '~> 0.22'
gem 'redis', '~> 4.8'
gem 'opentelemetry-metrics-sdk', github: "zvkemp/opentelemetry-ruby", glob: 'metrics_sdk/*.gemspec', ref: "metrics-kwargs"
gem 'opentelemetry-metrics-api', github: "zvkemp/opentelemetry-ruby", glob: 'metrics_api/*.gemspec', ref: "metrics-kwargs"
end

appraise 'redis-5.x-metrics-sdk' do
gem 'redis', '~> 5.0'
gem 'opentelemetry-metrics-sdk', github: "zvkemp/opentelemetry-ruby", glob: 'metrics_sdk/*.gemspec', ref: "metrics-kwargs"
gem 'opentelemetry-metrics-api', github: "zvkemp/opentelemetry-ruby", glob: 'metrics_api/*.gemspec', ref: "metrics-kwargs"
end

appraise 'redis-5.x-metrics-api' do
gem 'redis', '~> 5.0'
gem 'opentelemetry-metrics-api', github: "zvkemp/opentelemetry-ruby", glob: 'metrics_api/*.gemspec', ref: "metrics-kwargs"
end

appraise 'redis-4.x' do
gem 'redis-client', '~> 0.22'
gem 'redis', '~> 4.8'
Expand Down
2 changes: 2 additions & 0 deletions instrumentation/redis/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ gemspec
group :test do
gem 'opentelemetry-instrumentation-base', path: '../base'
end

gem 'pry-byebug'
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,32 @@ class Instrumentation < OpenTelemetry::Instrumentation::Base
option :peer_service, default: nil, validate: :string
option :trace_root_spans, default: true, validate: :boolean
option :db_statement, default: :obfuscate, validate: %I[omit include obfuscate]
option :metrics, default: false, validate: :boolean

# https://opentelemetry.io/docs/specs/semconv/database/database-metrics/#metric-dbclientoperationduration
histogram 'db.client.operation.duration',
attributes: { 'db.system.name' => 'redis' },
unit: 's',
boundaries: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5, 10]

def client_operation_duration_histogram
histogram('db.client.operation.duration')
end

private

def require_dependencies
require_relative 'patches/redis_v4_client' if defined?(::Redis) && ::Redis::VERSION < '5'
require_relative 'middlewares/redis_client' if defined?(::RedisClient)

return unless defined?(::RedisClient)

require_relative 'middlewares/redis_client'
require_relative 'middlewares/redis_client_metrics'
end

def patch_client
::RedisClient.register(Middlewares::RedisClientInstrumentation) if defined?(::RedisClient)
::RedisClient.register(Middlewares::RedisClientMetrics) if defined?(::RedisClient)
::Redis::Client.prepend(Patches::RedisV4Client) if defined?(::Redis) && ::Redis::VERSION < '5'
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def span_attributes(redis_config)

attributes['db.redis.database_index'] = redis_config.db unless redis_config.db.zero?
attributes['peer.service'] = instrumentation.config[:peer_service] if instrumentation.config[:peer_service]

attributes.merge!(OpenTelemetry::Instrumentation::Redis.attributes)
attributes
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# frozen_string_literal: true

# Copyright The OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

module OpenTelemetry
module Instrumentation
module Redis
module Middlewares
# Adapter for redis-client instrumentation interface
module RedisClientMetrics
def call(command, redis_config)
return super unless (histogram = instrumentation.client_operation_duration_histogram)

timed(histogram, command.first, redis_config) do
super
end
end

def call_pipelined(commands, redis_config)
return super unless (histogram = instrumentation.client_operation_duration_histogram)

timed(histogram, 'PIPELINE', redis_config) do
super
end
end

private

def timed(histogram, operation_name, redis_config)
t0 = monotonic_now

yield.tap do
duration = monotonic_now - t0

histogram.record(duration, attributes: metric_attributes(redis_config, operation_name))
end
end

def monotonic_now
Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second)
end

def metric_attributes(redis_config, operation_name)
attributes = {
'db.system' => 'redis',
'db.operation.name' => operation_name,
'net.peer.name' => redis_config.host,
'net.peer.port' => redis_config.port
}

attributes['db.redis.database_index'] = redis_config.db unless redis_config.db.zero?
attributes['peer.service'] = instrumentation.config[:peer_service] if instrumentation.config[:peer_service]
attributes.merge!(OpenTelemetry::Instrumentation::Redis.attributes)
attributes
end

def instrumentation
Redis::Instrumentation.instance
end
end
end
end
end
end

0 comments on commit 97ee174

Please sign in to comment.