Skip to content

Commit 9779dd4

Browse files
authored
fix: add back key for cache notification payloads (#600)
* fix: add back key for cache notification payloads This time we call `ActiveSupport::Cache.expand_cache_key` on the value for a more usable key for querying. * Handle multi operations differently * The hits data also contain keys, also add specs. * Use a mock instead of copying the logic
1 parent 47da420 commit 9779dd4

File tree

3 files changed

+83
-3
lines changed

3 files changed

+83
-3
lines changed

lib/honeybadger/notification_subscriber.rb

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,33 @@ def format_payload(payload)
4141

4242
class ActionControllerCacheSubscriber < NotificationSubscriber
4343
def format_payload(payload)
44-
payload.except(:key)
44+
payload[:key] = ::ActiveSupport::Cache.expand_cache_key(payload[:key]) if payload[:key]
45+
payload
4546
end
4647
end
4748

4849
class ActiveSupportCacheSubscriber < NotificationSubscriber
4950
def format_payload(payload)
50-
payload.except(:key)
51+
payload[:key] = ::ActiveSupport::Cache.expand_cache_key(payload[:key]) if payload[:key]
52+
payload
53+
end
54+
end
55+
56+
class ActiveSupportCacheMultiSubscriber < NotificationSubscriber
57+
def format_payload(payload)
58+
payload[:key] = expand_cache_keys_from_payload(payload[:key])
59+
payload[:hits] = expand_cache_keys_from_payload(payload[:hits])
60+
payload
61+
end
62+
63+
def expand_cache_keys_from_payload(data)
64+
return unless data
65+
66+
data = data.keys if data.is_a?(Hash)
67+
68+
Array(data).map do |k|
69+
::ActiveSupport::Cache.expand_cache_key(k)
70+
end
5171
end
5272
end
5373

lib/honeybadger/plugins/rails.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ def self.source_ignored?(source)
7777
if config.load_plugin_insights?(:rails)
7878
::ActiveSupport::Notifications.subscribe(/(process_action|send_file|redirect_to|halted_callback|unpermitted_parameters)\.action_controller/, Honeybadger::ActionControllerSubscriber.new)
7979
::ActiveSupport::Notifications.subscribe(/(write_fragment|read_fragment|expire_fragment|exist_fragment\?)\.action_controller/, Honeybadger::ActionControllerCacheSubscriber.new)
80-
::ActiveSupport::Notifications.subscribe(/cache_(read|read_multi|generate|fetch_hit|write|write_multi|increment|decrement|delete|delete_multi|cleanup|prune|exist\?)\.active_support/, Honeybadger::ActiveSupportCacheSubscriber.new)
80+
::ActiveSupport::Notifications.subscribe(/cache_(read|generate|fetch_hit|write|increment|decrement|delete|cleanup|prune|exist\?)\.active_support/, Honeybadger::ActiveSupportCacheSubscriber.new)
81+
::ActiveSupport::Notifications.subscribe(/cache_(read_multi|write_multi|delete_multi\?)\.active_support/, Honeybadger::ActiveSupportCacheMultiSubscriber.new)
8182
::ActiveSupport::Notifications.subscribe(/^render_(template|partial|collection)\.action_view/, Honeybadger::ActionViewSubscriber.new)
8283
::ActiveSupport::Notifications.subscribe("sql.active_record", Honeybadger::ActiveRecordSubscriber.new)
8384
::ActiveSupport::Notifications.subscribe("process.action_mailer", Honeybadger::ActionMailerSubscriber.new)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# encoding: utf-8
2+
3+
require 'honeybadger/notification_subscriber'
4+
5+
describe Honeybadger::ActiveSupportCacheMultiSubscriber do
6+
module ActiveSupport
7+
module Cache; end
8+
end
9+
10+
context "with a cache_write_multi.active_support payload" do
11+
let(:payload) do
12+
obj = Object.new
13+
{
14+
key: {'one' => 'data', 'object.cache_key' => obj },
15+
store: 'cache-store-name'
16+
}
17+
end
18+
19+
before do
20+
allow(::ActiveSupport::Cache).to receive(:expand_cache_key).with(payload[:key].keys[0]).and_return('one')
21+
allow(::ActiveSupport::Cache).to receive(:expand_cache_key).with(payload[:key].keys[1]).and_return('foo/bar')
22+
end
23+
24+
subject { described_class.new.format_payload(payload) }
25+
26+
it "returns a payload with all keys expanded and without cache values" do
27+
expect(subject).to be_a(Hash)
28+
expect(subject[:key]).to eq(%w(one foo/bar))
29+
expect(subject[:store]).to eq('cache-store-name')
30+
end
31+
end
32+
33+
context "with a cache_read_multi.active_support payload" do
34+
let(:payload) do
35+
{
36+
key: ['one', Object.new],
37+
hits: ['one'],
38+
store: 'cache-store-name',
39+
super_operation: :fetch_multi
40+
}
41+
end
42+
43+
before do
44+
allow(::ActiveSupport::Cache).to receive(:expand_cache_key).with(payload[:key][0]).and_return('one')
45+
allow(::ActiveSupport::Cache).to receive(:expand_cache_key).with(payload[:key][1]).and_return('foo/bar')
46+
allow(::ActiveSupport::Cache).to receive(:expand_cache_key).with(payload[:hits][0]).and_return('one')
47+
end
48+
49+
subject { described_class.new.format_payload(payload) }
50+
51+
it "returns a payload with all keys expanded" do
52+
expect(subject).to be_a(Hash)
53+
expect(subject[:key]).to eq(%w(one foo/bar))
54+
expect(subject[:hits]).to eq(%w(one))
55+
expect(subject[:store]).to eq('cache-store-name')
56+
expect(subject[:super_operation]).to eq(:fetch_multi)
57+
end
58+
end
59+
end

0 commit comments

Comments
 (0)