I have a rails app, sidekiq and sentry.
I want to find event in sentry by job arguments.
Sample:
I have SomeJob which executed with arguments [{some_arg: 'Arg1'}]
Job failed with error and send event to sentry.
How I can find event by job arguments?
I try full-text search, but it doesn't work
Search in sentry is limited by what they allow you to search by.
From reading their Search docs briefly you can either use:
sentry tags
messages
Either way, you would want to enrich your sentry events.
For example, let's assume you will rescue from the error raised in your job
class SomeJob
include Sidekiq::Worker
def perform(args)
# do stuff with args
rescue StandardError
SentryError.new(args: args)
end
end
SentryJobError is really just a PORO that would be called by your job classes.
class SentryJobError
def initialize(args:)
return if Rails.env.development?
Sentry.configure_scope do |scope|
scope.set_context('job_args', { args: args })
scope.set_context('message', 'job ${args[:some_arg]} failed')
end
end
end
Related
Some Sidekiq jobs in my app are scheduled to change the state of a resource to cancelled unless a user responds within a certain timeframe. There is a lot of information about how to best accomplish this task, but none of it actually cancels the job.
To cancel a job, the code in the wiki says:
class MyWorker
include Sidekiq::Worker
def perform(thing_id)
return if cancelled?
thing = Thing.find thing_id
thing.renege!
end
def cancelled?
Sidekiq.redis {|c| c.exists("cancelled-#{jid}") }
end
def self.cancel!(jid)
Sidekiq.redis {|c| c.setex("cancelled-#{jid}", 86400, 1) }
end
end
Yet here it's suggested that I do something like
def perform(thing_id)
thing = Thing.find thing_id
while !cancel?(thing)
thing.ignore!
end
end
def cancel?(thing_id)
thing = Thing.find thing_id
thing.matched? || thing.passed?
end
What's confusing about this and similar code on the wiki is none of it actually cancels the job. The above example just performs an update on thing if cancelled? returns false (as it should), but doesn't cancel if and when it returns true in the future. It just fails with an aasm transition error message and gets sent to the RetrySet. Calling MyWorker.cancel! jid in model code throws an undefined variable error. How can I access that jid in the model? How can actually cancel or delete that specific job? Thanks!
# The wiki code
class MyWorker
include Sidekiq::Worker
def perform(thing_id)
return if cancelled?
# do actual work
end
def cancelled?
Sidekiq.redis {|c| c.exists("cancelled-#{jid}") }
end
def self.cancel!(jid)
Sidekiq.redis {|c| c.setex("cancelled-#{jid}", 86400, 1) }
end
end
# create job
jid = MyWorker.perform_async("foo")
# cancel job
MyWorker.cancel!(jid)
You can do this but it won't be efficient. It's a linear scan for find a scheduled job by JID.
require 'sidekiq/api'
Sidekiq::ScheduledSet.new.find_job(jid).try(:delete)
Alternatively your job can look to see if it's still relevant when it runs.
Ok, so turns out I had one question already answered. One of the code sets I included was a functionally similar version of the code from the wiki. The solution to the other question ("how can I access that jid in the model?") seems really obvious if you're not still new to programming, but basically: store the jid in a database column and then retrieve/update it whenever it's needed! Duh!
given the delayed job worker,
class UserCommentsListWorker
attr_accessor :opts
def initialize opts = {}
#opts = opts
end
def perform
UserCommentsList.new(#opts)
end
def before job
p 'before hook', job
end
def after job
p 'after hook', job
end
def success job
p 'success hook', job
end
def error job, exception
p '4', exception
end
def failure job
p '5', job
end
def enqueue job
p '-1', job
end
end
When I run Delayed::Job.enqueue UserCommentsListWorker.new(client: client) from a rails console, I can get repeated sequences of print statements and a proper delayed job lifecyle even hooks to print including the feedback from the worker that the job was a success.
Including the same call to run the worker via a standard rails controller endpoint like;
include OctoHelper
include QueryHelper
include ObjHelper
include StructuralHelper
class CommentsController < ApplicationController
before_filter :authenticate_user!
def index
if params['updateCache'] == 'true'
client = build_octoclient current_user.octo_token
Delayed::Job.enqueue UserCommentsListWorker.new(client: client)
end
end
end
I'm noticing that the worker will run and created the delayed job, but none of the hooks get called and the worker nevers logs the job as completed.
Notice the screenshot,
Jobs 73,75,76 were all triggered via a roundtrip to the above referenced endpoint while job 74 was triggered via the rails console, what is wrong with my setup and/or what am I failing to notice in this process? I will stress that the first time the webserver hits the above controller endpoint, the job queues and runs properly but all subsequent instances where the job should run properly appear to be doing nothing and giving me no feedback in the process.
i would also highlight that i'm never seeing the failure, error or enqueue hooks run.
thanks :)
The long and the short of the answer to this problem was that if you notice, i was attempting to store a client object in the delayed job notification which was causing problems, so therefore, don't store complex objects in the job, just work with basic data ids 1 or strings foo or booleans true etc. capisce?
I'm running a sidekiq application on heroku with papertrails addon and I use exceptions to fail jobs. For each exception full stacktrace is stored in papertrail logs which is definitely not what I want.
I didn't find a way how to turn off that feature. Could you give me a hint what I could do with that?
Maybe I should handle job failing in a different way?
Thanks!
Here's a modification of the standard error logger that limits the backtrace logging to the lines unique to the application:
class ExceptionHandlerLogger
def call(ex, ctxHash)
Sidekiq.logger.warn(Sidekiq.dump_json(ctxHash)) if !ctxHash.empty?
Sidekiq.logger.warn "#{ex.class.name}: #{ex.message}"
unless ex.backtrace.nil?
Sidekiq.logger.warn filter_backtrace(ex.backtrace).join("\n")
end
end
def filter_backtrace(backtrace)
index = backtrace.index { |item| item.include?('/lib/sidekiq/processor.rb') }
backtrace.first(index.to_i)
end
end
if !Sidekiq.error_handlers.delete_if { |h| h.class == Sidekiq::ExceptionHandler::Logger }
fail "default sidekiq logger class changed!"
end
Sidekiq.error_handlers << ExceptionHandlerLogger.new
How can I enable emails to be sent from sidekiq when it fails? Currently I know exception notifier is working, though when a sidekiq job fails, it doesn't do anything.
class DelayedWorker
include Sidekiq::Worker
# Utils include watchdog, which will email on failures
include Sidekiq::Util
def perform(type, args)
watchdog('DelayedWorker failed') do
raise 'Doh!'
puts "Doing hard work #{type} #{args.to_json}"
end
end
end
Also make sure you have the newer version of exception notifier, which takes in 2 arguments into it's handle_background_exception method
I'm using delayed_job 2.1.4 from collectiveidea, and it seems the perform method is never called even though the jobs are processed and removed from the queue. Am I missing something?
I'm using Rails 3.0.5 on Heroku
In the Controller:
Delayed::Job.enqueue FacebookJob.new
In the Job class:
class FacebookJob
def initialize
end
def perform
fb_auths = Authentication.where(:provider => 'facebook')
fb_auths.each do |auth|
checkins = FbGraph::User.new('me', :access_token => URI.encode(auth.token)).checkins
if checkins != nil
checkins.each do |checkin|
[...]
end
end
end
end
end
(the whole code: https://gist.github.com/966509)
The simple answer: does DelayedJob know about the Authentication and FBGraph::User classes? If not, you'll see exactly the behavior you describe: the items will be silently removed from the queue.
See this entry in the Delayed Job Wiki in the Delayed Job Wiki.
Try adding 'require authentication' and 'require fb_graph' (or whatever) in your facebook_job.rb file.