Skip to content

Commit 4f2ab97

Browse files
authored
feat: logging improvements
feat: logging improvements
2 parents ba0a1fb + fda8ee2 commit 4f2ab97

File tree

11 files changed

+1102
-176
lines changed

11 files changed

+1102
-176
lines changed

crates/lambda-rs-logging/README.md

Lines changed: 87 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,48 +2,112 @@
22
![lambda-rs](https://img.shields.io/crates/d/lambda-rs-logging)
33
![lambda-rs](https://img.shields.io/crates/v/lambda-rs-logging)
44

5-
A simple logger implementation for lamba-rs crates. Inspired by
6-
python's [logging](https://docs.python.org/3/library/logging.html) module.
5+
Simple, lightweight logging for lambda-rs crates. Inspired by Python’s
6+
[logging](https://docs.python.org/3/library/logging.html) module.
77

88

9-
# Installation
10-
First, add the following to your `Cargo.toml`:
9+
## Installation
10+
Add to your `Cargo.toml`:
1111
```toml
1212
[dependencies]
13+
# Option A: use the crate name in code as `lambda_rs_logging`
1314
lambda-rs-logging = "2023.1.30"
15+
16+
# Option B: rename dependency so you can write `use logging;`
17+
# logging = { package = "lambda-rs-logging", version = "2023.1.30" }
1418
```
1519

16-
or run this command from your project directory:
20+
Or from your project directory:
1721
```bash
1822
cargo add lambda-rs-logging
1923
```
2024

21-
# Getting started
22-
## Using the global logger
25+
Then in code, either import with the default name:
26+
```rust
27+
use lambda_rs_logging as logging;
28+
```
29+
or, if you used the rename in Cargo.toml (Option B), simply:
30+
```rust
31+
use logging; // renamed in Cargo.toml
32+
```
33+
34+
## Getting Started
35+
### Global logger via macros
2336
```rust
24-
use logging;
37+
use lambda_rs_logging as logging;
2538

2639
fn main() {
27-
logging::trace!("Hello world");
28-
logging::debug!("Hello world");
29-
logging::info!("Hello world");
30-
logging::warn!("Hello world");
31-
logging::error!("Hello world");
32-
logging::fatal!("Hello world");
40+
logging::trace!("trace {}", 1);
41+
logging::debug!("debug {}", 2);
42+
logging::info!("info {}", 3);
43+
logging::warn!("warn {}", 4);
44+
logging::error!("error {}", 5);
45+
logging::fatal!("fatal {}", 6); // note: does not exit
3346
}
3447
```
3548

36-
## Using an instance of the logger
49+
### Custom logger instance
3750
```rust
38-
use logging::Logger;
51+
use lambda_rs_logging as logging;
3952

4053
fn main() {
41-
let logger = Logger::new("my-logger");
42-
logger.trace("Hello world");
43-
logger.debug("Hello world");
44-
logger.info("Hello world");
45-
logger.warn("Hello world");
46-
logger.error("Hello world");
47-
logger.fatal("Hello world");
54+
let logger = logging::Logger::builder()
55+
.name("my-app")
56+
.level(logging::LogLevel::INFO)
57+
.with_handler(Box::new(logging::handler::ConsoleHandler::new("my-app")))
58+
.build();
59+
60+
logger.info("Hello world".to_string());
61+
logger.warn("Be careful".to_string());
62+
}
63+
```
64+
65+
### Initialize a custom global
66+
```rust
67+
use lambda_rs_logging as logging;
68+
69+
fn main() {
70+
let logger = logging::Logger::builder()
71+
.name("app")
72+
.level(logging::LogLevel::DEBUG)
73+
.with_handler(Box::new(logging::handler::ConsoleHandler::new("app")))
74+
.build();
75+
76+
// Set the global logger before any macros are used
77+
logging::Logger::init(logger).expect("global logger can only be initialized once");
78+
79+
logging::debug!("from global");
4880
}
4981
```
82+
83+
### Configure level from environment
84+
```rust
85+
use lambda_rs_logging as logging;
86+
87+
fn main() {
88+
// LAMBDA_LOG can be: trace|debug|info|warn|error|fatal
89+
// Example: export LAMBDA_LOG=debug
90+
logging::env::init_global_from_env().ok();
91+
92+
logging::info!("respects env filter");
93+
}
94+
```
95+
96+
## Notes
97+
- Thread-safe global with `OnceLock<Arc<Logger>>`.
98+
- Handlers are `Send + Sync` and receive a `Record` internally (phase 1 refactor).
99+
- `fatal!` logs at FATAL level but does not exit the process. Prefer explicit exits in your app logic.
100+
- Console handler colors only when attached to a TTY and writes WARN+ to stderr.
101+
102+
## Examples
103+
This crate ships with examples. From the repository root:
104+
```bash
105+
cargo run -p lambda-rs-logging --example 01_global_macros
106+
cargo run -p lambda-rs-logging --example 02_custom_logger
107+
cargo run -p lambda-rs-logging --example 03_global_init
108+
```
109+
110+
### Environment example
111+
```bash
112+
LAMBDA_LOG=debug cargo run -p lambda-rs-logging --example 01_global_macros
113+
```
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fn main() {
2+
logging::trace!("trace example");
3+
logging::debug!("debug example: {}", 42);
4+
logging::info!("info example");
5+
logging::warn!("warn example");
6+
logging::error!("error example");
7+
logging::fatal!("fatal example (no exit)");
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fn main() {
2+
let logger = logging::Logger::new(logging::LogLevel::DEBUG, "custom");
3+
logger.add_handler(Box::new(logging::handler::ConsoleHandler::new("custom")));
4+
5+
logger.trace("this will be filtered unless level <= TRACE".to_string());
6+
logger.debug("debug from custom logger".to_string());
7+
logger.info("info from custom logger".to_string());
8+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
fn main() {
2+
let logger = logging::Logger::new(logging::LogLevel::INFO, "app");
3+
logger.add_handler(Box::new(logging::handler::ConsoleHandler::new("app")));
4+
5+
logging::Logger::init(logger)
6+
.expect("global logger can only be initialized once");
7+
8+
logging::info!("hello from initialized global");
9+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// When building examples inside the crate, refer to the library as `logging` directly.
2+
3+
fn main() {
4+
// Build a custom logger and apply env level
5+
let logger = logging::Logger::builder()
6+
.name("builder-env")
7+
.level(logging::LogLevel::INFO)
8+
.with_handler(Box::new(logging::handler::ConsoleHandler::new(
9+
"builder-env",
10+
)))
11+
.build();
12+
13+
logging::env::apply_env_level(&logger, Some("LAMBDA_LOG"));
14+
15+
logger.debug("filtered unless LAMBDA_LOG=debug".to_string());
16+
logger.info("visible at info".to_string());
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Inside this crate, refer to the lib as `logging` directly.
2+
3+
fn main() {
4+
let path = std::env::temp_dir().join("lambda_json_example.log");
5+
let path_s = path.to_string_lossy().to_string();
6+
7+
let logger = logging::Logger::builder()
8+
.name("json-example")
9+
.level(logging::LogLevel::TRACE)
10+
.with_handler(Box::new(logging::handler::JsonHandler::new(path_s.clone())))
11+
.build();
12+
13+
logger.info("json info".to_string());
14+
logger.error("json error".to_string());
15+
16+
println!("wrote JSON to {}", path_s);
17+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
fn main() {
2+
let base = std::env::temp_dir().join("lambda_rotate_example.log");
3+
let base_s = base.to_string_lossy().to_string();
4+
5+
let logger = logging::Logger::builder()
6+
.name("rotate-example")
7+
.level(logging::LogLevel::TRACE)
8+
.with_handler(Box::new(logging::handler::RotatingFileHandler::new(
9+
base_s.clone(),
10+
256, // bytes
11+
3, // keep 3 backups
12+
)))
13+
.build();
14+
15+
for i in 0..200 {
16+
logger.info(format!("log line {:03}", i));
17+
}
18+
19+
println!("rotation base: {} (check .1, .2, .3)", base_s);
20+
}

0 commit comments

Comments
 (0)