From f6b797b6c117f8f83b34fe35e73af8c7eab46906 Mon Sep 17 00:00:00 2001 From: Joey Hines Date: Sun, 17 Oct 2021 13:09:50 -0600 Subject: [PATCH] Added logging infrastructure + Using log and simple_logger libs + Added a command line argument to set the log level --- Cargo.lock | 30 +++++++++++++++++++++++ geoffrey_api/Cargo.toml | 4 +++- geoffrey_api/src/commands/mod.rs | 12 ++++++++-- geoffrey_api/src/logging.rs | 41 ++++++++++++++++++++++++++++++++ geoffrey_api/src/main.rs | 28 ++++++++++++++++++++-- geoffrey_db/Cargo.toml | 2 ++ geoffrey_db/src/database.rs | 2 ++ geoffrey_models/src/lib.rs | 3 ++- 8 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 geoffrey_api/src/logging.rs diff --git a/Cargo.lock b/Cargo.lock index f1b2dad..8838656 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "aho-corasick" version = "0.7.15" @@ -119,6 +121,17 @@ dependencies = [ "vec_map", ] +[[package]] +name = "colored" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59" +dependencies = [ + "atty", + "lazy_static", + "winapi", +] + [[package]] name = "config" version = "0.11.0" @@ -297,8 +310,10 @@ dependencies = [ "config", "geoffrey_db", "geoffrey_models", + "log", "serde 1.0.124", "serde_json", + "simple_logger", "structopt", "tokio", "warp", @@ -311,8 +326,10 @@ dependencies = [ "byteorder", "geoffrey_models", "lazy_static", + "log", "serde 1.0.124", "serde_json", + "simple_logger", "sled", ] @@ -1060,6 +1077,19 @@ dependencies = [ "libc", ] +[[package]] +name = "simple_logger" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7de33c687404ec3045d4a0d437580455257c0436f858d702f244e7d652f9f07" +dependencies = [ + "atty", + "chrono", + "colored", + "log", + "winapi", +] + [[package]] name = "slab" version = "0.4.2" diff --git a/geoffrey_api/Cargo.toml b/geoffrey_api/Cargo.toml index af35297..7afd971 100644 --- a/geoffrey_api/Cargo.toml +++ b/geoffrey_api/Cargo.toml @@ -14,4 +14,6 @@ serde_json = "1.0.64" geoffrey_models = { path = "../geoffrey_models" } geoffrey_db = { path = "../geoffrey_db" } config = "0.11.0" -structopt = "0.3.21" \ No newline at end of file +structopt = "0.3.21" +log = "0.4.14" +simple_logger = "1.13.0" diff --git a/geoffrey_api/src/commands/mod.rs b/geoffrey_api/src/commands/mod.rs index 741744d..81503e6 100644 --- a/geoffrey_api/src/commands/mod.rs +++ b/geoffrey_api/src/commands/mod.rs @@ -10,6 +10,7 @@ use serde::Serialize; use std::sync::Arc; use warp::filters::BoxedFilter; use warp::Filter; +use std::fmt::Debug; pub mod add_location; pub mod find; @@ -23,7 +24,7 @@ pub enum RequestType { } pub trait Command { - type Req: Serialize + DeserializeOwned + Send + 'static; + type Req: Serialize + DeserializeOwned + Send + 'static + Debug; type Resp: Serialize + DeserializeOwned + Send; fn command_name() -> String; @@ -38,11 +39,18 @@ pub fn create_command_filter(ctx: Arc) -> BoxedFilter<(impl .and(warp::any().map(move || ctx.clone())) .and(warp::body::json()) .map(|ctx: Arc, req: T::Req| { + + log::info!("Running command {}", T::command_name()); + log::debug!("Request: {:?}", req); + let reply = T::run_command(ctx, req); if let Ok(reply) = reply { + log::debug!("Successfully processed command"); warp::reply::json(&APIResponse::Response::(reply)) } else { - warp::reply::json(&APIResponse::::Error(reply.err().unwrap())) + let e = reply.err().unwrap(); + log::warn!("Got error when processing command: {:?}", e); + warp::reply::json(&APIResponse::::Error(e)) } }); diff --git a/geoffrey_api/src/logging.rs b/geoffrey_api/src/logging.rs new file mode 100644 index 0000000..cbe719f --- /dev/null +++ b/geoffrey_api/src/logging.rs @@ -0,0 +1,41 @@ +use serde::{Deserialize, Serialize}; +use log::{LevelFilter, SetLoggerError}; +use simple_logger::SimpleLogger; + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub enum LogLevel { + None, + Warn, + Info, + Debug +} + +impl From<&str> for LogLevel { + fn from(s: &str) -> Self { + match s { + "warn" | "w" => LogLevel::Warn, + "info" | "i" => LogLevel::Info, + "debug" | "d" => LogLevel::Debug, + "none" | _ => LogLevel::None, + } + } +} + +impl From for LevelFilter { + fn from(l: LogLevel) -> Self { + match l { + LogLevel::None => LevelFilter::Off, + LogLevel::Warn => LevelFilter::Warn, + LogLevel::Info => LevelFilter::Info, + LogLevel::Debug => LevelFilter::Debug + } + } +} + +pub fn init_logging(log_level: LogLevel) -> Result<(), SetLoggerError> { + SimpleLogger::new() + .with_level(log_level.into()) + .with_module_level("hyper", LevelFilter::Info) + .with_module_level("sled", LevelFilter::Info) + .init() +} diff --git a/geoffrey_api/src/main.rs b/geoffrey_api/src/main.rs index 57ea752..a4e9a05 100644 --- a/geoffrey_api/src/main.rs +++ b/geoffrey_api/src/main.rs @@ -2,6 +2,7 @@ mod commands; mod config; mod context; mod helper; +mod logging; use crate::commands::command_filter; use crate::config::GeoffreyAPIConfig; @@ -11,6 +12,7 @@ use std::net::SocketAddr; use std::path::PathBuf; use std::str::FromStr; use structopt::StructOpt; +use crate::logging::{init_logging, LogLevel}; pub type Result = std::result::Result; @@ -19,19 +21,41 @@ pub type Result = std::result::Result; struct Args { #[structopt(env = "GEOFFREY_CONFIG", parse(from_os_str))] config: PathBuf, + #[structopt(short, long, env = "GEOFFREY_LOG_LEVEL", parse(from_str), default_value="Info")] + log_level: LogLevel, } + #[tokio::main] async fn main() { let args: Args = Args::from_args(); - let cfg = GeoffreyAPIConfig::new(args.config.as_path()).unwrap(); + if let Err(e) = init_logging(args.log_level) { + println!("Unable to initialize logger: {}", e); + return; + } + + let cfg = match GeoffreyAPIConfig::new(args.config.as_path()) { + Ok(cfg) => cfg, + Err(e) => { + log::warn!("Error opening config: {}", e); + return; + } + }; + + let socket_addr = match SocketAddr::from_str(cfg.host.as_str()) { + Ok(socket_addr) => socket_addr, + Err(e) => { + log::warn!("Error parsing {} as address: {}", cfg.host, e); + return; + } + }; let ctx = Context::new(cfg).unwrap(); let api = command_filter(ctx.clone()); warp::serve(api) - .run(SocketAddr::from_str(ctx.cfg.host.as_str()).unwrap()) + .run(socket_addr) .await; } diff --git a/geoffrey_db/Cargo.toml b/geoffrey_db/Cargo.toml index 0190f89..8424591 100644 --- a/geoffrey_db/Cargo.toml +++ b/geoffrey_db/Cargo.toml @@ -12,6 +12,8 @@ serde = "1.0" serde_json = "1.0" geoffrey_models = { path = "../geoffrey_models" } byteorder = "1.4.2" +log = "0.4.14" +simple_logger = "1.13.0" [dev-dependencies] lazy_static = "1.4.0" diff --git a/geoffrey_db/src/database.rs b/geoffrey_db/src/database.rs index 6805164..62238eb 100644 --- a/geoffrey_db/src/database.rs +++ b/geoffrey_db/src/database.rs @@ -37,6 +37,7 @@ impl Database { let match_count = self.filter(|_, o: &T| !o.check_unique(&model))?.count(); if match_count > 0 { + log::debug!("{} is not unique: {:?}", T::tree(), model); return Err(GeoffreyDBError::NotUnique); } @@ -58,6 +59,7 @@ impl Database { if let Some(bytes) = tree.get(id_bytes)? { Ok(T::try_from_bytes(&bytes)?) } else { + log::debug!("{} of id {} was not found in the database", T::tree(), id); Err(GeoffreyDBError::NotFound) } } diff --git a/geoffrey_models/src/lib.rs b/geoffrey_models/src/lib.rs index dd322be..e71027e 100644 --- a/geoffrey_models/src/lib.rs +++ b/geoffrey_models/src/lib.rs @@ -1,12 +1,13 @@ #![allow(dead_code)] use serde::de::DeserializeOwned; use serde::Serialize; +use std::fmt::Debug; pub mod models; const DB_VERSION: u64 = 1; -pub trait GeoffreyDatabaseModel: Serialize + DeserializeOwned { +pub trait GeoffreyDatabaseModel: Serialize + DeserializeOwned + Debug { fn id(&self) -> Option; fn set_id(&mut self, id: u64); fn tree() -> String;