diff --git a/rust/.cargo/config.toml b/rust/.cargo/config.toml new file mode 100644 index 0000000..bff29e6 --- /dev/null +++ b/rust/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +rustflags = ["--cfg", "tokio_unstable"] diff --git a/rust/Cargo.lock b/rust/Cargo.lock index dff970e..bd7ba3b 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -93,6 +93,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + [[package]] name = "async-trait" version = "0.1.73" @@ -306,6 +312,42 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "console-api" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2895653b4d9f1538a83970077cb01dfc77a4810524e51a110944688e916b18e" +dependencies = [ + "prost", + "prost-types", + "tonic", + "tracing-core", +] + +[[package]] +name = "console-subscriber" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4cf42660ac07fcebed809cfe561dd8730bcd35b075215e6479c516bcd0d11cb" +dependencies = [ + "console-api", + "crossbeam-channel", + "crossbeam-utils", + "futures", + "hdrhistogram", + "humantime", + "prost-types", + "serde", + "serde_json", + "thread_local", + "tokio", + "tokio-stream", + "tonic", + "tracing", + "tracing-core", + "tracing-subscriber", +] + [[package]] name = "const-oid" version = "0.9.5" @@ -336,6 +378,25 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + [[package]] name = "crossbeam-queue" version = "0.3.8" @@ -462,6 +523,16 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +[[package]] +name = "flate2" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "flume" version = "0.10.14" @@ -660,6 +731,19 @@ dependencies = [ "hashbrown 0.14.0", ] +[[package]] +name = "hdrhistogram" +version = "7.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f19b9f54f7c7f55e31401bb647626ce0cf0f67b0004982ce815b3ee72a02aa8" +dependencies = [ + "base64 0.13.1", + "byteorder", + "flate2", + "nom", + "num-traits", +] + [[package]] name = "headers" version = "0.3.8" @@ -773,6 +857,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" version = "0.14.27" @@ -797,6 +887,18 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + [[package]] name = "idna" version = "0.4.0" @@ -827,6 +929,12 @@ dependencies = [ "hashbrown 0.14.0", ] +[[package]] +name = "integer-encoding" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02" + [[package]] name = "is-terminal" version = "0.4.9" @@ -1095,6 +1203,93 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "opentelemetry" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9591d937bc0e6d2feb6f71a559540ab300ea49955229c347a517a28d27784c54" +dependencies = [ + "opentelemetry_api", + "opentelemetry_sdk", +] + +[[package]] +name = "opentelemetry-jaeger" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876958ba9084f390f913fcf04ddf7bbbb822898867bb0a51cc28f2b9e5c1b515" +dependencies = [ + "async-trait", + "futures-core", + "futures-util", + "opentelemetry", + "opentelemetry-semantic-conventions", + "thrift", +] + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73c9f9340ad135068800e7f1b24e9e09ed9e7143f5bf8518ded3d3ec69789269" +dependencies = [ + "opentelemetry", +] + +[[package]] +name = "opentelemetry_api" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a81f725323db1b1206ca3da8bb19874bbd3f57c3bcd59471bfb04525b265b9b" +dependencies = [ + "futures-channel", + "futures-util", + "indexmap 1.9.3", + "js-sys", + "once_cell", + "pin-project-lite", + "thiserror", + "urlencoding", +] + +[[package]] +name = "opentelemetry_sdk" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa8e705a0612d48139799fcbaba0d4a90f06277153e43dd2bdc16c6f0edd8026" +dependencies = [ + "async-trait", + "crossbeam-channel", + "futures-channel", + "futures-executor", + "futures-util", + "once_cell", + "opentelemetry_api", + "ordered-float 3.9.0", + "percent-encoding", + "rand", + "regex", + "thiserror", +] + +[[package]] +name = "ordered-float" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" +dependencies = [ + "num-traits", +] + +[[package]] +name = "ordered-float" +version = "3.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126d3e6f3926bfb0fb24495b4f4da50626f547e54956594748e3d8882a0320b4" +dependencies = [ + "num-traits", +] + [[package]] name = "overload" version = "0.1.1" @@ -1107,10 +1302,14 @@ version = "0.1.0" dependencies = [ "axum", "clap", + "console-subscriber", "futures", + "http", "hyper", "log", "maud", + "opentelemetry", + "opentelemetry-jaeger", "serde", "serde_variant", "sqlx", @@ -1119,6 +1318,7 @@ dependencies = [ "tower", "tower-http", "tracing", + "tracing-opentelemetry", "tracing-subscriber", "uuid", ] @@ -1265,6 +1465,38 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "prost-types" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +dependencies = [ + "prost", +] + [[package]] name = "quote" version = "1.0.33" @@ -1940,6 +2172,28 @@ dependencies = [ "once_cell", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "thrift" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e54bc85fc7faa8bc175c4bab5b92ba8d9a3ce893d0e9f42cc455c8ab16a9e09" +dependencies = [ + "byteorder", + "integer-encoding", + "log", + "ordered-float 2.10.0", + "threadpool", +] + [[package]] name = "time" version = "0.3.26" @@ -2001,6 +2255,16 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-macros" version = "2.1.0" @@ -2037,6 +2301,34 @@ dependencies = [ "tracing", ] +[[package]] +name = "tonic" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" +dependencies = [ + "async-trait", + "axum", + "base64 0.21.2", + "bytes", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower" version = "0.4.13" @@ -2045,9 +2337,13 @@ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", + "indexmap 1.9.3", "pin-project", "pin-project-lite", + "rand", + "slab", "tokio", + "tokio-util", "tower-layer", "tower-service", "tracing", @@ -2070,6 +2366,7 @@ dependencies = [ "tower-layer", "tower-service", "tracing", + "uuid", ] [[package]] @@ -2129,6 +2426,20 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-opentelemetry" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc09e402904a5261e42cf27aea09ccb7d5318c6717a9eec3d8e2e65c56b18f19" +dependencies = [ + "once_cell", + "opentelemetry", + "tracing", + "tracing-core", + "tracing-log", + "tracing-subscriber", +] + [[package]] name = "tracing-serde" version = "0.1.3" @@ -2222,6 +2533,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "utf8parse" version = "0.2.1" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 4a3de8c..9657687 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -11,6 +11,14 @@ path = "src/main.rs" opt-level = 0 lto = "off" +[dependencies] +opentelemetry = "0.20" +tracing-opentelemetry = "0.20" +opentelemetry-jaeger = "0.19" + +[dependencies.http] +version = "0.2" + [dependencies.log] version = "0.4" @@ -26,6 +34,9 @@ features = ["headers"] version = "1" features = ["macros", "rt-multi-thread", "tracing"] +[dependencies.console-subscriber] +version = "0.1" + [dependencies.hyper] version = "0.14" features = ["full"] @@ -35,7 +46,7 @@ version = "0.4" [dependencies.tower-http] version = "0.4" -features = ["trace"] +features = ["trace", "request-id"] [dependencies.tracing] version = "0.1" diff --git a/rust/src/auth.rs b/rust/src/auth.rs index 2204314..28b0eb5 100644 --- a/rust/src/auth.rs +++ b/rust/src/auth.rs @@ -5,12 +5,13 @@ use hyper::Request; use super::models; use super::{AppState, Error, RequestError}; -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum Config { Enabled, Disabled { assume_user: String }, } +#[tracing::instrument(skip(state, request, next))] pub async fn authorize( State(state): State, mut request: Request, diff --git a/rust/src/htmx.rs b/rust/src/htmx.rs index 8fc4dd9..cb5d6a4 100644 --- a/rust/src/htmx.rs +++ b/rust/src/htmx.rs @@ -44,6 +44,7 @@ impl From for HeaderName { } } +#[tracing::instrument] pub fn is_htmx(headers: &HeaderMap) -> bool { headers .get::(RequestHeaders::HtmxRequest.into()) diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 8b9a446..3f86946 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -8,19 +8,20 @@ pub mod htmx; pub mod models; pub mod routing; pub mod sqlite; +pub mod telemetry; mod view; pub use error::{CommandError, Error, RequestError, StartError}; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct AppState { pub database_pool: sqlite::Pool, pub client_state: ClientState, pub auth_config: auth::Config, } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Context { user: models::user::User, } @@ -31,7 +32,7 @@ impl Context { } } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct ClientState { pub active_category_id: Option, pub edit_item: Option, @@ -70,7 +71,7 @@ impl<'a> From<&'a UriPath> for &'a str { } } -#[derive(PartialEq, Eq)] +#[derive(PartialEq, Eq, Debug)] pub enum TopLevelPage { Inventory, Trips, diff --git a/rust/src/main.rs b/rust/src/main.rs index 46589bc..b161e75 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -4,7 +4,7 @@ use std::str::FromStr; use clap::{Parser, Subcommand}; -use packager::{auth, models, routing, sqlite, AppState, ClientState, Error}; +use packager::{auth, models, routing, sqlite, telemetry, AppState, ClientState, Error}; #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] @@ -73,49 +73,9 @@ impl From for MainResult { } } -fn init_tracing() { - use std::io::stdout; - use tracing::Level; - use tracing_subscriber::{ - filter::Targets, - fmt::{format::Format, Layer}, - prelude::*, - registry::Registry, - }; - // default is the Full format, there is no way to specify this, but it can be - // overridden via builder methods - let console_format = Format::default() - .with_ansi(true) - .with_target(true) - .with_level(true) - .json(); - - let console_layer = Layer::default() - .event_format(console_format) - .with_writer(stdout); - - let console_level = Level::DEBUG; - - let console_filter = Targets::new().with_target(env!("CARGO_PKG_NAME"), console_level); - - let console_layer = if true { - console_layer.boxed() - } else { - console_layer.with_filter(console_filter).boxed() - }; - - let registry = Registry::default() - // just an example, you can actuall pass Options here for layers that might be - // set/unset at runtime - .with(Some(console_layer)) - .with(None::>); - - tracing::subscriber::set_global_default(registry).unwrap(); -} - #[tokio::main] async fn main() -> MainResult { - init_tracing(); + telemetry::init_tracing(); let args = Args::parse(); match args.command { Command::Serve(serve_args) => { @@ -140,6 +100,8 @@ async fn main() -> MainResult { // build our application with a route let app = routing::router(state); + let app = telemetry::init_request_tracing(app); + let addr = SocketAddr::from(( IpAddr::from_str(&serve_args.bind) .map_err(|error| { diff --git a/rust/src/models/inventory.rs b/rust/src/models/inventory.rs index 21ea011..f818a7d 100644 --- a/rust/src/models/inventory.rs +++ b/rust/src/models/inventory.rs @@ -9,6 +9,7 @@ pub struct Inventory { } impl Inventory { + #[tracing::instrument] pub async fn load(ctx: &Context, pool: &sqlx::Pool) -> Result { let user_id = ctx.user.id.to_string(); let mut categories = sqlx::query_as!( @@ -64,6 +65,7 @@ impl TryFrom for Category { } impl Category { + #[tracing::instrument] pub async fn _find( ctx: &Context, pool: &sqlx::Pool, @@ -90,6 +92,7 @@ impl Category { .transpose() } + #[tracing::instrument] pub async fn save( ctx: &Context, pool: &sqlx::Pool, @@ -113,16 +116,19 @@ impl Category { Ok(id) } + #[tracing::instrument] pub fn items(&self) -> &Vec { self.items .as_ref() .expect("you need to call populate_items()") } + #[tracing::instrument] pub fn total_weight(&self) -> i64 { self.items().iter().map(|item| item.weight).sum() } + #[tracing::instrument] pub async fn populate_items( &mut self, ctx: &Context, @@ -157,6 +163,7 @@ impl Category { } } +#[derive(Debug)] pub struct Product { pub id: Uuid, pub name: String, @@ -164,6 +171,7 @@ pub struct Product { pub comment: Option, } +#[derive(Debug)] pub struct InventoryItem { pub id: Uuid, pub name: String, @@ -218,6 +226,7 @@ impl TryFrom for InventoryItem { } impl InventoryItem { + #[tracing::instrument] pub async fn find( ctx: &Context, pool: &sqlx::Pool, @@ -257,6 +266,7 @@ impl InventoryItem { .transpose() } + #[tracing::instrument] pub async fn name_exists( ctx: &Context, pool: &sqlx::Pool, @@ -278,6 +288,7 @@ impl InventoryItem { .is_some()) } + #[tracing::instrument] pub async fn delete( ctx: &Context, pool: &sqlx::Pool, @@ -299,6 +310,7 @@ impl InventoryItem { Ok(results.rows_affected() != 0) } + #[tracing::instrument] pub async fn update( ctx: &Context, pool: &sqlx::Pool, @@ -330,6 +342,7 @@ impl InventoryItem { .await??) } + #[tracing::instrument] pub async fn save( ctx: &Context, pool: &sqlx::Pool, @@ -360,6 +373,7 @@ impl InventoryItem { Ok(id) } + #[tracing::instrument] pub async fn get_category_max_weight( ctx: &Context, pool: &sqlx::Pool, @@ -424,6 +438,7 @@ impl TryFrom for Item { } impl Item { + #[tracing::instrument] pub async fn _get_category_total_picked_weight( ctx: &Context, pool: &sqlx::Pool, diff --git a/rust/src/models/trips.rs b/rust/src/models/trips.rs index 50f39f6..2e206be 100644 --- a/rust/src/models/trips.rs +++ b/rust/src/models/trips.rs @@ -14,7 +14,7 @@ use serde_variant::to_variant_name; use time; use uuid::Uuid; -#[derive(sqlx::Type, PartialEq, PartialOrd, Deserialize)] +#[derive(sqlx::Type, PartialEq, PartialOrd, Deserialize, Debug)] pub enum TripState { Init, Planning, @@ -118,6 +118,7 @@ pub struct TripCategory { } impl TripCategory { + #[tracing::instrument] pub fn total_picked_weight(&self) -> i64 { self.items .as_ref() @@ -128,6 +129,7 @@ impl TripCategory { .sum() } + #[tracing::instrument] pub async fn find( ctx: &Context, pool: &sqlx::Pool, @@ -288,6 +290,7 @@ impl TryFrom for TripItem { } impl TripItem { + #[tracing::instrument] pub async fn find( ctx: &Context, pool: &sqlx::Pool, @@ -327,6 +330,7 @@ impl TripItem { .transpose() } + #[tracing::instrument] pub async fn set_state( ctx: &Context, pool: &sqlx::Pool, @@ -391,6 +395,7 @@ impl TryFrom for Trip { } } +#[derive(Debug)] pub struct Trip { pub id: Uuid, pub name: String, @@ -426,6 +431,7 @@ pub(crate) struct DbTripWeightRow { } impl Trip { + #[tracing::instrument] pub async fn all(ctx: &Context, pool: &sqlx::Pool) -> Result, Error> { let user_id = ctx.user.id.to_string(); sqlx::query_as!( @@ -452,6 +458,7 @@ impl Trip { .collect::, Error>>() } + #[tracing::instrument] pub async fn find( ctx: &Context, pool: &sqlx::Pool, @@ -482,6 +489,7 @@ impl Trip { .transpose() } + #[tracing::instrument] pub async fn trip_type_remove( ctx: &Context, pool: &sqlx::Pool, @@ -512,6 +520,7 @@ impl Trip { Ok(results.rows_affected() != 0) } + #[tracing::instrument] pub async fn trip_type_add( ctx: &Context, pool: &sqlx::Pool, @@ -545,6 +554,7 @@ impl Trip { Ok(()) } + #[tracing::instrument] pub async fn set_state( ctx: &Context, pool: &sqlx::Pool, @@ -567,6 +577,7 @@ impl Trip { Ok(result.rows_affected() != 0) } + #[tracing::instrument] pub async fn set_comment( ctx: &Context, pool: &sqlx::Pool, @@ -589,6 +600,7 @@ impl Trip { Ok(result.rows_affected() != 0) } + #[tracing::instrument] pub async fn set_attribute( ctx: &Context, pool: &sqlx::Pool, @@ -616,6 +628,7 @@ impl Trip { }) } + #[tracing::instrument] pub async fn save( ctx: &Context, pool: &sqlx::Pool, @@ -649,6 +662,7 @@ impl Trip { Ok(id) } + #[tracing::instrument] pub async fn find_total_picked_weight( ctx: &Context, pool: &sqlx::Pool, @@ -680,18 +694,21 @@ impl Trip { Ok(weight) } + #[tracing::instrument] pub fn types(&self) -> &Vec { self.types .as_ref() .expect("you need to call load_trips_types()") } + #[tracing::instrument] pub fn categories(&self) -> &Vec { self.categories .as_ref() .expect("you need to call load_trips_types()") } + #[tracing::instrument] pub fn total_picked_weight(&self) -> i64 { self.categories() .iter() @@ -707,6 +724,7 @@ impl Trip { .sum::() } + #[tracing::instrument] pub async fn load_trips_types( &mut self, ctx: &Context, @@ -758,6 +776,7 @@ impl Trip { Ok(()) } + #[tracing::instrument] pub async fn sync_trip_items_with_inventory( &mut self, ctx: &Context, @@ -838,6 +857,7 @@ impl Trip { Ok(()) } + #[tracing::instrument] pub async fn load_categories( &mut self, ctx: &Context, @@ -955,6 +975,7 @@ impl Trip { } } +#[derive(Debug)] pub struct TripType { pub id: Uuid, pub name: String, @@ -962,6 +983,7 @@ pub struct TripType { } impl TripsType { + #[tracing::instrument] pub async fn all(ctx: &Context, pool: &sqlx::Pool) -> Result, Error> { let user_id = ctx.user.id.to_string(); sqlx::query_as!( @@ -981,6 +1003,7 @@ impl TripsType { .collect::, Error>>() } + #[tracing::instrument] pub async fn save( ctx: &Context, pool: &sqlx::Pool, @@ -1004,6 +1027,7 @@ impl TripsType { Ok(id) } + #[tracing::instrument] pub async fn set_name( ctx: &Context, pool: &sqlx::Pool, @@ -1039,6 +1063,7 @@ pub enum TripTypeAttribute { Name, } +#[derive(Debug)] pub struct TripsType { pub id: Uuid, pub name: String, diff --git a/rust/src/models/user.rs b/rust/src/models/user.rs index 96cd63e..5c81a1a 100644 --- a/rust/src/models/user.rs +++ b/rust/src/models/user.rs @@ -8,6 +8,7 @@ pub struct User { pub fullname: String, } +#[derive(Debug)] pub struct NewUser<'a> { pub username: &'a str, pub fullname: &'a str, @@ -33,6 +34,7 @@ impl TryFrom for User { } impl User { + #[tracing::instrument] pub async fn find_by_name( pool: &sqlx::Pool, name: &str, @@ -49,6 +51,7 @@ impl User { } } +#[tracing::instrument] pub async fn create(pool: &sqlx::Pool, user: NewUser<'_>) -> Result { let id = Uuid::new_v4(); let id_param = id.to_string(); diff --git a/rust/src/routing/mod.rs b/rust/src/routing/mod.rs index fad5982..28ab37e 100644 --- a/rust/src/routing/mod.rs +++ b/rust/src/routing/mod.rs @@ -5,9 +5,6 @@ use axum::{ Router, }; -use tower_http::trace; -use tracing::Level; - use crate::{AppState, Error, RequestError, TopLevelPage}; use super::auth; @@ -16,6 +13,7 @@ mod html; mod routes; use routes::*; +#[tracing::instrument] fn get_referer(headers: &HeaderMap) -> Result<&str, Error> { headers .get("referer") @@ -28,6 +26,7 @@ fn get_referer(headers: &HeaderMap) -> Result<&str, Error> { }) } +#[tracing::instrument] pub fn router(state: AppState) -> Router { Router::new() .route("/favicon.svg", get(icon)) @@ -126,9 +125,4 @@ pub fn router(state: AppState) -> Router { }) }) .with_state(state) - .layer( - trace::TraceLayer::new_for_http() - .make_span_with(trace::DefaultMakeSpan::new().level(Level::INFO)) - .on_response(trace::DefaultOnResponse::new().level(Level::INFO)), - ) } diff --git a/rust/src/routing/routes.rs b/rust/src/routing/routes.rs index 4d4829f..19d668c 100644 --- a/rust/src/routing/routes.rs +++ b/rust/src/routing/routes.rs @@ -15,12 +15,12 @@ use crate::{AppState, Context, Error, RequestError, TopLevelPage}; use super::{get_referer, html}; -#[derive(Deserialize, Default)] +#[derive(Deserialize, Default, Debug)] pub struct InventoryQuery { edit_item: Option, } -#[derive(Deserialize)] +#[derive(Deserialize, Debug)] pub struct NewItem { #[serde(rename = "new-item-name")] name: String, @@ -32,13 +32,13 @@ pub struct NewItem { category_id: Uuid, } -#[derive(Deserialize)] +#[derive(Deserialize, Debug)] pub struct NewItemName { #[serde(rename = "new-item-name")] name: String, } -#[derive(Deserialize)] +#[derive(Deserialize, Debug)] pub struct EditItem { #[serde(rename = "edit-item-name")] name: String, @@ -46,7 +46,7 @@ pub struct EditItem { weight: u32, } -#[derive(Deserialize)] +#[derive(Deserialize, Debug)] pub struct NewTrip { #[serde(rename = "new-trip-name")] name: String, @@ -62,19 +62,19 @@ pub struct TripQuery { category: Option, } -#[derive(Deserialize)] +#[derive(Deserialize, Debug)] pub struct CommentUpdate { #[serde(rename = "new-comment")] new_comment: String, } -#[derive(Deserialize)] +#[derive(Deserialize, Debug)] pub struct TripUpdate { #[serde(rename = "new-value")] new_value: String, } -#[derive(Deserialize)] +#[derive(Deserialize, Debug)] pub struct NewCategory { #[serde(rename = "new-category-name")] name: String, @@ -85,18 +85,19 @@ pub struct TripTypeQuery { edit: Option, } -#[derive(Deserialize)] +#[derive(Deserialize, Debug)] pub struct NewTripType { #[serde(rename = "new-trip-type-name")] name: String, } -#[derive(Deserialize)] +#[derive(Deserialize, Debug)] pub struct TripTypeUpdate { #[serde(rename = "new-value")] new_value: String, } +#[tracing::instrument] pub async fn root(Extension(current_user): Extension) -> impl IntoResponse { view::Root::build( &Context::build(current_user), @@ -105,6 +106,7 @@ pub async fn root(Extension(current_user): Extension) -> imp ) } +#[tracing::instrument] pub async fn icon() -> impl IntoResponse { ( [(header::CONTENT_TYPE, "image/svg+xml")], @@ -112,6 +114,7 @@ pub async fn icon() -> impl IntoResponse { ) } +#[tracing::instrument] pub async fn debug(headers: HeaderMap) -> impl IntoResponse { let mut out = String::new(); for (key, value) in headers.iter() { @@ -120,6 +123,7 @@ pub async fn debug(headers: HeaderMap) -> impl IntoResponse { out } +#[tracing::instrument] pub async fn inventory_active( Extension(current_user): Extension, State(mut state): State, @@ -157,6 +161,7 @@ pub async fn inventory_active( )) } +#[tracing::instrument] pub async fn inventory_inactive( Extension(current_user): Extension, State(mut state): State, @@ -179,6 +184,7 @@ pub async fn inventory_inactive( )) } +#[tracing::instrument] pub async fn inventory_item_validate_name( Extension(current_user): Extension, State(state): State, @@ -195,6 +201,7 @@ pub async fn inventory_item_validate_name( )) } +#[tracing::instrument] pub async fn inventory_item_create( Extension(current_user): Extension, State(state): State, @@ -244,6 +251,8 @@ pub async fn inventory_item_create( .into_response()) } } + +#[tracing::instrument] pub async fn inventory_item_delete( Extension(current_user): Extension, State(state): State, @@ -262,6 +271,7 @@ pub async fn inventory_item_delete( } } +#[tracing::instrument] pub async fn inventory_item_edit( Extension(current_user): Extension, State(state): State, @@ -287,6 +297,7 @@ pub async fn inventory_item_edit( Ok(Redirect::to(&format!("/inventory/category/{id}/"))) } +#[tracing::instrument] pub async fn inventory_item_cancel( Extension(current_user): Extension, State(state): State, @@ -305,6 +316,7 @@ pub async fn inventory_item_cancel( ))) } +#[tracing::instrument] pub async fn trip_create( Extension(current_user): Extension, State(state): State, @@ -329,6 +341,7 @@ pub async fn trip_create( Ok(Redirect::to(&format!("/trips/{new_id}/"))) } +#[tracing::instrument] pub async fn trips( Extension(current_user): Extension, State(state): State, @@ -343,6 +356,7 @@ pub async fn trips( )) } +#[tracing::instrument] pub async fn trip( Extension(current_user): Extension, State(mut state): State, @@ -390,6 +404,7 @@ pub async fn trip( )) } +#[tracing::instrument] pub async fn trip_type_remove( Extension(current_user): Extension, State(state): State, @@ -408,6 +423,7 @@ pub async fn trip_type_remove( } } +#[tracing::instrument] pub async fn trip_type_add( Extension(current_user): Extension, State(state): State, @@ -419,6 +435,7 @@ pub async fn trip_type_add( Ok(Redirect::to(&format!("/trips/{trip_id}/"))) } +#[tracing::instrument] pub async fn trip_comment_set( Extension(current_user): Extension, State(state): State, @@ -443,6 +460,7 @@ pub async fn trip_comment_set( } } +#[tracing::instrument] pub async fn trip_edit_attribute( Extension(current_user): Extension, State(state): State, @@ -467,6 +485,7 @@ pub async fn trip_edit_attribute( Ok(Redirect::to(&format!("/trips/{trip_id}/"))) } +#[tracing::instrument] pub async fn trip_item_set_state( ctx: &Context, state: &AppState, @@ -480,6 +499,7 @@ pub async fn trip_item_set_state( Ok(()) } +#[tracing::instrument] pub async fn trip_row( ctx: &Context, state: &AppState, @@ -524,6 +544,7 @@ pub async fn trip_row( Ok(html::concat(&item_row, &category_row)) } +#[tracing::instrument] pub async fn trip_item_set_pick( Extension(current_user): Extension, State(state): State, @@ -545,6 +566,7 @@ pub async fn trip_item_set_pick( .map(|_| -> Result { Ok(Redirect::to(get_referer(&headers)?)) })? } +#[tracing::instrument] pub async fn trip_item_set_pick_htmx( Extension(current_user): Extension, State(state): State, @@ -568,6 +590,7 @@ pub async fn trip_item_set_pick_htmx( Ok((headers, trip_row(&ctx, &state, trip_id, item_id).await?)) } +#[tracing::instrument] pub async fn trip_item_set_unpick( Extension(current_user): Extension, State(state): State, @@ -589,6 +612,7 @@ pub async fn trip_item_set_unpick( .map(|_| -> Result { Ok(Redirect::to(get_referer(&headers)?)) })? } +#[tracing::instrument] pub async fn trip_item_set_unpick_htmx( Extension(current_user): Extension, State(state): State, @@ -612,6 +636,7 @@ pub async fn trip_item_set_unpick_htmx( Ok((headers, trip_row(&ctx, &state, trip_id, item_id).await?)) } +#[tracing::instrument] pub async fn trip_item_set_pack( Extension(current_user): Extension, State(state): State, @@ -633,6 +658,7 @@ pub async fn trip_item_set_pack( .map(|_| -> Result { Ok(Redirect::to(get_referer(&headers)?)) })? } +#[tracing::instrument] pub async fn trip_item_set_pack_htmx( Extension(current_user): Extension, State(state): State, @@ -656,6 +682,7 @@ pub async fn trip_item_set_pack_htmx( Ok((headers, trip_row(&ctx, &state, trip_id, item_id).await?)) } +#[tracing::instrument] pub async fn trip_item_set_unpack( Extension(current_user): Extension, State(state): State, @@ -677,6 +704,7 @@ pub async fn trip_item_set_unpack( .map(|_| -> Result { Ok(Redirect::to(get_referer(&headers)?)) })? } +#[tracing::instrument] pub async fn trip_item_set_unpack_htmx( Extension(current_user): Extension, State(state): State, @@ -700,6 +728,7 @@ pub async fn trip_item_set_unpack_htmx( Ok((headers, trip_row(&ctx, &state, trip_id, item_id).await?)) } +#[tracing::instrument] pub async fn trip_item_set_ready( Extension(current_user): Extension, State(state): State, @@ -721,6 +750,7 @@ pub async fn trip_item_set_ready( .map(|_| -> Result { Ok(Redirect::to(get_referer(&headers)?)) })? } +#[tracing::instrument] pub async fn trip_item_set_ready_htmx( Extension(current_user): Extension, State(state): State, @@ -744,6 +774,7 @@ pub async fn trip_item_set_ready_htmx( Ok((headers, trip_row(&ctx, &state, trip_id, item_id).await?)) } +#[tracing::instrument] pub async fn trip_item_set_unready( Extension(current_user): Extension, State(state): State, @@ -765,6 +796,7 @@ pub async fn trip_item_set_unready( .map(|_| -> Result { Ok(Redirect::to(get_referer(&headers)?)) })? } +#[tracing::instrument] pub async fn trip_item_set_unready_htmx( Extension(current_user): Extension, State(state): State, @@ -788,6 +820,7 @@ pub async fn trip_item_set_unready_htmx( Ok((headers, trip_row(&ctx, &state, trip_id, item_id).await?)) } +#[tracing::instrument] pub async fn trip_total_weight_htmx( Extension(current_user): Extension, State(state): State, @@ -802,6 +835,7 @@ pub async fn trip_total_weight_htmx( )) } +#[tracing::instrument] pub async fn inventory_category_create( Extension(current_user): Extension, State(state): State, @@ -820,6 +854,7 @@ pub async fn inventory_category_create( Ok(Redirect::to("/inventory/")) } +#[tracing::instrument] pub async fn trip_state_set( Extension(current_user): Extension, State(state): State, @@ -842,6 +877,8 @@ pub async fn trip_state_set( Ok(Redirect::to(&format!("/trips/{trip_id}/")).into_response()) } } + +#[tracing::instrument] pub async fn trips_types( Extension(current_user): Extension, State(mut state): State, @@ -859,6 +896,8 @@ pub async fn trips_types( Some(&TopLevelPage::Trips), )) } + +#[tracing::instrument] pub async fn trip_type_create( Extension(current_user): Extension, State(state): State, @@ -876,6 +915,8 @@ pub async fn trip_type_create( Ok(Redirect::to("/trips/types/")) } + +#[tracing::instrument] pub async fn trips_types_edit_name( Extension(current_user): Extension, State(state): State, @@ -906,6 +947,7 @@ pub async fn trips_types_edit_name( } } +#[tracing::instrument] pub async fn inventory_item( Extension(current_user): Extension, State(state): State, @@ -925,6 +967,7 @@ pub async fn inventory_item( )) } +#[tracing::instrument] pub async fn trip_category_select( Extension(current_user): Extension, State(state): State, @@ -959,6 +1002,7 @@ pub async fn trip_category_select( )) } +#[tracing::instrument] pub async fn inventory_category_select( Extension(current_user): Extension, State(state): State, @@ -995,6 +1039,7 @@ pub async fn inventory_category_select( )) } +#[tracing::instrument] pub async fn trip_packagelist( Extension(current_user): Extension, State(state): State, @@ -1016,6 +1061,7 @@ pub async fn trip_packagelist( )) } +#[tracing::instrument] pub async fn trip_item_packagelist_set_pack_htmx( Extension(current_user): Extension, State(state): State, @@ -1043,6 +1089,7 @@ pub async fn trip_item_packagelist_set_pack_htmx( )) } +#[tracing::instrument] pub async fn trip_item_packagelist_set_unpack_htmx( Extension(current_user): Extension, State(state): State, @@ -1072,6 +1119,7 @@ pub async fn trip_item_packagelist_set_unpack_htmx( )) } +#[tracing::instrument] pub async fn trip_item_packagelist_set_ready_htmx( Extension(current_user): Extension, State(state): State, @@ -1099,6 +1147,7 @@ pub async fn trip_item_packagelist_set_ready_htmx( )) } +#[tracing::instrument] pub async fn trip_item_packagelist_set_unready_htmx( Extension(current_user): Extension, State(state): State, diff --git a/rust/src/sqlite.rs b/rust/src/sqlite.rs index 999d77a..f05cd56 100644 --- a/rust/src/sqlite.rs +++ b/rust/src/sqlite.rs @@ -8,6 +8,7 @@ use std::str::FromStr as _; use crate::StartError; +#[tracing::instrument] pub async fn init_database_pool(url: &str) -> Result, StartError> { Ok(SqlitePoolOptions::new() .max_connections(5) @@ -20,6 +21,7 @@ pub async fn init_database_pool(url: &str) -> Result, StartError> { .await?) } +#[tracing::instrument] pub async fn migrate(url: &str) -> Result<(), StartError> { let pool = SqlitePoolOptions::new() .max_connections(5) diff --git a/rust/src/telemetry.rs b/rust/src/telemetry.rs new file mode 100644 index 0000000..588693d --- /dev/null +++ b/rust/src/telemetry.rs @@ -0,0 +1,157 @@ +use std::fmt; +use std::io; +use std::time::Duration; + +use axum::Router; +use http::Request; +use tower_http::{classify::ServerErrorsFailureClass, trace::TraceLayer}; +use tracing::{Level, Span}; + +use tracing_subscriber::{ + filter::{LevelFilter, Targets}, + fmt::{format::Format, Layer}, + layer::SubscriberExt, + prelude::*, + registry::Registry, +}; +use uuid::Uuid; + +use opentelemetry::global; + +pub fn otel_init(f: impl FnOnce() -> ()) { + f() +} + +pub fn init_tracing() { + // default is the Full format, there is no way to specify this, but it can be + // overridden via builder methods + let stdout_format = Format::default() + .pretty() + .with_ansi(true) + .with_target(true) + .with_level(true) + .with_file(false); + + let stdout_layer = Layer::default() + .event_format(stdout_format) + .with_writer(io::stdout); + + let stdout_filter = Targets::new() + .with_default(LevelFilter::OFF) + .with_targets(vec![ + (env!("CARGO_PKG_NAME"), Level::DEBUG), + // this is for axum requests + ("request", Level::DEBUG), + // required for tokio-console as by the docs + // ("tokio", Level::TRACE), + // ("runtime", Level::TRACE), + ]); + + let stdout_layer = stdout_layer.with_filter(stdout_filter); + + let console_layer = console_subscriber::Builder::default().spawn(); + + global::set_text_map_propagator(opentelemetry_jaeger::Propagator::new()); + // Sets up the machinery needed to export data to Jaeger + // There are other OTel crates that provide pipelines for the vendors + // mentioned earlier. + let tracer = opentelemetry_jaeger::new_agent_pipeline() + .with_service_name(env!("CARGO_PKG_NAME")) + .install_simple() + .unwrap(); + + let opentelemetry_filter = Targets::new() + .with_default(LevelFilter::OFF) + .with_targets(vec![ + (env!("CARGO_PKG_NAME"), Level::DEBUG), + // this is for axum requests + ("request", Level::DEBUG), + // required for tokio-console as by the docs + // ("tokio", Level::TRACE), + // ("runtime", Level::TRACE), + ]); + + let opentelemetry = tracing_opentelemetry::layer() + .with_tracer(tracer) + .with_filter(opentelemetry_filter); + + let registry = Registry::default() + .with(console_layer) + .with(opentelemetry) + // just an example, you can actuall pass Options here for layers that might be + // set/unset at runtime + .with(Some(stdout_layer)) + .with(None::>); + + tracing::subscriber::set_global_default(registry).unwrap(); +} + +struct Latency(Duration); + +impl fmt::Display for Latency { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0.as_micros()) + } +} + +pub fn init_request_tracing(router: Router) -> Router { + router.layer( + TraceLayer::new_for_http() + .make_span_with(|_request: &Request<_>| { + let request_id = Uuid::new_v4(); + tracing::debug_span!( + target: "request", + "request", + %request_id, + ) + }) + .on_request(|request: &Request<_>, _span: &Span| { + let request_headers = request.headers(); + let http_version = request.version(); + tracing::debug!( + target: "request", + method = request.method().as_str(), + path = request.uri().path(), + ?http_version, + ?request_headers, + "request received", + ); + }) + .on_response( + |response: &axum::response::Response, latency: Duration, _span: &Span| { + let response_headers = response.headers(); + let latency = Latency(latency); + tracing::debug!( + target: "request", + %latency, + status = response.status().as_str(), + ?response_headers, + "finished processing request", + ); + }, + ) + .on_failure( + |error: ServerErrorsFailureClass, latency: Duration, _span: &Span| { + let latency = Latency(latency); + match error { + ServerErrorsFailureClass::StatusCode(code) => { + tracing::error!( + target: "request", + %latency, + "request failed with error response {}", + code, + ); + } + ServerErrorsFailureClass::Error(message) => { + tracing::error!( + target: "request", + %latency, + "request failed: {}", + message, + ); + } + } + }, + ), + ) +} diff --git a/rust/src/view/home.rs b/rust/src/view/home.rs index b8374e5..9aefc8c 100644 --- a/rust/src/view/home.rs +++ b/rust/src/view/home.rs @@ -3,6 +3,7 @@ use maud::{html, Markup}; pub struct Home; impl Home { + #[tracing::instrument] pub fn build() -> Markup { html!( div diff --git a/rust/src/view/inventory.rs b/rust/src/view/inventory.rs index e219e07..088f778 100644 --- a/rust/src/view/inventory.rs +++ b/rust/src/view/inventory.rs @@ -7,6 +7,7 @@ use uuid::Uuid; pub struct Inventory; impl Inventory { + #[tracing::instrument] pub fn build( active_category: Option<&models::inventory::Category>, categories: &Vec, @@ -36,6 +37,7 @@ impl Inventory { pub struct InventoryCategoryList; impl InventoryCategoryList { + #[tracing::instrument] pub fn build( active_category: Option<&models::inventory::Category>, categories: &Vec, @@ -142,6 +144,7 @@ impl InventoryCategoryList { pub struct InventoryItemList; impl InventoryItemList { + #[tracing::instrument] pub fn build(edit_item_id: Option, items: &Vec) -> Markup { let biggest_item_weight: i64 = items.iter().map(|item| item.weight).max().unwrap_or(1); html!( @@ -317,6 +320,7 @@ impl InventoryItemList { pub struct InventoryNewItemFormName; impl InventoryNewItemFormName { + #[tracing::instrument] pub fn build(value: Option<&str>, error: bool) -> Markup { html!( div @@ -364,6 +368,7 @@ impl InventoryNewItemFormName { pub struct InventoryNewItemFormWeight; impl InventoryNewItemFormWeight { + #[tracing::instrument] pub fn build() -> Markup { html!( div @@ -406,6 +411,7 @@ impl InventoryNewItemFormWeight { pub struct InventoryNewItemFormCategory; impl InventoryNewItemFormCategory { + #[tracing::instrument] pub fn build( active_category: Option<&models::inventory::Category>, categories: &Vec, @@ -446,6 +452,7 @@ impl InventoryNewItemFormCategory { pub struct InventoryNewItemForm; impl InventoryNewItemForm { + #[tracing::instrument] pub fn build( active_category: Option<&models::inventory::Category>, categories: &Vec, @@ -492,6 +499,7 @@ impl InventoryNewItemForm { pub struct InventoryNewCategoryForm; impl InventoryNewCategoryForm { + #[tracing::instrument] pub fn build() -> Markup { html!( form @@ -546,6 +554,7 @@ impl InventoryNewCategoryForm { pub struct InventoryItem; impl InventoryItem { + #[tracing::instrument] pub fn build(_state: &ClientState, item: &models::inventory::InventoryItem) -> Markup { html!( div ."p-8" { diff --git a/rust/src/view/mod.rs b/rust/src/view/mod.rs index 82c91fb..edf3d64 100644 --- a/rust/src/view/mod.rs +++ b/rust/src/view/mod.rs @@ -11,6 +11,7 @@ pub struct Root; use crate::TopLevelPage; impl Root { + #[tracing::instrument] pub fn build(context: &Context, body: &Markup, active_page: Option<&TopLevelPage>) -> Markup { let menu_item = |item: TopLevelPage, active_page: Option<&TopLevelPage>| { let active = active_page.map_or(false, |page| *page == item); @@ -116,6 +117,7 @@ impl Root { pub struct ErrorPage; impl ErrorPage { + #[tracing::instrument] pub fn build(message: &str) -> Markup { html!( (DOCTYPE) diff --git a/rust/src/view/trip/mod.rs b/rust/src/view/trip/mod.rs index fac15d7..c79f8ff 100644 --- a/rust/src/view/trip/mod.rs +++ b/rust/src/view/trip/mod.rs @@ -12,6 +12,7 @@ pub mod packagelist; pub mod types; impl TripManager { + #[tracing::instrument] pub fn build(trips: Vec) -> Markup { html!( div @@ -28,6 +29,7 @@ impl TripManager { } } +#[derive(Debug)] pub enum InputType { Text, Number, @@ -35,6 +37,7 @@ pub enum InputType { } impl From for &'static str { + #[tracing::instrument] fn from(value: InputType) -> &'static str { match value { InputType::Text => "text", @@ -58,6 +61,7 @@ fn trip_state_icon(state: &models::trips::TripState) -> &'static str { pub struct TripTable; impl TripTable { + #[tracing::instrument] pub fn build(trips: Vec) -> Markup { html!( table @@ -101,6 +105,7 @@ impl TripTable { pub struct TripTableRow; impl TripTableRow { + #[tracing::instrument(skip(value))] pub fn build(trip_id: Uuid, value: impl maud::Render) -> Markup { html!( td ."border" ."p-0" ."m-0" { @@ -120,6 +125,7 @@ impl TripTableRow { pub struct NewTrip; impl NewTrip { + #[tracing::instrument] pub fn build() -> Markup { html!( form @@ -215,6 +221,7 @@ impl NewTrip { pub struct Trip; impl Trip { + #[tracing::instrument] pub fn build( trip: &models::trips::Trip, trip_edit_attribute: Option<&models::trips::TripAttribute>, @@ -342,9 +349,10 @@ impl Trip { pub struct TripInfoRow; impl TripInfoRow { + #[tracing::instrument] pub fn build( name: &str, - value: Option, + value: Option, attribute_key: &models::trips::TripAttribute, edit_attribute: Option<&models::trips::TripAttribute>, input_type: InputType, @@ -465,6 +473,7 @@ impl TripInfoRow { pub struct TripInfoTotalWeightRow; impl TripInfoTotalWeightRow { + #[tracing::instrument] pub fn build(trip_id: Uuid, value: i64) -> Markup { html!( span @@ -482,6 +491,7 @@ impl TripInfoTotalWeightRow { pub struct TripInfoStateRow; impl TripInfoStateRow { + #[tracing::instrument] pub fn build(trip_state: &models::trips::TripState) -> Markup { let prev_state = trip_state.prev(); let next_state = trip_state.next(); @@ -586,6 +596,7 @@ impl TripInfoStateRow { pub struct TripInfo; impl TripInfo { + #[tracing::instrument] pub fn build( trip_edit_attribute: Option<&models::trips::TripAttribute>, trip: &models::trips::Trip, @@ -755,6 +766,7 @@ impl TripInfo { pub struct TripComment; impl TripComment { + #[tracing::instrument] pub fn build(trip: &models::trips::Trip) -> Markup { html!( div @@ -809,6 +821,7 @@ impl TripComment { pub struct TripItems; impl TripItems { + #[tracing::instrument] pub fn build( active_category: Option<&models::trips::TripCategory>, trip: &models::trips::Trip, @@ -836,6 +849,7 @@ impl TripItems { pub struct TripCategoryListRow; impl TripCategoryListRow { + #[tracing::instrument] pub fn build( trip_id: Uuid, category: &models::trips::TripCategory, @@ -944,6 +958,7 @@ impl TripCategoryListRow { pub struct TripCategoryList; impl TripCategoryList { + #[tracing::instrument] pub fn build( active_category: Option<&models::trips::TripCategory>, trip: &models::trips::Trip, @@ -1000,6 +1015,7 @@ impl TripCategoryList { pub struct TripItemList; impl TripItemList { + #[tracing::instrument] pub fn build(trip_id: Uuid, items: &Vec) -> Markup { let biggest_item_weight: i64 = items.iter().map(|item| item.item.weight).max().unwrap_or(1); @@ -1039,6 +1055,7 @@ impl TripItemList { pub struct TripItemListRow; impl TripItemListRow { + #[tracing::instrument] pub fn build( trip_id: Uuid, item: &models::trips::TripItem, diff --git a/rust/src/view/trip/packagelist.rs b/rust/src/view/trip/packagelist.rs index 57cb92a..2276267 100644 --- a/rust/src/view/trip/packagelist.rs +++ b/rust/src/view/trip/packagelist.rs @@ -6,6 +6,7 @@ use crate::models; pub struct TripPackageListRowReady; impl TripPackageListRowReady { + #[tracing::instrument] pub fn build(trip_id: Uuid, item: &models::trips::TripItem) -> Markup { html!( li @@ -82,6 +83,7 @@ impl TripPackageListRowReady { pub struct TripPackageListRowUnready; impl TripPackageListRowUnready { + #[tracing::instrument] pub fn build(trip_id: Uuid, item: &models::trips::TripItem) -> Markup { html!( li @@ -158,6 +160,7 @@ impl TripPackageListRowUnready { pub struct TripPackageListCategoryBlockReady; impl TripPackageListCategoryBlockReady { + #[tracing::instrument] pub fn build(trip: &models::trips::Trip, category: &models::trips::TripCategory) -> Markup { let empty = !category .items @@ -214,6 +217,7 @@ impl TripPackageListCategoryBlockReady { pub struct TripPackageListCategoryBlockUnready; impl TripPackageListCategoryBlockUnready { + #[tracing::instrument] pub fn build(trip: &models::trips::Trip, category: &models::trips::TripCategory) -> Markup { let empty = !category .items @@ -269,6 +273,7 @@ impl TripPackageListCategoryBlockUnready { pub struct TripPackageList; impl TripPackageList { + #[tracing::instrument] pub fn build(trip: &models::trips::Trip) -> Markup { // let all_packed = trip.categories().iter().all(|category| { // category diff --git a/rust/src/view/trip/types.rs b/rust/src/view/trip/types.rs index 3503ba7..d3f8aa4 100644 --- a/rust/src/view/trip/types.rs +++ b/rust/src/view/trip/types.rs @@ -5,6 +5,7 @@ use maud::{html, Markup}; pub struct TypeList; impl TypeList { + #[tracing::instrument] pub fn build(state: &ClientState, trip_types: Vec) -> Markup { html!( div ."p-8" ."flex" ."flex-col" ."gap-8" { diff --git a/rust/start-jaeger.sh b/rust/start-jaeger.sh new file mode 100755 index 0000000..39c4723 --- /dev/null +++ b/rust/start-jaeger.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +docker run --rm --name packager-jaeger -p6831:6831/udp -p6832:6832/udp -p16686:16686 -p14268:14268 jaegertracing/all-in-one:latest diff --git a/rust/start-tokio-console.sh b/rust/start-tokio-console.sh new file mode 100755 index 0000000..f8cd89f --- /dev/null +++ b/rust/start-tokio-console.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +cargo install --locked tokio-console +tokio-console