dumbo_config 0.3.4

a config loader
Documentation

dumbo-config

dumbo-config 是一个灵活配置加载器,提供三种不同层次的 API 来满足各种配置加载需求。

核心 API

dumbo-config 提供三个主要入口函数,按使用场景从简单到复杂排列:

1. load_config - 自动搜索配置文件

最简单的使用方式,自动按顺序搜索以下配置文件:

  1. config.{ENV}.yml
  2. config.{ENV}.yaml
  3. config.yml
  4. config.yaml

其中 ENV 是环境变量 "ENV" 的值。如果未设置 "ENV",则默认搜索 config.ymlconfig.yaml

use dumbo_config::load_config;
use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct AppConfig {
    name: String,
    value: i32,
}

// 自动搜索并加载配置
let config: Option<AppConfig> = load_config();

适用场景:标准项目结构,配置文件位于项目根目录,使用默认命名约定。


2. load_named_config - 指定配置文件路径

当配置文件不在默认位置或使用非标准名称时,使用此函数指定具体路径。

use dumbo_config::load_named_config;
use serde::Deserialize;
use std::path::Path;

#[derive(Debug, Deserialize)]
struct AppConfig {
    name: String,
    value: i32,
}

// 从指定路径加载配置
let config_path = Path::new("configs/production.yaml");
let config: Option<AppConfig> = load_named_config(config_path);

适用场景:配置文件位于非标准位置,或需要根据运行时条件动态选择配置文件。


3. load_config_with_param - 高级配置加载

最强大的加载方式,支持从文件和环境变量组合加载配置,提供完善的错误处理。

LoadingParam 结构

load_config_with_param 函数接收一个 LoadingParam 参数,它定义配置加载的来源:

pub struct LoadingParam {
    /// 配置文件路径,如果为 None 则不从文件加载
    pub file: Option<&'static Path>,
    /// 环境变量前缀配置,如果为 None 则不从环境变量加载
    pub env_prefix: Option<EnvConfig>,
}

字段说明

  • file: 配置文件路径,设置为 Some(path) 时从文件加载
  • env_prefix: 环境变量前缀配置,设置为 Some(EnvConfig) 时从环境变量加载

使用示例

use dumbo_config::{LoadingParam, EnvConfig, load_config_with_param};
use serde::Deserialize;
use std::path::Path;

#[derive(Debug, Deserialize)]
struct AppConfig {
    database_url: String,
    port: u16,
    debug: bool,
}

// 仅从文件加载
let param = LoadingParam {
    file: Some(Path::new("config.yaml")),
    env_prefix: None,  // 不从环境变量加载
};
let config: AppConfig = load_config_with_param(&param)?;

// 仅从环境变量加载
let param = LoadingParam {
    file: None,  // 不从文件加载
    env_prefix: Some(EnvConfig::new("MY_APP".to_string(), None)),
};
let config: AppConfig = load_config_with_param(&param)?;

// 从文件和环境变量加载(环境变量优先)
let param = LoadingParam {
    file: Some(Path::new("config.yaml")),
    env_prefix: Some(EnvConfig::new("MY_APP".to_string(), None)),
};
let config: AppConfig = load_config_with_param(&param)?;

适用场景

  • 需要从环境变量覆盖配置文件
  • 需要详细的错误信息
  • 生产环境需要更严格的配置验证

返回值Result<T, ConfigError>,提供全面的错误处理。

最佳实践:文件 + 环境变量组合配置

推荐同时配置文件和环境变量,环境变量会自动覆盖配置文件中的值。这样可以在不同环境下使用同一套代码,只需通过环境变量覆盖需要变化的配置项。

优势

  • ✅ 代码简洁,无需环境判断逻辑
  • ✅ config.yml 作为默认配置模板,包含所有配置项的默认值
  • ✅ 生产环境只需设置需要覆盖的环境变量(如敏感信息)
  • ✅ 灵活,可以部分覆盖配置

配置对比示例

假设您的应用配置结构如下:

#[derive(Debug, Deserialize)]
struct AppConfig {
    database_url: String,
    port: u16,
    debug: bool,
}

config.yml(默认配置)

database_url: "postgres://localhost:5432/dev_db"
port: 3000
debug: true

.env(生产环境覆盖)

