From 7197bd0e52f70148a571602069a7388759135259 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Thu, 17 Feb 2022 18:06:45 +0000 Subject: [PATCH] Encapsulate extension helpers (#1725) * Encapsulate sentry-resque's helper methods * Encapsulate sentry-rails's ActiveJob integration --- sentry-rails/lib/sentry/rails/active_job.rb | 120 ++++++++++---------- sentry-resque/lib/sentry/resque.rb | 104 +++++++++-------- 2 files changed, 120 insertions(+), 104 deletions(-) diff --git a/sentry-rails/lib/sentry/rails/active_job.rb b/sentry-rails/lib/sentry/rails/active_job.rb index 33791b5a7..171f997e1 100644 --- a/sentry-rails/lib/sentry/rails/active_job.rb +++ b/sentry-rails/lib/sentry/rails/active_job.rb @@ -5,76 +5,80 @@ def perform_now if !Sentry.initialized? || already_supported_by_sentry_integration? super else - Sentry.with_scope do |scope| - capture_and_reraise_with_sentry(scope) do - super - end + SentryReporter.record(self) do + super end end end - def capture_and_reraise_with_sentry(scope, &block) - scope.set_transaction_name(self.class.name) - transaction = - if is_a?(::Sentry::SendEventJob) - nil - else - Sentry.start_transaction(name: scope.transaction_name, op: "active_job") - end - - scope.set_span(transaction) if transaction - - return_value = block.call + def already_supported_by_sentry_integration? + Sentry.configuration.rails.skippable_job_adapters.include?(self.class.queue_adapter.class.to_s) + end - finish_sentry_transaction(transaction, 200) + class SentryReporter + class << self + def record(job, &block) + Sentry.with_scope do |scope| + begin + scope.set_transaction_name(job.class.name) + transaction = + if job.is_a?(::Sentry::SendEventJob) + nil + else + Sentry.start_transaction(name: scope.transaction_name, op: "active_job") + end - return_value - rescue Exception => e # rubocop:disable Lint/RescueException - finish_sentry_transaction(transaction, 500) + scope.set_span(transaction) if transaction - Sentry::Rails.capture_exception( - e, - extra: sentry_context, - tags: { - job_id: job_id, - provider_job_id: provider_job_id - } - ) - raise e - end + yield.tap do + finish_sentry_transaction(transaction, 200) + end + rescue Exception => e # rubocop:disable Lint/RescueException + finish_sentry_transaction(transaction, 500) - def finish_sentry_transaction(transaction, status) - return unless transaction + Sentry::Rails.capture_exception( + e, + extra: sentry_context(job), + tags: { + job_id: job.job_id, + provider_job_id: job.provider_job_id + } + ) + raise + end + end + end - transaction.set_http_status(status) - transaction.finish - end + def finish_sentry_transaction(transaction, status) + return unless transaction - def already_supported_by_sentry_integration? - Sentry.configuration.rails.skippable_job_adapters.include?(self.class.queue_adapter.class.to_s) - end + transaction.set_http_status(status) + transaction.finish + end - def sentry_context - { - active_job: self.class.name, - arguments: sentry_serialize_arguments(arguments), - scheduled_at: scheduled_at, - job_id: job_id, - provider_job_id: provider_job_id, - locale: locale - } - end + def sentry_context(job) + { + active_job: job.class.name, + arguments: sentry_serialize_arguments(job.arguments), + scheduled_at: job.scheduled_at, + job_id: job.job_id, + provider_job_id: job.provider_job_id, + locale: job.locale + } + end - def sentry_serialize_arguments(argument) - case argument - when Hash - argument.transform_values { |v| sentry_serialize_arguments(v) } - when Array, Enumerable - argument.map { |v| sentry_serialize_arguments(v) } - when ->(v) { v.respond_to?(:to_global_id) } - argument.to_global_id.to_s rescue argument - else - argument + def sentry_serialize_arguments(argument) + case argument + when Hash + argument.transform_values { |v| sentry_serialize_arguments(v) } + when Array, Enumerable + argument.map { |v| sentry_serialize_arguments(v) } + when ->(v) { v.respond_to?(:to_global_id) } + argument.to_global_id.to_s rescue argument + else + argument + end + end end end end diff --git a/sentry-resque/lib/sentry/resque.rb b/sentry-resque/lib/sentry/resque.rb index b0e12a6f3..9b7204805 100644 --- a/sentry-resque/lib/sentry/resque.rb +++ b/sentry-resque/lib/sentry/resque.rb @@ -5,63 +5,75 @@ module Sentry module Resque def perform - return super unless Sentry.initialized? + if Sentry.initialized? + SentryReporter.record(queue, worker, payload) do + super + end + else + super + end + end - Sentry.with_scope do |scope| - begin - contexts = generate_contexts - scope.set_contexts(**contexts) - scope.set_tags("resque.queue" => queue) + class SentryReporter + class << self + def record(queue, worker, payload, &block) + Sentry.with_scope do |scope| + begin + contexts = generate_contexts(queue, worker, payload) + scope.set_contexts(**contexts) + scope.set_tags("resque.queue" => queue) - scope.set_transaction_name(contexts.dig(:"Active-Job", :job_class) || contexts.dig(:"Resque", :job_class)) - transaction = Sentry.start_transaction(name: scope.transaction_name, op: "resque") - scope.set_span(transaction) if transaction + scope.set_transaction_name(contexts.dig(:"Active-Job", :job_class) || contexts.dig(:"Resque", :job_class)) + transaction = Sentry.start_transaction(name: scope.transaction_name, op: "resque") + scope.set_span(transaction) if transaction - super + yield - finish_transaction(transaction, 200) - rescue Exception => exception - ::Sentry::Resque.capture_exception(exception, hint: { background: false }) - finish_transaction(transaction, 500) - raise + finish_transaction(transaction, 200) + rescue Exception => exception + ::Sentry::Resque.capture_exception(exception, hint: { background: false }) + finish_transaction(transaction, 500) + raise + end + end end - end - end - def generate_contexts - context = {} + def generate_contexts(queue, worker, payload) + context = {} - if payload["class"] == "ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper" - active_job_payload = payload["args"].first + if payload["class"] == "ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper" + active_job_payload = payload["args"].first - context[:"Active-Job"] = { - job_class: active_job_payload["job_class"], - job_id: active_job_payload["job_id"], - arguments: active_job_payload["arguments"], - executions: active_job_payload["executions"], - exception_executions: active_job_payload["exception_executions"], - locale: active_job_payload["locale"], - enqueued_at: active_job_payload["enqueued_at"], - queue: queue, - worker: worker.to_s - } - else - context[:"Resque"] = { - job_class: payload["class"], - arguments: payload["args"], - queue: queue, - worker: worker.to_s - } - end + context[:"Active-Job"] = { + job_class: active_job_payload["job_class"], + job_id: active_job_payload["job_id"], + arguments: active_job_payload["arguments"], + executions: active_job_payload["executions"], + exception_executions: active_job_payload["exception_executions"], + locale: active_job_payload["locale"], + enqueued_at: active_job_payload["enqueued_at"], + queue: queue, + worker: worker.to_s + } + else + context[:"Resque"] = { + job_class: payload["class"], + arguments: payload["args"], + queue: queue, + worker: worker.to_s + } + end - context - end + context + end - def finish_transaction(transaction, status) - return unless transaction + def finish_transaction(transaction, status) + return unless transaction - transaction.set_http_status(status) - transaction.finish + transaction.set_http_status(status) + transaction.finish + end + end end end end