diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c9e6f046..8418479bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Features +- Log Redis command arguments when sending PII is enabled [#1726](https://github.com/getsentry/sentry-ruby/pull/1726) - Add request env to sampling context [#1749](https://github.com/getsentry/sentry-ruby/pull/1749) ### Bug Fixes diff --git a/sentry-ruby/lib/sentry/redis.rb b/sentry-ruby/lib/sentry/redis.rb index a2f37ed0b..483563ce7 100644 --- a/sentry-ruby/lib/sentry/redis.rb +++ b/sentry-ruby/lib/sentry/redis.rb @@ -3,8 +3,8 @@ module Sentry # @api private class Redis - OP_NAME ||= "db.redis.command" - LOGGER_NAME ||= :redis_logger + OP_NAME = "db.redis.command" + LOGGER_NAME = :redis_logger def initialize(commands, host, port, db) @commands, @host, @port, @db = commands, host, port, db @@ -60,9 +60,11 @@ def commands_description def parsed_commands commands.map do |statement| - command, key, *_values = statement + command, key, *arguments = statement - { command: command.to_s.upcase, key: key } + { command: command.to_s.upcase, key: key }.tap do |command_set| + command_set[:arguments] = arguments.join(" ") if Sentry.configuration.send_default_pii + end end end diff --git a/sentry-ruby/spec/sentry/breadcrumb/redis_logger_spec.rb b/sentry-ruby/spec/sentry/breadcrumb/redis_logger_spec.rb index 89d4a12cd..4e10c77c1 100644 --- a/sentry-ruby/spec/sentry/breadcrumb/redis_logger_spec.rb +++ b/sentry-ruby/spec/sentry/breadcrumb/redis_logger_spec.rb @@ -11,14 +11,48 @@ end end - it "adds Redis command breadcrumb with command and key" do - result = redis.set("key", "value") - - expect(result).to eq("OK") - expect(Sentry.get_current_scope.breadcrumbs.peek).to have_attributes( - category: "db.redis.command", - data: { commands: [{ command: "SET", key: "key" }], server: "127.0.0.1:6379/0" } - ) + context "config.send_default_pii = false" do + before { Sentry.configuration.send_default_pii = false } + + it "adds Redis command breadcrumb with command and key" do + result = redis.set("key", "value") + + expect(result).to eq("OK") + expect(Sentry.get_current_scope.breadcrumbs.peek).to have_attributes( + category: "db.redis.command", + data: { commands: [{ command: "SET", key: "key" }], server: "127.0.0.1:6379/0" } + ) + end + end + + context "config.send_default_pii = true" do + before { Sentry.configuration.send_default_pii = true } + + it "adds Redis command breadcrumb with command, key and arguments" do + result = redis.set("key", "value") + + expect(result).to eq("OK") + expect(Sentry.get_current_scope.breadcrumbs.peek).to have_attributes( + category: "db.redis.command", + data: { commands: [{ command: "SET", key: "key", arguments: "value" }], server: "127.0.0.1:6379/0" } + ) + end + + it "logs complex Redis commands with multiple arguments" do + redis.hmset("hashkey", "key1", "value1", "key2", "value2") + + expect(Sentry.get_current_scope.breadcrumbs.peek).to have_attributes( + data: include(commands: [{ command: "HMSET", key: "hashkey", arguments: "key1 value1 key2 value2" }]) + ) + end + + it "logs Redis command with options" do + redis.zrangebyscore("sortedsetkey", "1", "2", with_scores: true, limit: [0, 10]) + + expect(Sentry.get_current_scope.breadcrumbs.peek).to have_attributes( + data: include(commands: [{ command: "ZRANGEBYSCORE", key: "sortedsetkey", arguments: "1 2 WITHSCORES LIMIT 0 10" }]) + ) + end end context "calling Redis command which doesn't require a key" do diff --git a/sentry-ruby/spec/sentry/redis_spec.rb b/sentry-ruby/spec/sentry/redis_spec.rb index 0ef45e81b..438d84988 100644 --- a/sentry-ruby/spec/sentry/redis_spec.rb +++ b/sentry-ruby/spec/sentry/redis_spec.rb @@ -12,21 +12,41 @@ end end - context "calling Redis SET command" do - let(:result) { redis.set("key", "value") } + context "config.send_default_pii = true" do + before { Sentry.configuration.send_default_pii = true } - it "records the Redis call's span with command and key" do - transaction = Sentry.start_transaction - Sentry.get_current_scope.set_span(transaction) + context "calling Redis SET command" do + let(:result) { redis.set("key", "value") } - expect(result).to eq("OK") - request_span = transaction.span_recorder.spans.last - expect(request_span.op).to eq("db.redis.command") - expect(request_span.start_timestamp).not_to be_nil - expect(request_span.timestamp).not_to be_nil - expect(request_span.start_timestamp).not_to eq(request_span.timestamp) - expect(request_span.description).to eq("SET key") - expect(request_span.data).to eq({ server: "127.0.0.1:6379/0" }) + it "records the Redis call's span with command and key" do + transaction = Sentry.start_transaction + Sentry.get_current_scope.set_span(transaction) + + expect(result).to eq("OK") + request_span = transaction.span_recorder.spans.last + expect(request_span.op).to eq("db.redis.command") + expect(request_span.start_timestamp).not_to be_nil + expect(request_span.timestamp).not_to be_nil + expect(request_span.start_timestamp).not_to eq(request_span.timestamp) + expect(request_span.description).to eq("SET key value") + expect(request_span.data).to eq({ server: "127.0.0.1:6379/0" }) + end + end + end + + context "config.send_default_pii = false" do + before { Sentry.configuration.send_default_pii = false } + + context "calling Redis SET command" do + let(:result) { redis.set("key", "value") } + + it "records the Redis call's span with command and key" do + transaction = Sentry.start_transaction + Sentry.get_current_scope.set_span(transaction) + + expect(result).to eq("OK") + expect(transaction.span_recorder.spans.last.description).to eq("SET key") + end end end