Packages

Application to track metrics for Verk queues & jobs

Current section

Files

Jump to
verk_stats lib verk_stats.ex
Raw

lib/verk_stats.ex

defmodule VerkStats do
@moduledoc """
A GenStage consumer that generate metrics to the defined sink
The default sink simply logs everything
"""
use GenStage
alias Verk.Events.{JobFailed, JobStarted, JobFinished}
@doc """
Start GenStage consumer that generates metrics using a `sink`
"""
def start_link(sink), do: GenStage.start_link(__MODULE__, sink)
@job_events [JobFailed, JobStarted, JobFinished]
@doc false
def init(sink) do
filter = fn event -> event.__struct__ in @job_events end
{:consumer, sink, subscribe_to: [{Verk.EventProducer, selector: filter}]}
end
@doc false
def handle_events(events, _from, sink) do
Enum.each(events, &handle_event(&1, sink))
{:noreply, [], sink}
end
@doc false
defp handle_event(%JobStarted{job: job}, sink) do
:ok = sink.collect(:counter, "jobs.start", 1, tags(job))
end
defp handle_event(
%JobFinished{job: job, started_at: started_at, finished_at: finished_at},
sink
) do
tags = tags(job)
:ok =
sink.collect(
:timing,
"jobs.success",
DateTime.diff(finished_at, started_at, :milliseconds),
tags
)
enqueued_at = DateTime.from_unix!(trunc(job.enqueued_at))
:ok =
sink.collect(
:timing,
"jobs.success.total_time",
DateTime.diff(finished_at, enqueued_at, :milliseconds),
tags
)
{:ok, sink}
end
defp handle_event(%JobFailed{job: job, started_at: started_at, failed_at: failed_at}, sink) do
:ok =
sink.collect(
:timing,
"jobs.failure",
DateTime.diff(failed_at, started_at, :milliseconds),
tags(job)
)
{:ok, sink}
end
defp tags(job), do: ["worker:#{job.class}", "queue:#{job.queue}"]
end