Skip to content

Commit

Permalink
feat: completely rewrite logger
Browse files Browse the repository at this point in the history
  • Loading branch information
newtykip committed Jul 23, 2023
1 parent 7194318 commit d98562d
Show file tree
Hide file tree
Showing 13 changed files with 224 additions and 292 deletions.
File renamed without changes.
5 changes: 3 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
},
"files.exclude": {
"target": true,
"Cargo.lock": true
"Cargo.lock": true,
"src/build_data.rs": true
},
"rust-analyzer.cargo.features": "all",
"rust-analyzer.cargo.buildScripts.enable": true
// "rust-analyzer.cargo.buildScripts.enable": true
}
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ dev = ["dep:dotenvy_macro"] # never enable this in production

[dependencies]
async-trait = { version = "0.1.71", optional = true }
bitflags = "2.3.3"
cfg-if = "1.0.0"
chrono = "0.4.26"
color-eyre = "0.6.2"
Expand All @@ -54,6 +55,7 @@ rustflake = { version = "0.1.1", optional = true }
sea-orm = { version = "0.11.3", optional = true, features = ["runtime-tokio-rustls", "macros"] }
serde = "1.0.171"
serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "cache"] }
strip-ansi = "0.1.0"
strum = { version = "0.25.0", optional = true }
tokio = { version = "1.28.2", features = ["full"] }
toml = "0.7.6"
Expand Down
36 changes: 24 additions & 12 deletions src/events/general/ready.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
use johnny::{logger::Style, preludes::event::*};
use johnny::{build_data::FEATURES, preludes::event::*};
#[cfg(johnny)]
use poise::serenity_prelude::Activity;
use poise::serenity_prelude::Ready;

