Skip to content

Commit

Permalink
Remove ActiveJob keys for both Sidekiq and DelayedJob
Browse files Browse the repository at this point in the history
  • Loading branch information
alissonbrunosa committed Apr 17, 2019
1 parent 729c22f commit 3221522
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 51 deletions.
38 changes: 38 additions & 0 deletions lib/raven/context_filter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module Raven
class ContextFilter
ACTIVEJOB_RESERVED_PREFIX = "_aj_".freeze
HAS_GLOBALID = const_defined?('GlobalID')

class << self
# Once an ActiveJob is queued, ActiveRecord references get serialized into
# some internal reserved keys, such as _aj_globalid.
#
# The problem is, if this job in turn gets queued back into ActiveJob with
# these magic reserved keys, ActiveJob will throw up and error. We want to
# capture these and mutate the keys so we can sanely report it.
def filter(context)
case context
when Array
context.map { |arg| filter(arg) }
when Hash
context.each_with_object({}) do |(key, value), hash|
next hash if key[0..3] == ACTIVEJOB_RESERVED_PREFIX
hash[key] = filter(value)
end
else
format_globalid(context)
end
end

private

def format_globalid(context)
if HAS_GLOBALID && context.is_a?(GlobalID)
context.to_s
else
context
end
end
end
end
end
6 changes: 5 additions & 1 deletion lib/raven/integrations/delayed_job.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
require 'delayed_job'

require 'raven/context_filter'

module Delayed
module Plugins
class Raven < ::Delayed::Plugin
include Raven::ContextFilter

callbacks do |lifecycle|
lifecycle.around(:invoke_job) do |job, *args, &block|
begin
Expand Down Expand Up @@ -30,7 +34,7 @@ class Raven < ::Delayed::Plugin
extra[:handler] = job.handler[0...1000] if job.handler

if job.respond_to?('payload_object') && job.payload_object.respond_to?('job_data')
extra[:active_job] = job.payload_object.job_data
extra[:active_job] = Raven::ContextFilter.filter(job.payload_object.job_data)
end
::Raven.capture_exception(exception,
:logger => 'delayed_job',
Expand Down
37 changes: 3 additions & 34 deletions lib/raven/integrations/sidekiq.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
require 'time'
require 'sidekiq'

require 'raven/context_filter'

module Raven
class SidekiqCleanupMiddleware
def call(_worker, job, queue)
Expand All @@ -13,11 +15,8 @@ def call(_worker, job, queue)
end

class SidekiqErrorHandler
ACTIVEJOB_RESERVED_PREFIX = "_aj_".freeze
HAS_GLOBALID = const_defined?('GlobalID')

def call(ex, context)
context = filter_context(context)
context = Raven::ContextFilter.filter(context)
Raven.context.transaction.push transaction_from_context(context)
Raven.capture_exception(
ex,
Expand All @@ -30,28 +29,6 @@ def call(ex, context)

private

# Once an ActiveJob is queued, ActiveRecord references get serialized into
# some internal reserved keys, such as _aj_globalid.
#
# The problem is, if this job in turn gets queued back into ActiveJob with
# these magic reserved keys, ActiveJob will throw up and error. We want to
# capture these and mutate the keys so we can sanely report it.
def filter_context(context)
case context
when Array
context.map { |arg| filter_context(arg) }
when Hash
Hash[context.map { |key, value| filter_context_hash(key, value) }]
else
format_globalid(context)
end
end

def filter_context_hash(key, value)
(key = key[3..-1]) if key [0..3] == ACTIVEJOB_RESERVED_PREFIX
[key, filter_context(value)]
end

# this will change in the future:
# https://github.com/mperham/sidekiq/pull/3161
def transaction_from_context(context)
Expand All @@ -66,14 +43,6 @@ def transaction_from_context(context)
"Sidekiq"
end
end

def format_globalid(context)
if HAS_GLOBALID && context.is_a?(GlobalID)
context.to_s
else
context
end
end
end
end

Expand Down
40 changes: 40 additions & 0 deletions spec/raven/context_filter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
require "spec_helper"

require "raven/context_filter"

RSpec.describe Raven::ContextFilter do
context "filters out ActiveJob keys from context" do
let(:context) do
{ :_aj_globalid => GlobalID.new("gid://app/model/id"), :key => "value" }
end
let(:expected_context) do
{ :key => "value" }
end

it "removes reserved keys" do
new_context = described_class.filter(context)

expect(new_context).to eq(expected_context)
end
end

context "filters out ActiveJob keys from nested context" do
let(:context) do
{
:_aj_globalid => GlobalID.new("gid://app/model/id"),
:arguments => { "key" => "value", "_aj_symbol_keys" => ["key"] }
}
end
let(:expected_context) do
{
:arguments => { "key" => "value" }
}
end

it "removes reserved keys" do
new_context = described_class.filter(context)

expect(new_context).to eq(expected_context)
end
end
end
16 changes: 0 additions & 16 deletions spec/raven/integrations/sidekiq_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,6 @@
Raven::SidekiqErrorHandler.new.call(exception, context)
end
end

it "filters out ActiveJob keys", :rails => true do
exception = build_exception
aj_context = context
aj_context["_aj_globalid"] = GlobalID.new('gid://app/model/id')
expected_context = aj_context.dup
expected_context.delete("_aj_globalid")
expected_context["_globalid"] = "gid://app/model/id"
expected_options = {
:message => exception.message,
:extra => { :sidekiq => expected_context }
}
expect(Raven).to receive(:capture_exception).with(exception, expected_options)

Raven::SidekiqErrorHandler.new.call(exception, aj_context)
end
end

class HappyWorker
Expand Down

0 comments on commit 3221522

Please sign in to comment.