Field Summary
Modifier and TypeFieldDescriptionprivate final AtomicLongTotal coalesce failures isolated since startup, across all stats.private final AtomicLongNumber of completed coalesce sweeps, used by tests and by the watchdog to distinguish "never ran" from "ran once then stopped".private final I2PAppContextThe context whose stats are managed.private final RateSampleDeliveryOff-timer queue for summary listener delivery, shared by every rate this manager creates.private final ConcurrentHashMap<String, FrequencyStat> Stat name to FrequencyStat.private longClock value of the last completed coalesce sweep, or 0 if none has run.private final LogLogger for this class.private final ConcurrentHashMap<String, RateStat> Stat name to RateStat.private static final longLog one coalesce-failure line per this many failures.private intWrites since the stats files were last coalesced.private static final intFrequency stats are coalesced every this many minutes.static final StringEnables full stat collection; default false.Constructor Summary
ConstructorsConstructorDescriptionStatManager(I2PAppContext context) The stat manager should only be constructed and accessed through the application context.Method Summary
Modifier and TypeMethodDescriptionvoidaddRateData(String name, long data) Update the given rate statistic, taking note that the given data point was received (and recalculating all rates).voidaddRateData(String name, long data, long eventDuration) Update the given rate statistic, taking note that the given data point was received (and recalculating all rates).voidCoalesce all rate stats and periodically coalesce frequency stats, isolating every stat from every other.voidcreateFrequencyStat(String name, String description, String group, long[] periods) Create a new statistic to monitor the frequency of some event.voidcreateRateStat(String name, String description, String group, long[] periods) Create a new statistic to monitor the average value and confidence of some action.voidcreateRequiredFrequencyStat(String name, String description, String group, long[] periods) Create a new statistic to monitor the frequency of some event.voidcreateRequiredRateStat(String name, String description, String group, long[] periods) Create a new statistic to monitor the average value and confidence of some action.longSum ofRate.getCoalesceBacklogCollapses()across every rate in the table.longTotal coalesce failures isolated since startup.longSum ofRate.getCoalesceSkips()across every rate in the table.longgetCoalesceSweepAgeMs(long now) How long ago the last coalesce sweep completed, or -1 if none ever has.getFrequency(String name) Misnamed, as it returns a FrequencyStat, not a Frequency.Names of all frequency statistics.getOrCreateFrequencyStat(String name, String description, String group, long[] periods) Resolve a frequency stat by name, creating it if it does not exist yet, and return the handle to it.getOrCreateRateStat(String name, String description, String group, long[] periods) Resolve a rate stat by name, creating it if it does not exist yet, and return the handle to it.Misnamed, as it returns a RateStat, not a Rate.Names of all rate statistics.longAge of the oldest sample still waiting for delivery.longSamples evicted because the delivery queue hit its hard capacity.intCoalesced samples waiting to be handed to their listener.longSamples replaced in place by a newer value for the same archive step.Group name (untranslated String) to a SortedSet of untranslated stat names.booleanWhether any coalesce sweep has ever completed.booleanignoreStat(String statName) Save memory by not creating stats unless they are required for router operation.booleanisFrequency(String statName) Whether the given stat is a monitored frequency.booleanWhether the given stat is a monitored rate.private voidnoteCoalesceFailure(String statName, String period, Throwable cause) Count an isolated coalesce failure and log it, naming the stat at fault.voidremoveFrequencyStat(String name) Remove a frequency stat by name.voidremoveRateStat(String name) Remove a rate stat by name.voidshutdown()Shut down the statistics manager and clear all statistics.voidstore(OutputStream out, String prefix) Serializes all Frequencies and Rates to the provided OutputStream.voidupdateFrequency(String name) Update the given frequency statistic, taking note that an event occurred (and recalculating all frequencies).
Field Details
_context
The context whose stats are managed._log
Logger for this class._frequencyStats
Stat name to FrequencyStat._rateStats
Stat name to RateStat._delivery
Off-timer queue for summary listener delivery, shared by every rate this manager creates. One thread serves the whole table; a per-rate queue would mean a thread per rate._coalesceFailures
Total coalesce failures isolated since startup, across all stats.Nonzero means at least one stat stopped recording. It is reported rather than absorbed because the failure it counts is silent by nature: a skipped rate produces no exception for anyone to notice.
_lastCoalesceSweepAt
private volatile long _lastCoalesceSweepAtClock value of the last completed coalesce sweep, or 0 if none has run.This is a heartbeat for the whole stat subsystem. The sweep runs on the shared coalesce timer, so it can stop without any exception: the task is simply queued behind other work and never runs. Nothing inside the stats package can detect its own non-execution, so an observer outside it needs this to tell "a rate failed to coalesce" apart from "no rate was asked to coalesce at all".
GraphGenerator's health watchdog reads it, from a scheduler independent of the timer that could be wedged._coalesceSweeps
Number of completed coalesce sweeps, used by tests and by the watchdog to distinguish "never ran" from "ran once then stopped".COALESCE_FAILURE_LOG_INTERVAL
private static final long COALESCE_FAILURE_LOG_INTERVALLog one coalesce-failure line per this many failures. The first is always logged; after that a stat failing every cycle would otherwise emit one ERROR per coalesce period for the life of the router.- See Also:
coalesceCounter
private int coalesceCounterWrites since the stats files were last coalesced.FREQ_COALESCE_RATE
private static final int FREQ_COALESCE_RATEFrequency stats are coalesced every this many minutes.- See Also:
PROP_STAT_FULL
Enables full stat collection; default false.- See Also:
Constructor Details
StatManager
The stat manager should only be constructed and accessed through the application context. This constructor should only be used by the appropriate application context itself.- Parameters:
context- the application context
Method Details
shutdown
public void shutdown()Shut down the statistics manager and clear all statistics.createFrequencyStat
Create a new statistic to monitor the frequency of some event. The stat is ONLY created if thestat.fullproperty is true or we are not in the router context.- Parameters:
name- unique name of the statisticdescription- simple description of the statisticgroup- used to group statistics togetherperiods- array of period lengths (in milliseconds)
createRequiredFrequencyStat
public void createRequiredFrequencyStat(String name, String description, String group, long[] periods) Create a new statistic to monitor the frequency of some event. The stat is always created, independent of thestat.fullsetting or context.- Parameters:
name- unique name of the statisticdescription- simple description of the statisticgroup- used to group statistics togetherperiods- array of period lengths (in milliseconds)
getOrCreateFrequencyStat
public FrequencyStat getOrCreateFrequencyStat(String name, String description, String group, long[] periods) Resolve a frequency stat by name, creating it if it does not exist yet, and return the handle to it.Lets a caller on a repeated event stop re-resolving the name. The handle stays valid until
removeFrequencyStat(String)orshutdown(); there is deliberately no handle-invalidation step, because dropping one would cost the very lookup it was meant to remove.- Parameters:
name- unique name of the statisticdescription- simple description of the statistic, used only if the stat has to be createdgroup- used to group statistics togetherperiods- array of period lengths (in milliseconds)- Returns:
- the stat for
name, never null
removeFrequencyStat
Remove a frequency stat by name.Any handle previously returned by
getOrCreateFrequencyStat(String, String, String, long[])is orphaned by this and must not be used again.- Parameters:
name- the stat name to remove
createRateStat
Create a new statistic to monitor the average value and confidence of some action. The stat is ONLY created if thestat.fullproperty is true or we are not in the router context.- Parameters:
name- unique name of the statisticdescription- simple description of the statisticgroup- used to group statistics togetherperiods- array of period lengths (in milliseconds)
createRequiredRateStat
Create a new statistic to monitor the average value and confidence of some action. The stat is always created, independent of thestat.fullsetting or context.- Parameters:
name- unique name of the statisticdescription- simple description of the statisticgroup- used to group statistics togetherperiods- array of period lengths (in milliseconds)
getOrCreateRateStat
Resolve a rate stat by name, creating it if it does not exist yet, and return the handle to it.Lets a caller reporting the same stat repeatedly avoid the string-keyed map lookup that
addRateData(String, long)pays on every call. Resolution is check-then-act, not a singleConcurrentMap.computeIfAbsent(K, Function): the creation itself goes throughcreateRequiredRateStat(String, String, String, long[]), which does usecomputeIfAbsent, so concurrent callers may both attempt it but exactly one stat is built and the delivery queue is attached before that stat is published. The handle is therefore usable the instant this returns.The handle is not invalidated when the stat is removed: a stale handle keeps updating an orphaned stat, which is inert rather than harmful, and detecting that would cost the lookup this exists to remove. It is valid until
removeRateStat(String)orshutdown().- Parameters:
name- unique name of the statisticdescription- simple description of the statistic, used only if the stat has to be createdgroup- used to group statistics togetherperiods- array of period lengths (in milliseconds)- Returns:
- the stat for
name, or null if this manager is not collecting it and it does not already exist
getCoalesceSkips
public long getCoalesceSkips()Sum ofRate.getCoalesceSkips()across every rate in the table.A rate normally skips one coalesce per period, so this grows steadily and is not by itself a problem. It is reported so that a rate which stopped coalescing entirely can be told apart from one that is merely visited early.
- Returns:
- total coalesce skips across all rates
getCoalesceBacklogCollapses
public long getCoalesceBacklogCollapses()Sum ofRate.getCoalesceBacklogCollapses()across every rate in the table.Unlike a skip, a collapse is permanent: the steps it abandoned can never be written, so every count here is a gap in the graph data. Zero is the healthy state. A nonzero value points at the shared coalesce timer rather than at any one rate, since all rates are coalesced from the same
SimpleTimer2pool.- Returns:
- total backlog collapses across all rates
getSampleOverruns
public long getSampleOverruns()Samples evicted because the delivery queue hit its hard capacity.Unlike
RateSampleDelivery.getSuperseded()this must never happen: same-step supersession means a slow consumer does not grow the queue, so reaching the cap means the consumer is not draining at all. Surfaced here because the delivery queue is package-private and the console watchdog, which is the only thing positioned to act on it, lives in another package.- Returns:
- eviction count since startup, zero in the healthy state
getSampleSuperseded
public long getSampleSuperseded()Samples replaced in place by a newer value for the same archive step.High but non-zero is normal under load and is not loss - only one value per step is storable and the newest is the correct one. A count that stops advancing while
getSamplePending()climbs means the consumer has stopped draining.- Returns:
- supersession count since startup
getSamplePending
public int getSamplePending()Coalesced samples waiting to be handed to their listener.- Returns:
- current queue depth, zero when delivery is keeping up
getSampleOldestPendingAgeMs
public long getSampleOldestPendingAgeMs()Age of the oldest sample still waiting for delivery.The direct measure of delivery lag, and therefore the only signal that distinguishes a stalled consumer from a rate that has stopped coalescing: both leave the graph frozen, but only the second one drains this queue.
- Returns:
- ms since the oldest pending sample was submitted, zero when idle
removeRateStat
Remove a rate stat by name.Any handle previously returned by
getOrCreateRateStat(String, String, String, long[])is orphaned by this and must not be used again.- Parameters:
name- the stat name to remove
updateFrequency
Update the given frequency statistic, taking note that an event occurred (and recalculating all frequencies).- Parameters:
name- the stat name
addRateData
Update the given rate statistic, taking note that the given data point was received (and recalculating all rates).- Parameters:
name- the stat namedata- the data point valueeventDuration- how long the event took, or 0
addRateData
Update the given rate statistic, taking note that the given data point was received (and recalculating all rates). Zero duration.- Parameters:
name- the stat namedata- the data point value
coalesceStats
public void coalesceStats()Coalesce all rate stats and periodically coalesce frequency stats, isolating every stat from every other.Isolation is the whole point of this method. It runs as one pass over the whole table on the shared coalesce timer, so a single exception escaping a stat would abandon every stat later in the pass: their rates would stop coalescing, their listeners would receive nothing, and their graphs would freeze while every health check still reported them healthy. One broken stat must therefore be able to affect only itself.
getCoalesceSweepAgeMs
public long getCoalesceSweepAgeMs(long now) How long ago the last coalesce sweep completed, or -1 if none ever has.Callers use this to distinguish a rate that will not coalesce from a coalesce task that is not running. A sweep older than a few rate periods means the latter, which no counter inside this package can report.
- Parameters:
now- current clock value in ms- Returns:
- ms since the last completed sweep, or -1 if there has never been one
hasCoalesced
public boolean hasCoalesced()Whether any coalesce sweep has ever completed.- Returns:
- true if at least one sweep has completed
noteCoalesceFailure
Count an isolated coalesce failure and log it, naming the stat at fault.ERROR rather than WARN because the failure is silent data loss, and
logger.defaultLevelis ERROR: a WARN would be suppressed in a default configuration and the loss would go unnoticed. ERROR also reaches the console's error log page, so the stat is identifiable without reading the log file.- Parameters:
statName- name of the stat that failedperiod- the failing rate's period in ms, or null if not per-ratecause- what went wrong
getCoalesceFailures
public long getCoalesceFailures()Total coalesce failures isolated since startup.Zero is the healthy state. Nonzero means at least one stat has silently stopped recording; the log line names which one.
- Returns:
- the running failure count across all stats
getFrequency
Misnamed, as it returns a FrequencyStat, not a Frequency.- Parameters:
name- the stat name- Returns:
- the FrequencyStat, or null if no stat of that name is registered
getRate
getFrequencyNames
getRateNames
isRate
Whether the given stat is a monitored rate.- Parameters:
statName- the stat name- Returns:
- true if a RateStat is registered under that name
isFrequency
Whether the given stat is a monitored frequency.- Parameters:
statName- the stat name- Returns:
- true if a FrequencyStat is registered under that name
getStatsByGroup
ignoreStat
Save memory by not creating stats unless they are required for router operation. For backward compatibility of any external clients, always returns false if not in router context.- Parameters:
statName- stat being registered; the decision applies to every name, so none is examined- Returns:
- true if the stat should be ignored.
store
Serializes all Frequencies and Rates to the provided OutputStream.- Parameters:
out- to write toprefix- to use when serializing- Throws:
IOException- if something goes wrong