log_loki facilitates collecting and shipping your application's logs to a Loki instance. It does this by integrating with the log crate.
Please be advised that I do not consider this crate production ready at this time. I've verified that it "basically works," but I have yet to write comphrensive tests and optimize out any inefficiencies that may exist. Caveat emptor!
To add log_loki to your project, ensure the following two lines are present in your Cargo.toml
:
toml
log = "^0.4.17"
log_loki = "^0.1.0"
The crate supports the following features:
- tls
- Use rustls to support communicating with Loki over TLS.
- tls-native-certs
- Tell ureq, the underlying HTTP library, to use the system's certificate store instead of the webpki-roots store for TLS.
- compress
- Compress logs en route to Loki using GZIP (through the flate2 crate).
- kv_unstable
- Enable experimental support for the log crate's structured logging.
- logfmt
- Enable the logfmt formatter for logs.
The default features are tls
, tls-native-certs
, logfmt
, and compress
. By default, the logfmt
feature is used to format logs. If the feature is disabled, you must provide
your own LokiFormatter
implementation.
## Usage
To log exclusively to an unauthenticated Loki instance, the following may be used:
```Rust use log::{info, logger}; use log_loki::LokiBuilder; use url::Url; use std::collections::HashMap;
fn main() { let mut labels = HashMap::new(); labels.insert("app", "myapp");
LokiBuilder::new(
Url::parse("https://loki.example.com/loki/api/v1/push").unwrap(),
labels,
).build().apply().unwrap();
info!("Hello, {}!", "world");
// The logger must be flushed before the application quits to ensure logs are not lost.
logger().flush();
} ``` Through the .addheader() and .tlsconfig() LokiBuilder methods, header and mTLS-based authentication schemes can be used.
If you'd like to log to Loki as well as other locations (such as a log file, console, etc), you can use a logging framework like Fern to combine log_loki with other logging implementations:
```Rust // Let loki be a Loki object let colors = ColoredLevelConfig::default();
fern::Dispatch::new()
.level(log::LevelFilter::Trace)
.chain(Box::new(loki) as Box
info!("Test!");
// call somewhere before the program ends logger().flush(); ```
For efficiency's sake, the logger buffers log messages internally and waits until either a certain amount of messages have been logged or a certain amount of time has passed. You can tweek the number of messages
or the duration between auto-flushes using the max_logs()
and max_log_lifetime()
LokiBuilder
methods respectively. It is also recommended that you arrange for all exit paths in your code to call logger().flush();
to minimize the risk of any logs being dropped.
```Rust /* Copyright (C) 2022 Aurora McGinnis
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ ```