1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
|
# frozen_string_literal: true
module Sentry
# @api private
class Redis
OP_NAME = "db.redis"
SPAN_ORIGIN = "auto.db.redis"
LOGGER_NAME = :redis_logger
def initialize(commands, host, port, db)
@commands, @host, @port, @db = commands, host, port, db
end
def instrument
return yield unless Sentry.initialized?
Sentry.with_child_span(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f, origin: SPAN_ORIGIN) do |span|
yield.tap do
record_breadcrumb
if span
span.set_description(commands_description)
span.set_data(Span::DataConventions::DB_SYSTEM, "redis")
span.set_data(Span::DataConventions::DB_NAME, db)
span.set_data(Span::DataConventions::SERVER_ADDRESS, host)
span.set_data(Span::DataConventions::SERVER_PORT, port)
end
end
end
end
private
attr_reader :commands, :host, :port, :db
def record_breadcrumb
return unless Sentry.initialized?
return unless Sentry.configuration.breadcrumbs_logger.include?(LOGGER_NAME)
Sentry.add_breadcrumb(
Sentry::Breadcrumb.new(
level: :info,
category: OP_NAME,
type: :info,
data: {
commands: parsed_commands,
server: server_description
}
)
)
end
def commands_description
parsed_commands.map do |statement|
statement.values.join(" ").strip
end.join(", ")
end
def parsed_commands
commands.map do |statement|
command, key, *arguments = statement
command_set = { command: command.to_s.upcase }
command_set[:key] = key if Utils::EncodingHelper.valid_utf_8?(key)
if Sentry.configuration.send_default_pii
command_set[:arguments] = arguments
.select { |a| Utils::EncodingHelper.valid_utf_8?(a) }
.join(" ")
end
command_set
end
end
def server_description
"#{host}:#{port}/#{db}"
end
module OldClientPatch
def logging(commands, &block)
Sentry::Redis.new(commands, host, port, db).instrument { super }
end
end
module GlobalRedisInstrumentation
def call(command, redis_config)
Sentry::Redis
.new([command], redis_config.host, redis_config.port, redis_config.db)
.instrument { super }
end
def call_pipelined(commands, redis_config)
Sentry::Redis
.new(commands, redis_config.host, redis_config.port, redis_config.db)
.instrument { super }
end
end
end
end
if defined?(::Redis::Client)
if Gem::Version.new(::Redis::VERSION) < Gem::Version.new("5.0")
Sentry.register_patch(:redis, Sentry::Redis::OldClientPatch, ::Redis::Client)
elsif defined?(RedisClient)
Sentry.register_patch(:redis) do
RedisClient.register(Sentry::Redis::GlobalRedisInstrumentation)
end
end
end
|