Metrics
Every worker keeps three counters over its lifetime. Metrics() returns them. They tell you how many jobs the worker ran and how they ended, without tracking jobs yourself.
The three counters
Metrics has three read methods, each returning a uint64:
| Method | Counts |
|---|---|
Completed() | jobs whose function has returned, whether it succeeded or failed. |
Successful() | jobs whose function returned without an error and without a panic. A plain worker’s function has no error to return, so for it this means it returned normally. |
Failed() | jobs whose function returned an error, or panicked. |
A job that runs counts once in Completed and once in Successful or Failed. After a worker has gone idle, Completed equals Successful plus Failed, unless you called Reset partway.
Only a job that ran counts. A job closed or cancelled before it starts counts in none of them. A job removed by Purge, or a topic payload that is dropped unread, does not count either.
Jobs a queue received
A worker does not count the jobs its queues receive. Each queue counts them itself, because several workers or processes can share one queue. Read the count as totals.submitted from GET /queues in the REST API. Lifecycle explains how the jobs that wait relate to NumPending and Len.
Reading them
The program below adds three jobs to an error worker. Job 2 returns an error. It waits until the worker is idle and reads the three counters.
8 lines: package and imports
package main
import (
"fmt"
"github.com/goptics/varmq"
)
func main() {
worker := varmq.NewErrWorker(func(j varmq.Job[int]) error {
if j.Data() == 2 {
return fmt.Errorf("job %d failed", j.Data())
}
return nil
})
queue := worker.BindQueue()
for i := 1; i <= 3; i++ {
queue.Add(i)
}
worker.WaitUntilIdle()
m := worker.Metrics()
fmt.Println("completed", m.Completed())
fmt.Println("successful", m.Successful())
fmt.Println("failed", m.Failed())
}
Tab inserts a tab. Esc leaves the editor. Ctrl+Enter runs.
Output
All three jobs completed. Two succeeded, and job 2 is the one failed job, so Completed equals Successful plus Failed.
- The counters are cumulative. They start at zero when the worker is created, and nothing but
Resetclears them. Pausing, stopping, restarting and purging do not change them. - They are safe to read from any goroutine. Each method is one atomic read.
- Three reads are not one snapshot. A job can finish between two of them. So three values read while jobs run can be off by as many jobs as finish between the reads.
- A job’s own
Waitcan return a moment beforeCompletedcounts it. The worker closes a finished job, which releasesWait. Just after that, the worker counts the job as completed.SuccessfulandFailedare already counted by then. To read settled values, wait for the worker withWaitUntilIdleorWaitfirst. Waiting compares them.
Reset
Reset sets all three counters to zero. It does not touch the queue or the jobs that are running.
- The three counters are cleared one after another, not in one step.
- A job that was waiting or running when you call it is counted when it finishes. So after a
Resetin the middle of a run, the counters do not stay at zero.
Call Reset when the worker is idle, as the program below does.
8 lines: package and imports
package main
import (
"fmt"
"github.com/goptics/varmq"
)
func main() {
worker := varmq.NewWorker(func(j varmq.Job[int]) {
fmt.Println("ran job", j.Data())
})
queue := worker.BindQueue()
m := worker.Metrics()
queue.Add(1)
queue.Add(2)
worker.WaitUntilIdle()
fmt.Println("before Reset: completed", m.Completed())
m.Reset()
fmt.Println("after Reset: completed", m.Completed())
}
Tab inserts a tab. Esc leaves the editor. Ctrl+Enter runs.
Output
Both jobs ran before the Reset, so the counters read 2 before it and 0 after.
Where else the counters appear
A named worker’s counters are also what the REST handler reports, and the Prometheus example exports the same three. See REST API and Prometheus.
Next: Function helpers.