Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c0fe7a9

Browse files
committedMay 18, 2024·
Try adding some diesel metrics
1 parent 6925ef7 commit c0fe7a9

File tree

6 files changed

+175
-11
lines changed

6 files changed

+175
-11
lines changed
 

‎Cargo.lock

Lines changed: 99 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ diesel_migrations = { version = "2.1.0", features = ["sqlite"] }
1515
dotenvy = "0.15.0"
1616
either = "1.9.0"
1717
encoding_rs = "0.8.33"
18+
headers = "0.3.0"
1819
itertools = "0.12.1"
20+
once_cell = "1.19.0"
21+
prometheus = { version = "0.13.4", default-features = false }
1922
reqwest = { version = "0.11.24", features = ["multipart", "json"] }
2023
rocket = { version = "0.5.0", features = ["uuid", "secrets"] }
2124
rocket_oauth2 = "0.5.0"
@@ -41,3 +44,4 @@ walkdir = "2.5.0"
4144

4245
[patch.crates-io]
4346
rocket_prometheus = { git = "https://github.com/Eijebong/rocket_prometheus.git", branch = "add-request-filter" }
47+
diesel = { git = "https://github.com/diesel-rs/diesel.git" }

‎src/db.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
use std::collections::HashMap;
2+
use std::time::Instant;
23

34
use crate::diesel_uuid::Uuid as DieselUuid;
45
use crate::error::Result;
56
use crate::schema::{discord_users, rooms, yamls};
67
use crate::Context;
78

89
use chrono::NaiveDateTime;
10+
use diesel::connection::Instrumentation;
911
use diesel::dsl::{exists, now, AsSelect, SqlTypeOf};
1012
use diesel::prelude::*;
1113
use diesel::sqlite::Sqlite;
14+
use once_cell::sync::Lazy;
15+
use prometheus::{HistogramOpts, HistogramVec};
1216
use rocket::State;
1317
use uuid::Uuid;
1418

@@ -344,3 +348,40 @@ impl RoomFilter {
344348
self
345349
}
346350
}
351+
352+
#[derive(Default)]
353+
pub struct DbInstrumentation {
354+
query_start: Option<Instant>,
355+
}
356+
357+
pub(crate) static QUERY_HISTOGRAM: Lazy<HistogramVec> = Lazy::new(|| {
358+
HistogramVec::new(
359+
HistogramOpts::new("diesel_query_seconds", "SQL query duration").buckets(vec![
360+
0.000005, 0.00001, 0.00005, 0.0001, 0.0005, 0.001, 0.005, 0.01, 0.1, 1.0,
361+
]),
362+
&["query"],
363+
)
364+
.expect("Failed to create query histogram")
365+
});
366+
367+
impl Instrumentation for DbInstrumentation {
368+
fn on_connection_event(&mut self, event: diesel::connection::InstrumentationEvent<'_>) {
369+
match event {
370+
diesel::connection::InstrumentationEvent::StartQuery { .. } => {
371+
self.query_start = Some(Instant::now());
372+
}
373+
diesel::connection::InstrumentationEvent::FinishQuery { query, .. } => {
374+
let Some(query_start) = self.query_start else {
375+
return;
376+
};
377+
let elapsed = Instant::now().duration_since(query_start);
378+
let query = query.to_string().replace('\n', " ");
379+
let query = query.split("--").next().unwrap().trim();
380+
QUERY_HISTOGRAM
381+
.with_label_values(&[query])
382+
.observe(elapsed.as_secs_f64());
383+
}
384+
_ => {}
385+
};
386+
}
387+
}

‎src/diesel_uuid.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use diesel::backend::Backend;
22
use diesel::deserialize::FromSqlRow;
33
use diesel::expression::AsExpression;
4+
use diesel::serialize::ToSql;
45
use diesel::sql_types::{Binary, SqlType};
56
use std::fmt;
67
use std::fmt::{Display, Formatter};
@@ -48,6 +49,6 @@ where
4849
out: &mut diesel::serialize::Output<'b, '_, DB>,
4950
) -> diesel::serialize::Result {
5051
// XXX: This is probably wrong
51-
self.0.as_bytes().to_sql(out)
52+
<[u8; 16] as ToSql<Binary, DB>>::to_sql(self.0.as_bytes(), out)
5253
}
5354
}

‎src/main.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use db::{DbInstrumentation, QUERY_HISTOGRAM};
12
use diesel::r2d2::Pool;
23
use diesel::sqlite::Sqlite;
34
use diesel::{r2d2::ConnectionManager, SqliteConnection};
@@ -116,6 +117,11 @@ fn rocket() -> _ {
116117
let admin_token =
117118
AdminToken(std::env::var("ADMIN_TOKEN").expect("Plox provide a ADMIN_TOKEN env variable"));
118119

120+
diesel::connection::set_default_instrumentation(|| {
121+
Some(Box::new(DbInstrumentation::default()))
122+
})
123+
.expect("Failed to set diesel instrumentation");
124+
119125
let manager = ConnectionManager::<SqliteConnection>::new(db_url);
120126
let db_pool = Pool::new(manager).expect("Failed to create database pool, aborting");
121127
{
@@ -145,6 +151,10 @@ fn rocket() -> _ {
145151
let figment = rocket::Config::figment().merge(("limits", limits));
146152
let prometheus =
147153
PrometheusMetrics::new().with_request_filter(|request| request.uri().path() != "/metrics");
154+
prometheus
155+
.registry()
156+
.register(Box::new(QUERY_HISTOGRAM.clone()))
157+
.expect("Failed to register query histogram");
148158

149159
rocket::custom(figment.clone())
150160
.attach(prometheus.clone())

‎src/views/auth.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::str::FromStr;
33
use crate::error::Result;
44
use crate::{AdminToken, Context, Discord};
55
use anyhow::anyhow;
6+
use headers::authorization::{Basic, Credentials};
67
use reqwest::header::HeaderValue;
78
use reqwest::Url;
89
use rocket::figment::{Figment, Profile, Provider};
@@ -57,8 +58,24 @@ impl LoggedInSession {
5758
impl Session {
5859
pub fn from_request_sync(request: &Request) -> Self {
5960
let admin_token = request.rocket().state::<AdminToken>();
60-
let x_api_key = request.headers().get("X-Api-Key").next();
61-
if x_api_key == admin_token.map(|t| t.0.as_str()) {
61+
let admin_token = admin_token.map(|t| t.0.as_str());
62+
63+
let authorization = request.headers().get_one("Authorization");
64+
if let Some(authorization) = authorization {
65+
let creds = Basic::decode(&HeaderValue::from_str(authorization).unwrap());
66+
if let Some(creds) = creds {
67+
if creds.username() == "admin" && Some(creds.password()) == admin_token {
68+
return Session {
69+
is_admin: true,
70+
is_logged_in: true,
71+
..Default::default()
72+
};
73+
}
74+
}
75+
}
76+
77+
let x_api_key = request.headers().get_one("X-Api-Key");
78+
if x_api_key == admin_token {
6279
return Session {
6380
is_admin: true,
6481
is_logged_in: true,

0 commit comments

Comments
 (0)
Please sign in to comment.