13 / EDGE
metrics
Two Prometheus families over the process registry: a duration histogram and a code counter, labelled path, method and code — three labels, so a dashboard can select on any one of them.
WHERE IT SITS
INTERFACE
let default_latency_buckets : Array[Double] = [letThe latency buckets registers for a server route, in milliseconds.
let exposition_content_type : String = "text/plain; version=0.0.4; charset=utf-8"letThe content type a /metrics scrape carries so a Prometheus server reads the body as the text exposition format.
struct ServerMetricsstructThe request metrics an HTTP service exposes: http_server_requests_duration_ms and http_server_requests_code_total, each partitioned by path, method and code. Held by the caller so it can be scraped after serving, and shared with RestEngine so the prometheus layer and the /metrics route read one set.
fn ServerMetrics::new() -> ServerMetrics raise @metric.RefusedfnA fresh metric set on its own registry — the two families ready, nothing observed yet. Raises Refused only if a metric or label name is invalid, which cannot happen for the fixed names here.
fn ServerMetrics::registry(self : ServerMetrics) -> @moonp8s.RegistryfnThe registry the families hang off, so a caller can add collectors of its own and publish everything through one scrape.
fn ServerMetrics::requests( self : ServerMetrics) -> @moonp8s.Family[@moonp8s.Counter]fnThe request counter family, labelled path, method, code.
fn ServerMetrics::latency( self : ServerMetrics) -> @moonp8s.Family[@moonp8s.Histogram]fnThe request-duration family, in milliseconds, labelled path, method, code.
fn ServerMetrics::observe( self : ServerMetrics, path : String, verb : String, code : Int32, duration_ms : Double) -> UnitfnRecord one finished request: count it under its path/method/code and observe duration_ms. A label set whose arity does not match the registered names is dropped rather than raised — both families always carry three labels, so this is unreachable from observe_request.
fn ServerMetrics::request_count( self : ServerMetrics, path : String, verb : String, code : Int32) -> DoublefnThe counter value recorded for one route and status, 0 before the first request. A read-out for tests and for a health endpoint that reports its own traffic without scraping.
fn ServerMetrics::latency_total( self : ServerMetrics, path : String, verb : String, code : Int32) -> Int64fnThe latency observations recorded for one route and status.
fn ServerMetrics::to_exposition(self : ServerMetrics) -> StringfnRender this set as the Prometheus text exposition format — the body metrics_handler serves.
fn metrics_handler(m : ServerMetrics) -> @moonapi.ApiHandlerfnA handler that serves the current metric set in the text exposition format, with the Prometheus content type.
fn mount_metrics(app : @moonapi.App, m : ServerMetrics) -> UnitfnRegister the GET /metrics scrape endpoint on app, so a Prometheus server can pull the exposition.
fn metrics(m : ServerMetrics, clock : @clock.Clock) -> MiddlewarefnMetrics middleware: time each HTTP request on the shared clock and, when the response starts, count it under its path, method and status and record its latency in milliseconds. The record is taken once per request even if a downstream emits a second start. Non-HTTP scopes pass through unmeasured.