Trim comments across Rust and webapp source to direct one-liners (ticket 030)

Pass over src/*.rs, webapp/src/**, and the in-app "?" docs prose:
condensed multi-paragraph doc comments to single lines that state the
non-obvious why, deleted comments that only restated adjacent code, and
tightened the Docs.tsx help-panel wording. No logic, structure, or code
formatting changed — verified via cargo test (143 passed) and
tsc -b && vite build.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
This commit is contained in:
Hugh Kaznowski
2026-09-05 17:02:33 +01:00
co-authored by Claude Sonnet 5
parent 3cef6dc8ae
commit 00c21c8032
32 changed files with 347 additions and 1550 deletions
+11 -65
View File
@@ -1,47 +1,5 @@
//! Hand-rolled parser for a small PromQL subset (ticket 013).
//!
//! Design decision: a crates.io PromQL parser (e.g. `promql-parser`) was considered
//! but rejected — the required subset here is tiny (metric name + label matchers,
//! plus an optional `[5m]` range and a single top-level `sum()`/`avg()`/`rate()`
//! wrapper), while a full PromQL parser brings a large, largely-unused AST plus an
//! extra maintenance dependency. Mirroring `filter_parser.rs`'s approach (a small,
//! engine-independent parser module) is simpler and easier to control/extend, and
//! keeps parsing fully decoupled from the engine's index — this module knows nothing
//! about `IndexKey`/`DataValue`, only `PromqlQuery`'s own types below.
//!
//! ## Supported grammar
//!
//! ```text
//! query := aggregation | vector_selector
//! aggregation := agg_op "(" vector_selector ")"
//! agg_op := "sum" | "avg" | "rate" | "histogram" | "gauge"
//! vector_selector := metric_name label_matchers? range_selector?
//! metric_name := [a-zA-Z_][a-zA-Z0-9_]*
//! label_matchers := "{" label_matcher ("," label_matcher)* "}"
//! label_matcher := label_name "=" quoted_string
//! label_name := [a-zA-Z_][a-zA-Z0-9_]*
//! quoted_string := '"' (any char except '"' or '\')* '"'
//! range_selector := "[" digits duration_unit? "]"
//! duration_unit := "s" | "m" | "h" | "d"
//! ```
//!
//! Only exact-match label matchers (`=`) are supported — PromQL's `!=`, `=~`, `!~`
//! are out of scope for this ticket's required subset. `rate()` requires its inner
//! vector selector to carry a range selector with a duration unit (matching real
//! PromQL), and is rejected at parse time otherwise.
//!
//! Ticket 022 (metrics-as-counters rethink) adds two derived forms on top of the
//! same grammar, both consumed as regular `PromqlSeriesDto` series like every
//! other query shape:
//! - `histogram(metric_name[width])`: buckets every matching counter event's
//! (coerced-to-f64) value into fixed-width buckets of size `width` (a bare
//! number, no duration unit — reusing the `[...]` range-selector slot for a
//! different purpose than `rate()`'s duration), and emits one series per
//! bucket, labeled `le` (Prometheus's "less-than-or-equal" convention) with
//! that bucket's upper bound, holding a single `(timestamp_ms, count)` point.
//! - `gauge(metric_name)`: takes no range selector; emits the most-recent
//! matching counter event's value per label combination as a single point,
//! i.e. the counter's series collapsed down to its last value.
//! Hand-rolled parser for a small PromQL subset: metric name + label matchers, an optional `[5m]` range, and a top-level `sum()`/`avg()`/`rate()`/`histogram()`/`gauge()` wrapper.
//! Only exact-match (`=`) label matchers are supported; `rate()` requires a duration range selector, while `histogram(metric[width])` reuses that `[...]` slot for a bare bucket width instead.
use std::time::Duration;
@@ -50,10 +8,9 @@ pub enum AggOp {
Sum,
Avg,
Rate,
/// Ticket 022: buckets counter values into fixed-width buckets. Requires
/// `bucket_width`.
/// Buckets counter values into fixed-width buckets; requires `bucket_width`.
Histogram,
/// Ticket 022: the most-recent counter value per label combination.
/// The most-recent counter value per label combination.
Gauge,
}
@@ -68,23 +25,19 @@ pub struct PromqlQuery {
pub agg: Option<AggOp>,
pub metric_name: String,
pub matchers: Vec<LabelMatcher>,
/// Duration range selector, e.g. `[5m]`. Only meaningful for `rate()`.
/// Duration range selector, e.g. `[5m]`; only meaningful for `rate()`.
pub range: Option<Duration>,
/// Bare-number range selector, e.g. `[10]`. Only meaningful for
/// `histogram()`, where it's the bucket width.
/// Bare-number range selector, e.g. `[10]`; only meaningful for `histogram()`, where it's the bucket width.
pub bucket_width: Option<f64>,
}
/// What a `[...]` range selector turned out to hold, disambiguated by whether
/// a duration unit followed the digits.
/// What a `[...]` range selector turned out to hold: a duration, or a bare width.
enum RangeSelector {
Duration(Duration),
BareWidth(f64),
}
/// Parses a PromQL query string per the grammar documented above. Returns a
/// human-readable error message (suitable for surfacing directly to an API caller)
/// on any malformed input.
/// Parses a PromQL query string, returning a human-readable error message on malformed input.
pub fn parse_query(input: &str) -> Result<PromqlQuery, String> {
let mut parser = Parser::new(input);
let query = parser.parse_query()?;
@@ -143,7 +96,6 @@ impl<'a> Parser<'a> {
}
}
/// `[a-zA-Z_][a-zA-Z0-9_]*`, used for both metric names and label names.
fn parse_identifier(&mut self) -> Result<String, String> {
self.skip_whitespace();
let rest = self.remaining();
@@ -214,9 +166,7 @@ impl<'a> Parser<'a> {
Ok(matchers)
}
/// `[<digits><unit>]` (e.g. `[5m]`, a duration — used by `rate()`) or a
/// bare `[<digits>]` with no unit (a plain number — used by `histogram()`
/// as a bucket width).
/// Parses `[<digits><unit>]` (a duration, e.g. `[5m]`) or a bare `[<digits>]` (a bucket width).
fn parse_range_selector(&mut self) -> Result<Option<RangeSelector>, String> {
self.skip_whitespace();
if self.peek() != Some('[') {
@@ -290,10 +240,7 @@ impl<'a> Parser<'a> {
inner.agg = agg;
Ok(inner)
} else {
// Not (or not followed by) an aggregation call — rewind and parse the
// whole thing as a plain vector selector (covers metric names that
// happen to collide with an agg_op keyword, e.g. a metric named `rate`
// used without a call).
// Rewind and parse as a plain vector selector, covering metric names that collide with an agg_op keyword.
self.pos = checkpoint;
self.parse_vector_selector()
}
@@ -387,8 +334,7 @@ mod tests {
#[test]
fn rejects_unknown_aggregation() {
// `count` isn't a supported agg_op, so this parses as a bare metric named
// `count`, then trips on the unexpected trailing `(...)`.
// `count` isn't a supported agg_op, so this parses as a bare metric name and trips on the trailing `(...)`.
let err = parse_query("count(requests)").unwrap_err();
assert!(err.contains("unexpected trailing input"));
}