Skip to content
Open
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
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,38 @@ end

**Note**: Since the notifications are registered on install make sure to setup your after_event_block before calling install!

## Custom Tags

You can add custom tags to all metrics emitted for a specific job by defining a `yabeda_tags` instance method on your job class. This works similarly to [yabeda-sidekiq's custom tags](https://github.com/yabeda-rb/yabeda-sidekiq#custom-tags).

```ruby
class ImportJob < ActiveJob::Base
def perform(tenant_id, data)
# ...
end

def yabeda_tags
{ tenant: arguments.first }
end
end
```

The returned hash is merged into every metric's label set for that job (enqueued, executed, success, failed, runtime, latency).

If your `yabeda_tags` method accepts arguments, the job's arguments will be forwarded to it:

```ruby
class ImportJob < ActiveJob::Base
def perform(tenant_id, data)
# ...
end

def yabeda_tags(tenant_id, _data)
{ tenant: tenant_id }
end
end
```

## Metrics

- Total enqueued jobs: `activejob.enqueued_total` segmented by: queue, activejob(job class name), executions(number of executions)
Expand Down
10 changes: 10 additions & 0 deletions lib/yabeda/activejob.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ module ActiveJob

mattr_accessor :after_event_block, default: proc { |_event| }

def self.custom_tags(job)
return {} unless job.respond_to?(:yabeda_tags)

if job.method(:yabeda_tags).arity.zero?
job.yabeda_tags
else
job.yabeda_tags(*job.arguments)
end
end

# rubocop: disable Metrics/MethodLength, Metrics/BlockLength, Metrics/AbcSize
def self.install!
Yabeda.configure do
Expand Down
9 changes: 3 additions & 6 deletions lib/yabeda/activejob/event_handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,8 @@ def initialize(*event_args)
end

def handle_perform
labels = {
activejob: event.payload[:job].class.to_s,
queue: event.payload[:job].queue_name.to_s,
executions: event.payload[:job].executions.to_s,
}
labels = common_labels(event.payload[:job])

if event.payload[:exception].present?
Yabeda.activejob_failed_total.increment(
labels.merge(failure_reason: event.payload[:exception].first.to_s),
Expand Down Expand Up @@ -99,7 +96,7 @@ def common_labels(job)
activejob: job.class.to_s,
queue: job.queue_name,
executions: job.executions.to_s,
)
).merge(Yabeda::ActiveJob.custom_tags(job))
end

def call_after_event_block
Expand Down
20 changes: 20 additions & 0 deletions spec/support/rails_app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,26 @@ def perform
end
end

class TaggedJob < ActiveJob::Base
def perform(tenant_id)
puts "Tagged job for #{tenant_id}"
end

def yabeda_tags
{ tenant: arguments.first }
end
end

class TaggedArgsErrorJob < ActiveJob::Base
def perform(tenant_id)
raise StandardError
end

def yabeda_tags(tenant_id)
{ tenant: tenant_id }
end
end

Rails.application = TestApplication

TestApplication.initialize!
21 changes: 21 additions & 0 deletions spec/yabeda/activejob_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -244,4 +244,25 @@
expect(Yabeda.activejob.scheduled_total.values.values.sum).to eq(jobs_count)
end
end

context "when job defines yabeda_tags" do
it "includes zero-arity custom tags in perform metrics" do
expect { TaggedJob.perform_later("tenant_1") }.to \
increment_yabeda_counter(Yabeda.activejob.success_total)
.with_tags(queue: "default", activejob: "TaggedJob", executions: "1", tenant: "tenant_1")
.by(1)
end

it "includes argument-forwarded custom tags in failed metrics" do
expect { TaggedArgsErrorJob.perform_later("tenant_1") }.to \
increment_yabeda_counter(Yabeda.activejob.failed_total)
.with_tags(
queue: "default",
activejob: "TaggedArgsErrorJob",
executions: "1",
failure_reason: "StandardError",
tenant: "tenant_1",
).by(1).and(raise_error(StandardError))
end
end
end