feat: add logging

This commit is contained in:
Max Hohlfeld 2025-04-23 10:23:56 +02:00
parent 60c7d16392
commit 8849d46fd3
8 changed files with 253 additions and 10 deletions

1
.env
View File

@ -14,3 +14,4 @@ SMTP_PORT="1025"
# SMTP_LOGIN=""
# SMTP_PASSWORD=""
SMTP_TLSTYPE="none"
RUST_LOG="info,actix_server=error"

147
Cargo.lock generated
View File

@ -818,6 +818,10 @@ dependencies = [
"sqlx",
"static-files",
"thiserror",
"tracing",
"tracing-actix-web",
"tracing-panic",
"tracing-subscriber",
"zxcvbn",
]
@ -1432,8 +1436,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "531e46835a22af56d1e3b66f04844bed63158bc094a628bec1d321d9b4c44bf2"
dependencies = [
"bit-set",
"regex-automata",
"regex-syntax",
"regex-automata 0.4.9",
"regex-syntax 0.8.5",
]
[[package]]
@ -2248,6 +2252,15 @@ dependencies = [
"value-bag",
]
[[package]]
name = "matchers"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
dependencies = [
"regex-automata 0.1.10",
]
[[package]]
name = "maud"
version = "0.27.0"
@ -2323,6 +2336,12 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "mutually_exclusive_features"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e94e1e6445d314f972ff7395df2de295fe51b71821694f0b0e1e79c4f12c8577"
[[package]]
name = "nom"
version = "8.0.0"
@ -2332,6 +2351,16 @@ dependencies = [
"memchr",
]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
dependencies = [
"overload",
"winapi",
]
[[package]]
name = "num-bigint-dig"
version = "0.8.4"
@ -2406,6 +2435,12 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "parking"
version = "2.2.1"
@ -2747,8 +2782,17 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
"regex-automata 0.4.9",
"regex-syntax 0.8.5",
]
[[package]]
name = "regex-automata"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
dependencies = [
"regex-syntax 0.6.29",
]
[[package]]
@ -2759,7 +2803,7 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"regex-syntax 0.8.5",
]
[[package]]
@ -2768,6 +2812,12 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a"
[[package]]
name = "regex-syntax"
version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
version = "0.8.5"
@ -2991,6 +3041,15 @@ dependencies = [
"digest",
]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]]
name = "shlex"
version = "1.3.0"
@ -3399,6 +3458,16 @@ dependencies = [
"syn 2.0.100",
]
[[package]]
name = "thread_local"
version = "1.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
dependencies = [
"cfg-if",
"once_cell",
]
[[package]]
name = "time"
version = "0.3.41"
@ -3497,6 +3566,19 @@ dependencies = [
"tracing-core",
]
[[package]]
name = "tracing-actix-web"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2340b7722695166c7fc9b3e3cd1166e7c74fedb9075b8f0c74d3822d2e41caf5"
dependencies = [
"actix-web",
"mutually_exclusive_features",
"pin-project",
"tracing",
"uuid",
]
[[package]]
name = "tracing-attributes"
version = "0.1.28"
@ -3515,6 +3597,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
dependencies = [
"once_cell",
"valuable",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-panic"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bf1298a179837099f9309243af3b554e840f7f67f65e9f55294913299bd4cc5"
dependencies = [
"tracing",
"tracing-subscriber",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
dependencies = [
"matchers",
"nu-ansi-term",
"once_cell",
"regex",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
]
[[package]]
@ -3607,12 +3729,27 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9"
dependencies = [
"getrandom 0.3.2",
]
[[package]]
name = "v_htmlescape"
version = "0.15.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e8257fbc510f0a46eb602c10215901938b5c2a7d5e70fc11483b1d3c9b5b18c"
[[package]]
name = "valuable"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]]
name = "value-bag"
version = "1.11.1"

View File

@ -32,6 +32,10 @@ actix-http = "3.9.0"
askama = "0.13.0"
garde = { version = "0.22.0", features = ["derive", "email"] }
maud = "0.27.0"
tracing-actix-web = "0.7.18"
tracing = "0.1.41"
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
tracing-panic = "0.1.2"
[build-dependencies]
built = "0.7.4"

View File

