Skip to content

feat: improved leopard saturation metrics#50

Merged
pmcclory-pp merged 1 commit into
rubyists:mainfrom
pmcclory-pp:improved-saturation-metrics
May 19, 2026
Merged

feat: improved leopard saturation metrics#50
pmcclory-pp merged 1 commit into
rubyists:mainfrom
pmcclory-pp:improved-saturation-metrics

Conversation

@pmcclory-pp
Copy link
Copy Markdown
Contributor

This improves the Leopard saturation metrics. The original version of the metrics assumed that the processing concurrency for a subject was always set to the default of 1. So if the semaphore for a given subject had no available permits, then the subject for the worker was busy - if it did it was idle.

In our prod environment where we are using leopard we monkey patch nats-pure to increase the processing concurrency which breaks this assumption. Update to return the number of actual inflight requests for a subject (in flight means that less then the processing concurrency is in flight - it still might not get immediately run by the executors thread pool if that is saturated - more on that below).

The second issue was subject saturation was telling an incomplete story of the full worker saturation. Each worker gets a thread pool with 24 threads, and all subjects requests are assigned to that thread pool. So it is possible with enough subjects registered that no individual subject will be fully saturated but the threadpool itself is. Expose metrics on this as well.

Here's a summary of the metric changes:

Metrics

Subject metrics (labels: subject, worker)

  • leopard_subject_busy_slots — thread slots actively processing a message for this subject on this worker
  • leopard_subject_capacity_slots — total thread slots allocated for this subject on this worker (reflects actual configured processing concurrency, not the default of 1)
  • leopard_subject_pending_messages — messages waiting to acquire a processing slot for this subject on this worker

Executor metrics (labels: worker)

  • leopard_executor_active_threads — approximate number of active threads in the worker's subscription executor thread pool
  • leopard_executor_max_threads — maximum threads available in the subscription executor thread pool
  • leopard_executor_queued_tasks — tasks holding a semaphore permit but waiting for a free executor thread; nonzero only when the executor pool is fully saturated

Replaced metrics

  • leopard_subject_busy_instancesleopard_subject_busy_slots / leopard_subject_capacity_slots
  • leopard_subject_total_instancesleopard_subject_capacity_slots
  • leopard_subject_pending_messages — retained but labels changed (now includes worker)

Note - opened as a feat: - but could see the argument that this is a breaking change - let me know if it should be major release

@pmcclory-pp pmcclory-pp force-pushed the improved-saturation-metrics branch from 29223b6 to c143056 Compare May 19, 2026 21:58
@pmcclory-pp pmcclory-pp requested a review from bougyman May 19, 2026 22:00
Copy link
Copy Markdown
Member

@bougyman bougyman left a comment

Choose a reason for hiding this comment

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

Feat seems reasonable to me.

@pmcclory-pp pmcclory-pp merged commit 2303ef2 into rubyists:main May 19, 2026
5 checks passed
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