Crates.io | relastic |
lib.rs | relastic |
version | 0.4.5 |
source | src |
created_at | 2021-11-16 08:49:30.32496 |
updated_at | 2023-08-21 12:55:33.512802 |
description | Simple rust lib inspired by Serilog for application-wide logging to Elastic |
homepage | https://intility.com |
repository | https://gitlab.intility.com |
max_upload_size | |
id | 482570 |
size | 37,199 |
Simple rust lib inspired by Serilog for application-wide logging:
Log to Elastic from Rust applications
Everyone. Do not use in production without first assessing the risks involved.
crates.io (relastic)
cargo doc --open
or docs.rscargo test
in the main folder to run testsfn main() {
let elastic_config = match elastic_config::ElasticConfig::new() {
Ok(x) => x,
Err(err) => panic!("Elastic not/improperly configured: {:?}", err),
};
log::setup_elastic_log(
elastic_config,
100,
);
/* ... */
log::flush();
}
Rocket by default does not allow blocking services to run in it's Tokio
runtime. It does have a functionality for running blocking tasks as async, but the logging service should hold precendence over it; If rocket panics, the logger should be able to log this before the application terminates.
Here's how you can setup relastic with Rocket:
fn main() {
let elastic_config = match elastic_config::ElasticConfig::new() {
Ok(x) => x,
Err(err) => panic!("Elastic not/improperly configured: {:?}", err),
};
log::setup_elastic_log(
elastic_config,
100,
);
// Create multi-threaded tokio runtime for rocket
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async {
rocket_main().await;
});
log::flush();
}
This also makes it so that we don't have to rely on Rocket-specific dependencies.
You may want to simplify logging while you're developing, by logging to console instead:
use intility_cloud_lib::env_tools::{get_env, get_env_enum, Error};
use relastic::log::{self, ElasticConfig, LogEnvironment};
use std::collections::HashMap;
fn load_if_prod(name: &str, env_type: &LogEnvironment) -> Result<String, Error> {
match env_type {
LogEnvironment::Development => Ok(String::with_capacity(0)),
LogEnvironment::Production => get_env(name),
}
}
pub fn get_config() -> Result<ElasticConfig, Error> {
let env_type = get_env_enum::<LogEnvironment>("APPLICATION_ENVIRONMENT")?;
let username = load_if_prod("ELASTIC_USERNAME", &env_type)?;
let password = load_if_prod("ELASTIC_PASSWORD", &env_type)?;
let url = load_if_prod("ELASTIC_URL", &env_type)?;
let environment_string = get_env_enum::<LogEnvironment>("APPLICATION_ENVIRONMENT")?;
let application_name = get_env("APPLICATION_NAME")?;
Ok(ElasticConfig {
username,
password,
url,
environment: environment_string,
application_name,
})
}
pub fn get_config_or_log_and_panic() -> ElasticConfig {
match get_config() {
Ok(x) => x,
Err(err) => {
log::fatal(
"Elastic config is missing or is misconfigured: {err}",
HashMap::from([("err", format!("{}", err))]),
);
panic!("{}", err)
}
}
}
fn main() {
let elastic_config = get_config_or_log_and_panic();
if elastic_config.environment == LogEnvironment::Production {
log::setup_elastic_log(elastic_config.clone(), 100);
} else {
log::setup_console_log()
}
/* ... */
log::flush();
}
This way you don't have to actually set any environment variables when working locally.
When logging you can either use the log functions directly, or you can use the included macros to reduce the amount of boilerplate code needed.
pub fn my_fn()
{
// Logging with a macro
log_information!("Got the following message: {message}", "Hello world");
// Logging with a function:
log::information(
"Got the following message: {message}",
HashMap::from([
("message", "Hello World!".to_string())
])
);
}
You are welcome to reports bugs, contribute code or open issues.