pub struct RecentRequest {Show 15 fields
pub request_id: String,
pub at_ms: u64,
pub route: String,
pub model: Option<String>,
pub status: u16,
pub prompt_tokens: usize,
pub completion_tokens: usize,
pub ttft_ms: Option<f64>,
pub duration_ms: u64,
pub decode_ms: Option<f64>,
pub stream: bool,
pub acceptance_length: Option<f64>,
pub draft_accept_rate_per_position: Option<Vec<f64>>,
pub via_api_key: Option<String>,
pub client: Option<String>,
}Expand description
One finished request, as recorded in the ring buffer.
duration_ms and decode_ms are separate on purpose and must stay
that way: duration_ms carries queue wait plus prefill plus decode,
so dividing completion tokens by it reports a 50 tok/s model as 5
whenever the prompt is long. Everything downstream of that number is
then wrong in the same direction.
Fields§
§request_id: StringThe same id the response carried, so a UI can join a log line to the message it produced without a claiming heuristic.
at_ms: u64Unix epoch milliseconds when the request finished.
route: String§model: Option<String>The model that served this request, as /v1/models names it.
Not the model field the client sent. ferrox serves whatever is
loaded and ignores that string, so echoing it back would make
the log agree with the caller’s belief rather than with what
happened – and after a model swap those are different answers.
null when nothing was loaded, which is what a 503 row means.
status: u16§prompt_tokens: usize§completion_tokens: usize§ttft_ms: Option<f64>§duration_ms: u64Total server-side wall time for the request.
decode_ms: Option<f64>Time inside the decode loop only. null when the engine did not
time itself, or the answer came from cache.
stream: bool§acceptance_length: Option<f64>Completion tokens per verification step when this request used
speculative decoding; null when it did not. See
crate::Usage::acceptance_length.
draft_accept_rate_per_position: Option<Vec<f64>>Accept rate at each position within the draft block. Kept in the ring rather than only in the response body because suffix decay is a property of the drafter over time, and a single request’s numbers are too few to read it off.
via_api_key: Option<String>Which bearer key served this request, as a short fingerprint – never the key itself, and never reversible into it.
null means the request carried no Authorization: Bearer
header at all, which on a server started without
FERROX_API_KEY is every request. Two rows with the same
fingerprint were authenticated with the same key; two rows with
different fingerprints were not. That is the whole of what this
field claims.
The fingerprint is salted per process, so it is stable within
one server run and deliberately meaningless across restarts: a
captured /admin/stats payload cannot be used offline to test
guesses at the key.
client: Option<String>The caller’s self-declared label, from the X-Ferrox-Client
request header, truncated and stripped of anything that is not a
plain label character.
A claim, not proof. Ferrox Studio sends ferrox-studio, and
so could any other client; nothing here authenticates it. It is
recorded because a self-declared label plus a key fingerprint is
still the difference between “an editor is hammering this
server” and “that was me in the other tab”, and because
inventing the distinction from timing would be worse. A UI that
shows it must say it is self-declared.
Trait Implementations§
Source§impl Clone for RecentRequest
impl Clone for RecentRequest
Source§fn clone(&self) -> RecentRequest
fn clone(&self) -> RecentRequest
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more