# Rotation Logger
A simple async rotation logger library for Rust. It can be safely used across threads by passing a logger instance as an argument or via macros.
## Example
### 1. Configure the Formatter
Define how log strings and timestamps are formatted:
```rust
let formatter = MessageFormatter::new(
"::",
"{timestamp:-6:30:right}{splitter}{modules:_:_:left}{splitter}{message}",
"%Y-%m-%d %H:%M:%S.%f",
);
```
The configuration consists of three parts:
- **Splitter symbol** — a character used to separate fields in the log line.
- **Format string** — defines the layout of each log line using masks. Each mask (except `splitter`) is surrounded by curly braces and supports formatting options separated by `:`.
Available masks:
- `timestamp` — where the timestamp will be printed.
- `splitter` — where the splitter character will be inserted.
- `modules` — the source modules of the log entry (joined by the splitter).
- `message` — the log message itself.
Formatting syntax inside curly braces:
```
{<mask>:<string_length>:<column_width>:<text_halign>}
```
- `string_length` — limits string length. Positive value trims from the end; negative value trims from the start.
- `column_width` — fixed column width. Content is sliced if it doesn't fit.
- `text_halign` — horizontal alignment: `left`, `right`, or `center`.
Any formatting option can be omitted using `_`:
```
{<mask>:_:<column_width>:_}
```
- **Timestamp format** — a `chrono`-compatible format string used for the `timestamp` mask.
---
### 2. Configure the Output Channel
Choose where logs are written: `file`, `console`, or `auto` (console in debug mode, file in release mode).
```rust
let output = OutputChannel::file(
"./".into(),
10,
FileSize::from_megabytes(5),
"new_logger".into(),
"log".into(),
);
```
---
### 3. Create Settings
The first argument enables or disables the logger. When disabled, all log methods remain available but do nothing internally.
```rust
let settings = Settings::new(true, 5, output, formatter);
```
---
### 4. Create a Logger Instance
A logger instance can be safely `.clone()`d and passed to other threads.
```rust
let logger = Logger::new(settings);
let logger_01 = logger.clone();
let logger_02 = logger.clone();
```
---
### 5. Run the Logger
Start the async logger. You can join on its handle or keep another long-lived thread alive.
```rust
let joiner = logger.run_async();
```
---
### 6. Use the Logger in Other Threads
Pass cloned instances into spawned threads:
```rust
let _ = thread::spawn(move || {
logger_02.log(&vec!["THREAD2".into(), "MAIN".into()], "Starting...");
let mut counter = 0;
loop {
logger_02.log(
&vec!["THREAD2".into(), "WORKER".into()],
format!("Processing Job: {counter}").as_str(),
);
counter += 2;
sleep(Duration::from_millis(400));
}
});
```
---
For a complete example, see [Demo](./examples/demo.rs).