# 只需覆盖需要变化的配置项
MY_APP__DATABASE_URL=postgres://prod-server:5432/prod_db
MY_APP__DEBUG=false
# port 未设置,将使用 config.yml 中的默认值 3000

统一的加载代码

use dumbo_config::{LoadingParam, EnvConfig, load_config_with_param};
use std::path::Path;

fn load_app_config() -> Result<AppConfig, ConfigError> {
    // 同时配置文件和环境变量
    // 开发环境:只使用 config.yml
    // 生产环境:config.yml + 环境变量覆盖
    let param = LoadingParam {
        file: Some(Path::new("config.yml")),
        env_prefix: Some(EnvConfig::new("MY_APP".to_string(), None)),
    };
    
    load_config_with_param(&param)
}

工作流程

  1. 首先加载 config.yml 中的所有配置项作为默认值
  2. 然后加载以 MY_APP__ 为前缀的环境变量
  3. 环境变量会覆盖 config.yml 中同名的配置项
  4. 未设置环境变量的配置项保持 config.yml 中的默认值

环境变量配置

使用 load_config_with_param 时,可以通过 EnvConfig 配置环境变量加载。

EnvConfig 结构

pub struct EnvConfig {
    /// 环境变量前缀,例如 "MY_APP"
    pub name: String,
    /// 环境变量分隔符,默认为 "__"
    pub separator: Option<String>,
}

创建方式

// 使用默认分隔符 "__"
let env_config = EnvConfig::new("MY_APP".to_string(), None);

// 使用自定义分隔符
let env_config = EnvConfig::new("MY_APP".to_string(), Some("_".to_string()));

环境变量命名规则

给定以下配置结构:

struct DatabaseConfig {
    host: String,
    port: u16,
    credentials: Credentials,
}

struct Credentials {
    username: String,
    password: String,
}

使用 EnvConfig::new("MY_APP".to_string(), None)(默认分隔符 "__"),对应的环境变量为:

# 顶层字段
export MY_APP__HOST="localhost"
export MY_APP__PORT="5432"

# 嵌套字段(使用双下划线作为分隔符)
export MY_APP__CREDENTIALS__USERNAME="myuser"
export MY_APP__CREDENTIALS__PASSWORD="mypass"

注意:环境变量前缀不应包含分隔符。例如,如果前缀是 "RESUME_AGENT" 而分隔符是 "_",这将导致配置加载错误。


日志记录和调试

该库在 INFO 级别提供详细的日志记录:

  • 始终记录正在使用的配置源
  • 当设置了 env_prefix 并且 SHOW_SETTINGS 环境变量设置为 "true"(不区分大小写)时,记录配置加载成功的信息
  • 如果未找到指定前缀的环境变量,则记录警告并继续加载配置,不使用环境变量

注意SHOW_SETTINGS 环境变量仅在配置了 env_prefix 时才会被检查。这是因为如果没有设置 env_prefix,意味着用户直接从文件加载配置,他们可以直接检查配置文件来查看设置。当使用环境变量进行配置(通过 env_prefix)时,实际值可能不容易看到,因此 SHOW_SETTINGS 提供了一种记录加载的配置以进行调试的方法。

要启用配置调试,如果 env_prefix 是 'MY_APP',请设置 SHOW_SETTINGS 环境变量:

export MY_APP__SHOW_SETTINGS=true
./your-application

SHOW_SETTINGS 支持的值(不区分大小写):"true"、"1"、"yes"、"on"


错误处理

load_config_with_param 提供全面的错误处理,所有错误都包装在 ConfigError 枚举中:

  • InvalidLoadingParam: LoadingParamfileenv_prefix 字段都为 None - 告诉运维人员需要配置至少一个来源
  • InvalidEnvConfig: 环境前缀包含分隔符
  • FileNotFound: 指定的配置文件不存在
  • ShowSettingsParseError: SHOW_SETTINGS 环境变量无法解析为布尔值

load_configload_named_config 返回 Option<T>,加载失败时返回 None,错误信息通过日志记录。


功能特性总结

  • ✅ 三种加载 API,适应不同使用场景
  • ✅ 支持环境变量,可配置前缀和自定义分隔符
  • ✅ 增强的日志记录,包含加载源信息
  • ✅ SHOW_SETTINGS 环境变量用于调试配置
  • ✅ 全面的错误处理,提供运维友好的错误信息

联系方式

电子邮件: zongying_cao@163.com

涵树的微信公众号