Skip to content

Commit a4d87d2

Browse files
committed
guest-agent: Add prometheus metrics API
1 parent 5ee967f commit a4d87d2

File tree

3 files changed

+113
-1
lines changed

3 files changed

+113
-1
lines changed

guest-agent/src/http_routes.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rocket::{get, response::content::RawHtml, routes, Route, State};
1616
pub fn external_routes(config: &Config) -> Vec<Route> {
1717
let mut routes = routes![index];
1818
if config.public_logs {
19-
routes.extend(routes![get_logs]);
19+
routes.extend(routes![get_logs, metrics]);
2020
}
2121
routes
2222
}
@@ -69,6 +69,25 @@ async fn index(state: &State<AppState>) -> Result<RawHtml<String>, String> {
6969
}
7070
}
7171

72+
// Returns metrics about the guest in prometheus format if public_sysinfo is enabled
73+
#[get("/metrics")]
74+
async fn metrics(state: &State<AppState>) -> Result<String, String> {
75+
let public_sysinfo = state.config().public_sysinfo;
76+
if !public_sysinfo {
77+
return Err("Sysinfo API is disabled".to_string());
78+
}
79+
let context = CallContext::builder().state(&**state).build();
80+
let handler = GuestApiHandler::construct(context.clone())
81+
.map_err(|e| format!("Failed to construct RPC handler: {}", e))?;
82+
83+
let system_info = handler.sys_info().await.unwrap_or_default();
84+
let model = crate::models::Metrics { system_info };
85+
match model.render() {
86+
Ok(body) => Ok(body),
87+
Err(err) => Err(format!("Failed to render template: {err}")),
88+
}
89+
}
90+
7291
#[get("/logs/<container_name>?<since>&<until>&<follow>&<text>&<timestamps>&<bare>&<tail>&<ansi>")]
7392
#[allow(clippy::too_many_arguments)]
7493
fn get_logs(

guest-agent/src/models.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,9 @@ pub struct Dashboard {
4444
pub public_sysinfo: bool,
4545
pub public_logs: bool,
4646
}
47+
48+
#[derive(Template)]
49+
#[template(path = "metrics.tpl", escape = "none")]
50+
pub struct Metrics {
51+
pub system_info: SystemInfo,
52+
}

guest-agent/templates/metrics.tpl

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# HELP system_os_name Operating system name
2+
# TYPE system_os_name gauge
3+
system_os_name{os_name="{{system_info.os_name}}"} 1
4+
5+
# HELP system_os_version Operating system version
6+
# TYPE system_os_version gauge
7+
system_os_version{os_version="{{system_info.os_version}}"} 1
8+
9+
# HELP system_kernel_version Kernel version
10+
# TYPE system_kernel_version gauge
11+
system_kernel_version{kernel_version="{{system_info.kernel_version}}"} 1
12+
13+
# HELP system_cpu_model CPU model information
14+
# TYPE system_cpu_model gauge
15+
system_cpu_model{cpu_model="{{system_info.cpu_model}}"} 1
16+
17+
# HELP system_num_cpus Number of logical CPUs
18+
# TYPE system_num_cpus gauge
19+
system_num_cpus {{system_info.num_cpus}}
20+
21+
# HELP system_memory_total Total memory in bytes
22+
# TYPE system_memory_total gauge
23+
system_memory_total {{system_info.total_memory}}
24+
25+
# HELP system_memory_available Available memory in bytes
26+
# TYPE system_memory_available gauge
27+
system_memory_available {{system_info.available_memory}}
28+
29+
# HELP system_memory_used Used memory in bytes
30+
# TYPE system_memory_used gauge
31+
system_memory_used {{system_info.used_memory}}
32+
33+
# HELP system_memory_free Free memory in bytes
34+
# TYPE system_memory_free gauge
35+
system_memory_free {{system_info.free_memory}}
36+
37+
# HELP system_swap_total Total swap memory in bytes
38+
# TYPE system_swap_total gauge
39+
system_swap_total {{system_info.total_swap}}
40+
41+
# HELP system_swap_used Used swap memory in bytes
42+
# TYPE system_swap_used gauge
43+
system_swap_used {{system_info.used_swap}}
44+
45+
# HELP system_swap_free Free swap memory in bytes
46+
# TYPE system_swap_free gauge
47+
system_swap_free {{system_info.free_swap}}
48+
49+
# HELP system_uptime System uptime in seconds
50+
# TYPE system_uptime gauge
51+
system_uptime {{system_info.uptime}}
52+
53+
# HELP system_load_average_1m System load average (1 minute)
54+
# TYPE system_load_average_1m gauge
55+
system_load_average_1m {{system_info.loadavg_one}}
56+
57+
# HELP system_load_average_5m System load average (5 minutes)
58+
# TYPE system_load_average_5m gauge
59+
system_load_average_5m {{system_info.loadavg_five}}
60+
61+
# HELP system_load_average_15m System load average (15 minutes)
62+
# TYPE system_load_average_15m gauge
63+
system_load_average_15m {{system_info.loadavg_fifteen}}
64+
65+
# HELP disk_total_size Disk total size in bytes
66+
# TYPE disk_total_size gauge
67+
{% for disk in system_info.disks %}
68+
disk_total_size{name="{{disk.name}}", mount_point="{{disk.mount_point}}"} {{disk.total_size}}
69+
{% endfor %}
70+
71+
# HELP disk_free_size Disk free size in bytes
72+
# TYPE disk_free_size gauge
73+
{% for disk in system_info.disks %}
74+
disk_free_size{name="{{disk.name}}", mount_point="{{disk.mount_point}}"} {{disk.free_size}}
75+
{% endfor %}
76+
77+
# HELP disk_used_size Disk used size in bytes
78+
# TYPE disk_used_size gauge
79+
{% for disk in system_info.disks %}
80+
disk_used_size{name="{{disk.name}}", mount_point="{{disk.mount_point}}"} {{disk.total_size - disk.free_size}}
81+
{% endfor %}
82+
83+
# HELP disk_usage_percentage Disk usage percentage
84+
# TYPE disk_usage_percentage gauge
85+
{% for disk in system_info.disks %}
86+
disk_usage_percentage{name="{{disk.name}}", mount_point="{{disk.mount_point}}"} {% if disk.total_size > 0 %}{{(disk.total_size - disk.free_size) as f64 / disk.total_size as f64 * 100.0}}{% else %}0{% endif %}
87+
{% endfor %}

0 commit comments

Comments
 (0)