pub struct PollHealth {
pub feeds_tracked: i64,
pub polled_last_hour: i64,
pub overdue: i64,
pub last_poll_secs_ago: Option<i64>,
pub oldest_poll_secs_ago: Option<i64>,
pub never_polled: i64,
pub in_backoff: i64,
pub badly_broken: i64,
pub failure_kinds: Vec<(String, i64)>,
}Expand description
Aggregate poll health, for the public stats page.
Deliberately aggregate-only. No user counts, no error rates, no per-feed detail: this is published to anyone, and a reader does not need to know how many people use an instance or which feeds are failing. What it does answer is the only question the page exists for — is the poller keeping up?
Fields§
§feeds_tracked: i64Distinct feeds the poller is responsible for.
polled_last_hour: i64How many were polled within the last hour.
overdue: i64Feeds whose next_poll has passed — the backlog. A healthy instance
clears this every tick; a growing number is the signal that the poller
cannot keep up with the feed count.
last_poll_secs_ago: Option<i64>Seconds since the most recent poll of any feed. None before the first.
oldest_poll_secs_ago: Option<i64>Seconds since the LEAST recently polled feed was polled — the worst staleness any reader is currently seeing.
None when any feed has NEVER been polled, because that is a worse
staleness than any finite age and reporting the finite one would make
the page read healthiest exactly when it is least healthy.
never_polled: i64How many feeds have never been polled at all.
in_backoff: i64Feeds currently in error backoff (consecutive_errors > 0).
One of the two states that stop feeds updating, and previously visible
nowhere: consecutive_errors was written by bump_feed_errors and read
by nothing outside the backoff calculation — no page, no endpoint. Worse,
a feed in backoff is NOT counted in overdue, because backoff is applied
by pushing next_poll forward. So the one number a reader might have
checked moved the wrong way: a feed failing every fetch made overdue
look BETTER.
badly_broken: i64Of those, how many have reached [BADLY_BROKEN_ERRORS] consecutive
failures — retried 2h40m apart rather than every 5 minutes.
Not “will not recover on their own”: the backoff ceiling is 24h at ten
errors, and any of these recovers on its next successful poll. See
[BADLY_BROKEN_ERRORS].
failure_kinds: Vec<(String, i64)>Failing feeds grouped by cause, descending, as
(kind, count) — fetch, status, body, parse.
Counts, never identities. /stats is public and states that it
reports machines rather than people: no per-feed detail, never which feed
and never whose. A cause histogram keeps that promise and still answers
the question badly_broken could not — whether sixty feeds are failing
for sixty reasons or for one. Had this existed, #159 would have read
fetch: 60 on a page anyone could load, instead of costing a production
investigation.
Trait Implementations§
Source§impl Clone for PollHealth
impl Clone for PollHealth
Source§fn clone(&self) -> PollHealth
fn clone(&self) -> PollHealth
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for PollHealth
impl Debug for PollHealth
impl Eq for PollHealth
Source§impl PartialEq for PollHealth
impl PartialEq for PollHealth
impl StructuralPartialEq for PollHealth
Auto Trait Implementations§
impl Freeze for PollHealth
impl RefUnwindSafe for PollHealth
impl Send for PollHealth
impl Sync for PollHealth
impl Unpin for PollHealth
impl UnsafeUnpin for PollHealth
impl UnwindSafe for PollHealth
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more