pub async fn ready(
#[cfg(any(johnny, sqlite))] ctx: &Context,
ready: &Ready,
data: &Data,
) -> Result<()> {
data.logger
.info(
vec![
("Logged in as ".into(), None),
(ready.user.name.clone(), Some(Style::default().bold())),
pub async fn ready(#[cfg(any(johnny, sqlite))] ctx: &Context, ready: &Ready) -> Result<()> {
// list enabled features
if !FEATURES.is_empty() {
logger::info(
components![
"Enabled features: " => Bold,
FEATURES.join(", ") => None
],
None,
)
.await?;
}

// log that the bot is ready
logger::info(
components![
"Logged in as " => None,
ready.user.name.clone() => Bold
],
None,
)
.await?;

// set the activity
#[cfg(johnny)]
Expand All @@ -26,7 +34,11 @@ pub async fn ready(
// ? is 100 really a sane quantity?
#[cfg(sqlite)]
if ctx.cache.guild_count() > 100 {
data.logger.warn(vec![("hi".into(), None)], None).await?;
logger::warn(
components!["You are in over 100 guilds. Perhaps you should swap from sqlite?"],
None,
)
.await?;
}

Ok(())
Expand Down
7 changes: 3 additions & 4 deletions src/events/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use ::johnny::preludes::general::*;
#[cfg(johnny)]
use ::johnny::SUGGESTIONS_ID;
use ::johnny::{preludes::general::*, Data};
use poise::Event;
use serenity::client::Context;

Expand All @@ -11,16 +11,15 @@ mod johnny;
pub async fn event_handler(
event: &Event<'_>,
#[allow(unused_variables)] ctx: &Context,
data: &Data,
) -> Result<()> {
match event {
// ready
Event::Ready { data_about_bot } => {
cfg_if! {
if #[cfg(any(johnny, sqlite))] {
general::ready(ctx, data_about_bot, data).await
general::ready(ctx, data_about_bot).await
} else {
general::ready(data_about_bot, data).await
general::ready(data_about_bot).await
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
pub mod build_data;
#[cfg(db)]
pub mod db;
pub mod embed;
pub mod logger;
mod macros;
pub mod preludes;

use logger::Logger;
#[cfg(johnny)]
use poise::serenity_prelude::{ChannelId, EmojiId, ReactionType};
#[cfg(db)]
Expand All @@ -25,7 +25,6 @@ pub struct Data {
pub johnny_images: Vec<String>,
#[cfg(db)]
pub db: DatabaseConnection,
pub logger: Logger,
#[cfg(db)]
pub guilds_in_db: RwLock<HashSet<GuildId>>,
#[cfg(db)]
Expand Down
145 changes: 93 additions & 52 deletions src/logger/entry.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,27 @@
use super::LogLevel;
use super::Style;
use super::{Components, LogLevel, Style};
use crate::preludes::general::*;
use chrono::{DateTime, Local};

cfg_if! {
if #[cfg(tui)] {
use ratatui::{
style::{Color as RatColour, Modifier as RatModifier, Style as RatStyle},
text::{Line, Span, Text},
widgets::Paragraph,
};
use poise::serenity_prelude::{ChannelId, Guild, User};
} else {
use owo_colors::{OwoColorize, Stream::Stdout};
use poise::serenity_prelude::{Guild, User, ChannelId};
}
}

pub type Message = Vec<(String, Option<Style>)>;
// https://docs.rs/chrono/latest/chrono/format/strftime/index.html
const TIMESTAMP_FORMAT: &str = "%d/%m/%y %r %Z";

#[derive(Debug, Clone)]
pub struct Entry {
pub timestamp: DateTime<Local>,
pub level: LogLevel,
pub message: Message,
#[cfg(tui)]
pub components: Components,
pub timestamp: DateTime<Local>,
pub guild: Option<Guild>,
#[cfg(tui)]
pub user: Option<User>,
#[cfg(tui)]
pub channel: Option<ChannelId>,
}

unsafe impl Sync for Entry {}

impl PartialEq for Entry {
fn eq(&self, other: &Self) -> bool {
self.timestamp == other.timestamp
Expand All @@ -39,32 +30,56 @@ impl PartialEq for Entry {

cfg_if! {
if #[cfg(tui)] {
use ratatui::{
style::{Color as Colour, Modifier, Style as RatStyle},
text::{Line, Span, Text},
widgets::Paragraph,
};

impl Entry {
fn lines(&self) -> Vec<Line> {
vec![Line::from({
let mut spans = vec![
Span::styled(
self.timestamp.to_string() + " ",
RatStyle::default().fg(RatColour::Cyan),
self.timestamp.format(TIMESTAMP_FORMAT).to_string() + " ",
RatStyle::default().fg(Colour::Cyan),
),
Span::styled(
format!("[{}] ", self.level.to_string()),
RatStyle::default()
.add_modifier(RatModifier::BOLD)
.add_modifier(Modifier::BOLD)
.fg(match self.level {
LogLevel::Info => RatColour::Green,
LogLevel::Warn => RatColour::Yellow,
LogLevel::Command => RatColour::White,
LogLevel::Error => RatColour::Red,
LogLevel::Info => Colour::Green,
LogLevel::Warn => Colour::Yellow,
LogLevel::Error => Colour::Red,
LogLevel::Command => Colour::White
}),
),
];

spans.extend(self.message.iter().map(|(content, style)| {
if let Some(style) = style {
Span::styled(content, (*style).into())
spans.extend(self.components.iter().map(|(text, style)| {
let text = text.to_string();
let mut tui_style = Some(RatStyle::default());

// apply styles to component
for flag in style.iter() {
if let Some(x) = tui_style {
match flag {
Style::Bold => tui_style = Some(x.add_modifier(Modifier::BOLD)),
Style::Red => tui_style = Some(x.fg(Colour::Red)),
Style::Green => tui_style = Some(x.fg(Colour::Green)),
Style::Yellow => tui_style = Some(x.fg(Colour::Yellow)),
_ => tui_style = None
};
} else {
break;
}
}

if let Some(tui_style) = tui_style {
Span::styled(text, tui_style)
} else {
Span::raw(content)
Span::raw(text)
}
}));

Expand All @@ -77,39 +92,65 @@ cfg_if! {
}

pub fn paragraph(&self) -> Paragraph {
Paragraph::new(self.lines())
Paragraph::new(self.text())
}
}
} else {
use owo_colors::{Stream::Stdout, OwoColorize};
use strip_ansi::strip_ansi;

impl ToString for Entry {
fn to_string(&self) -> String {
[
self.timestamp
.if_supports_color(Stdout, |text| text.cyan())
.to_string(),
format!("[{}]", self.level.to_string())
.if_supports_color(Stdout, |text| match self.level {
LogLevel::Info => text.green().bold().to_string(),
LogLevel::Warn => text.yellow().bold().to_string(),
LogLevel::Command => text.white().bold().to_string(),
LogLevel::Error => text.red().bold().to_string()
})
.to_string(),
self.message
format!(
"{} {} {}",
// format timestamp
self.timestamp.format(TIMESTAMP_FORMAT).to_string().if_supports_color(Stdout, |x| x.cyan()),
// format level
format!("[{}]", self.level.to_string()).if_supports_color(Stdout, |x| match self.level {
LogLevel::Info => x.green().bold().to_string(),
LogLevel::Warn => x.yellow().bold().to_string(),
LogLevel::Error => x.red().bold().to_string(),
LogLevel::Command => x.bold().to_string()
}),
// build message from components
self
.components
.iter()
.map(|(content, style)| {
if let Some(style) = style {
content
.if_supports_color(Stdout, |text| text.style((*style).into()))
.to_string()
} else {
content.clone()
.map(|(text, style)| {
let mut text = text.to_string();

// apply styles to component
for flag in style.iter() {
text = text
.if_supports_color(Stdout, |x| match flag {
Style::BOLD => x.bold().to_string(),
Style::RED => x.red().to_string(),
Style::GREEN => x.green().to_string(),
Style::YELLOW => x.yellow().to_string(),
_ => x.to_string(),
})
.to_string();
}

// colour code booleans
text.split_whitespace()
.map(|word| {
let stripped = strip_ansi(word);

word.if_supports_color(Stdout, |x| match stripped.as_str() {
"true" => x.green().to_string(),
"false" => x.red().to_string(),
_ => x.to_string(),
})
.to_string()
})
.collect::<Vec<String>>()
.join(" ")
})
.collect::<String>(),
]
.join(" ")
.collect::<String>()
)
}
}

}
}
5 changes: 2 additions & 3 deletions src/logger/level.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
#[derive(Debug, Clone, PartialEq)]
pub enum LogLevel {
Info,
Command,
Warn,
Error,
Command,
}

impl ToString for LogLevel {
fn to_string(&self) -> String {
match self {
LogLevel::Info => "INFO".to_string(),
LogLevel::Command => "COMMAND".to_string(),
LogLevel::Warn => "WARN".to_string(),
LogLevel::Error => "ERROR".to_string(),
LogLevel::Command => "COMMAND".to_string(),
}
}
}
Loading

0 comments on commit d98562d

Please sign in to comment.