From 6e435bfc2e4c95b52ef5c6047056bc48895559d1 Mon Sep 17 00:00:00 2001 From: jude Date: Sun, 29 Oct 2023 18:00:45 +0000 Subject: [PATCH] Add metrics Change dashboards to load an index.html file compiled otherwise --- .gitignore | 2 ++ Cargo.lock | 30 +++++++++++++++++++++ web/Cargo.toml | 1 + web/src/lib.rs | 16 +++++++++--- web/src/metrics.rs | 43 +++++++++++++++++++++++++++++++ web/src/routes/dashboard/guild.rs | 1 - web/src/routes/dashboard/mod.rs | 30 +++++++++++++-------- web/src/routes/metrics.rs | 18 +++++++++++++ web/src/routes/mod.rs | 1 + web/static/css/style.css | 4 +++ 10 files changed, 130 insertions(+), 16 deletions(-) create mode 100644 web/src/metrics.rs delete mode 100644 web/src/routes/dashboard/guild.rs create mode 100644 web/src/routes/metrics.rs diff --git a/.gitignore b/.gitignore index 1b9cd34..7c89042 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ /venv .cargo /.idea +web/static/index.html +web/static/assets diff --git a/Cargo.lock b/Cargo.lock index c617b30..00d0846 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2051,6 +2051,27 @@ dependencies = [ "yansi", ] +[[package]] +name = "prometheus" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c" +dependencies = [ + "cfg-if", + "fnv", + "lazy_static", + "memchr", + "parking_lot", + "protobuf", + "thiserror", +] + +[[package]] +name = "protobuf" +version = "2.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" + [[package]] name = "quote" version = "1.0.33" @@ -2174,7 +2195,11 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reminder-rs" +<<<<<<< HEAD version = "1.6.50" +======= +version = "1.6.48" +>>>>>>> 97f186d (Add metrics) dependencies = [ "base64 0.21.5", "chrono", @@ -2202,7 +2227,11 @@ dependencies = [ [[package]] name = "reminder_web" +<<<<<<< HEAD version = "0.1.4" +======= +version = "0.1.3" +>>>>>>> 97f186d (Add metrics) dependencies = [ "base64 0.13.1", "chrono", @@ -2211,6 +2240,7 @@ dependencies = [ "lazy_static", "log", "oauth2", + "prometheus", "rand", "reqwest", "rocket", diff --git a/web/Cargo.toml b/web/Cargo.toml index a274d4b..e10e8ef 100644 --- a/web/Cargo.toml +++ b/web/Cargo.toml @@ -19,3 +19,4 @@ lazy_static = "1.4.0" rand = "0.8" base64 = "0.13" csv = "1.2" +prometheus = "0.13.3" diff --git a/web/src/lib.rs b/web/src/lib.rs index 7e02265..b340464 100644 --- a/web/src/lib.rs +++ b/web/src/lib.rs @@ -6,6 +6,7 @@ mod consts; mod macros; mod catchers; mod guards; +mod metrics; mod routes; use std::{env, path::Path}; @@ -25,7 +26,10 @@ use serenity::{ }; use sqlx::{MySql, Pool}; -use crate::consts::{CNC_GUILD, DISCORD_OAUTH_AUTHORIZE, DISCORD_OAUTH_TOKEN, SUBSCRIPTION_ROLES}; +use crate::{ + consts::{CNC_GUILD, DISCORD_OAUTH_AUTHORIZE, DISCORD_OAUTH_TOKEN, SUBSCRIPTION_ROLES}, + metrics::{init_metrics, MetricProducer}, +}; type Database = MySql; @@ -64,7 +68,10 @@ pub async fn initialize( let static_path = if Path::new("web/static").exists() { "web/static" } else { "/lib/reminder-rs/static" }; + init_metrics(); + rocket::build() + .attach(MetricProducer) .attach(Template::fairing()) .register( "/", @@ -85,12 +92,13 @@ pub async fn initialize( .mount( "/", routes![ - routes::index, routes::cookies, + routes::index, + routes::metrics::metrics, routes::privacy, - routes::terms, - routes::return_to_same_site, routes::report::report_error, + routes::return_to_same_site, + routes::terms, ], ) .mount( diff --git a/web/src/metrics.rs b/web/src/metrics.rs new file mode 100644 index 0000000..13754ae --- /dev/null +++ b/web/src/metrics.rs @@ -0,0 +1,43 @@ +use lazy_static::lazy_static; +use prometheus::{IntCounterVec, Opts, Registry}; +use rocket::{ + fairing::{Fairing, Info, Kind}, + Data, Request, Response, +}; + +lazy_static! { + pub static ref REGISTRY: Registry = Registry::new(); + static ref REQUEST_COUNTER: IntCounterVec = + IntCounterVec::new(Opts::new("requests", "Requests"), &["method", "route"]).unwrap(); + static ref RESPONSE_COUNTER: IntCounterVec = + IntCounterVec::new(Opts::new("responses", "Responses"), &["status", "route"]).unwrap(); +} + +pub fn init_metrics() { + REGISTRY.register(Box::new(REQUEST_COUNTER.clone())).unwrap(); +} + +pub struct MetricProducer; + +#[rocket::async_trait] +impl Fairing for MetricProducer { + fn info(&self) -> Info { + Info { name: "Metrics fairing", kind: Kind::Request } + } + + async fn on_request(&self, req: &mut Request<'_>, _data: &mut Data<'_>) { + if let Some(route) = req.route() { + REQUEST_COUNTER + .with_label_values(&[req.method().as_str(), &route.uri.to_string()]) + .inc(); + } + } + + async fn on_response<'r>(&self, req: &'r Request<'_>, resp: &mut Response<'r>) { + if let Some(route) = req.route() { + RESPONSE_COUNTER + .with_label_values(&[&resp.status().code.to_string(), &route.uri.to_string()]) + .inc(); + } + } +} diff --git a/web/src/routes/dashboard/guild.rs b/web/src/routes/dashboard/guild.rs deleted file mode 100644 index 8b13789..0000000 --- a/web/src/routes/dashboard/guild.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/web/src/routes/dashboard/mod.rs b/web/src/routes/dashboard/mod.rs index 06bd35d..2a51e01 100644 --- a/web/src/routes/dashboard/mod.rs +++ b/web/src/routes/dashboard/mod.rs @@ -1,8 +1,13 @@ -use std::collections::HashMap; +use std::path::Path; use chrono::{naive::NaiveDateTime, Utc}; use rand::{rngs::OsRng, seq::IteratorRandom}; -use rocket::{http::CookieJar, response::Redirect, serde::json::json}; +use rocket::{ + fs::{relative, NamedFile}, + http::CookieJar, + response::Redirect, + serde::json::json, +}; use rocket_dyn_templates::Template; use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use serenity::{ @@ -27,7 +32,6 @@ use crate::{ pub mod api; pub mod export; -pub mod guild; type Unset = Option; @@ -655,22 +659,26 @@ async fn create_database_channel( } #[get("/")] -pub async fn dashboard_home(cookies: &CookieJar<'_>) -> Result { +pub async fn dashboard_home(cookies: &CookieJar<'_>) -> Result { if cookies.get_private("userid").is_some() { - let mut map = HashMap::new(); - map.insert("version", env!("CARGO_PKG_VERSION")); - Ok(Template::render("dashboard", &map)) + NamedFile::open(Path::new(relative!("static/index.html"))).await.map_err(|e| { + warn!("Couldn't render dashboard: {:?}", e); + + Redirect::to("/login/discord") + }) } else { Err(Redirect::to("/login/discord")) } } #[get("/<_..>")] -pub async fn dashboard(cookies: &CookieJar<'_>) -> Result { +pub async fn dashboard(cookies: &CookieJar<'_>) -> Result { if cookies.get_private("userid").is_some() { - let mut map = HashMap::new(); - map.insert("version", env!("CARGO_PKG_VERSION")); - Ok(Template::render("dashboard", &map)) + NamedFile::open(Path::new(relative!("static/index.html"))).await.map_err(|e| { + warn!("Couldn't render dashboard: {:?}", e); + + Redirect::to("/login/discord") + }) } else { Err(Redirect::to("/login/discord")) } diff --git a/web/src/routes/metrics.rs b/web/src/routes/metrics.rs new file mode 100644 index 0000000..0421264 --- /dev/null +++ b/web/src/routes/metrics.rs @@ -0,0 +1,18 @@ +use prometheus; + +use crate::metrics::REGISTRY; + +#[get("/metrics")] +pub async fn metrics() -> String { + let encoder = prometheus::TextEncoder::new(); + let res_custom = encoder.encode_to_string(®ISTRY.gather()); + + match res_custom { + Ok(s) => s, + Err(e) => { + warn!("Error encoding metrics: {:?}", e); + + String::new() + } + } +} diff --git a/web/src/routes/mod.rs b/web/src/routes/mod.rs index b9c871e..568f5f3 100644 --- a/web/src/routes/mod.rs +++ b/web/src/routes/mod.rs @@ -1,6 +1,7 @@ pub mod admin; pub mod dashboard; pub mod login; +pub mod metrics; pub mod report; use std::collections::HashMap; diff --git a/web/static/css/style.css b/web/static/css/style.css index 4fffab7..deb519d 100644 --- a/web/static/css/style.css +++ b/web/static/css/style.css @@ -633,6 +633,10 @@ li.highlight { display: flex; } +.button-row-edit > button { + margin-right: 4px; +} + .button-row .button-row-reminder { flex-grow: 0; padding: 2px;