///|
/// One response header emitted by the framework-neutral metrics adapter.
pub(all) struct Header {
name : String
value : String
}
///|
/// A complete HTTP response ready for a framework-specific adapter to send.
///
/// `content_type` remains as a convenience field for the M0 API. The same
/// value is always present exactly once in `headers` as `Content-Type`.
pub(all) struct MetricsResponse {
status : Int
headers : Array[Header]
content_type : String
body : String
}
///|
fn success_response(content_type : String, body : String) -> MetricsResponse {
{
status: 200,
headers: [
{ name: "Content-Type", value: content_type },
{ name: "Cache-Control", value: "no-cache" },
],
content_type,
body,
}
}
///|
/// Wrap a fully encoded exposition without depending on an HTTP framework.
pub fn metrics_response(
format : @openmetrics.ExpositionFormat,
body : String,
) -> MetricsResponse {
success_response(@openmetrics.content_type(format), body)
}
///|
/// Wrap an encoder result while preserving its format/content-type contract.
pub fn metrics_response_from_exposition(
exposition : @openmetrics.EncodedExposition,
) -> MetricsResponse {
success_response(exposition.content_type, exposition.body)
}
///|
fn error_response(status : Int, body : String) -> MetricsResponse {
{
status,
headers: [
{ name: "Content-Type", value: "text/plain; charset=utf-8" },
{ name: "Cache-Control", value: "no-store" },
],
content_type: "text/plain; charset=utf-8",
body,
}
}
///|
/// Return the stable response used for malformed or oversized Accept headers.
pub fn bad_request_response() -> MetricsResponse {
error_response(400, "invalid Accept header\n")
}
///|
/// Return the stable response used when neither supported format is acceptable.
pub fn not_acceptable_response() -> MetricsResponse {
error_response(406, "no supported metrics format is acceptable\n")
}
///|
/// Return the stable response used after gather or encoding fails.
///
/// The body intentionally does not contain internal collector errors, label
/// values, or a partial exposition.
pub fn internal_error_response() -> MetricsResponse {
error_response(500, "metrics collection failed\n")
}
///|
/// Look up a response header case-insensitively for framework adapter tests.
pub fn MetricsResponse::header(
self : MetricsResponse,
name : String,
) -> String? {
let wanted = name.to_lower()
for header in self.headers {
if header.name.to_lower() == wanted {
return Some(header.value)
}
}
None
}