Why this exists: every expired build was logged with per-hop state, but only once per minute under a global throttle, so roughly 1 in 19,000 expiries was visible. Sample counts that thin cannot answer "which hop position fails?" — 18 samples named 47 distinct peers. This class turns the same per-hop state into rate stats on every expiry, which is the only way to see the distribution rather than an anecdote.
The first observation on this router was that Hop1 (the first *remote* hop; Hop0 is ourselves) accounted for the most silent hops, which is what makes the first-hop failure cooldown the most consequential tuning parameter.
Pure and static so the stat-name derivation is unit-testable without a router; the caller supplies the already-computed classification from BuildExecutor.classifyExpiredHop(boolean, boolean, boolean, boolean, boolean, boolean).
Method Summary
All MethodsModifier and TypeMethodDescriptionstatic booleanisEstablishedSilent(String classification) Whether a classification means the peer never answered at all.static booleanisPeerFailure(int hopIndex, String classification) Whether this hop position is worth counting as a peer failure.static StringLower-case a classification for display or comparison.static String[]The peer-failure classifications worth registering a stat for.static int[]The hop positions worth registering a stat for.static StringBuild the stat name for one hop position and classification.
Method Details
statName
Build the stat name for one hop position and classification.Shape:
tunnel.buildExpired.Hop1.establishedSilent. Lower-cased and stripped of non-alphanumerics so a classification containing a space or comma still yields one legal stat name. Those come fromBuildExecutor.HOP_ESTABLISHED_SILENTand friends, and a stat name containing a space would not register.- Parameters:
hopIndex- zero-based position in the build path; 0 is usclassification- token fromBuildExecutor.classifyExpiredHop(boolean, boolean, boolean, boolean, boolean, boolean)- Returns:
- a stat name safe to pass to
addRateData
isPeerFailure
Whether this hop position is worth counting as a peer failure.Hop0 is this router and several classifications are expected states rather than failures —
selfExpectedon the gateway, and an unassigned hop that simply was not needed. Counting those would make the distribution say "hop 0 fails most", which is meaningless.- Parameters:
hopIndex- zero-based position in the build pathclassification- token fromBuildExecutor.classifyExpiredHop(boolean, boolean, boolean, boolean, boolean, boolean)- Returns:
- true if this hop should be attributed as a failure
isEstablishedSilent
Whether a classification means the peer never answered at all.This is the distinction that matters for the build path: an established peer that stays silent is a different problem from a peer that was never reachable, and they warrant opposite responses. Confirmed 18/18 and then 3/3 silent on two deployments, so the split is worth measuring rather than assuming.
- Parameters:
classification- token fromBuildExecutor.classifyExpiredHop(boolean, boolean, boolean, boolean, boolean, boolean)- Returns:
- true if the hop was established but produced no reply
registeredClassifications
The peer-failure classifications worth registering a stat for.A fixed set, not the full hop-index x classification cross-product:
StatManager.addRateData(String, long, long)silently drops names that were never registered, so an open-ended name generator records nothing at all. This set covers every classificationBuildExecutor.classifyExpiredHop(boolean, boolean, boolean, boolean, boolean, boolean)can return for a remote hop.- Returns:
- stat-name suffixes, in registration order
registeredHopIndexes
public static int[] registeredHopIndexes()The hop positions worth registering a stat for.Hop0 is this router, so it can never be a peer failure.
- Returns:
- zero-based hop indexes, in registration order
normalise
Lower-case a classification for display or comparison.- Parameters:
classification- token fromBuildExecutor.classifyExpiredHop(boolean, boolean, boolean, boolean, boolean, boolean)- Returns:
- the token lower-cased, or the empty string when null