Skip to content

Commit

Permalink
feat: Add configuration parsing (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
evanpurkhiser authored Jun 11, 2024
1 parent a589971 commit 34ed278
Show file tree
Hide file tree
Showing 6 changed files with 251 additions and 11 deletions.
114 changes: 114 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ tokio-cron-scheduler = "0.10.2"
uuid = { version = "1.8.0", features = ["serde", "v4"] }
serde = { version = "1.0.159", features = ["derive", "rc"] }
serde_json = "1.0.93"
figment = { version = "0.10", features = ["yaml", "env", "test"] }
similar-asserts = "1.4.2"
sentry = "0.34.0"
thiserror = "1.0.61"
Expand Down
8 changes: 5 additions & 3 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
use std::io;

use clap::Parser;
use tokio::signal::ctrl_c;

use crate::{
cliapp::{Cli, Commands},
logging,
config::Config,
logging::{self, LoggingConfig},
scheduler::run_scheduler,
};
use clap::Parser;

pub fn execute() -> io::Result<()> {
let app = Cli::parse();
let config = Config::extract(&app.config).expect("Configuration invalid");

logging::init();
logging::init(LoggingConfig::from_config(&config));

match app.command {
Commands::Run => tokio::runtime::Builder::new_multi_thread()
Expand Down
94 changes: 94 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use std::{borrow::Cow, path::PathBuf};

use figment::{
providers::{Env, Format, Yaml},
Figment,
};

use serde::{Deserialize, Serialize};

#[derive(PartialEq, Debug, Serialize, Deserialize)]
pub struct Config {
/// The sentry DSN to use for error reporting.
pub sentry_dsn: Option<String>,

/// The environment to report to sentry errors to.
pub sentry_env: Option<Cow<'static, str>>,
}

impl Config {
/// Load configuration from an optional configuration file and environment
pub fn extract(path: &Option<PathBuf>) -> anyhow::Result<Config> {
let builder = Figment::new();

let builder = match path {
Some(path) => builder.merge(Yaml::file(path)),
_ => builder,
};

// Override env variables if provided
let config: Config = builder.merge(Env::prefixed("UPTIME_CHECKER_")).extract()?;

Ok(config)
}
}

#[cfg(test)]
mod tests {
use figment::Jail;
use similar_asserts::assert_eq;

use super::*;

#[test]
fn test_simple() {
Jail::expect_with(|jail| {
jail.create_file(
"config.yaml",
r#"
sentry_dsn: my_dsn
sentry_env: my_env
"#,
)?;

let config = Config::extract(&Some(PathBuf::from("config.yaml")))
.expect("Invalid configuration");

assert_eq!(
config,
Config {
sentry_dsn: Some("my_dsn".to_owned()),
sentry_env: Some(Cow::from("my_env")),
}
);
Ok(())
});
}

#[test]
fn test_onv_override() {
Jail::expect_with(|jail| {
jail.create_file(
"config.yaml",
r#"
sentry_dsn: my_dsn
sentry_env: my_env
"#,
)?;

jail.set_env("UPTIME_CHECKER_SENTRY_ENV", "my_env_override");

let config = Config::extract(&Some(PathBuf::from("config.yaml")))
.expect("Invalid configuration");

assert_eq!(
config,
Config {
sentry_dsn: Some("my_dsn".to_owned()),
sentry_env: Some(Cow::from("my_env_override")),
}
);
Ok(())
});
}
}
44 changes: 36 additions & 8 deletions src/logging.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,40 @@
pub fn init() {
let guard = sentry::init((
"https://[email protected]/4507408549347328",
sentry::ClientOptions {
use std::{borrow::Cow, str::FromStr};

use sentry::types::Dsn;

use crate::config::Config;

#[derive(Debug)]
pub struct LoggingConfig {
/// The DSN key to use for sentry error reporting. If left empty sentry will not be
/// initialized.
pub sentry_dsn: Option<String>,

/// The sentry environment to report errors to.
pub sentry_env: Option<Cow<'static, str>>,
}

impl LoggingConfig {
pub fn from_config(config: &Config) -> Self {
Self {
sentry_dsn: config.sentry_dsn.to_owned(),
sentry_env: config.sentry_env.to_owned(),
}
}
}

pub fn init(config: LoggingConfig) {
if let Some(dsn) = &config.sentry_dsn {
let dsn = Some(Dsn::from_str(dsn).expect("Invalid Sentry DSN"));

let guard = sentry::init(sentry::ClientOptions {
dsn,
release: sentry::release_name!(),
environment: config.sentry_env.to_owned(),
..Default::default()
},
));
});

// We'll release the sentry hub in main.rs
std::mem::forget(guard)
// We manually deinitalize sentry later
std::mem::forget(guard)
}
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
mod checker;
mod cli;
mod cliapp;
mod config;
mod logging;
mod scheduler;
mod types;
Expand Down

0 comments on commit 34ed278

Please sign in to comment.