Skip to content

Commit

Permalink
Added basic Good Job collectors
Browse files Browse the repository at this point in the history
  • Loading branch information
AndersGM committed May 25, 2023
1 parent 9ea664f commit d002076
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 0 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,17 @@ PrometheusExporter::Instrumentation::Resque.start
| Gauge | `resque_workers` | Total number of Resque workers running |
| Gauge | `resque_working` | Total number of Resque workers working |

### GoodJob metrics

The metrics are generated from the database using the relevant scopes. To start monitoring your GoodJob
installation, you'll need to start the instrumentation:

```ruby
# e.g. config/initializers/good_job.rb
require 'prometheus_exporter/instrumentation'
PrometheusExporter::Instrumentation::GoodJob.start
```

### Unicorn process metrics

In order to gather metrics from unicorn processes, we use `rainbows`, which exposes `Rainbows::Linux.tcp_listener_stats` to gather information about active workers and queued requests. To start monitoring your unicorn processes, you'll need to know both the path to unicorn PID file and the listen address (`pid_file` and `listen` in your unicorn config file)
Expand Down
30 changes: 30 additions & 0 deletions lib/prometheus_exporter/instrumentation/good_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

# collects stats from GoodJob
module PrometheusExporter::Instrumentation
class GoodJob < PeriodicStats
def self.start(client: nil, frequency: 30)
good_job_collector = new
client ||= PrometheusExporter::Client.default

worker_loop do
client.send_json(good_job_collector.collect)
end

super
end

def collect
{
type: "good_job",
scheduled: ::GoodJob::Job.scheduled.size,
retried: ::GoodJob::Job.retried.size,
queued: ::GoodJob::Job.queued.size,
running: ::GoodJob::Job.running.size,
finished: ::GoodJob::Job.finished.size,
succeeded: ::GoodJob::Job.succeeded.size,
discarded: ::GoodJob::Job.discarded.size
}
end
end
end
1 change: 1 addition & 0 deletions lib/prometheus_exporter/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@
require_relative "server/active_record_collector"
require_relative "server/shoryuken_collector"
require_relative "server/resque_collector"
require_relative "server/good_job_collector"
1 change: 1 addition & 0 deletions lib/prometheus_exporter/server/collector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def initialize(json_serializer: nil)
register_collector(ActiveRecordCollector.new)
register_collector(ShoryukenCollector.new)
register_collector(ResqueCollector.new)
register_collector(GoodJobCollector.new)
end

def register_collector(collector)
Expand Down
52 changes: 52 additions & 0 deletions lib/prometheus_exporter/server/good_job_collector.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# frozen_string_literal: true

module PrometheusExporter::Server
class GoodJobCollector < TypeCollector
MAX_GOOD_JOB_METRIC_AGE = 30
GOOD_JOB_GAUGES = {
scheduled: "Total number of scheduled GoodJob jobs.",
retried: "Total number of retried GoodJob jobs.",
queued: "Total number of queued GoodJob jobs.",
running: "Total number of running GoodJob jobs.",
finished: "Total number of finished GoodJob jobs.",
succeeded: "Total number of succeeded GoodJob jobs.",
discarded: "Total number of discarded GoodJob jobs."
}

def initialize
@good_job_metrics = []
@gauges = {}
end

def type
"good_job"
end

def metrics
return [] if good_job_metrics.length == 0

good_job_metrics.map do |metric|
labels = metric.fetch("custom_labels", {})

GOOD_JOB_GAUGES.map do |name, help|
gauge = gauges[name] ||= PrometheusExporter::Metric::Gauge.new("good_job_#{name}", help)
gauge.observe(metric.fetch(name.to_s), labels)
end
end

gauges.values
end

def collect(object)
now = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)

object["created_at"] = now
good_job_metrics.delete_if { |metric| metric["created_at"] + MAX_GOOD_JOB_METRIC_AGE < now }
good_job_metrics << object
end

private

attr_reader :good_job_metrics, :gauges
end
end

0 comments on commit d002076

Please sign in to comment.