1
0
Fork 0
mirror of https://github.com/mperham/sidekiq.git synced 2022-11-09 13:52:34 -05:00
mperham--sidekiq/test/test_metrics.rb
Adam McCrea 0b3751bf29
Histogram chart for job-specific metrics (#5473)
* Refactor job query

* First attempt at a histogram chart

* Explore a box plot chart

* Show 3 chart variations

* Outline boxes instead of solid boxes

* Remove box plot chart

* Use linear y-axis

This matches the axis for the metrics overview page, and it clarifies the data.

* Data tables for job metrics

* Add histogram totals chart

* Move things around

* Tooltip for histogram chart

* Fix deploy tooltip

* Extract marks query

* Extract chart base class

* Renaming

* Ensure a min radius for histogram bubbles

High job counts can result in a very small multiplier, which was making some of the bubbles too small to be visible.

* Round everything to two decimals for consistency

* styling for metrics headers

* Show emdash when timing info is n/a

* No job results found message

* No need for metrics header
2022-08-16 10:56:36 -07:00

162 lines
5.5 KiB
Ruby

# frozen_string_literal: true
require_relative "helper"
require "sidekiq/component"
require "sidekiq/metrics/tracking"
require "sidekiq/metrics/query"
require "sidekiq/metrics/deploy"
require "sidekiq/api"
describe Sidekiq::Metrics do
before do
Sidekiq.redis { |c| c.flushdb }
end
def fixed_time
@whence ||= Time.utc(2022, 7, 22, 22, 3, 0)
end
def create_known_metrics(time = fixed_time)
smet = Sidekiq::Metrics::ExecutionTracker.new(Sidekiq)
smet.track("critical", "App::SomeJob") { sleep 0.001 }
smet.track("critical", "App::FooJob") { sleep 0.001 }
assert_raises RuntimeError do
smet.track("critical", "App::SomeJob") do
raise "boom"
end
end
smet.flush(time)
smet.track("critical", "App::FooJob") { sleep 0.001 }
smet.track("critical", "App::FooJob") { sleep 0.025 }
smet.track("critical", "App::FooJob") { sleep 0.001 }
smet.track("critical", "App::SomeJob") { sleep 0.001 }
smet.flush(time - 60)
end
it "tracks metrics" do
count = create_known_metrics
assert_equal 12, count
end
describe "marx" do
it "owns the means of production" do
whence = Time.local(2022, 7, 17, 18, 43, 15)
floor = whence.utc.rfc3339.sub(":15", ":00")
d = Sidekiq::Metrics::Deploy.new
d.mark(at: whence, label: "cafed00d - some git summary line")
q = Sidekiq::Metrics::Query.new(now: whence)
rs = q.for_job("FooJob")
refute_nil rs.marks
assert_equal 1, rs.marks.size
assert_equal "cafed00d - some git summary line", rs.marks.first.label, rs.marks.inspect
d = Sidekiq::Metrics::Deploy.new
rs = d.fetch(whence)
refute_nil rs
assert_equal 1, rs.size
assert_equal "cafed00d - some git summary line", rs[floor]
end
end
describe "histograms" do
it "buckets a bunch of times" do
h = Sidekiq::Metrics::Histogram.new("App::FooJob")
assert_equal 0, h.sum
h.record_time(10)
h.record_time(46)
h.record_time(47)
h.record_time(48)
h.record_time(300)
h.record_time(301)
h.record_time(302)
h.record_time(300000000)
assert_equal 8, h.sum
key = Sidekiq.redis do |conn|
h.persist(conn, fixed_time)
end
assert_equal 0, h.sum
refute_nil key
assert_equal "App::FooJob-22-22:3", key
h = Sidekiq::Metrics::Histogram.new("App::FooJob")
data = Sidekiq.redis { |c| h.fetch(c, fixed_time) }
{0 => 1, 3 => 3, 7 => 3, 25 => 1}.each_pair do |idx, val|
assert_equal val, data[idx]
end
end
end
describe "querying" do
it "handles empty metrics" do
q = Sidekiq::Metrics::Query.new(now: fixed_time)
result = q.top_jobs
assert_equal 60, result.buckets.size
assert_equal([], result.job_results.keys)
q = Sidekiq::Metrics::Query.new(now: fixed_time)
result = q.for_job("DoesntExist")
assert_equal 60, result.buckets.size
assert_equal(["DoesntExist"], result.job_results.keys)
end
it "fetches top job data" do
create_known_metrics
d = Sidekiq::Metrics::Deploy.new
d.mark(at: fixed_time - 300, label: "cafed00d - some git summary line")
q = Sidekiq::Metrics::Query.new(now: fixed_time)
result = q.top_jobs
assert_equal fixed_time - 59 * 60, result.starts_at
assert_equal fixed_time, result.ends_at
assert_equal 1, result.marks.size
assert_equal "cafed00d - some git summary line", result.marks[0].label
assert_equal "21:58", result.marks[0].bucket
assert_equal 60, result.buckets.size
assert_equal "21:04", result.buckets.first
assert_equal "22:03", result.buckets.last
assert_equal %w[App::SomeJob App::FooJob].sort, result.job_results.keys.sort
job_result = result.job_results["App::SomeJob"]
refute_nil job_result
assert_equal %w[p f ms s].sort, job_result.series.keys.sort
assert_equal %w[p f ms s].sort, job_result.totals.keys.sort
assert_equal 2, job_result.series.dig("p", "22:03")
assert_equal 3, job_result.totals["p"]
# Execution time is not consistent, so these assertions are not exact
assert job_result.total_avg("ms").between?(0.5, 2), job_result.total_avg("ms")
assert job_result.series_avg("s")["22:03"].between?(0.0005, 0.002), job_result.series_avg("s")
end
it "fetches job-specific data" do
create_known_metrics
d = Sidekiq::Metrics::Deploy.new
d.mark(at: fixed_time - 300, label: "cafed00d - some git summary line")
q = Sidekiq::Metrics::Query.new(now: fixed_time)
result = q.for_job("App::FooJob")
assert_equal fixed_time - 59 * 60, result.starts_at
assert_equal fixed_time, result.ends_at
assert_equal 1, result.marks.size
assert_equal "cafed00d - some git summary line", result.marks[0].label
assert_equal "21:58", result.marks[0].bucket
assert_equal 60, result.buckets.size
assert_equal "21:04", result.buckets.first
assert_equal "22:03", result.buckets.last
# from create_known_data
assert_equal %w[App::FooJob], result.job_results.keys
job_result = result.job_results["App::FooJob"]
refute_nil job_result
assert_equal %w[p ms s].sort, job_result.series.keys.sort
assert_equal %w[p ms s].sort, job_result.totals.keys.sort
assert_equal 1, job_result.series.dig("p", "22:03")
assert_equal 4, job_result.totals["p"]
assert_equal 2, job_result.hist.dig("22:02", 0)
assert_equal 1, job_result.hist.dig("22:02", 1)
end
end
end