brokkr-utils::config Rust
Structs
brokkr-utils::config::Settings
pub
Derives: Debug, Deserialize, Clone
Represents the main settings structure for the application
Fields
| Name | Type | Description |
|---|---|---|
database | Database | Database configuration |
log | Log | Logging configuration |
pak | PAK | PAK configuration |
agent | Agent | Agent configuration |
broker | Broker | Broker configuration |
cors | Cors | CORS configuration |
telemetry | Telemetry | Telemetry configuration |
Methods
new pub
#![allow(unused)]
fn main() {
fn new (file : Option < String >) -> Result < Self , ConfigError >
}
Creates a new Settings instance
Parameters:
| Name | Type | Description |
|---|---|---|
file | - | An optional path to a configuration file |
Returns:
Returns a Result containing the Settings instance or a ConfigError
Source
#![allow(unused)]
fn main() {
pub fn new(file: Option<String>) -> Result<Self, ConfigError> {
// Start with default settings from the embedded TOML file
let mut s = Config::builder()
.add_source(File::from_str(DEFAULT_SETTINGS, config::FileFormat::Toml));
// If a configuration file is provided, add it as a source
s = match file {
Some(x) => s.add_source(File::with_name(x.as_str())),
None => s,
};
// Add environment variables as a source, prefixed with "BROKKR" and using "__" as a separator
s = s.add_source(Environment::with_prefix("BROKKR").separator("__"));
// Build the configuration
let settings = s.build().unwrap();
// Deserialize the configuration into a Settings instance
settings.try_deserialize()
}
}
brokkr-utils::config::Cors
pub
Derives: Debug, Deserialize, Clone
Represents the CORS configuration
Fields
| Name | Type | Description |
|---|---|---|
allowed_origins | Vec < String > | Allowed origins for CORS requests |
| Use “*” to allow all origins (not recommended for production) | ||
| Can be set as comma-separated string via env var: “origin1,origin2” | ||
allowed_methods | Vec < String > | Allowed HTTP methods |
| Can be set as comma-separated string via env var: “GET,POST,PUT” | ||
allowed_headers | Vec < String > | Allowed HTTP headers |
| Can be set as comma-separated string via env var: “Authorization,Content-Type” | ||
max_age_seconds | u64 | Max age for preflight cache in seconds |
brokkr-utils::config::Broker
pub
Derives: Debug, Deserialize, Clone
Fields
| Name | Type | Description |
|---|---|---|
pak_hash | Option < String > | PAK Hash |
diagnostic_cleanup_interval_seconds | Option < u64 > | Interval for diagnostic cleanup task in seconds (default: 900 = 15 minutes) |
diagnostic_max_age_hours | Option < i64 > | Maximum age for completed/expired diagnostics before deletion in hours (default: 1) |
webhook_encryption_key | Option < String > | Webhook encryption key (hex-encoded, 32 bytes for AES-256) |
| If not provided, a random key will be generated on startup (not recommended for production) | ||
webhook_delivery_interval_seconds | Option < u64 > | Webhook delivery worker interval in seconds (default: 5) |
webhook_delivery_batch_size | Option < i64 > | Webhook delivery batch size (default: 50) |
webhook_cleanup_retention_days | Option < i64 > | Webhook delivery cleanup retention in days (default: 7) |
audit_log_retention_days | Option < i64 > | Audit log retention in days (default: 90) |
auth_cache_ttl_seconds | Option < u64 > | Auth cache TTL in seconds (default: 60). Set to 0 to disable caching. |
brokkr-utils::config::Agent
pub
Derives: Debug, Deserialize, Clone
Represents the agent configuration
Fields
| Name | Type | Description |
|---|---|---|
broker_url | String | Broker URL |
polling_interval | u64 | Polling interval in seconds |
kubeconfig_path | Option < String > | Kubeconfig path |
max_retries | u32 | Max number of retries |
pak | String | PAK |
agent_name | String | Agent name |
cluster_name | String | Cluster name |
max_event_message_retries | usize | Max number of retries for event messages |
event_message_retry_delay | u64 | Delay between event message retries in seconds |
health_port | Option < u16 > | Health check HTTP server port |
deployment_health_enabled | Option < bool > | Whether deployment health checking is enabled |
deployment_health_interval | Option < u64 > | Interval for deployment health checks in seconds |
brokkr-utils::config::Database
pub
Derives: Debug, Deserialize, Clone
Represents the database configuration
Fields
| Name | Type | Description |
|---|---|---|
url | String | Database connection URL |
schema | Option < String > | Optional schema name for multi-tenant isolation |
brokkr-utils::config::Log
pub
Derives: Debug, Deserialize, Clone
Represents the logging configuration
Fields
| Name | Type | Description |
|---|---|---|
level | String | Log level (e.g., “info”, “debug”, “warn”, “error”) |
format | String | Log format: “text” for human-readable, “json” for structured JSON |
brokkr-utils::config::Telemetry
pub
Derives: Debug, Deserialize, Clone
Represents the telemetry (OpenTelemetry) configuration with hierarchical overrides
Fields
| Name | Type | Description |
|---|---|---|
enabled | bool | Whether telemetry is enabled (base default) |
otlp_endpoint | String | OTLP endpoint for trace export (gRPC) |
service_name | String | Service name for traces |
sampling_rate | f64 | Sampling rate (0.0 to 1.0) |
broker | TelemetryOverride | Broker-specific overrides |
agent | TelemetryOverride | Agent-specific overrides |
Methods
for_broker pub
#![allow(unused)]
fn main() {
fn for_broker (& self) -> ResolvedTelemetry
}
Get resolved telemetry config for broker (base merged with broker overrides)
Source
#![allow(unused)]
fn main() {
pub fn for_broker(&self) -> ResolvedTelemetry {
ResolvedTelemetry {
enabled: self.broker.enabled.unwrap_or(self.enabled),
otlp_endpoint: self
.broker
.otlp_endpoint
.clone()
.unwrap_or_else(|| self.otlp_endpoint.clone()),
service_name: self
.broker
.service_name
.clone()
.unwrap_or_else(|| self.service_name.clone()),
sampling_rate: self.broker.sampling_rate.unwrap_or(self.sampling_rate),
}
}
}
for_agent pub
#![allow(unused)]
fn main() {
fn for_agent (& self) -> ResolvedTelemetry
}
Get resolved telemetry config for agent (base merged with agent overrides)
Source
#![allow(unused)]
fn main() {
pub fn for_agent(&self) -> ResolvedTelemetry {
ResolvedTelemetry {
enabled: self.agent.enabled.unwrap_or(self.enabled),
otlp_endpoint: self
.agent
.otlp_endpoint
.clone()
.unwrap_or_else(|| self.otlp_endpoint.clone()),
service_name: self
.agent
.service_name
.clone()
.unwrap_or_else(|| self.service_name.clone()),
sampling_rate: self.agent.sampling_rate.unwrap_or(self.sampling_rate),
}
}
}
brokkr-utils::config::TelemetryOverride
pub
Derives: Debug, Deserialize, Clone, Default
Component-specific telemetry overrides (all fields optional)
Fields
| Name | Type | Description |
|---|---|---|
enabled | Option < bool > | Override enabled flag |
otlp_endpoint | Option < String > | Override OTLP endpoint |
service_name | Option < String > | Override service name |
sampling_rate | Option < f64 > | Override sampling rate |
brokkr-utils::config::ResolvedTelemetry
pub
Derives: Debug, Clone
Resolved telemetry configuration after merging base with overrides
Fields
| Name | Type | Description |
|---|---|---|
enabled | bool | |
otlp_endpoint | String | |
service_name | String | |
sampling_rate | f64 |
brokkr-utils::config::PAK
pub
Derives: Debug, Deserialize, Clone
Represents the PAK configuration
Fields
| Name | Type | Description |
|---|---|---|
prefix | Option < String > | PAK prefix |
digest | Option < String > | Digest algorithm for PAK |
rng | Option < String > | RNG type for PAK |
short_token_length | Option < usize > | Short token length for PAK |
short_token_length_str | Option < String > | Short token length as a string |
short_token_prefix | Option < String > | Prefix for short tokens |
long_token_length | Option < usize > | Long token length for PAK |
long_token_length_str | Option < String > | Long token length as a string |
Methods
short_length_as_str pub
#![allow(unused)]
fn main() {
fn short_length_as_str (& mut self)
}
Convert short token length to string
Source
#![allow(unused)]
fn main() {
pub fn short_length_as_str(&mut self) {
self.short_token_length_str = self.short_token_length.map(|v| v.to_string());
}
}
long_length_as_str pub
#![allow(unused)]
fn main() {
fn long_length_as_str (& mut self)
}
Convert long token length to string
Source
#![allow(unused)]
fn main() {
pub fn long_length_as_str(&mut self) {
self.long_token_length_str = self.long_token_length.map(|v| v.to_string());
}
}
brokkr-utils::config::DynamicConfig
pub
Derives: Debug, Clone
Dynamic configuration values that can be hot-reloaded at runtime.
These settings can be updated without restarting the application. Changes are applied atomically via the RwLock in ReloadableConfig.
Fields
| Name | Type | Description |
|---|---|---|
log_level | String | Log level (e.g., “info”, “debug”, “warn”, “error”) |
diagnostic_cleanup_interval_seconds | u64 | Interval for diagnostic cleanup task in seconds |
diagnostic_max_age_hours | i64 | Maximum age for completed/expired diagnostics before deletion in hours |
webhook_delivery_interval_seconds | u64 | Webhook delivery worker interval in seconds |
webhook_delivery_batch_size | i64 | Webhook delivery batch size |
webhook_cleanup_retention_days | i64 | Webhook delivery cleanup retention in days |
cors_allowed_origins | Vec < String > | Allowed origins for CORS requests |
cors_max_age_seconds | u64 | Max age for CORS preflight cache in seconds |
Methods
from_settings pub
#![allow(unused)]
fn main() {
fn from_settings (settings : & Settings) -> Self
}
Create DynamicConfig from Settings
Source
#![allow(unused)]
fn main() {
pub fn from_settings(settings: &Settings) -> Self {
Self {
log_level: settings.log.level.clone(),
diagnostic_cleanup_interval_seconds: settings
.broker
.diagnostic_cleanup_interval_seconds
.unwrap_or(900),
diagnostic_max_age_hours: settings.broker.diagnostic_max_age_hours.unwrap_or(1),
webhook_delivery_interval_seconds: settings
.broker
.webhook_delivery_interval_seconds
.unwrap_or(5),
webhook_delivery_batch_size: settings.broker.webhook_delivery_batch_size.unwrap_or(50),
webhook_cleanup_retention_days: settings
.broker
.webhook_cleanup_retention_days
.unwrap_or(7),
cors_allowed_origins: settings.cors.allowed_origins.clone(),
cors_max_age_seconds: settings.cors.max_age_seconds,
}
}
}
brokkr-utils::config::ConfigChange
pub
Derives: Debug, Clone
Represents a configuration change detected during reload
Fields
| Name | Type | Description |
|---|---|---|
key | String | The configuration key that changed |
old_value | String | The old value (as string for display) |
new_value | String | The new value (as string for display) |
brokkr-utils::config::ReloadableConfig
pub
Derives: Clone
Configuration wrapper that separates static (restart-required) settings from dynamic (hot-reloadable) settings.
Static settings are immutable after creation and require an application
restart to change. Dynamic settings can be updated at runtime via the
reload() method.
Examples:
use brokkr_utils::config::ReloadableConfig;
let config = ReloadableConfig::new(None)?;
// Read dynamic config (thread-safe)
let log_level = config.log_level();
// Reload config from sources
let changes = config.reload()?;
for change in changes {
println!("Changed {}: {} -> {}", change.key, change.old_value, change.new_value);
}
Fields
| Name | Type | Description |
|---|---|---|
static_config | Settings | Static configuration that requires restart to change |
dynamic | Arc < RwLock < DynamicConfig > > | Dynamic configuration that can be hot-reloaded |
config_file | Option < String > | Optional path to config file for reloading |
Methods
new pub
#![allow(unused)]
fn main() {
fn new (file : Option < String >) -> Result < Self , ConfigError >
}
Creates a new ReloadableConfig instance
Parameters:
| Name | Type | Description |
|---|---|---|
file | - | An optional path to a configuration file |
Returns:
Returns a Result containing the ReloadableConfig instance or a ConfigError
Source
#![allow(unused)]
fn main() {
pub fn new(file: Option<String>) -> Result<Self, ConfigError> {
let settings = Settings::new(file.clone())?;
let dynamic = DynamicConfig::from_settings(&settings);
Ok(Self {
static_config: settings,
dynamic: Arc::new(RwLock::new(dynamic)),
config_file: file,
})
}
}
from_settings pub
#![allow(unused)]
fn main() {
fn from_settings (settings : Settings , config_file : Option < String >) -> Self
}
Creates a ReloadableConfig from an existing Settings instance
Parameters:
| Name | Type | Description |
|---|---|---|
settings | - | The Settings instance to wrap |
config_file | - | An optional path to the config file for future reloads |
Returns:
Returns a ReloadableConfig instance
Source
#![allow(unused)]
fn main() {
pub fn from_settings(settings: Settings, config_file: Option<String>) -> Self {
let dynamic = DynamicConfig::from_settings(&settings);
Self {
static_config: settings,
dynamic: Arc::new(RwLock::new(dynamic)),
config_file,
}
}
}
static_config pub
#![allow(unused)]
fn main() {
fn static_config (& self) -> & Settings
}
Get a reference to the static (immutable) settings
These settings require an application restart to change.
Source
#![allow(unused)]
fn main() {
pub fn static_config(&self) -> &Settings {
&self.static_config
}
}
reload pub
#![allow(unused)]
fn main() {
fn reload (& self) -> Result < Vec < ConfigChange > , ConfigError >
}
Reload dynamic configuration from sources (file + environment)
Returns a list of configuration changes that were applied. Thread-safe: blocks writers during reload.
Source
#![allow(unused)]
fn main() {
pub fn reload(&self) -> Result<Vec<ConfigChange>, ConfigError> {
// Load fresh settings from sources
let new_settings = Settings::new(self.config_file.clone())?;
let new_dynamic = DynamicConfig::from_settings(&new_settings);
// Acquire write lock and compute changes
let mut dynamic = self
.dynamic
.write()
.map_err(|e| ConfigError::Message(format!("Failed to acquire write lock: {}", e)))?;
let mut changes = Vec::new();
// Check each field for changes
if dynamic.log_level != new_dynamic.log_level {
changes.push(ConfigChange {
key: "log.level".to_string(),
old_value: dynamic.log_level.clone(),
new_value: new_dynamic.log_level.clone(),
});
}
if dynamic.diagnostic_cleanup_interval_seconds
!= new_dynamic.diagnostic_cleanup_interval_seconds
{
changes.push(ConfigChange {
key: "broker.diagnostic_cleanup_interval_seconds".to_string(),
old_value: dynamic.diagnostic_cleanup_interval_seconds.to_string(),
new_value: new_dynamic.diagnostic_cleanup_interval_seconds.to_string(),
});
}
if dynamic.diagnostic_max_age_hours != new_dynamic.diagnostic_max_age_hours {
changes.push(ConfigChange {
key: "broker.diagnostic_max_age_hours".to_string(),
old_value: dynamic.diagnostic_max_age_hours.to_string(),
new_value: new_dynamic.diagnostic_max_age_hours.to_string(),
});
}
if dynamic.webhook_delivery_interval_seconds
!= new_dynamic.webhook_delivery_interval_seconds
{
changes.push(ConfigChange {
key: "broker.webhook_delivery_interval_seconds".to_string(),
old_value: dynamic.webhook_delivery_interval_seconds.to_string(),
new_value: new_dynamic.webhook_delivery_interval_seconds.to_string(),
});
}
if dynamic.webhook_delivery_batch_size != new_dynamic.webhook_delivery_batch_size {
changes.push(ConfigChange {
key: "broker.webhook_delivery_batch_size".to_string(),
old_value: dynamic.webhook_delivery_batch_size.to_string(),
new_value: new_dynamic.webhook_delivery_batch_size.to_string(),
});
}
if dynamic.webhook_cleanup_retention_days != new_dynamic.webhook_cleanup_retention_days {
changes.push(ConfigChange {
key: "broker.webhook_cleanup_retention_days".to_string(),
old_value: dynamic.webhook_cleanup_retention_days.to_string(),
new_value: new_dynamic.webhook_cleanup_retention_days.to_string(),
});
}
if dynamic.cors_allowed_origins != new_dynamic.cors_allowed_origins {
changes.push(ConfigChange {
key: "cors.allowed_origins".to_string(),
old_value: format!("{:?}", dynamic.cors_allowed_origins),
new_value: format!("{:?}", new_dynamic.cors_allowed_origins),
});
}
if dynamic.cors_max_age_seconds != new_dynamic.cors_max_age_seconds {
changes.push(ConfigChange {
key: "cors.max_age_seconds".to_string(),
old_value: dynamic.cors_max_age_seconds.to_string(),
new_value: new_dynamic.cors_max_age_seconds.to_string(),
});
}
// Apply the new configuration
*dynamic = new_dynamic;
Ok(changes)
}
}
log_level pub
#![allow(unused)]
fn main() {
fn log_level (& self) -> String
}
Get current log level
Source
#![allow(unused)]
fn main() {
pub fn log_level(&self) -> String {
self.dynamic
.read()
.map(|d| d.log_level.clone())
.unwrap_or_else(|_| "info".to_string())
}
}
diagnostic_cleanup_interval_seconds pub
#![allow(unused)]
fn main() {
fn diagnostic_cleanup_interval_seconds (& self) -> u64
}
Get diagnostic cleanup interval in seconds
Source
#![allow(unused)]
fn main() {
pub fn diagnostic_cleanup_interval_seconds(&self) -> u64 {
self.dynamic
.read()
.map(|d| d.diagnostic_cleanup_interval_seconds)
.unwrap_or(900)
}
}
diagnostic_max_age_hours pub
#![allow(unused)]
fn main() {
fn diagnostic_max_age_hours (& self) -> i64
}
Get diagnostic max age in hours
Source
#![allow(unused)]
fn main() {
pub fn diagnostic_max_age_hours(&self) -> i64 {
self.dynamic
.read()
.map(|d| d.diagnostic_max_age_hours)
.unwrap_or(1)
}
}
webhook_delivery_interval_seconds pub
#![allow(unused)]
fn main() {
fn webhook_delivery_interval_seconds (& self) -> u64
}
Get webhook delivery interval in seconds
Source
#![allow(unused)]
fn main() {
pub fn webhook_delivery_interval_seconds(&self) -> u64 {
self.dynamic
.read()
.map(|d| d.webhook_delivery_interval_seconds)
.unwrap_or(5)
}
}
webhook_delivery_batch_size pub
#![allow(unused)]
fn main() {
fn webhook_delivery_batch_size (& self) -> i64
}
Get webhook delivery batch size
Source
#![allow(unused)]
fn main() {
pub fn webhook_delivery_batch_size(&self) -> i64 {
self.dynamic
.read()
.map(|d| d.webhook_delivery_batch_size)
.unwrap_or(50)
}
}
webhook_cleanup_retention_days pub
#![allow(unused)]
fn main() {
fn webhook_cleanup_retention_days (& self) -> i64
}
Get webhook cleanup retention in days
Source
#![allow(unused)]
fn main() {
pub fn webhook_cleanup_retention_days(&self) -> i64 {
self.dynamic
.read()
.map(|d| d.webhook_cleanup_retention_days)
.unwrap_or(7)
}
}
cors_allowed_origins pub
#![allow(unused)]
fn main() {
fn cors_allowed_origins (& self) -> Vec < String >
}
Get CORS allowed origins
Source
#![allow(unused)]
fn main() {
pub fn cors_allowed_origins(&self) -> Vec<String> {
self.dynamic
.read()
.map(|d| d.cors_allowed_origins.clone())
.unwrap_or_else(|_| vec!["*".to_string()])
}
}
cors_max_age_seconds pub
#![allow(unused)]
fn main() {
fn cors_max_age_seconds (& self) -> u64
}
Get CORS max age in seconds
Source
#![allow(unused)]
fn main() {
pub fn cors_max_age_seconds(&self) -> u64 {
self.dynamic
.read()
.map(|d| d.cors_max_age_seconds)
.unwrap_or(3600)
}
}
dynamic_snapshot pub
#![allow(unused)]
fn main() {
fn dynamic_snapshot (& self) -> Option < DynamicConfig >
}
Get a snapshot of all dynamic config values
Source
#![allow(unused)]
fn main() {
pub fn dynamic_snapshot(&self) -> Option<DynamicConfig> {
self.dynamic.read().ok().map(|d| d.clone())
}
}
Functions
brokkr-utils::config::deserialize_string_or_vec
private
#![allow(unused)]
fn main() {
fn deserialize_string_or_vec < 'de , D > (deserializer : D) -> Result < Vec < String > , D :: Error > where D : Deserializer < 'de > ,
}
Deserializes a comma-separated string or array into Vec
Source
#![allow(unused)]
fn main() {
fn deserialize_string_or_vec<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
where
D: Deserializer<'de>,
{
use serde::de::{self, SeqAccess, Visitor};
use std::fmt;
struct StringOrVec;
impl<'de> Visitor<'de> for StringOrVec {
type Value = Vec<String>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string or sequence of strings")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
// Split by comma and trim whitespace
Ok(value.split(',').map(|s| s.trim().to_string()).collect())
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut vec = Vec::new();
while let Some(item) = seq.next_element::<String>()? {
vec.push(item);
}
Ok(vec)
}
}
deserializer.deserialize_any(StringOrVec)
}
}
brokkr-utils::config::default_log_format
private
#![allow(unused)]
fn main() {
fn default_log_format () -> String
}
Source
#![allow(unused)]
fn main() {
fn default_log_format() -> String {
"text".to_string()
}
}
brokkr-utils::config::default_otlp_endpoint
private
#![allow(unused)]
fn main() {
fn default_otlp_endpoint () -> String
}
Source
#![allow(unused)]
fn main() {
fn default_otlp_endpoint() -> String {
"http://localhost:4317".to_string()
}
}
brokkr-utils::config::default_service_name
private
#![allow(unused)]
fn main() {
fn default_service_name () -> String
}
Source
#![allow(unused)]
fn main() {
fn default_service_name() -> String {
"brokkr".to_string()
}
}
brokkr-utils::config::default_sampling_rate
private
#![allow(unused)]
fn main() {
fn default_sampling_rate () -> f64
}
Source
#![allow(unused)]
fn main() {
fn default_sampling_rate() -> f64 {
0.1
}
}