-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
425 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# Ftail | ||
|
||
Ftail is simple logging implementation for the `log` crate with support for multiple drivers. | ||
|
||
- Stdout (standard output logging) | ||
- Console (formatted output logging) | ||
- Daily (daily log rotation) | ||
- Single (single log file) | ||
|
||
## Usage | ||
|
||
```rust | ||
use ftail::Ftail; | ||
|
||
Ftail::new() | ||
.add_driver(ConsoleLogger::new(), log::LevelFilter::Trace) | ||
.init()?; | ||
|
||
log::debug!("This is a debug message"); | ||
log::info!("This is an info message"); | ||
``` | ||
|
||
## Drivers | ||
|
||
### Stdout | ||
|
||
Logs to the standard output. | ||
|
||
```sh | ||
2024-09-10 14:41:57 TRACE stdout This is a trace message | ||
2024-09-10 14:41:57 DEBUG stdout This is a debug message | ||
2024-09-10 14:41:57 INFO foo bar | ||
2024-09-10 14:41:57 WARN stdout This is a warning | ||
2024-09-10 14:41:57 ERROR stdout This is an error | ||
``` | ||
|
||
### Console | ||
|
||
Logs to the standard output with formatted and colored output. | ||
|
||
```sh | ||
2024-09-10 14:42:21 · TRACE | ||
This is a trace message | ||
examples\console\src/main.rs:8 | ||
|
||
2024-09-10 14:42:21 · DEBUG | ||
This is a debug message | ||
examples\console\src/main.rs:10 | ||
|
||
2024-09-10 14:42:21 · INFO | ||
bar | ||
examples\console\src/main.rs:12 | ||
|
||
2024-09-10 14:42:21 · WARN | ||
This is a warning | ||
examples\console\src/main.rs:14 | ||
|
||
2024-09-10 14:42:21 · ERROR | ||
This is an error | ||
examples\console\src/main.rs:16 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[package] | ||
name = "stdout" | ||
version = "0.1.0" | ||
edition = "2021" | ||
publish = false | ||
|
||
[dependencies] | ||
log = "0.4" | ||
ftail = { path = "../../../ftail" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
use ftail::{drivers::stdout::StdOutLogger, Ftail}; | ||
|
||
fn main() -> Result<(), Box<dyn std::error::Error>> { | ||
Ftail::new() | ||
.add_driver(StdOutLogger::new(), log::LevelFilter::Trace) | ||
.init()?; | ||
|
||
log::trace!("This is a trace message"); | ||
|
||
log::debug!("This is a debug message"); | ||
|
||
log::info!(target: "foo", "bar"); | ||
|
||
log::warn!("This is a warning"); | ||
|
||
log::error!("This is an error"); | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,270 @@ | ||
use std::fmt::{Display, Formatter, Result}; | ||
|
||
macro_rules! generate_styling_functions { | ||
( | ||
$(#[$enum_attrs:meta])* | ||
$vis:vis enum $enum_name:ident { | ||
$( | ||
#[code = $code:literal] | ||
$(#[$variant_attrs:meta])* | ||
$variant:ident | ||
),* | ||
$(,)? | ||
} | ||
) => { | ||
$(#[$enum_attrs])* | ||
$vis enum $enum_name { | ||
$( | ||
$(#[$variant_attrs])* | ||
$variant, | ||
)* | ||
} | ||
|
||
impl $enum_name { | ||
#[allow(dead_code)] | ||
pub fn code(&self) -> u8 { | ||
match self { | ||
$(Self::$variant => $code,)* | ||
} | ||
} | ||
} | ||
|
||
impl $enum_name { | ||
$( | ||
#[allow(dead_code)] | ||
pub fn $variant() -> Self { | ||
Self::$variant | ||
} | ||
)* | ||
} | ||
|
||
#[allow(dead_code)] | ||
pub trait TextStyling: Display { | ||
$( | ||
fn $variant(self) -> Style<Self> | ||
where | ||
Self: Sized, | ||
{ | ||
self.style($enum_name::$variant) | ||
} | ||
)* | ||
} | ||
|
||
impl<T: Display> TextStyling for T {} | ||
} | ||
} | ||
|
||
pub struct Style<T> { | ||
text: T, | ||
code: u8, | ||
} | ||
|
||
generate_styling_functions! { | ||
#[allow(dead_code)] | ||
#[allow(non_camel_case_types)] | ||
pub enum StyleCode { | ||
#[code = 30] | ||
black, | ||
#[code = 31] | ||
red, | ||
#[code = 32] | ||
green, | ||
#[code = 33] | ||
yellow, | ||
#[code = 34] | ||
blue, | ||
#[code = 35] | ||
magenta, | ||
#[code = 36] | ||
cyan, | ||
#[code = 37] | ||
white, | ||
#[code = 90] | ||
bright_black, | ||
#[code = 91] | ||
bright_red, | ||
#[code = 92] | ||
bright_green, | ||
#[code = 93] | ||
bright_yellow, | ||
#[code = 94] | ||
bright_blue, | ||
#[code = 95] | ||
bright_magenta, | ||
#[code = 96] | ||
bright_cyan, | ||
#[code = 97] | ||
bright_white, | ||
#[code = 40] | ||
bg_black, | ||
#[code = 41] | ||
bg_red, | ||
#[code = 42] | ||
bg_green, | ||
#[code = 43] | ||
bg_yellow, | ||
#[code = 44] | ||
bg_blue, | ||
#[code = 45] | ||
bg_magenta, | ||
#[code = 46] | ||
bg_cyan, | ||
#[code = 47] | ||
bg_white, | ||
#[code = 100] | ||
bg_bright_black, | ||
#[code = 101] | ||
bg_bright_red, | ||
#[code = 102] | ||
bg_bright_green, | ||
#[code = 103] | ||
bg_bright_yellow, | ||
#[code = 104] | ||
bg_bright_blue, | ||
#[code = 105] | ||
bg_bright_magenta, | ||
#[code = 106] | ||
bg_bright_cyan, | ||
#[code = 107] | ||
bg_bright_white, | ||
#[code = 1] | ||
bold, | ||
#[code = 3] | ||
italic, | ||
#[code = 4] | ||
underline, | ||
#[code = 9] | ||
strikethrough, | ||
} | ||
} | ||
|
||
pub trait GeneratedTextStyling: Display + TextStyling { | ||
fn style(self, style_code: StyleCode) -> Style<Self> | ||
where | ||
Self: Sized, | ||
{ | ||
Style { | ||
text: self, | ||
code: style_code.code(), | ||
} | ||
} | ||
} | ||
|
||
impl<T: Display> GeneratedTextStyling for T {} | ||
|
||
impl<T: Display> Display for Style<T> { | ||
fn fmt(&self, f: &mut Formatter) -> Result { | ||
write!(f, "\x1b[{}m{}\x1b[0m", self.code, self.text) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_text_styling() { | ||
let text = "Hello, world!"; | ||
|
||
let black = text.black(); | ||
let red = text.red(); | ||
let green = text.green(); | ||
let yellow = text.yellow(); | ||
let blue = text.blue(); | ||
let magenta = text.magenta(); | ||
let cyan = text.cyan(); | ||
let white = text.white(); | ||
let bright_black = text.bright_black(); | ||
let bright_red = text.bright_red(); | ||
let bright_green = text.bright_green(); | ||
let bright_yellow = text.bright_yellow(); | ||
let bright_blue = text.bright_blue(); | ||
let bright_magenta = text.bright_magenta(); | ||
let bright_cyan = text.bright_cyan(); | ||
let bright_white = text.bright_white(); | ||
let bg_black = text.bg_black(); | ||
let bg_red = text.bg_red(); | ||
let bg_green = text.bg_green(); | ||
let bg_yellow = text.bg_yellow(); | ||
let bg_blue = text.bg_blue(); | ||
let bg_magenta = text.bg_magenta(); | ||
let bg_cyan = text.bg_cyan(); | ||
let bg_white = text.bg_white(); | ||
let bg_bright_black = text.bg_bright_black(); | ||
let bg_bright_red = text.bg_bright_red(); | ||
let bg_bright_green = text.bg_bright_green(); | ||
let bg_bright_yellow = text.bg_bright_yellow(); | ||
let bg_bright_blue = text.bg_bright_blue(); | ||
let bg_bright_magenta = text.bg_bright_magenta(); | ||
let bg_bright_cyan = text.bg_bright_cyan(); | ||
let bg_bright_white = text.bg_bright_white(); | ||
let bold = text.bold(); | ||
let italic = text.italic(); | ||
let underline = text.underline(); | ||
let strikethrough = text.strikethrough(); | ||
|
||
assert_eq!(format!("{}", black), "\x1b[30mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", red), "\x1b[31mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", green), "\x1b[32mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", yellow), "\x1b[33mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", blue), "\x1b[34mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", magenta), "\x1b[35mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", cyan), "\x1b[36mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", white), "\x1b[37mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", bright_black), "\x1b[90mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", bright_red), "\x1b[91mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", bright_green), "\x1b[92mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", bright_yellow), "\x1b[93mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", bright_blue), "\x1b[94mHello, world!\x1b[0m"); | ||
assert_eq!( | ||
format!("{}", bright_magenta), | ||
"\x1b[95mHello, world!\x1b[0m" | ||
); | ||
assert_eq!(format!("{}", bright_cyan), "\x1b[96mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", bright_white), "\x1b[97mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", bg_black), "\x1b[40mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", bg_red), "\x1b[41mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", bg_green), "\x1b[42mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", bg_yellow), "\x1b[43mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", bg_blue), "\x1b[44mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", bg_magenta), "\x1b[45mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", bg_cyan), "\x1b[46mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", bg_white), "\x1b[47mHello, world!\x1b[0m"); | ||
assert_eq!( | ||
format!("{}", bg_bright_black), | ||
"\x1b[100mHello, world!\x1b[0m" | ||
); | ||
assert_eq!( | ||
format!("{}", bg_bright_red), | ||
"\x1b[101mHello, world!\x1b[0m" | ||
); | ||
assert_eq!( | ||
format!("{}", bg_bright_green), | ||
"\x1b[102mHello, world!\x1b[0m" | ||
); | ||
assert_eq!( | ||
format!("{}", bg_bright_yellow), | ||
"\x1b[103mHello, world!\x1b[0m" | ||
); | ||
assert_eq!( | ||
format!("{}", bg_bright_blue), | ||
"\x1b[104mHello, world!\x1b[0m" | ||
); | ||
assert_eq!( | ||
format!("{}", bg_bright_magenta), | ||
"\x1b[105mHello, world!\x1b[0m" | ||
); | ||
assert_eq!( | ||
format!("{}", bg_bright_cyan), | ||
"\x1b[106mHello, world!\x1b[0m" | ||
); | ||
assert_eq!( | ||
format!("{}", bg_bright_white), | ||
"\x1b[107mHello, world!\x1b[0m" | ||
); | ||
assert_eq!(format!("{}", bold), "\x1b[1mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", italic), "\x1b[3mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", underline), "\x1b[4mHello, world!\x1b[0m"); | ||
assert_eq!(format!("{}", strikethrough), "\x1b[9mHello, world!\x1b[0m"); | ||
} | ||
} |
Oops, something went wrong.