mirror of
https://git.madhouse-project.org/algernon/iocaine.git
synced 2025-02-23 18:08:47 +01:00
Lift out the metrics into its own module
Signed-off-by: Gergely Nagy <me@gergo.csillger.hu>
This commit is contained in:
parent
6fa438ebcb
commit
7c6ac855d8
3 changed files with 89 additions and 100 deletions
109
src/app.rs
109
src/app.rs
|
@ -5,24 +5,20 @@
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use axum::{
|
use axum::{
|
||||||
extract::{Path, Request, State},
|
extract::{Path, State},
|
||||||
middleware::{self, Next},
|
middleware,
|
||||||
response::{Html, IntoResponse},
|
response::Html,
|
||||||
routing::get,
|
routing::get,
|
||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use metrics_exporter_prometheus::{PrometheusBuilder, PrometheusHandle};
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
assembled_statistical_sequences::AssembledStatisticalSequences,
|
assembled_statistical_sequences::AssembledStatisticalSequences, config::Config,
|
||||||
config::{Config, MetricsLabel},
|
garglebargle::GargleBargle, tenx_programmer, wurstsalat_generator_pro::WurstsalatGeneratorPro,
|
||||||
garglebargle::GargleBargle,
|
|
||||||
wurstsalat_generator_pro::WurstsalatGeneratorPro,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type StatefulIocaine = Arc<Iocaine>;
|
pub type StatefulIocaine = Arc<Iocaine>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Iocaine {
|
pub struct Iocaine {
|
||||||
|
@ -60,85 +56,13 @@ impl Iocaine {
|
||||||
if state.config.metrics.enable {
|
if state.config.metrics.enable {
|
||||||
app = app.route_layer(middleware::from_fn_with_state(
|
app = app.route_layer(middleware::from_fn_with_state(
|
||||||
state.clone(),
|
state.clone(),
|
||||||
Self::track_metrics,
|
tenx_programmer::track_metrics,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
app.with_state(state)
|
app.with_state(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn metrics_app() -> Router {
|
|
||||||
let recorder_handle = Self::setup_metrics_recorder();
|
|
||||||
Router::new().route("/metrics", get(|| async move { recorder_handle.render() }))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn track_metrics(
|
|
||||||
State(iocaine): State<StatefulIocaine>,
|
|
||||||
req: Request,
|
|
||||||
next: Next,
|
|
||||||
) -> impl IntoResponse {
|
|
||||||
let headers = req.headers().clone();
|
|
||||||
let response = next.run(req).await;
|
|
||||||
|
|
||||||
let mut labels = Vec::new();
|
|
||||||
if iocaine.config.metrics.labels.contains(&MetricsLabel::Host) {
|
|
||||||
if let Some(host) = headers.get("host") {
|
|
||||||
let host = host.to_str().unwrap().to_string();
|
|
||||||
labels.push(("host", host));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if iocaine
|
|
||||||
.config
|
|
||||||
.metrics
|
|
||||||
.labels
|
|
||||||
.contains(&MetricsLabel::UserAgent)
|
|
||||||
|| iocaine
|
|
||||||
.config
|
|
||||||
.metrics
|
|
||||||
.labels
|
|
||||||
.contains(&MetricsLabel::UserAgentGroup)
|
|
||||||
{
|
|
||||||
if let Some(ua) = headers.get("user-agent") {
|
|
||||||
let user_agent = ua.to_str().unwrap().to_string();
|
|
||||||
|
|
||||||
if iocaine
|
|
||||||
.config
|
|
||||||
.metrics
|
|
||||||
.labels
|
|
||||||
.contains(&MetricsLabel::UserAgent)
|
|
||||||
{
|
|
||||||
labels.push(("user-agent", user_agent.clone()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if iocaine
|
|
||||||
.config
|
|
||||||
.metrics
|
|
||||||
.labels
|
|
||||||
.contains(&MetricsLabel::UserAgentGroup)
|
|
||||||
{
|
|
||||||
if let Some(group) = iocaine
|
|
||||||
.config
|
|
||||||
.metrics
|
|
||||||
.agent_group
|
|
||||||
.iter()
|
|
||||||
.find(|agent_group_config| agent_group_config.agent.is_match(&user_agent))
|
|
||||||
{
|
|
||||||
labels.push(("user-agent-group", group.group.clone()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
metrics::counter!("iocaine_requests_total", &labels).increment(1);
|
|
||||||
|
|
||||||
response
|
|
||||||
}
|
|
||||||
|
|
||||||
fn setup_metrics_recorder() -> PrometheusHandle {
|
|
||||||
PrometheusBuilder::new().install_recorder().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn start_main_server(self) -> std::result::Result<(), std::io::Error> {
|
async fn start_main_server(self) -> std::result::Result<(), std::io::Error> {
|
||||||
let bind = &self.config.server.bind.clone();
|
let bind = &self.config.server.bind.clone();
|
||||||
|
|
||||||
|
@ -149,25 +73,10 @@ impl Iocaine {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn start_metrics_server(metrics_bind: String) -> std::result::Result<(), std::io::Error> {
|
|
||||||
let metrics_listener = tokio::net::TcpListener::bind(metrics_bind).await?;
|
|
||||||
let app = Self::metrics_app().await;
|
|
||||||
|
|
||||||
let ts = SystemTime::now()
|
|
||||||
.duration_since(UNIX_EPOCH)
|
|
||||||
.expect("Time went backwards");
|
|
||||||
let labels = [("service", "iocaine".to_string())];
|
|
||||||
metrics::gauge!("process_start_time_seconds", &labels).set(ts);
|
|
||||||
|
|
||||||
axum::serve(metrics_listener, app)
|
|
||||||
.with_graceful_shutdown(shutdown_signal())
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn run(self) -> Result<()> {
|
pub async fn run(self) -> Result<()> {
|
||||||
if self.config.metrics.enable {
|
if self.config.metrics.enable {
|
||||||
let metrics_bind = &self.config.metrics.bind.clone();
|
let metrics_bind = &self.config.metrics.bind.clone();
|
||||||
let metrics_server = Self::start_metrics_server(metrics_bind.to_string());
|
let metrics_server = tenx_programmer::start_metrics_server(metrics_bind.to_string());
|
||||||
let (main_server, _metrics_server) =
|
let (main_server, _metrics_server) =
|
||||||
tokio::join!(self.start_main_server(), metrics_server);
|
tokio::join!(self.start_main_server(), metrics_server);
|
||||||
Ok(main_server?)
|
Ok(main_server?)
|
||||||
|
@ -178,7 +87,7 @@ impl Iocaine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn shutdown_signal() {
|
pub async fn shutdown_signal() {
|
||||||
let ctrl_c = async {
|
let ctrl_c = async {
|
||||||
tokio::signal::ctrl_c()
|
tokio::signal::ctrl_c()
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -10,4 +10,5 @@ pub mod config;
|
||||||
pub mod assembled_statistical_sequences;
|
pub mod assembled_statistical_sequences;
|
||||||
pub mod garglebargle;
|
pub mod garglebargle;
|
||||||
pub mod gobbledygook;
|
pub mod gobbledygook;
|
||||||
|
pub mod tenx_programmer;
|
||||||
pub mod wurstsalat_generator_pro;
|
pub mod wurstsalat_generator_pro;
|
||||||
|
|
79
src/tenx_programmer.rs
Normal file
79
src/tenx_programmer.rs
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
// SPDX-FileCopyrightText: 2025 Gergely Nagy
|
||||||
|
// SPDX-FileContributor: Gergely Nagy
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
extract::{Request, State},
|
||||||
|
middleware::Next,
|
||||||
|
response::IntoResponse,
|
||||||
|
routing::get,
|
||||||
|
Router,
|
||||||
|
};
|
||||||
|
use metrics_exporter_prometheus::PrometheusBuilder;
|
||||||
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
app::{shutdown_signal, StatefulIocaine},
|
||||||
|
config::MetricsLabel,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub async fn track_metrics(
|
||||||
|
State(iocaine): State<StatefulIocaine>,
|
||||||
|
req: Request,
|
||||||
|
next: Next,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
let headers = req.headers().clone();
|
||||||
|
let response = next.run(req).await;
|
||||||
|
let cfg = &iocaine.config.metrics;
|
||||||
|
|
||||||
|
let mut labels = Vec::new();
|
||||||
|
if cfg.labels.contains(&MetricsLabel::Host) {
|
||||||
|
if let Some(host) = headers.get("host") {
|
||||||
|
let host = host.to_str().unwrap().to_string();
|
||||||
|
labels.push(("host", host));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.labels.contains(&MetricsLabel::UserAgent)
|
||||||
|
|| cfg.labels.contains(&MetricsLabel::UserAgentGroup)
|
||||||
|
{
|
||||||
|
if let Some(ua) = headers.get("user-agent") {
|
||||||
|
let user_agent = ua.to_str().unwrap().to_string();
|
||||||
|
|
||||||
|
if cfg.labels.contains(&MetricsLabel::UserAgent) {
|
||||||
|
labels.push(("user-agent", user_agent.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.labels.contains(&MetricsLabel::UserAgentGroup) {
|
||||||
|
if let Some(group) = cfg
|
||||||
|
.agent_group
|
||||||
|
.iter()
|
||||||
|
.find(|agent_group_config| agent_group_config.agent.is_match(&user_agent))
|
||||||
|
{
|
||||||
|
labels.push(("user-agent-group", group.group.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
metrics::counter!("iocaine_requests_total", &labels).increment(1);
|
||||||
|
|
||||||
|
response
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn start_metrics_server(metrics_bind: String) -> std::result::Result<(), std::io::Error> {
|
||||||
|
let metrics_listener = tokio::net::TcpListener::bind(metrics_bind).await?;
|
||||||
|
let recorder_handle = PrometheusBuilder::new().install_recorder().unwrap();
|
||||||
|
let app = Router::new().route("/metrics", get(|| async move { recorder_handle.render() }));
|
||||||
|
|
||||||
|
let ts = SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.expect("Time went backwards");
|
||||||
|
let labels = [("service", "iocaine".to_string())];
|
||||||
|
metrics::gauge!("process_start_time_seconds", &labels).set(ts);
|
||||||
|
|
||||||
|
axum::serve(metrics_listener, app)
|
||||||
|
.with_graceful_shutdown(shutdown_signal())
|
||||||
|
.await
|
||||||
|
}
|
Loading…
Reference in a new issue