class DelayedJobMetrics::Exporter
Public Class Methods
new(app, options = {})
click to toggle source
# File lib/delayed_job_metrics/exporter.rb, line 7 def initialize(app, options = {}) @app = app @registry = options[:registry] || Prometheus::Client.registry @path = options[:path] || '/metrics' @acceptable = build_dictionary(FORMATS, FALLBACK) init_delayed_jobs_metrics end
Public Instance Methods
call(env)
click to toggle source
# File lib/delayed_job_metrics/exporter.rb, line 16 def call(env) if env['PATH_INFO'] == @path if ENV['HTAUTH_METRICS_USER'] && ENV['HTAUTH_METRICS_PASSWORD'] http_auth_call(env, :expose_metrics) else expose_metrics(env) end else @app.call(env) end end
collect_metrics()
click to toggle source
# File lib/delayed_job_metrics/exporter.rb, line 53 def collect_metrics @dj_total_count.set(Delayed::Job.count) @dj_total_pending_count.set( Delayed::Job.where(attempts: 0, locked_at: nil).count ) Delayed::Job.group(:queue, :priority, :attempts) .count.each do |data, count| @dj_count.set(count, labels: { queue: data[0], priority: data[1], attempts: data[2] }) next unless (data[2]).zero? @dj_pending_count.set(count, labels: { queue: data[0], priority: data[1] }) end Delayed::Job.where.not(last_error: nil) .where(failed_at: nil).group( :queue, :priority, :attempts ).count.each do |data, count| @dj_error_count.set(count, labels: { queue: data[0], priority: data[1], attempts: data[2] }) end Delayed::Job.where.not(failed_at: nil) .group(:queue, :priority).count.each do |data, count| @dj_failed_count.set(count, labels: { queue: data.first, priority: data.last }) end Delayed::Job.where(failed_at: nil) .where('DATE(run_at) = DATE(?)', Time.now) .group(:queue, :priority, :attempts).count .each do |data, count| @dj_to_be_executed_today_count.set(count, labels: { queue: data[0], priority: data[1], attempts: data[2] }) end Delayed::Job.where.not(failed_at: nil) .where('DATE(run_at) = DATE(?)', Time.now) .group(:queue, :priority).count .each do |data, count| @dj_failed_today_count.set(count, labels: { queue: data[0], priority: data[1] }) end jobs_handler('failed_at is NULL').each do |data, count| @dj_handler_count.set(count, labels: { queue: data[0], priority: data[1], attempts: data[2], handler: data[3] }) end jobs_handler('last_error is not NULL').each do |data, count| @dj_handler_error_count.set(count, labels: { queue: data[0], priority: data[1], attempts: data[2], handler: data[3] }) end jobs_methods(false).each do |data, count| @dj_performable_count.set(count, labels: { queue: data[0], priority: data[1], attempts: data[2], handler: data[3], object: data[4], method_name: data[5] }) end jobs_methods(true).each do |data, count| @dj_performable_failed_count.set(count, labels: { queue: data[0], priority: data[1], attempts: data[2], handler: data[3], object: data[4], method_name: data[5] }) end end
expose_metrics(env)
click to toggle source
# File lib/delayed_job_metrics/exporter.rb, line 36 def expose_metrics(env) format = negotiate(env, @acceptable) format ? process_mertics_request(format) : not_acceptable(FORMATS) end
http_auth_call(env, callback)
click to toggle source
# File lib/delayed_job_metrics/exporter.rb, line 28 def http_auth_call(env, callback) auth = BasicAuth.new(env) do |u, p| u == ENV['HTAUTH_METRICS_USER'] && p == ENV['HTAUTH_METRICS_PASSWORD'] end auth.call(env, method(callback)) end
init_delayed_jobs_metrics()
click to toggle source
# File lib/delayed_job_metrics/exporter.rb, line 195 def init_delayed_jobs_metrics @dj_total_count = @registry.gauge( :delayed_jobs_total_count, docstring: 'The Delayed Jobs total count.' ) @dj_total_pending_count = @registry.gauge( :delayed_jobs_pending_total_count, docstring: 'The Pending Delayed Jobs total '\ 'count (Jobs with 0 attempts).' ) @dj_count = @registry.gauge( :delayed_jobs_queue_total_count, docstring: 'The Delayed Jobs total count Per Queue.', labels: %i[queue priority attempts] ) @dj_pending_count = @registry.gauge( :delayed_jobs_queue_pending_total_count, docstring: 'The Pending Delayed Jobs total count Per Queue.', labels: %i[queue priority] ) @dj_error_count = @registry.gauge( :delayed_jobs_queue_error_total_count, docstring: 'The total count of delayed jobs with '\ 'errors (Terminated Jobs do not count).', labels: %i[queue priority attempts] ) @dj_failed_count = @registry.gauge( :delayed_jobs_queue_failed_total_count, docstring: 'The total count of the failed delayed '\ 'jobs with errors (Jobs will not be retried anymore).', labels: %i[queue priority] ) @dj_to_be_executed_today_count = @registry.gauge( :delayed_jobs_to_be_executed_today_count, docstring: 'The total count of the delayed jobs '\ 'that should be executed today).', labels: %i[queue priority attempts] ) @dj_failed_today_count = @registry.gauge( :delayed_jobs_failed_today_count, docstring: 'The total count of the delayed jobs that failed today).', labels: %i[queue priority] ) @dj_handler_count = @registry.gauge( :delayed_jobs_handler_count, docstring: 'The total count of the active delayed '\ 'jobs per handler class).', labels: %i[queue priority attempts handler] ) @dj_handler_error_count = @registry.gauge( :delayed_jobs_handler_error_count, docstring: 'The total count of the delayed jobs '\ 'with errors per handler class).', labels: %i[queue priority attempts handler] ) @dj_performable_count = @registry.gauge( :delayed_jobs_performable_count, docstring: 'The total count of the delayed jobs '\ 'for the performable actions).', labels: %i[queue priority attempts handler object method_name] ) @dj_performable_failed_count = @registry.gauge( :delayed_jobs_performable_failed_count, docstring: 'The total count of the delayed jobs '\ 'for the performable actions).', labels: %i[queue priority attempts handler object method_name] ) end
jobs_handler(condition)
click to toggle source
# File lib/delayed_job_metrics/exporter.rb, line 158 def jobs_handler(condition) Delayed::Job.where(condition.to_s) .each_with_object(Hash.new(0)) do |dj, counts| handler = dj.handler.to_s.match( %r{!ruby/object:([^\n]+)} ).to_a[1].to_s.gsub(/ {}/, '') key = [dj.queue, dj.priority, dj.attempts, handler] counts[key] += 1 end end
jobs_methods(failed = false)
click to toggle source
# File lib/delayed_job_metrics/exporter.rb, line 169 def jobs_methods(failed = false) not_val = 'not ' if failed Delayed::Job.where("failed_at is #{not_val}NULL") .where("handler like '%Delayed::Performable%'") .reduce(Hash.new(0)) do |counts, dj| process(dj, counts) end end
process(job, counts)
click to toggle source
# File lib/delayed_job_metrics/exporter.rb, line 178 def process(job, counts) handler_str = job.handler.to_s handler = handler_str.match( %r{!ruby/object:([^\n]+)} ).to_a[1].to_s.gsub(/ {}/, '') object = handler_str.match( %r{(serialized_)?object: !ruby/(class '|object:)([^(\n|')]+)} ).to_a[3] method_name = handler_str.match(/method_name: ([^\n]+)/).to_a[1] key = [job.queue, job.priority, job.attempts, handler, object, method_name] counts[key] += 1 counts end
process_mertics_request(format)
click to toggle source
# File lib/delayed_job_metrics/exporter.rb, line 41 def process_mertics_request(format) reset_metrics collect_metrics respond_with(format) end
reset_metrics()
click to toggle source
# File lib/delayed_job_metrics/exporter.rb, line 47 def reset_metrics Prometheus::Client.registry.metrics.each do |metric| metric.values.keys.each { |key| metric.set(0, labels: key) } end end