Skip to main content

MetricsSnapshot

Struct MetricsSnapshot 

Source
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: u64

TCP connections russh handed to gunnar.

§connections_accepted: u64

Connections whose offered key named a principal.

§connections_anonymous: u64

Connections 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: u64

Connections whose offered key named nobody. Not the same as MetricsSnapshot::auth_faults.

§auth_faults: u64

Connections 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: u64

Exec requests refused or denied after authentication: a non-git command, an unknown repository, a missing grant.

§transfers_started: u64

Transfers admitted and begun.

§transfers_in_flight: u64

Transfers running right now. A gauge, not a total.

§transfers_failed: u64

Transfers that ended with a protocol or storage error.

§packs_served: u64

upload-pack sessions that sent a packfile.

§objects_sent: u64

Objects written into those packs.

§bytes_out: u64

Bytes gunnar wrote to git clients, counted at the wire.

§bytes_in: u64

Bytes gunnar read from git clients, counted at the wire.

§pushes_accepted: u64

Pushes in which every reference landed.

§pushes_rejected: u64

Pushes in which at least one reference was refused.

§refs_updated: u64

References moved.

§refs_deleted: u64

References deleted.

§refs_rejected: u64

Reference updates refused, for any reason.

§gate_refusals: u64

Reference 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: u64

Ticks 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

Source

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.

Source

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

Source

pub fn is_zero(&self) -> bool

Has anything at all been served? Used by the heartbeat to stay quiet on an idle server without going quiet on a busy one.

Source§

impl MetricsSnapshot

Source

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

Source§

fn clone(&self) -> MetricsSnapshot

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for MetricsSnapshot

Source§

impl Debug for MetricsSnapshot

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Default for MetricsSnapshot

Source§

fn default() -> MetricsSnapshot

Returns the “default value” for a type. Read more
Source§

impl Eq for MetricsSnapshot

Source§

impl PartialEq for MetricsSnapshot

Source§

fn eq(&self, other: &MetricsSnapshot) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for MetricsSnapshot

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Allocation for T
where T: RefUnwindSafe + Send + Sync,

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more