Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions sentry-sidekiq/lib/sentry/sidekiq-scheduler/scheduler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,46 @@ def new_job(name, interval_type, config, schedule, options)

rufus_job
end

def enqueue_job(job_config, *args)
# make sure the current thread has a clean hub
Sentry.clone_hub_to_current_thread

Sentry.with_scope do |scope|
Sentry.with_session_tracking do
begin
scope.set_transaction_name(job_config["class"].to_s)

transaction = sentry_start_transaction(scope)
scope.set_span(transaction) if transaction
super

sentry_finish_transaction(transaction, 200)
rescue
sentry_finish_transaction(transaction, 500)
raise
end
end
end
end

private

def sentry_start_transaction(scope)
Sentry.start_transaction(
name: scope.transaction_name,
source: scope.transaction_source,
op: "queue.sidekiq-scheduler",
origin: "auto.queue.sidekiq.scheduler"
)
end

def sentry_finish_transaction(transaction, status_code)
return unless transaction

transaction.set_http_status(status_code)
transaction.finish
end
end
end
end
Expand Down
47 changes: 46 additions & 1 deletion sentry-sidekiq/spec/sentry/sidekiq-scheduler/scheduler_spec.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
# frozen_string_literal: true

require 'spec_helper'
require 'sidekiq/api'

return unless defined?(SidekiqScheduler::Scheduler)

RSpec.describe Sentry::SidekiqScheduler::Scheduler do
before do
perform_basic_setup { |c| c.enabled_patches += [:sidekiq_scheduler] }
perform_basic_setup do |c|
c.enabled_patches += [:sidekiq_scheduler]
c.traces_sample_rate = 1.0
end
end

before do
Expand Down Expand Up @@ -75,4 +79,45 @@
expect(VeryLongOuterModule::VeryVeryVeryVeryLongInnerModule::Job.sentry_monitor_config.schedule).to be_a(Sentry::Cron::MonitorSchedule::Crontab)
expect(VeryLongOuterModule::VeryVeryVeryVeryLongInnerModule::Job.sentry_monitor_config.schedule.value).to eq('* * * * *')
end

describe '#enqueue_job' do
let(:transport) { Sentry.get_current_client.transport }
let(:scheduler) { SidekiqScheduler::Scheduler.instance }

before do
Sidekiq::Queue.all.each(&:clear)
end

it 'adds job to sidekiq within transaction' do
scheduler.enqueue_job({ 'class' => 'HappyWorkerForScheduler' })

expect(::Sidekiq::Queue.new.size).to eq(1)
expect(transport.events.count).to eq(1)

transaction = transport.events.last
expect(transaction.transaction).to eq('HappyWorkerForScheduler')
expect(transaction.contexts.dig(:trace, :op)).to eq('queue.sidekiq-scheduler')
expect(transaction.contexts.dig(:trace, :origin)).to eq('auto.queue.sidekiq.scheduler')

span = transaction.spans.detect { |span| span[:op] == 'queue.publish' }
expect(span).not_to be_nil
expect(span[:data]['messaging.destination.name']).to eq('default')
end

it 'starts a new trace for each enqueue' do
scheduler.enqueue_job({ 'class' => 'HappyWorkerForScheduler' })
scheduler.enqueue_job({ 'class' => 'HappyWorkerForScheduler' })

events = transport.events
expect(events.count).to eq(2)
expect(events[0].dynamic_sampling_context['trace_id']).not_to eq(events[1].dynamic_sampling_context['trace_id'])

jobs = ::Sidekiq::Queue.new.map(&:item)
trace_ids = jobs.map { |job| job.dig('trace_propagation_headers', 'sentry-trace').split('-').first }
sample_rands = jobs.map { |job| job.dig('trace_propagation_headers', 'baggage')[/sentry-sample_rand=([^,]+)/, 1] }

expect(trace_ids).to match_array(events.map { |event| event.dynamic_sampling_context['trace_id'] })
expect(sample_rands.uniq.size).to eq(2)
end
end
end
Loading