# Relastic Simple rust lib inspired by Serilog for application-wide logging: - Application wide logs - Posting logs to Elastic to access them with Kibana ## Purpose Log to Elastic from Rust applications ## Intended consumers Everyone. Do not use in production without first assessing the risks involved. ## Main technologies - Rust - NixShell ## Available at crates.io (relastic) ## Requirements - Rust or Nix and Direnv (this will install rust for you) ## More documentation - `cargo doc --open` or [docs.rs](https://docs.rs/relastic/latest/relastic/) ## Testing locally - `cargo test` in the main folder to run tests ## Known issues - Needs to explicitly wait before closing sender since sender is non-blocking. - No support for creating/updating templates from code - HashMaps for mapping values - We probably don't need to put sender behind RwLock (although the RwLock has no cap on readers) ## Usage ```rs 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, ); /* ... */ log::flush(); } ``` ## Usage with Rocket.rs [Rocket](https://rocket.rs) 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: ```rs 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. ## Log to console in dev-environment You may want to simplify logging while you're developing, by logging to console instead: ```rs 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 { match env_type { LogEnvironment::Development => Ok(String::with_capacity(0)), LogEnvironment::Production => get_env(name), } } pub fn get_config() -> Result { let env_type = get_env_enum::("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::("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. ## How to log 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. ```rs 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()) ]) ); } ``` ## Contributing You are welcome to reports bugs, contribute code or open issues.