diff --git a/internal/standup-bot/Cargo.lock b/internal/standup-bot/Cargo.lock index d4537add8..08f982dbb 100644 --- a/internal/standup-bot/Cargo.lock +++ b/internal/standup-bot/Cargo.lock @@ -8,6 +8,15 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "aho-corasick" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" +dependencies = [ + "memchr", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -217,6 +226,8 @@ dependencies = [ "serenity", "thiserror 2.0.19", "tokio", + "tracing", + "tracing-subscriber", ] [[package]] @@ -784,6 +795,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "levenshtein" version = "1.0.5" @@ -829,6 +846,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + [[package]] name = "memchr" version = "2.8.0" @@ -887,6 +913,15 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "num-conv" version = "0.2.0" @@ -1177,6 +1212,23 @@ dependencies = [ "bitflags", ] +[[package]] +name = "regex-automata" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + [[package]] name = "reqwest" version = "0.12.28" @@ -1471,6 +1523,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" @@ -1656,6 +1717,15 @@ dependencies = [ "syn 3.0.3", ] +[[package]] +name = "thread_local" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" +dependencies = [ + "cfg-if", +] + [[package]] name = "time" version = "0.3.47" @@ -1864,6 +1934,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" 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-serde" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" +dependencies = [ + "serde", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "serde", + "serde_json", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", + "tracing-serde", ] [[package]] @@ -1989,6 +2102,12 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4bf03e0ca70d626ecc4ba6b0763b934b6f2976e8c744088bb3c1d646fbb1ad0" +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "version_check" version = "0.9.5" diff --git a/internal/standup-bot/Cargo.toml b/internal/standup-bot/Cargo.toml index a808c8687..a2fd06c88 100644 --- a/internal/standup-bot/Cargo.toml +++ b/internal/standup-bot/Cargo.toml @@ -12,3 +12,5 @@ tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread"] } chrono = "0.4.43" chrono-tz = "0.10.4" bb8-redis = "0.26.0" +tracing = "0.1.44" +tracing-subscriber = { version = "0.3.23", features = ["json", "env-filter"] } diff --git a/internal/standup-bot/example.env b/internal/standup-bot/example.env index 788ccfc50..acd641b66 100644 --- a/internal/standup-bot/example.env +++ b/internal/standup-bot/example.env @@ -7,3 +7,6 @@ DISCORD_GUILD_ID= DISCORD_CHANNEL_ID= REDIS_URI= + +# Leave unset locally. +ENVIRONMENT= diff --git a/internal/standup-bot/example.env.production b/internal/standup-bot/example.env.production index 788ccfc50..000a8784b 100644 --- a/internal/standup-bot/example.env.production +++ b/internal/standup-bot/example.env.production @@ -7,3 +7,5 @@ DISCORD_GUILD_ID= DISCORD_CHANNEL_ID= REDIS_URI= + +ENVIRONMENT=production diff --git a/internal/standup-bot/src/discord/handlers.rs b/internal/standup-bot/src/discord/handlers.rs index b443c6520..442a34d16 100644 --- a/internal/standup-bot/src/discord/handlers.rs +++ b/internal/standup-bot/src/discord/handlers.rs @@ -20,6 +20,11 @@ use serenity::{ }, async_trait, }; +use tracing::{ + error, + info, + warn, +}; use crate::{ common::latch::CountdownLatch, @@ -44,12 +49,12 @@ impl Handler { return Ok(()); }; - println!("Received command interaction: {command:#?}"); + info!("Received command interaction: {command:#?}"); let content = match command.data.name.as_str() { "hello" => Some(commands::hello::run(&command.data.options())), cmd => { - eprintln!("Command {cmd} not supported"); + warn!("Command {cmd} not supported"); None } }; @@ -86,7 +91,7 @@ impl Handler { async fn on_ready(&self, ctx: Context) -> anyhow::Result<()> { let commands = get_commands(self.guild_id, ctx).await?; - println!("I now have the following guild slash commands: {commands:#?}"); + info!("I now have the following guild slash commands: {commands:#?}"); Ok(()) } @@ -96,21 +101,21 @@ impl Handler { impl EventHandler for Handler { async fn interaction_create(&self, ctx: Context, interaction: Interaction) { if let Err(e) = self.on_interaction(ctx, interaction).await { - eprintln!("interaction handler failed: {e:#?}"); + error!("interaction handler failed: {e:#?}"); } } async fn message(&self, _ctx: Context, new_message: Message) { if let Err(e) = self.on_message(new_message).await { - eprintln!("message handler failed: {e:#?}"); + error!("message handler failed: {e:#?}"); } } async fn ready(&self, ctx: Context, ready: Ready) { - println!("{} is connected!", ready.user.name); + info!("{} is connected!", ready.user.name); if let Err(e) = self.on_ready(ctx).await { - eprintln!("ready handler failed: {e:#?}"); + error!("ready handler failed: {e:#?}"); } self.latch.count_down(); diff --git a/internal/standup-bot/src/discord/mod.rs b/internal/standup-bot/src/discord/mod.rs index ad6cbc5d3..4fb22fe16 100644 --- a/internal/standup-bot/src/discord/mod.rs +++ b/internal/standup-bot/src/discord/mod.rs @@ -22,6 +22,10 @@ use serenity::{ }, http::Http, }; +use tracing::{ + error, + info, +}; use crate::{ common::latch::CountdownLatch, @@ -64,7 +68,7 @@ impl DiscordClient { tokio::spawn(async move { if let Err(e) = client.start().await { - eprintln!("Client error: {e:?}"); + error!("Client error: {e:?}"); } }); @@ -79,7 +83,7 @@ impl DiscordClient { } pub async fn send_standup_message(&self) -> Result { - println!("Sending standup message!"); + info!("Sending standup message!"); let embed = CreateEmbed::new() .title("Codebloom Standup") @@ -99,14 +103,14 @@ impl DiscordClient { let msg = channel .send_message(self.http.as_ref(), create_msg) .await - .inspect_err(|e| eprintln!("Error sending message: {e:#?}"))?; + .inspect_err(|e| error!("Error sending message: {e:#?}"))?; let thread_builder = CreateThread::new("Daily Standup Thread"); let thread = channel .create_thread_from_message(self.http.as_ref(), msg.id, thread_builder) .await - .inspect_err(|e| eprintln!("Error creating thread: {e:#?}"))?; + .inspect_err(|e| error!("Error creating thread: {e:#?}"))?; Ok(thread.id.get()) } diff --git a/internal/standup-bot/src/main.rs b/internal/standup-bot/src/main.rs index 979c55939..30c1efe6c 100644 --- a/internal/standup-bot/src/main.rs +++ b/internal/standup-bot/src/main.rs @@ -8,6 +8,7 @@ use tokio::time::{ Duration, interval, }; +use tracing::error; use crate::{ common::standup::{ @@ -27,12 +28,35 @@ mod discord; mod env; mod redis; +fn init_tracing() { + let is_production = std::env::var("ENVIRONMENT") + .map(|v| v.eq_ignore_ascii_case("production")) + .unwrap_or(false); + + let env_filter = tracing_subscriber::EnvFilter::try_from_default_env() + .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")); + + if is_production { + tracing_subscriber::fmt() + .json() + .with_env_filter(env_filter) + .init(); + } else { + tracing_subscriber::fmt() + .pretty() + .with_env_filter(env_filter) + .init(); + } +} + #[tokio::main] async fn main() -> Result<()> { if let Err(e) = dotenv() { eprintln!("Failed to load .env but continuing anyways...: {e:#?}\n\n"); } + init_tracing(); + let redis_creds = RedisCredentials::new()?; let redis_client = Arc::new(RedisClient::new(&redis_creds).await?); @@ -52,21 +76,21 @@ async fn main() -> Result<()> { let thread_id = match standup_discord.send_standup_message().await { Ok(id) => id, Err(e) => { - eprintln!("Failed to send standup message: {e:#?}"); + error!("Failed to send standup message: {e:#?}"); return; } }; if let Err(e) = standup_redis.set_standup_thread_id(thread_id).await { - eprintln!("Failed to persist standup thread id: {e:#?}"); + error!("Failed to persist standup thread id: {e:#?}"); } if let Err(e) = standup_redis.set_last_standup(Utc::now()).await { - eprintln!("Failed to save standup to Redis: {e:#?}"); + error!("Failed to save standup to Redis: {e:#?}"); } } Err(e) => { - eprintln!("Failed to get last standup from Redis: {e:#?}"); + error!("Failed to get last standup from Redis: {e:#?}"); } _ => (), } @@ -80,7 +104,7 @@ async fn main() -> Result<()> { let already_sent = match eod_redis.get_eod_reminder_sent(today).await { Ok(v) => v, Err(e) => { - eprintln!("Failed to get eod_reminder_sent from Redis: {e:#?}"); + error!("Failed to get eod_reminder_sent from Redis: {e:#?}"); return; } }; @@ -92,7 +116,7 @@ async fn main() -> Result<()> { let members = match eod_discord.get_standup_role_members().await { Ok(m) => m, Err(e) => { - eprintln!("Failed to fetch standup role members: {e:#?}"); + error!("Failed to fetch standup role members: {e:#?}"); return; } }; @@ -100,7 +124,7 @@ async fn main() -> Result<()> { let replied = match eod_redis.get_standup_replies(today).await { Ok(r) => r, Err(e) => { - eprintln!("Failed to get standup replies from Redis: {e:#?}"); + error!("Failed to get standup replies from Redis: {e:#?}"); return; } }; @@ -111,12 +135,12 @@ async fn main() -> Result<()> { continue; } if let Err(e) = eod_discord.send_eod_reminder_dm(user_id).await { - eprintln!("Failed to send EOD reminder DM to {user_id}: {e:#?}"); + error!("Failed to send EOD reminder DM to {user_id}: {e:#?}"); } } if let Err(e) = eod_redis.set_eod_reminder_sent(today).await { - eprintln!("Failed to save eod_reminder_sent to Redis: {e:#?}"); + error!("Failed to save eod_reminder_sent to Redis: {e:#?}"); } }); }