flex-logger 0.0.2

Simple logger implementing the log crate interface. Multi thread and buffered.
Documentation
# flex-logger
This is a simple logger implementing the log crate interface. 

- It is simple to initialize and use, and supports logging directly on the caller thread as well as on a separate thread. 
- It supports logging with different timestamps format (utc/local)
- It supports tracing the thread id of the called as well.
- It supports logging on different targets (stdout/file) and the logging is buffered with a custom buffer size (which should make it faster to avoid a lot of locks on the resource in use.) 

## Note
The `flush` method of the log crate interface was implemented here as cleanup. 
In other words, this call ensures that all the buffered logs are immediately flushed but destroys the logger. 
**Ensure to call this method only at the end of your program**

## Example
```rust
use std::{path::PathBuf, thread};

use rslogger::Logger;
use log::{info, warn, error};

fn main() {
    Logger::new()
        // This is setting the level max to Trace,
        .with_level(log::LevelFilter::Trace)
        // This is setting the timestamps as local
        .with_local_timestamps()
        // This is configuring the logger to log the thread id (if available)
        .with_thread()
        // Add a writer on the stdout. It will use a dedicated thread to log and a buffer capacity of 1000 bytes
        .add_writer_stdout(true, Some(1000))
        // Add a writer on the file. If the file does not exists, it will be created. It will use a dedicated thread to log and a buffer capacity of 10 bytes
        .add_writer_file(PathBuf::from("./LOGS/genercs_1.log"), true, Some(10))
        // Another writer on another file. For this, no buffering will happen
        .add_writer_file(PathBuf::from("./LOGS/genercs_2.log"), true, Some(0))
        // Another writer with default buffer size (100 bytes)
        .add_writer_file(PathBuf::from("./LOGS/genercs_3.log"), true, None)
        // Always call init to allow logging
        .init().unwrap();

    info!("This is a info test");
    warn!("This is a warn test");
    error!("This is an error test");

    let handler1 = thread::Builder::new().name("Thread 1".to_string()).spawn(move | | {
        for i in 0..10 {
            info!("This is a info, i: {i}");
        }
    }).unwrap();

    let handler2 = thread::Builder::new().name("Thread 2".to_string()).spawn(move | | {
        for i in 0..10 {
            info!("This is a info, i: {i}");
        }
    }).unwrap();
    
    warn!("Warning on main!");

    handler1.join().unwrap();
    handler2.join().unwrap();

    // Note: This method must be called only at the end of the program. After that, you can no longer log.
    log::logger().flush();

    // This would panic
    // info!("Test");
}
```
And here is the output of the program: 
```
09:34:31:222312-[][main] -> {INFO} This is a info test
09:34:31:222400-[][main] -> {WARN} This is a warn test
09:34:31:222432-[][main] -> {ERROR} This is an error test
09:34:31:222551-[][main] -> {WARN} Warning on main!
09:34:31:222570-[][Thread 1] -> {INFO} This is a info, i: 0
09:34:31:222622-[][Thread 1] -> {INFO} This is a info, i: 1
09:34:31:222616-[][Thread 2] -> {INFO} This is a info, i: 0
09:34:31:222657-[][Thread 1] -> {INFO} This is a info, i: 2
09:34:31:222666-[][Thread 2] -> {INFO} This is a info, i: 1
09:34:31:222685-[][Thread 1] -> {INFO} This is a info, i: 3
09:34:31:222693-[][Thread 2] -> {INFO} This is a info, i: 2
09:34:31:222712-[][Thread 1] -> {INFO} This is a info, i: 4
09:34:31:222714-[][Thread 2] -> {INFO} This is a info, i: 3
09:34:31:222738-[][Thread 1] -> {INFO} This is a info, i: 5
09:34:31:222740-[][Thread 2] -> {INFO} This is a info, i: 4
09:34:31:222769-[][Thread 2] -> {INFO} This is a info, i: 5
09:34:31:222768-[][Thread 1] -> {INFO} This is a info, i: 6
09:34:31:222801-[][Thread 2] -> {INFO} This is a info, i: 6
09:34:31:222802-[][Thread 1] -> {INFO} This is a info, i: 7
09:34:31:222851-[][Thread 1] -> {INFO} This is a info, i: 8
09:34:31:222860-[][Thread 2] -> {INFO} This is a info, i: 7
09:34:31:222883-[][Thread 1] -> {INFO} This is a info, i: 9
09:34:31:222885-[][Thread 2] -> {INFO} This is a info, i: 8
09:34:31:222911-[][Thread 2] -> {INFO} This is a info, i: 9
```
In the [examples](./examples/) directory you will find more examples.