pub struct MetricsSnapshot {Show 20 fields
pub connections_opened: u64,
pub connections_accepted: u64,
pub connections_anonymous: u64,
pub connections_refused: u64,
pub auth_faults: u64,
pub exec_refused: u64,
pub transfers_started: u64,
pub transfers_in_flight: u64,
pub transfers_failed: u64,
pub packs_served: u64,
pub objects_sent: u64,
pub bytes_out: u64,
pub bytes_in: u64,
pub pushes_accepted: u64,
pub pushes_rejected: u64,
pub refs_updated: u64,
pub refs_deleted: u64,
pub refs_rejected: u64,
pub gate_refusals: u64,
pub usage_reconcile_missed: u64,
}Expand description
A reading of ServerMetrics, taken at one moment.
Fields§
§connections_opened: u64TCP connections russh handed to gunnar.
connections_accepted: u64Connections whose offered key named a principal.
connections_anonymous: u64Connections admitted with no key at all, served as the anonymous principal, which can only ever read a public repository.
Counted separately from MetricsSnapshot::connections_accepted rather
than folded into it: “how much of my traffic is strangers” is the first
question an operator asks after making anything public, and a total that
mixed the two could not answer it.
connections_refused: u64Connections whose offered key named nobody. Not the same as
MetricsSnapshot::auth_faults.
auth_faults: u64Connections refused because the identity table could not be read. A storage fault looks exactly like an empty table from the client’s side, and an operator must be able to tell them apart.
exec_refused: u64Exec requests refused or denied after authentication: a non-git command, an unknown repository, a missing grant.
transfers_started: u64Transfers admitted and begun.
transfers_in_flight: u64Transfers running right now. A gauge, not a total.
transfers_failed: u64Transfers that ended with a protocol or storage error.
packs_served: u64upload-pack sessions that sent a packfile.
objects_sent: u64Objects written into those packs.
bytes_out: u64Bytes gunnar wrote to git clients, counted at the wire.
bytes_in: u64Bytes gunnar read from git clients, counted at the wire.
pushes_accepted: u64Pushes in which every reference landed.
pushes_rejected: u64Pushes in which at least one reference was refused.
refs_updated: u64References moved.
refs_deleted: u64References deleted.
refs_rejected: u64Reference updates refused, for any reason.
gate_refusals: u64Reference updates refused by a named policy gate. A subset of
MetricsSnapshot::refs_rejected, which also counts connectivity
failures and the collateral refusals of an --atomic push.
usage_reconcile_missed: u64Ticks of the usage ledger’s reconcile pass that could not run (the catalog could not be read, so nothing was re-measured). Counted, warned and published rather than dropped (A28 M17): a pass that silently skips is a ledger that silently goes stale.
Implementations§
Source§impl MetricsSnapshot
impl MetricsSnapshot
Sourcepub fn fields(&self) -> Vec<(&'static str, MetricKind, u64)>
pub fn fields(&self) -> Vec<(&'static str, MetricKind, u64)>
Every counter as (name, kind, value), in declaration order.
Generated by the same macro arm that declares the fields, so a
counter added to ServerMetrics appears here — and therefore
on the scrape endpoint — without anyone remembering to add
it. The alternative was a second hand-written list of nineteen
names, and the counter left out of it would be the one nobody
could see.
That is not a hypothetical. The heartbeat was such a list, and
it carried eighteen of the nineteen: connections_anonymous —
written by both transports, and the answer to how much of my
traffic is strangers — never appeared in a single line gunnar
ever printed. See MetricsSnapshot::emit_heartbeat.
Sourcepub fn emit_heartbeat(&self)
pub fn emit_heartbeat(&self)
The heartbeat line: one info on TARGET_METRICS naming every
counter.
Here, and generated, for the reason above: this used to be a
hand-written tracing::info! in gunnar-cli listing eighteen of
the nineteen fields. Expanding from the declaration is the only
version of it that cannot fall behind (one implementation), and it puts the
log line and MetricsSnapshot::fields — the log and the wire —
on one source of truth rather than two that agree today.
Structured fields and not a rendered string, unchanged from what
it replaced: bytes_out= has to stay greppable in the server’s
stderr, and a JSON subscriber has to still see nineteen typed
numbers rather than one blob.
Source§impl MetricsSnapshot
impl MetricsSnapshot
Sourcepub fn render_prometheus(&self) -> String
pub fn render_prometheus(&self) -> String
This reading in the Prometheus text exposition format.
# TYPE gunnar_bytes_out counter
gunnar_bytes_out 4096
# TYPE gunnar_transfers_in_flight gauge
gunnar_transfers_in_flight 1§Why the names are not suffixed _total
Prometheus convention would call the first one gunnar_bytes_out_total.
It is a convention and not a requirement — # TYPE is what actually
carries the semantics, and this renderer emits it for every series — and
paying it would mean one counter with two names: bytes_out= in the
log and gunnar_bytes_out_total on the wire. The module’s opening
section argues for one vocabulary across the whole server, and an
operator who greps the heartbeat and then greps the endpoint for the
same string is exactly who that section is for. The prefix is worth its
cost because it prevents collision; the suffix buys a lint.
§Why there is no # HELP
Every one of these fields is documented on MetricsSnapshot, and a
HELP line would be a second copy of that prose, in a macro table,
diverging from the first (one implementation). # TYPE is the part a scraper reads.
§Why this is here and not in the listener
It is pure — a &self to a String, no clock, no I/O, no socket — so
the format can be asserted without binding a port, and the listener that
serves it stays a listener. It also means gunnar-core gained no
dependency for the endpoint: the HTTP is somebody else’s problem.
Trait Implementations§
Source§impl Clone for MetricsSnapshot
impl Clone for MetricsSnapshot
Source§fn clone(&self) -> MetricsSnapshot
fn clone(&self) -> MetricsSnapshot
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl Copy for MetricsSnapshot
Source§impl Debug for MetricsSnapshot
impl Debug for MetricsSnapshot
Source§impl Default for MetricsSnapshot
impl Default for MetricsSnapshot
Source§fn default() -> MetricsSnapshot
fn default() -> MetricsSnapshot
impl Eq for MetricsSnapshot
Source§impl PartialEq for MetricsSnapshot
impl PartialEq for MetricsSnapshot
impl StructuralPartialEq for MetricsSnapshot
Auto Trait Implementations§
impl Freeze for MetricsSnapshot
impl RefUnwindSafe for MetricsSnapshot
impl Send for MetricsSnapshot
impl Sync for MetricsSnapshot
impl Unpin for MetricsSnapshot
impl UnsafeUnpin for MetricsSnapshot
impl UnwindSafe for MetricsSnapshot
Blanket Implementations§
impl<T> Allocation for T
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
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
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
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§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.