- Enclosing class:
SimpleTimer2
It cannot run on the pool it watches: a wedged pool has no spare worker to run the watchdog on, which is the whole failure. It also does nothing but read counters, so no event running on this timer can delay it. Every sample is four counter reads and a few field writes - no allocation, no synchronization beyond the monitor it sleeps on - so it is free to leave running for the life of the router.
Everything below is touched only by the watchdog thread, except _stopped, which is guarded by the watchdog monitor.
Field Summary
FieldsModifier and TypeFieldDescriptionprivate longCompleted count at the previous sample.private longWall clock at which we last saw the completion count rise.private longLongest quiet period this timer has previously come back from.private intConsecutive samples that completed a task; recovery needs this many.private longCompleted count seen at the last saturated sample.private intSamples seen with the queue saturated.private booleanTrue once the saturation was logged.private intSamples seen with no completions.private booleanTrue once the stall was logged.private longCompletion count when the current quiet episode began.private booleanGuarded by this.private booleanWhether any task was due during the current quiet episode.Constructor Summary
ConstructorsMethod Summary
Private MethodsModifier and TypeMethodDescriptionprivate voidcheckSaturation(int active, int pool, int queued, long completed) Warn once per episode of a fully occupied pool with a backlog.private voidcheckStall(long completed, boolean workDue) Warn once per episode of a pool that completes nothing at all.private booleanIs a task actually due on this timer right now?private Loglog()The timer log, looked up per message rather than cached: the router replaces its LogManager after start-up, and a cached Log would go quiet from then on.private voidrun()Sample everySimpleTimer2.WATCHDOG_INTERVAL_MSuntilshutdown().private voidsample()Take one sample and act on it.(package private) voidshutdown()Stop sampling.private voidstart()Start the sampling thread, warning if the JVM will not run it - a watchdog that silently failed to start is the same invisible failure this class exists to prevent.
Field Details
_saturatedSamples
private int _saturatedSamplesSamples seen with the queue saturated._saturationReported
private boolean _saturationReportedTrue once the saturation was logged._saturatedCompleted
private long _saturatedCompletedCompleted count seen at the last saturated sample._stalledSamples
private int _stalledSamplesSamples seen with no completions._stallReported
private boolean _stallReportedTrue once the stall was logged._progressSamples
private int _progressSamplesConsecutive samples that completed a task; recovery needs this many._workDueThisEpisode
private boolean _workDueThisEpisodeWhether any task was due during the current quiet episode._stallStartCompleted
private long _stallStartCompletedCompletion count when the current quiet episode began._lastCompleted
private long _lastCompletedCompleted count at the previous sample._lastProgressAt
private long _lastProgressAtWall clock at which we last saw the completion count rise._maxObservedGapMs
private long _maxObservedGapMsLongest quiet period this timer has previously come back from. Grows only while the watchdog observes recovery, so it is a floor learned from the timer's own behaviour rather than a guess._stopped
private boolean _stoppedGuarded by this.
Constructor Details
SaturationWatchdog
SaturationWatchdog()Builds the saturation watchdog.
Method Details
start
private void start()Start the sampling thread, warning if the JVM will not run it - a watchdog that silently failed to start is the same invisible failure this class exists to prevent. No reference to the thread is kept: it runs untilshutdown(), and being a daemon it cannot hold up JVM exit either way.shutdown
void shutdown()Stop sampling. Idempotent, cannot throw, and safe whenstart()failed. The thread is a daemon, so it cannot hold up JVM exit even if this is never called.run
private void run()Sample everySimpleTimer2.WATCHDOG_INTERVAL_MSuntilshutdown().The stopped test and the wait share the monitor, so shutdown() cannot land between them and leave this thread parked for the rest of the interval - hence no interrupt is needed.
sample
private void sample()Take one sample and act on it. All the executor counters are safe to read after shutdown, so a sample racingSimpleTimer2.stop()degrades to reporting nothing rather than throwing.isWorkDue
private boolean isWorkDue()Is a task actually due on this timer right now?A pool that has completed nothing may be idle or wedged, and completion counts cannot tell them apart - only this can. It is a property of the work offered, not of the timer's history, so unlike a calibrated gap threshold it cannot be tuned into uselessness by a timer that has always been quiet: a streaming retransmission shard that simply has nothing to retransmit has no due task and is correctly silent, while a shard with a due task and no progress is the thing worth reporting.
- Returns:
- true if the queue holds a task whose delay has already elapsed
checkSaturation
private void checkSaturation(int active, int pool, int queued, long completed) Warn once per episode of a fully occupied pool with a backlog.- Parameters:
active- the number of currently active threadspool- the configured pool sizequeued- the number of tasks queued behind the active threadscompleted- the total number of tasks completed so far
checkStall
private void checkStall(long completed, boolean workDue) Warn once per episode of a pool that completes nothing at all.The bar is the timer's own longest observed gap, learned as the timer comes and goes, rather than its mean interval. See
SimpleTimer2.evaluateStall(long, long, int, int, boolean, long).- Parameters:
completed- the total number of tasks completed so farworkDue- true if a task is due to run right now
log
The timer log, looked up per message rather than cached: the router replaces its LogManager after start-up, and a cached Log would go quiet from then on. Only log paths pay for this, never a sample.- Returns:
- the current log for this class