Module: Philiprehberger::JobMeter

Defined in:
lib/philiprehberger/job_meter.rb,
lib/philiprehberger/job_meter/stats.rb,
lib/philiprehberger/job_meter/bucket.rb,
lib/philiprehberger/job_meter/report.rb,
lib/philiprehberger/job_meter/version.rb,
lib/philiprehberger/job_meter/exporter.rb,
lib/philiprehberger/job_meter/collector.rb,
lib/philiprehberger/job_meter/histogram.rb

Defined Under Namespace

Modules: Exporter, Histogram, Report, Stats Classes: Bucket, Collector

Constant Summary collapse

VERSION =
'0.5.0'

Class Method Summary collapse

Class Method Details

.clear!(job_class) ⇒ Object



53
54
55
56
57
58
# File 'lib/philiprehberger/job_meter.rb', line 53

def clear!(job_class)
  cleared = @collector.clear!(job_class)
  bucket = @buckets.delete(job_class)
  bucket&.reset!
  cleared
end

.histogram(job_class, buckets:) ⇒ Object



78
79
80
81
82
83
# File 'lib/philiprehberger/job_meter.rb', line 78

def histogram(job_class, buckets:)
  data = @collector.entries(job_class)
  return nil unless data

  Histogram.compute(data[:durations], buckets)
end

.job_classesArray

Return all job classes with at least one recorded entry.

Useful for dashboards that need to enumerate registered jobs without serializing the full Prometheus or JSON export.

Returns:

  • (Array)

    job class identifiers seen by the collector



49
50
51
# File 'lib/philiprehberger/job_meter.rb', line 49

def job_classes
  @collector.all_job_classes
end

.measure(job_class, tags: {}) ⇒ Object

Raises:

  • (ArgumentError)


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/philiprehberger/job_meter.rb', line 23

def measure(job_class, tags: {})
  raise ArgumentError, 'measure requires a block' unless block_given?

  start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  success = true
  begin
    yield
  rescue StandardError
    success = false
    raise
  ensure
    duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
    record(job_class, duration: duration, success: success, tags: tags)
  end
end

.record(job_class, duration:, success:, tags: {}) ⇒ Object



18
19
20
21
# File 'lib/philiprehberger/job_meter.rb', line 18

def record(job_class, duration:, success:, tags: {})
  @collector.record(job_class, duration: duration, success: success, tags: tags)
  (@buckets[job_class] ||= Bucket.new).record(duration: duration, success: success)
end

.reset!Object



101
102
103
104
105
# File 'lib/philiprehberger/job_meter.rb', line 101

def reset!
  @collector.reset!
  @buckets.each_value(&:reset!)
  @buckets.clear
end

.stats(job_class, tags: {}) ⇒ Object



71
72
73
74
75
76
# File 'lib/philiprehberger/job_meter.rb', line 71

def stats(job_class, tags: {})
  data = @collector.entries(job_class, tags: tags)
  return nil unless data

  Stats.compute(data[:durations], data[:successes])
end

.tag_values(job_class, key) ⇒ Object



39
40
41
# File 'lib/philiprehberger/job_meter.rb', line 39

def tag_values(job_class, key)
  @collector.tag_values(job_class, key)
end

.to_json_exportObject



89
90
91
# File 'lib/philiprehberger/job_meter.rb', line 89

def to_json_export
  Exporter.to_json_export(@collector)
end

.to_prometheusObject



85
86
87
# File 'lib/philiprehberger/job_meter.rb', line 85

def to_prometheus
  Exporter.to_prometheus(@collector)
end

.top_failing(num = 5) ⇒ Object



97
98
99
# File 'lib/philiprehberger/job_meter.rb', line 97

def top_failing(num = 5)
  Report.top_failing(@collector, num)
end

.top_slowest(num = 5) ⇒ Object



93
94
95
# File 'lib/philiprehberger/job_meter.rb', line 93

def top_slowest(num = 5)
  Report.top_slowest(@collector, num)
end


60
61
62
63
64
65
66
67
68
69
# File 'lib/philiprehberger/job_meter.rb', line 60

def trending(job_class)
  bucket = @buckets[job_class]
  unless bucket
    return Bucket::WINDOWS.each_with_object({}) do |(label, _), h|
      h[label] = { avg_duration: 0.0, success_rate: 0.0, total: 0, failed: 0 }
    end
  end

  bucket.trending
end