From c45bb592dbe1a0e0a2040769822359be20e9b56b Mon Sep 17 00:00:00 2001 From: Joey Hines Date: Sun, 12 Dec 2021 11:55:09 -0700 Subject: [PATCH] Added logging to bot + Cleaned up error handling to make it easier to handle multiple error levels --- Cargo.lock | 3 ++ geoffrey_api/src/logging.rs | 32 +------------------ geoffrey_api/src/main.rs | 32 +++++++++++-------- geoffrey_bot/Cargo.toml | 2 ++ geoffrey_bot/src/bot/commands/mod.rs | 48 +++++++++++++--------------- geoffrey_bot/src/logging.rs | 11 +++++++ geoffrey_bot/src/main.rs | 40 +++++++++++++++++------ geoffrey_models/Cargo.toml | 1 + geoffrey_models/src/lib.rs | 1 + geoffrey_models/src/logging/mod.rs | 34 ++++++++++++++++++++ 10 files changed, 124 insertions(+), 80 deletions(-) create mode 100644 geoffrey_bot/src/logging.rs create mode 100644 geoffrey_models/src/logging/mod.rs diff --git a/Cargo.lock b/Cargo.lock index e2e23e7..98a3f09 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -442,11 +442,13 @@ dependencies = [ "async-trait", "config", "geoffrey_models", + "log", "reqwest", "serde 1.0.130", "serde_json", "serde_plain", "serenity", + "simple_logger", "structopt", "tokio", ] @@ -471,6 +473,7 @@ name = "geoffrey_models" version = "0.1.0" dependencies = [ "chrono", + "log", "serde 1.0.130", "serde_json", ] diff --git a/geoffrey_api/src/logging.rs b/geoffrey_api/src/logging.rs index a661759..0a0dc9f 100644 --- a/geoffrey_api/src/logging.rs +++ b/geoffrey_api/src/logging.rs @@ -2,37 +2,7 @@ use log::{LevelFilter, SetLoggerError}; use serde::{Deserialize, Serialize}; use simple_logger::SimpleLogger; -#[derive(Serialize, Deserialize, Clone, Debug)] -pub enum LogLevel { - None, - Warn, - Info, - Debug, -} - -impl From<&str> for LogLevel { - #[allow(clippy::wildcard_in_or_patterns)] - fn from(s: &str) -> Self { - let s = s.to_lowercase(); - match s.as_str() { - "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, - } - } -} +use geoffrey_models::logging::LogLevel; pub fn init_logging(log_level: LogLevel) -> Result<(), SetLoggerError> { SimpleLogger::new() diff --git a/geoffrey_api/src/main.rs b/geoffrey_api/src/main.rs index f41fd23..32b29d0 100644 --- a/geoffrey_api/src/main.rs +++ b/geoffrey_api/src/main.rs @@ -1,24 +1,28 @@ -mod commands; -mod config; -mod context; -mod helper; -mod logging; - -use crate::commands::add_token::AddToken; -use crate::commands::{command_filter, Command}; -use crate::config::GeoffreyAPIConfig; -use crate::context::Context; -use crate::logging::{init_logging, LogLevel}; -use geoffrey_models::models::parameters::add_token_params::AddTokenParams; -use geoffrey_models::models::response::api_error::GeoffreyAPIError; -use geoffrey_models::models::token::Permissions; use std::convert::TryFrom; use std::net::SocketAddr; use std::path::PathBuf; use std::str::FromStr; use std::sync::Arc; + use structopt::StructOpt; +use geoffrey_models::logging::LogLevel; +use geoffrey_models::models::parameters::add_token_params::AddTokenParams; +use geoffrey_models::models::response::api_error::GeoffreyAPIError; +use geoffrey_models::models::token::Permissions; + +use crate::commands::{Command, command_filter}; +use crate::commands::add_token::AddToken; +use crate::config::GeoffreyAPIConfig; +use crate::context::Context; +use crate::logging::init_logging; + +mod commands; +mod config; +mod context; +mod helper; +mod logging; + pub type Result = std::result::Result; #[derive(Debug, StructOpt, Clone)] diff --git a/geoffrey_bot/Cargo.toml b/geoffrey_bot/Cargo.toml index c6eab4e..8eb5dd6 100644 --- a/geoffrey_bot/Cargo.toml +++ b/geoffrey_bot/Cargo.toml @@ -16,3 +16,5 @@ serde_plain = "1.0.0" async-trait = "0.1.51" config = "0.11.0" structopt = "0.3.21" +log = "0.4.14" +simple_logger = "1.13.0" diff --git a/geoffrey_bot/src/bot/commands/mod.rs b/geoffrey_bot/src/bot/commands/mod.rs index deff298..3c6b033 100644 --- a/geoffrey_bot/src/bot/commands/mod.rs +++ b/geoffrey_bot/src/bot/commands/mod.rs @@ -98,33 +98,29 @@ pub trait BotCommand { resp } else { match err { - CommandError::GeoffreyApi(err) => match err { - GeoffreyAPIError::PlayerNotRegistered => { - "You need to register before using this command!".to_string() - } - GeoffreyAPIError::EntryNotFound => { + CommandError::GeoffreyApi(GeoffreyAPIError::PlayerNotRegistered) => { + "You need to register before using this command!".to_string() + } + CommandError::GeoffreyApi(GeoffreyAPIError::EntryNotFound) => { "Couldn't find that, maybe look for something that exists?".to_string() - } - GeoffreyAPIError::PermissionInsufficient => { - "Looks like you don't have permission for that.".to_string() - } - GeoffreyAPIError::EntryNotUnique => { - "Slow down, I already know that thing. Try a new name.".to_string() - } - GeoffreyAPIError::DatabaseError(_) => "How the heck u mess that up".to_string(), - GeoffreyAPIError::TokenNotAuthorized => "WHO ARE YOU????".to_string(), - GeoffreyAPIError::MultipleLocationsMatch => { - "I couldn't match a single location, narrow down your search".to_string() - } - GeoffreyAPIError::ParameterInvalid(err) => { - format!( - "Welp, you some how messed up the {} parameter, great job", - err - ) - } - }, + } + CommandError::GeoffreyApi(GeoffreyAPIError::PermissionInsufficient) => { + "Looks like you don't have permission for that.".to_string() + } + CommandError::GeoffreyApi(GeoffreyAPIError::EntryNotUnique) => { + "Slow down, I already know that thing. Try a new name.".to_string() + } + CommandError::GeoffreyApi(GeoffreyAPIError::MultipleLocationsMatch) => { + "I couldn't match a single location, narrow down your search".to_string() + } + CommandError::GeoffreyApi(GeoffreyAPIError::ParameterInvalid(err)) => { + format!( + "Welp, you some how messed up the {} parameter, great job", + err + ) + } _ => { - println!("GeoffreyBot got an unhandled error: {}", err); + log::warn!("GeoffreyBot got an unhandled error: {}", err); format!("OOPSIE WOOPSIE!! Uwu We made a fucky wucky!! A wittle fucko boingo! The admins at our \ headquarters are working VEWY HAWD to fix this! (Error in command {})", Self::command_name()) } @@ -149,6 +145,8 @@ pub trait BotCommand { ) -> Result { let mut args = Self::process_arguments(command_interact).await?; + log::info!("Running command {}, with args {:?}", Self::command_name(), args); + args.set_token(ctx.cfg.api.token.clone()); args.set_user_id(user_id); diff --git a/geoffrey_bot/src/logging.rs b/geoffrey_bot/src/logging.rs new file mode 100644 index 0000000..ebe03e6 --- /dev/null +++ b/geoffrey_bot/src/logging.rs @@ -0,0 +1,11 @@ +use log::{LevelFilter, SetLoggerError}; +use simple_logger::SimpleLogger; + +use geoffrey_models::logging::LogLevel; + +pub fn init_logging(log_level: LogLevel) -> Result<(), SetLoggerError> { + SimpleLogger::new() + .with_level(LevelFilter::Warn) + .with_module_level("geoffrey_bot", log_level.into()) + .init() +} \ No newline at end of file diff --git a/geoffrey_bot/src/main.rs b/geoffrey_bot/src/main.rs index 863c0f0..94a5b1f 100644 --- a/geoffrey_bot/src/main.rs +++ b/geoffrey_bot/src/main.rs @@ -1,6 +1,7 @@ mod bot; mod configs; mod context; +mod logging; use crate::bot::create_commands; use crate::configs::GeoffreyBotConfig; @@ -22,12 +23,22 @@ use serenity::{ }; use std::path::PathBuf; use structopt::StructOpt; +use geoffrey_models::logging::LogLevel; +use crate::logging::init_logging; #[derive(Debug, StructOpt, Clone)] #[structopt(name = "GeoffreyBot", about = "Geoffrey Discord Bot")] struct Args { #[structopt(env = "GEOFFREY_BOT_CONFIG", parse(from_os_str))] config: PathBuf, + #[structopt( + short, + long, + env = "GEOFFREY_LOG_LEVEL", + parse(from_str), + default_value = "Info" + )] + log_level: LogLevel, } struct HttpClient; @@ -41,13 +52,13 @@ struct Handler; #[async_trait] impl EventHandler for Handler { async fn ready(&self, ctx: Context, ready: Ready) { - println!("{} is connected!", ready.user.name); + log::info!("{} is connected!", ready.user.name); let commands = create_commands(&ctx).await.unwrap(); - println!("The following bot have been registered:"); + log::debug!("The following bot have been registered:"); for command in commands { - println!( + log::debug!( "{}: {} - {:?}", command.name, command.description, command.options ); @@ -92,7 +103,7 @@ impl EventHandler for Handler { .await .unwrap() } else if let Interaction::Ping(_) = interaction { - println!("Ping recv'ed"); + // do nothing } } } @@ -100,21 +111,30 @@ impl EventHandler for Handler { #[tokio::main] async fn main() { let args: Args = Args::from_args(); + init_logging(args.log_level).expect("Unable to init logging"); let cfg = match GeoffreyBotConfig::new(args.config.as_path()) { Ok(cfg) => cfg, Err(e) => { - println!("Error opening config: {}", e); + log::warn!("Error opening config: {}", e); return; } }; - let mut client = Client::builder(cfg.discord.token.clone()) + let client = Client::builder(cfg.discord.token.clone()) .event_handler(Handler) .application_id(cfg.discord.app_id) - .await - .expect("Error creating Geoffrey client"); + .await; + let mut client = match client { + Ok(client) => client, + Err(e) => { + log::warn!("Unable to init serenity client: {}", e); + return; + } + }; + + // Block for initializing global data { let mut data = client.data.write().await; @@ -124,7 +144,7 @@ async fn main() { }) } - if let Err(why) = client.start().await { - println!("Client error: {:?}", why); + if let Err(e) = client.start().await { + log::warn!("Client error: {:?}", e); } } diff --git a/geoffrey_models/Cargo.toml b/geoffrey_models/Cargo.toml index 7505875..9edb437 100644 --- a/geoffrey_models/Cargo.toml +++ b/geoffrey_models/Cargo.toml @@ -10,3 +10,4 @@ edition = "2018" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" chrono = { version = "0.4.19", features = ["serde"] } +log = "0.4.14" diff --git a/geoffrey_models/src/lib.rs b/geoffrey_models/src/lib.rs index fd7afcb..3a5cad0 100644 --- a/geoffrey_models/src/lib.rs +++ b/geoffrey_models/src/lib.rs @@ -4,6 +4,7 @@ use serde::Serialize; use std::fmt::Debug; pub mod models; +pub mod logging; pub trait GeoffreyDatabaseModel: Serialize + DeserializeOwned + Debug { fn id(&self) -> Option; diff --git a/geoffrey_models/src/logging/mod.rs b/geoffrey_models/src/logging/mod.rs new file mode 100644 index 0000000..de0d30f --- /dev/null +++ b/geoffrey_models/src/logging/mod.rs @@ -0,0 +1,34 @@ +use log::LevelFilter; +use serde::{Serialize, Deserialize}; + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub enum LogLevel { + None, + Warn, + Info, + Debug, +} + +impl From<&str> for LogLevel { + #[allow(clippy::wildcard_in_or_patterns)] + fn from(s: &str) -> Self { + let s = s.to_lowercase(); + match s.as_str() { + "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, + } + } +}