From d86ac5822cddf888d2c34528637ff0337d56c362 Mon Sep 17 00:00:00 2001 From: Nico Fricke Date: Mon, 13 Jan 2025 07:38:26 +0100 Subject: [PATCH] add proper configuration and logging --- Cargo.lock | 159 +++++++++++++++++++++++++++++++++++ application.toml | 2 - casket-backend/Cargo.toml | 5 +- casket-backend/README.md | 25 ++++++ casket-backend/casket.toml | 3 + casket-backend/src/config.rs | 21 +++-- casket-backend/src/main.rs | 40 ++++++--- 7 files changed, 235 insertions(+), 20 deletions(-) delete mode 100644 application.toml create mode 100644 casket-backend/README.md create mode 100644 casket-backend/casket.toml diff --git a/Cargo.lock b/Cargo.lock index ddaa340..9ed286c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -127,6 +127,9 @@ dependencies = [ "figment", "serde", "tokio", + "tracing", + "tracing-log", + "tracing-subscriber", ] [[package]] @@ -148,6 +151,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" dependencies = [ "atomic", + "pear", "serde", "toml", "uncased", @@ -305,12 +309,24 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "inlinable_string" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" + [[package]] name = "itoa" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.169" @@ -371,6 +387,16 @@ dependencies = [ "windows-sys", ] +[[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 = "object" version = "0.36.7" @@ -386,6 +412,12 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "parking_lot" version = "0.12.3" @@ -409,6 +441,29 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "pear" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a386cd715229d399604b50d1361683fe687066f42d56f54be995bc6868f71c" +dependencies = [ + "inlinable_string", + "pear_codegen", + "yansi", +] + +[[package]] +name = "pear_codegen" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f0f13dac8069c139e8300a6510e3f4143ecf5259c60b116a9b271b4ca0d54" +dependencies = [ + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -436,6 +491,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proc-macro2-diagnostics" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "version_check", + "yansi", +] + [[package]] name = "quote" version = "1.0.38" @@ -541,6 +609,15 @@ dependencies = [ "serde", ] +[[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 = "signal-hook-registry" version = "1.4.2" @@ -583,6 +660,16 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +[[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 = "tokio" version = "1.42.0" @@ -682,9 +769,21 @@ checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tracing-core" version = "0.1.33" @@ -692,6 +791,32 @@ 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-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", ] [[package]] @@ -709,6 +834,12 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "version_check" version = "0.9.5" @@ -721,6 +852,28 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-sys" version = "0.52.0" @@ -802,3 +955,9 @@ checksum = "39281189af81c07ec09db316b302a3e67bf9bd7cbf6c820b50e35fee9c2fa980" dependencies = [ "memchr", ] + +[[package]] +name = "yansi" +version = "1.0.0-rc" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ee746ad3851dd3bc40e4a028ab3b00b99278d929e48957bcb2d111874a7e43e" diff --git a/application.toml b/application.toml deleted file mode 100644 index b938de2..0000000 --- a/application.toml +++ /dev/null @@ -1,2 +0,0 @@ -port = 3000 -listen = "0.0.0.0" \ No newline at end of file diff --git a/casket-backend/Cargo.toml b/casket-backend/Cargo.toml index 38fcf88..5379bc0 100644 --- a/casket-backend/Cargo.toml +++ b/casket-backend/Cargo.toml @@ -6,5 +6,8 @@ edition = "2021" [dependencies] axum = { version = "0.8.1" } tokio = { version = "1.42.0", features = ["full"] } -figment = { version = "0.10.19", features = ["toml"] } +figment = { version = "0.10.19", features = ["toml", "env"] } serde = {version = "1.0.217", features = ["derive"]} +tracing = "0.1.41" +tracing-log = "0.2.0" +tracing-subscriber = "0.3.19" \ No newline at end of file diff --git a/casket-backend/README.md b/casket-backend/README.md new file mode 100644 index 0000000..9cb65a2 --- /dev/null +++ b/casket-backend/README.md @@ -0,0 +1,25 @@ +# Casket backend + +Backend server for casket. + +## Running + +```bash +cd casket-backend +cargo run +``` + +## Configuration + +See [casket.toml](./casket.toml) for an example config file. By default, the following files are checked +to exist: + +- `./casket-backend/casket.toml` +- `/config/casket.toml` + +Additionally, it is possible to provide configs via environment variables. Use the prefix `CASKET_`. +For nested configs use two underscores to mark the place to split: + +```bash +CASKET_SERVER__port=1234 +``` \ No newline at end of file diff --git a/casket-backend/casket.toml b/casket-backend/casket.toml new file mode 100644 index 0000000..e5c18c6 --- /dev/null +++ b/casket-backend/casket.toml @@ -0,0 +1,3 @@ +[server] +port = 3000 +bind_address = "127.0.0.1" \ No newline at end of file diff --git a/casket-backend/src/config.rs b/casket-backend/src/config.rs index 04c16e2..b8a4f74 100644 --- a/casket-backend/src/config.rs +++ b/casket-backend/src/config.rs @@ -1,15 +1,26 @@ +use figment::providers::{Env, Format}; use figment::{providers::Toml, Figment}; -use figment::providers::Format; use serde::Deserialize; +pub const CONFIG_LOCATIONS: [&str; 2] = ["casket-backend/casket.toml", "/config/casket.toml"]; + #[derive(Deserialize, Clone, Debug)] pub struct Config { - port: u16, - listen: String, + pub server: Server, +} + +#[derive(Deserialize, Clone, Debug)] +pub struct Server { + pub port: u16, + pub bind_address: String, } pub fn get_config() -> figment::Result { - Figment::new() - .merge(Toml::file("application.toml")) + CONFIG_LOCATIONS + .iter() + .fold(Figment::new(), |figment, location| { + figment.merge(Toml::file(location)) + }) + .join(Env::prefixed("CASKET_").split("__")) .extract() } diff --git a/casket-backend/src/main.rs b/casket-backend/src/main.rs index a270afe..ddf1065 100644 --- a/casket-backend/src/main.rs +++ b/casket-backend/src/main.rs @@ -2,32 +2,48 @@ mod config; mod routes; use axum::Router; +use std::env; +use std::process::exit; +use std::str::FromStr; +use tracing::{debug, error, info}; #[derive(Clone)] -pub struct AppState { - config: config::Config, -} +pub struct AppState {} #[tokio::main] async fn main() { + tracing_subscriber::fmt() + .with_max_level(get_log_level()) + .init(); let config = config::get_config(); match config { Ok(config) => { - println!("Loaded config: {:#?}", &config); - // build our application with a route + debug!("Config loaded {:?}", &config,); + let bind = format!("{}:{}", &config.server.bind_address, &config.server.port); let app = Router::new() .merge(routes::routes()) - .with_state(AppState { config }); + .with_state(AppState {}); - // run it - let listener = tokio::net::TcpListener::bind("127.0.0.1:3000") - .await - .unwrap(); - println!("listening on {}", listener.local_addr().unwrap()); + let listener = tokio::net::TcpListener::bind(bind).await.unwrap(); + info!("listening on {}", listener.local_addr().unwrap()); axum::serve(listener, app).await.unwrap(); } Err(error) => { - println!("Error while loading config: {}", error); + error!( + "Error while loading config: {}. Tried loading from the following files {:?} and env variables prefixed by CASKET_.", + error, + config::CONFIG_LOCATIONS + ); + exit(1) } } } + +fn get_log_level() -> tracing::Level { + let env = env::var("CASKET_LOG_LEVEL"); + match env { + Ok(value) => tracing::Level::from_str(&value) + .unwrap_or_else(|_| panic!("Failed to parse log level env {}", value)), + Err(_) => tracing::Level::INFO, + } +}