This commit is contained in:
Mateusz Gruszczyński committed 2026-10-04 11:15:58 +02:00
1 parent 87e571c170
commit fa7abc9e53
308 files changed
+49746 -50237

No files matched your search

+245
View File
@@ -0,0 +1,245 @@
fn render_misc(app: &App, snapshot: &crate::config::Snapshot, f: &mut Families) {
let config = &snapshot.envelope.config;
let settings = &config.prometheus;
if settings.include_streams {
for host in &config.streams {
let protocol = match host.protocol {
crate::stream::Protocol::Tcp => "tcp",
crate::stream::Protocol::Udp => "udp",
};
f.add(
"rust_proxy_stream_enabled",
"gauge",
"Desired Layer-4 stream enable flag.",
&labels(&[("stream", &host.id), ("protocol", protocol)]),
u8::from(host.enabled),
);
}
for host in &app.active_streams {
let Some(metrics) = app.stream_metrics.get(&host.id) else {
continue;
};
let protocol = match host.protocol {
crate::stream::Protocol::Tcp => "tcp",
crate::stream::Protocol::Udp => "udp",
};
let l = labels(&[("stream", &host.id), ("protocol", protocol)]);
let view = metrics.view();
for (name, kind, value) in [
("sessions_total", "counter", view.sessions_total),
(
"sessions_completed_total",
"counter",
view.sessions_completed,
),
("active", "gauge", view.active),
("rejected_total", "counter", view.rejected),
("errors_total", "counter", view.errors),
("bytes_in_total", "counter", view.bytes_in),
("bytes_out_total", "counter", view.bytes_out),
("packets_in_total", "counter", view.packets_in),
("packets_out_total", "counter", view.packets_out),
] {
f.add(
&format!("rust_proxy_stream_{name}"),
kind,
"Layer-4 stream observation; reset on process restart.",
&l,
value,
);
}
f.add(
"rust_proxy_stream_max_connections",
"gauge",
"Configured stream connection/session capacity.",
&l,
host.max_connections,
);
}
}
if settings.include_logging {
let stats = app.logs.stats();
f.add(
"rust_proxy_log_sink_queue_capacity",
"gauge",
"Structured log sink queue capacity.",
"",
stats.queue_capacity,
);
f.add(
"rust_proxy_log_sink_queue_dropped_total",
"counter",
"Structured log entries dropped because the sink queue was full.",
"",
stats.queue_dropped,
);
f.add(
"rust_proxy_log_sink_sent_total",
"counter",
"Structured log entries delivered to configured sinks.",
"",
stats.sent,
);
f.add(
"rust_proxy_log_sink_errors_total",
"counter",
"Structured log sink delivery errors.",
"",
stats.errors,
);
}
if settings.include_cache_domains {
// Bounded resident inspector. Counter families are gauges deliberately:
// these per-domain values reset on config publication, unlike globals.
let dashboard = app.cache.dashboard(None, 0, 1);
f.add(
"rust_proxy_cache_statistics_revision",
"gauge",
"Revision that owns domain statistics.",
"",
dashboard.statistics_revision,
);
for domain in dashboard.domains {
// Only configured names, never arbitrary Host input or unknown scope.
if !config
.vhosts
.iter()
.any(|h| h.id == domain.vhost && h.frontend.hosts.contains(&domain.domain))
{
continue;
}
let l = labels(&[("vhost", &domain.vhost), ("domain", &domain.domain)]);
for (name, n) in [
("objects", domain.entries as u64),
("hot_objects", domain.hot_entries as u64),
("resident_bytes", domain.resident_bytes as u64),
("cold_objects", domain.cold_entries as u64),
("cold_bytes", domain.cold_bytes),
("hits", domain.counters.hits),
("misses", domain.counters.misses),
("bypasses", domain.counters.bypasses),
("stored", domain.counters.stored),
("saved_body_bytes", domain.counters.saved_body_bytes),
] {
f.add(
&format!("rust_proxy_cache_domain_{name}"),
"gauge",
"Domain cache observation since current configuration revision.",
&l,
n,
);
}
f.add(
"rust_proxy_cache_domain_hit_ratio",
"gauge",
"Domain HIT ratio 0..1.",
&l,
domain.hit_ratio,
);
for (reason, count) in domain.counters.reasons {
f.add(
"rust_proxy_cache_domain_decisions",
"gauge",
"Decision reasons since config publication.",
&format!("{l},reason=\"{}\"", escaped(&reason)),
count,
);
}
}
}
}
fn render_histograms(snapshot: &crate::config::Snapshot, docker_targets: &DockerTargets<'_>, out: &mut String) {
let config = &snapshot.envelope.config;
let settings = &config.prometheus;
if settings.include_vhosts {
out.push_str("# HELP rust_proxy_vhost_exchange_duration_seconds Full exchange lifetime including streaming and cancellation.\n# TYPE rust_proxy_vhost_exchange_duration_seconds histogram\n");
for (id, m) in &snapshot.vhost_metrics {
if docker_targets.contains_key(id) {
continue;
}
let l = labels(&[("vhost", id)]);
let _ = writeln!(
out,
"rust_proxy_vhost_exchange_duration_seconds_sum{{{l}}} {:.6}",
m.duration_us.load(Ordering::Relaxed) as f64 / 1e6
);
// Read the cumulative last bucket once for +Inf and count.
let count =
m.buckets[crate::metrics::DURATION_BUCKETS_US.len()].load(Ordering::Relaxed);
let mut previous = 0;
for (i, threshold) in crate::metrics::DURATION_BUCKETS_US.iter().enumerate() {
let value = m.buckets[i]
.load(Ordering::Relaxed)
.max(previous)
.min(count);
previous = value;
let _ = writeln!(
out,
"rust_proxy_vhost_exchange_duration_seconds_bucket{{{l},le=\"{}\"}} {value}",
*threshold as f64 / 1e6
);
}
let _ = writeln!(out, "rust_proxy_vhost_exchange_duration_seconds_bucket{{{l},le=\"+Inf\"}} {count}\nrust_proxy_vhost_exchange_duration_seconds_count{{{l}}} {count}");
}
}
if settings.include_docker_vhosts {
out.push_str("# HELP rust_proxy_docker_vhost_exchange_duration_seconds Full Docker-vhost exchange lifetime including streaming and cancellation.\n# TYPE rust_proxy_docker_vhost_exchange_duration_seconds histogram\n");
for (id, m) in &snapshot.vhost_metrics {
let Some((agent, assignment)) = docker_targets.get(id) else {
continue;
};
let l = labels(&[
("agent", &agent.id),
("vhost", id),
("service", &assignment.service_key),
]);
let _ = writeln!(
out,
"rust_proxy_docker_vhost_exchange_duration_seconds_sum{{{l}}} {:.6}",
m.duration_us.load(Ordering::Relaxed) as f64 / 1e6
);
let count =
m.buckets[crate::metrics::DURATION_BUCKETS_US.len()].load(Ordering::Relaxed);
let mut previous = 0;
for (i, threshold) in crate::metrics::DURATION_BUCKETS_US.iter().enumerate() {
let value = m.buckets[i]
.load(Ordering::Relaxed)
.max(previous)
.min(count);
previous = value;
let _ = writeln!(
out,
"rust_proxy_docker_vhost_exchange_duration_seconds_bucket{{{l},le=\"{}\"}} {value}",
*threshold as f64 / 1e6
);
}
let _ = writeln!(out, "rust_proxy_docker_vhost_exchange_duration_seconds_bucket{{{l},le=\"+Inf\"}} {count}\nrust_proxy_docker_vhost_exchange_duration_seconds_count{{{l}}} {count}");
}
}
}
pub fn render(app: &App) -> String {
let snapshot = app.config.load_full();
let config = &snapshot.envelope.config;
let docker_targets = docker_targets(config);
let mut out = app.metrics.prometheus(
app.logs.dropped.load(Ordering::Relaxed),
snapshot.envelope.revision,
);
out.push_str(&app.cache.prometheus());
if config.prometheus.include_system {
out.push_str(&app.diagnostics.prometheus());
}
let mut families = Families::default();
render_core(app, &snapshot, &mut out, &mut families);
render_vhosts(&snapshot, &mut families);
render_backends(&snapshot, &docker_targets, &mut families);
render_docker(&snapshot, &docker_targets, &mut families);
render_misc(app, &snapshot, &mut families);
families.finish(&mut out);
render_histograms(&snapshot, &docker_targets, &mut out);
out
}