-
Notifications
You must be signed in to change notification settings - Fork 0
Metrics and Diagnosis
PoolWatch analyzes intervals, not terminal progress characters or textual logs. For each observed test attempt, the interval begins at the earliest pytest phase start and ends at the latest phase finish.
Pytest report timestamps are authoritative when they exist. This matters for
concurrent schedulers that emit pytest_runtest_logstart or
pytest_runtest_logfinish after a coroutine has already completed. Lifecycle
hooks remain a fallback for interrupted or incomplete attempts.
The phases are:
setupcallteardown
Aggregate phase totals may exceed wall-clock duration because concurrent tests overlap.
Every test interval contributes two boundaries:
(started_at, +1)
(finished_at, -1)
PoolWatch groups equal timestamps and sweeps the sorted boundaries. Completions are applied before starts, then the state for the following segment is measured. This produces active-test and queued-test step functions.
The target is the expected maximum number of concurrently active tests. It can be explicit, detected from a supported scheduler, or unknown.
A known target is required for a definitive underfill diagnosis. When PoolWatch has only an observed peak, it reports a useful baseline but does not claim that the scheduler left known capacity unused.
The maximum value of the active-test timeline.
Peak proves that a concurrency level was reached at least once; it does not show whether that level was sustained.
Let each timeline segment have active count aᵢ and duration Δtᵢ:
active area = Σ(aᵢ × Δtᵢ)
average active = active area / observed duration
The average is time-weighted. A brief high-concurrency spike cannot dominate a long underfilled period.
For target T and observed duration D:
utilization = active area / (T × D)
Examples:
-
1.0means all configured slots were occupied for the full observed interval. -
0.75means the suite used 75% of available slot-time. - a value above
1.0indicates that the supplied target was lower than observed concurrency and should be corrected.
Utilization includes natural suite drain. Use underfill windows to distinguish drain from a scheduler failing to refill slots.
For each segment:
idle slot-seconds = Σ(max(0, T - aᵢ) × Δtᵢ)
This is lost capacity area, not elapsed time. Four idle slots for ten seconds contribute forty idle slot-seconds.
Idle slot-seconds include normal drain after the queue empties.
Queued tests are collected tests that have not started their first observed attempt. The queue decreases when a node ID starts for the first time.
Peak queued tests is the largest queue value represented after a timeline event.
A timeline segment is scheduler underfill only when all conditions are true:
target is known
queued > 0
active < target
segment duration > 0
Adjacent underfilled segments are merged. Each window records:
- start and finish offsets;
- minimum active tests;
- maximum queued tests;
- idle slot-seconds inside the window.
Windows shorter than poolwatch_underfill_threshold are excluded from the
underfill duration and report table.
When queued == 0, reduced concurrency is expected: no unstarted work remains
to refill empty slots. PoolWatch still includes those empty slots in utilization
and idle slot-seconds, but does not diagnose scheduler underfill.
Version 0.1 cannot determine whether active async tests are making progress, waiting on external services, or blocking an event loop. An active test occupies one observed test slot in all three cases.
PoolWatch therefore avoids claiming event-loop responsiveness or root-cause attribution. See Roadmap for possible future measurements.
pytest-poolwatch documentation · Source · PyPI · MIT License