Skip to content

Add faktory.queue.paused gauge to metrics plugin - #41

Merged
lackstein merged 4 commits into
mainfrom
nl/paused-queue-metrics
May 7, 2026
Merged

Add faktory.queue.paused gauge to metrics plugin#41
lackstein merged 4 commits into
mainfrom
nl/paused-queue-metrics

Conversation

@lackstein

Copy link
Copy Markdown
Member

Summary

  • Emits a per-queue faktory.queue.paused gauge (1 if the queue is paused, 0 otherwise) on the existing 30s metrics task tick. Dashboards and alerts can now distinguish "queue has no work" from "queue is paused and won't drain."
  • Pause state is read once per tick via store.PausedQueues(ctx) and checked in-memory inside the existing EachQueue loop — one Redis round trip per tick regardless of queue count.
  • Marks the legacy namespaced <namespace>.* metrics in metrics/task.go and metrics/middleware.go as deprecated. They are retained for backward compatibility; new metrics should be added only in the canonical faktory.* tagged form.
  • README updated with a row for the new metric.

Test plan

  • go build ./metrics/... clean
  • go vet ./metrics/... clean
  • go test -count=1 ./metrics/... passes (existing happy-path subtest extended with faktory.queue.paused=0 expectations for each queue; new "paused queue is reported as 1" subtest pushes a job, calls Pause(ctx), and asserts the gauge fires with value 1)
  • Optional manual check against a local Faktory: push a job to q1, PAUSE q1, and confirm faktory.queue.paused:1|g|#queue:q1,... appears within 30s; RESUME q1 flips it back to 0

Emits a per-queue gauge (1 if paused, 0 otherwise) so dashboards and
alerts can distinguish "queue has no work" from "queue is paused and
won't drain." Pause state is read once per tick via
store.PausedQueues(ctx) and checked against each queue in-memory inside
the existing EachQueue loop.

Also marks the legacy namespaced "<namespace>.*" metrics in task.go and
middleware.go as deprecated; new metrics should be emitted exclusively
via the canonical faktory.* tagged form.
@coderabbitai

coderabbitai Bot commented May 7, 2026

Copy link
Copy Markdown

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 40d5d52c-e38f-41ba-8353-2e4adf87e621

📥 Commits

Reviewing files that changed from the base of the PR and between a603990 and ec68617.

📒 Files selected for processing (1)
  • metrics/metrics_test.go

Walkthrough

This pull request introduces a new per-queue gauge metric faktory.queue.paused that reports the paused state of each queue. The metric is fetched during metrics collection by calling PausedQueues(ctx) from storage, converting the result into a lookup set, and emitting a gauge value of 1 for paused queues and 0 for active queues with queue-specific tags. The change includes test coverage verifying the metric is correctly emitted for paused queues, and adds deprecation documentation noting that older namespaced metrics are retained only for backward compatibility.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main change: adding a new gauge metric faktory.queue.paused to the metrics plugin, which is the primary focus across all modified files.
Description check ✅ Passed The description is well-detailed and directly related to the changeset, explaining the metric's purpose, implementation approach (reading pause state once per tick), deprecation of legacy metrics, test coverage, and build verification steps.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@metrics/metrics_test.go`:
- Around line 271-273: The fixed 500ms sleep is flaky; remove time.Sleep(500 *
time.Millisecond) and instead wait deterministically for the expected paused
metric emission by wiring a synchronization primitive (channel or
sync.WaitGroup) into the mocked emitter used in this test: have the code that
emits the paused metric signal a channel (e.g., close a doneCh or send on
doneCh) and then block the test on receiving from that channel before letting
the deferred pausedCtrl.Finish() run; update the test to reference the existing
pausedCtrl and the metric emission point (the mocked emitter or Pause handler
that currently produces the paused metric) so the test proceeds only after the
actual emission is observed.

In `@metrics/task.go`:
- Around line 75-93: Paused queue retrieval errors cause pausedSet to be empty
and emit false "faktory.queue.paused=0" for every queue; change the logic so
that when m.Subsystem.Server.Store().PausedQueues(ctx) returns an error you log
the error and skip emitting the "faktory.queue.paused" Gauge for that tick
(i.e., don't call m.Subsystem.StatsDClient().Gauge("faktory.queue.paused", ...)
inside the EachQueue loop). Implement this by recording the error state (e.g., a
boolean like pausedLookupFailed) after calling PausedQueues(ctx) and only
computing/using pausedValue and calling the Gauge when the lookup succeeded.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 275672c8-2158-40a1-80ba-810bba83ce27

📥 Commits

Reviewing files that changed from the base of the PR and between 6e4eb6f and fd2cc15.

📒 Files selected for processing (4)
  • README.md
  • metrics/metrics_test.go
  • metrics/middleware.go
  • metrics/task.go

Comment thread metrics/metrics_test.go Outdated
Comment thread metrics/task.go
lackstein added 2 commits May 7, 2026 10:54
- task.go: skip the faktory.queue.paused emission when PausedQueues
  returns an error, instead of emitting "0" for every queue (which
  would falsely report queues as active when we don't actually know).
- metrics_test.go: replace the fixed 500ms sleep in the paused-queue
  subtest with a deterministic channel close via DoAndReturn, plus a
  5s timeout fallback.

@t-duddy t-duddy left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea

@lackstein

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 7, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@metrics/metrics_test.go`:
- Around line 251-282: The test races because pausedEmitted is closed on the
first metric emission; change synchronization to wait for the final
unconditional metric emission instead: stop closing pausedEmitted in the Gauge
expectation for "faktory.queue.paused" and instead close a new (or reuse
pausedEmitted) channel in the Gauge expectation that matches the final
unconditional metric "jobs.enqueued.count" (the Gauge call with name
"jobs.enqueued.count") so the test waits for the goroutine's last mockDoer call
before runSystem returns and pausedCtrl.Finish() runs; update the
mockDoer.EXPECT() that currently DoAndReturn-closes the channel to target the
"jobs.enqueued.count" Gauge call (leave the paused queue Gauge expectation as a
simple Times(1) check).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2502e638-0626-4256-9638-e406037994e1

📥 Commits

Reviewing files that changed from the base of the PR and between fd2cc15 and 7fe0c79.

📒 Files selected for processing (2)
  • metrics/metrics_test.go
  • metrics/task.go

Comment thread metrics/metrics_test.go
Closing the channel on the paused gauge (the first per-queue emission)
left the goroutine still running through later emissions while
runSystem returned and pausedCtrl.Finish() validated expectations.
Switch the synchronization to fire on Gauge("jobs.enqueued.count", ...),
the last unconditional mock call in Execute, so the goroutine is fully
done before the test returns. The paused gauge expectation goes back
to a plain Times(1).
@lackstein
lackstein merged commit 60f7e33 into main May 7, 2026
2 checks passed
@lackstein
lackstein deleted the nl/paused-queue-metrics branch May 7, 2026 15:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants