From f3ea6ee9d5b8c4ca6b9f2b8b756b2c5cef8acae4 Mon Sep 17 00:00:00 2001 From: clerie Date: Sat, 25 Mar 2023 13:42:58 +0100 Subject: [PATCH] Refactor, add NixStorePath class --- Cargo.lock | 2 +- Cargo.toml | 2 +- flake.nix | 2 +- src/main.rs | 88 ++++++++++++++++++++++++++++++++++------------------- 4 files changed, 59 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f7d435f..5fdc77b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -450,7 +450,7 @@ dependencies = [ [[package]] name = "nixos-exporter" -version = "0.3.0" +version = "0.4.0" dependencies = [ "axum", "reqwest", diff --git a/Cargo.toml b/Cargo.toml index 9dd0125..f8fa6d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nixos-exporter" -version = "0.3.0" +version = "0.4.0" edition = "2021" [dependencies] diff --git a/flake.nix b/flake.nix index 6dd91c1..a8eab61 100644 --- a/flake.nix +++ b/flake.nix @@ -10,7 +10,7 @@ in { nixos-exporter = pkgs.rustPlatform.buildRustPackage rec { pname = "nixos-exporter"; - version = "0.3.0"; + version = "0.4.0"; src = ./.; diff --git a/src/main.rs b/src/main.rs index 6d675e3..e1cae60 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ use axum::{ use std::collections::HashMap; use std::net::SocketAddr; use std::str::FromStr; +use std::path::PathBuf; #[derive(Clone, PartialEq)] enum OperationMode { @@ -58,16 +59,44 @@ impl AppState{ } } -fn parse_nix_store_path(path: std::path::PathBuf) -> Result<(String, String), String> { - let (hash, name) = path.iter().nth(3) - .ok_or_else(|| String::from("Can't read store path name"))? - .to_str() - .ok_or_else(|| String::from("Failed converting store path name to string"))? - .split_once("-") - .ok_or_else(|| String::from("Failed splitting store path name for hash and name"))?; - return Ok((hash.to_string(), name.to_string())); +#[derive(Clone)] +struct NixStorePath { + hash: String, + name: String, } +impl NixStorePath { + pub fn from_str_symlink(path: &str) -> Result { + Ok(Self::from_path_buf_symlink(PathBuf::from(path))?) + } + + pub fn from_path_buf_symlink(path: PathBuf) -> Result { + Ok(Self::from_path_buf(path.read_link().map_err(|err| err.to_string())?)?) + } + + pub fn from_path_buf(path: PathBuf) -> Result { + let store_path_name = path.iter().nth(3) + .ok_or_else(|| String::from("Can't read store path name"))? + .to_str() + .ok_or_else(|| String::from("Failed converting store path name to string"))? + .to_string(); + Ok(Self::from_store_path_name(store_path_name)?) + } + + pub fn from_store_path_name(store_path_name: String) -> Result { + let (hash, name) = store_path_name + .split_once("-") + .ok_or_else(|| String::from("Failed splitting store path name for hash and name"))?; + Ok(Self { + hash: hash.to_string(), + name: name.to_string(), + }) + } + + pub fn to_prometheus_metric(self, infix: String) -> Result { + return Ok(format!("nixos_{}_hash{{hash=\"{}\"}} 1\nnixos_{}_name{{name=\"{}\"}} 1\n", infix, self.hash, infix, self.name)); + } +} #[tokio::main] async fn main() { @@ -143,30 +172,24 @@ async fn main() { .unwrap(); } -fn parse_symlink(path: String) -> Result<(String, String), String> { - let symlink = std::fs::read_link(path).map_err(|err| err.to_string())?; - - let (hash, name) = parse_nix_store_path(symlink)?; - - Ok((String::from(hash), String::from(name))) -} - -fn gen_prometheus_metric(path: String, infix: String) -> Result { - let (hash, name) = parse_symlink(path).map_err(|err| err)?; - - return Ok(format!("nixos_{}_hash{{hash=\"{}\"}} 1\nnixos_{}_name{{name=\"{}\"}} 1\n", infix, hash, infix, name)); -} - async fn metrics() -> Result<(StatusCode, impl IntoResponse), (StatusCode, impl IntoResponse)> { + let nix_store_paths = HashMap::from([ + ("current_system", NixStorePath::from_str_symlink("/run/current-system") + .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err))?), + ("current_system_kernel", NixStorePath::from_str_symlink("/run/current-system/kernel") + .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err))?), + ("booted_system", NixStorePath::from_str_symlink("/run/booted-system") + .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err))?), + ("booted_system_kernel", NixStorePath::from_str_symlink("/run/booted-system/kernel") + .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err))?), + ]); + let mut out = String::new(); - out.push_str(&gen_prometheus_metric(String::from("/run/current-system"), String::from("current_system")) - .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err))?); - out.push_str(&gen_prometheus_metric(String::from("/run/current-system/kernel"), String::from("current_system_kernel")) - .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err))?); - out.push_str(&gen_prometheus_metric(String::from("/run/booted-system"), String::from("booted_system")) - .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err))?); - out.push_str(&gen_prometheus_metric(String::from("/run/booted-system/kernel"), String::from("booted_system_kernel")) - .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err))?); + for (infix, nix_store_path) in nix_store_paths.iter() { + out.push_str(nix_store_path.clone().to_prometheus_metric(infix.to_string()) + .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err))?.as_str()); + } + return Ok(( StatusCode::OK, out, @@ -213,8 +236,9 @@ async fn check(State(app_state): State, Query(params): Query