@ -13,15 +13,21 @@ use chrono::NaiveTime;
use mail::Mailer;
use sqlx::postgres::PgPool;
use sqlx::{Pool, Postgres};
use tracing::info;
use tracing_actix_web::TracingLogger;
use tracing_panic::panic_hook;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::{fmt, EnvFilter};
use crate::postgres_session_store::SqlxPostgresqlSessionStore;
use crate::utils::manage_commands::{handle_command, parse_args};
mod endpoints;
mod mail;
mod middleware;
mod models;
mod utils;
mod mail;
mod filters;
mod postgres_session_store;
@ -37,6 +43,8 @@ async fn main() -> anyhow::Result<()> {
let env = get_env()?;
let config: Config = load_config(&env)?;
init_tracing();
let args = parse_args()?;
let pool = PgPool::connect(&config.database_url).await?;
@ -46,7 +54,7 @@ async fn main() -> anyhow::Result<()> {
let address = config.server_address;
let port = config.server_port;
println!("Starting server on http://{address}:{port}.",);
info!("Starting server on http://{address}:{port}.");
HttpServer::new(move || create_app(config.clone(), pool.clone(), mailer.clone()))
.bind((address, port))?
@ -77,6 +85,8 @@ pub fn create_app(
.app_data(web::Data::new(pool))
.app_data(web::Data::new(mailer))
.configure(endpoints::init)
.wrap(middleware::ErrorAppender)
.wrap(TracingLogger::default())
.wrap(middleware::RedirectToLogin)
.wrap(middleware::LoadCurrentUser)
.wrap(
@ -87,3 +97,16 @@ pub fn create_app(
.wrap(SessionMiddleware::new(store.clone(), secret_key.clone()))
.service(ResourceFiles::new("/static", generated))
}
fn init_tracing() {
let filter = EnvFilter::try_from_default_env()
.or_else(|_| EnvFilter::try_new("info"))
.unwrap();
tracing_subscriber::registry()
.with(fmt::layer())
.with(filter)
.init();
std::panic::set_hook(Box::new(panic_hook));
}

View File

@ -0,0 +1,77 @@
use std::{
future::{ready, Ready},
str::from_utf8,
};
use actix_web::{
body::BoxBody,
dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform},
Error, HttpMessage,
};
use futures_util::future::LocalBoxFuture;
use tracing_actix_web::RequestId;
pub struct ErrorAppender;
impl<S> Transform<S, ServiceRequest> for ErrorAppender
where
S: Service<ServiceRequest, Response = ServiceResponse, Error = Error>,
S::Future: 'static,
{
type Response = ServiceResponse;
type Error = Error;
type InitError = ();
type Transform = ErrorAppenderMiddleware<S>;
type Future = Ready<Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future {
ready(Ok(ErrorAppenderMiddleware { service }))
}
}
pub struct ErrorAppenderMiddleware<S> {
service: S,
}
impl<S> Service<ServiceRequest> for ErrorAppenderMiddleware<S>
where
S: Service<ServiceRequest, Response = ServiceResponse, Error = Error>,
S::Future: 'static,
{
type Response = ServiceResponse;
type Error = Error;
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
forward_ready!(service);
fn call(&self, req: ServiceRequest) -> Self::Future {
let id = req.extensions().get::<RequestId>().copied();
let fut = self.service.call(req);
Box::pin(async move {
let res = fut.await?;
if res.status().is_server_error() {
let (req, res) = res.into_parts();
let (res, body) = res.into_parts();
let body_bytes = actix_web::body::to_bytes(body).await.ok().unwrap();
let mut s = from_utf8(&body_bytes).unwrap().to_string();
let id_str = if let Some(id) = id {
id.to_string()
} else {
String::new()
};
s.push_str(" // request-id: ");
s.push_str(&id_str);
let res = res.set_body(BoxBody::new(s));
return Ok(ServiceResponse::new(req, res));
}
Ok(res)
})
}
}

View File

@ -1,5 +1,7 @@
mod redirect_to_login;
mod load_current_user_from_db;
mod append_request_id_to_error;
pub use redirect_to_login::RedirectToLogin;
pub use load_current_user_from_db::LoadCurrentUser;
pub use append_request_id_to_error::ErrorAppender;

View File

@ -3,7 +3,6 @@ use thiserror::Error;
use super::password_change::PasswordChangeError;
#[derive(Debug, Error)]
pub enum ApplicationError {
#[error("unsupported value '{value}' for enum '{enum_name}'")]

View File

@ -2,9 +2,9 @@ mod application_error;
pub mod auth;
pub mod event_planning_template;
pub mod manage_commands;
pub mod token_generation;
mod template_response_trait;
pub mod password_change;
mod template_response_trait;
pub mod token_generation;
#[cfg(test)]
pub mod test_helper;