#logging #applications #wide #lib #access #serilog #kibana

relastic

受 Serilog 启发的简单 Rust 库,用于应用程序范围内的日志记录到 Elastic

15 个不稳定版本 (3 个重大变更)

0.4.5 2023 年 8 月 21 日
0.4.4 2023 年 6 月 7 日
0.3.2 2023 年 5 月 26 日
0.2.1 2022 年 10 月 6 日
0.1.1 2021 年 11 月 30 日

#299 in 数据库接口

MIT 许可证

38KB
777

Relastic

受 Serilog 启发的简单 Rust 库,用于应用程序范围内的日志记录

  • 应用程序范围内的日志
  • 将日志发布到 Elastic 以使用 Kibana 访问

目的

从 Rust 应用程序将日志记录到 Elastic

目标用户

所有人。在评估涉及的风险之前,不要在生产环境中使用。

主要技术

  • Rust
  • NixShell

可在以下位置获得

crates.io (relastic)

要求

  • Rust 或 Nix 和 Direnv(这将为您安装 rust)

更多文档

本地测试

  • cargo test 在主文件夹中运行测试

已知问题

  • 由于发送者是非阻塞的,需要在关闭发送者之前显式等待。
  • 不支持从代码中创建/更新模板
  • 使用 HashMap 映射值
  • 我们可能不需要将发送者放在 RwLock 后面(尽管 RwLock 对读取者没有限制)

用法

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();
}

与 Rocket.rs 一起使用

Rocket 默认情况下不允许在它的 Tokio 运行时中运行阻塞服务。它确实有一个功能可以在异步中运行阻塞任务,但日志服务应该优先于它;如果 Rocket 发生 panic,则记录器应该在应用程序终止之前记录此信息。

以下是设置 relastic 与 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();
}

这也使得我们不必依赖于 Rocket 特定的依赖项。

在开发环境中将日志记录到控制台

在开发过程中,您可能希望通过将日志记录到控制台来简化日志记录

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();
}

这样,在本地工作时,您实际上不必设置任何环境变量。

如何记录

在记录日志时,您可以直接使用日志函数,或者可以使用包含的宏来减少所需样板代码的数量。

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())
        ])
    );
}

贡献

欢迎您报告错误、贡献代码或打开问题。

依赖项

~5–19MB
~301K SLoC