Browse Source

Refactor the logging system

ng
Rodolphe Bréard 3 weeks ago
parent
commit
2937edcb8c
Failed to extract signature
  1. 12
      Cargo.lock
  2. 2
      Cargo.toml
  3. 12
      src/config.rs
  4. 31
      src/http.rs
  5. 47
      src/main.rs

12
Cargo.lock

@ -1526,9 +1526,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
dependencies = [
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.33"

2
Cargo.toml

@ -31,7 +31,7 @@ reqwest = { version = "0.12.10", default-features = false, features = ["http2",
serde = { version = "1.0.216", default-features = false, features = ["derive"] }
syslog-tracing = { version = "0.3.1", default-features = false }
tokio = { version = "1.42.0", default-features = false, features = ["rt", "rt-multi-thread", "time", "sync"] }
tracing = { version = "0.1.41", default-features = false, features = ["std"] }
tracing = { version = "0.1.41", default-features = false, features = ["std", "attributes"] }
tracing-subscriber = { version = "0.3.19", default-features = false, features = ["ansi", "fmt", "std"] }
walkdir = { version = "2.5.0", default-features = false }

12
src/config.rs

@ -138,9 +138,10 @@ impl<'de> Deserialize<'de> for AcmedConfig {
}
}
pub fn load<P: AsRef<Path>>(config_dir: P) -> Result<AcmedConfig> {
#[tracing::instrument(level = "trace", err(Debug))]
pub fn load<P: AsRef<Path> + std::fmt::Debug>(config_dir: P) -> Result<AcmedConfig> {
let config_dir = config_dir.as_ref();
tracing::debug!("loading config directory: {config_dir:?}");
tracing::debug!("loading config directory");
let settings = Config::builder()
.add_source(
get_files(config_dir)?
@ -149,9 +150,9 @@ pub fn load<P: AsRef<Path>>(config_dir: P) -> Result<AcmedConfig> {
.collect::<Vec<_>>(),
)
.build()?;
tracing::trace!("loaded config: {settings:?}");
tracing::trace!(?settings, "loaded config");
let config: AcmedConfig = settings.try_deserialize().context("invalid setting")?;
tracing::debug!("computed config: {config:?}");
tracing::debug!(?config, "computed config");
Ok(config)
}
@ -169,11 +170,12 @@ fn get_files(config_dir: &Path) -> Result<Vec<PathBuf>> {
}
}
file_lst.sort();
tracing::debug!("configuration files found: {file_lst:?}");
tracing::debug!(files = ?file_lst, "configuration files found");
Ok(file_lst)
}
#[cfg(test)]
#[tracing::instrument(level = "trace", err(Debug))]
fn load_str<'de, T: serde::de::Deserialize<'de>>(config_str: &str) -> Result<T> {
let settings = Config::builder()
.add_source(File::from_str(config_str, config::FileFormat::Toml))

31
src/http.rs

@ -21,7 +21,12 @@ pub struct HttpClient {
}
impl HttpClient {
pub async fn send<S: AsRef<str>>(&self, endpoint: S, request: Request) -> Result<Response> {
#[tracing::instrument(skip(self), level = "trace", err(Debug))]
pub async fn send<S: AsRef<str> + std::fmt::Debug>(
&self,
endpoint: S,
request: Request,
) -> Result<Response> {
let (tx, rx) = oneshot::channel();
let raw_req = RawRequest {
request,
@ -29,11 +34,7 @@ impl HttpClient {
tx,
};
self.tx.send(raw_req)?;
let ret = rx.await?;
if let Err(ref e) = ret {
tracing::error!("http error: {e:#?}");
}
Ok(ret?)
Ok(rx.await??)
}
}
@ -50,11 +51,12 @@ pub(super) struct HttpRoutine {
}
impl HttpRoutine {
#[tracing::instrument(skip_all, level = "trace")]
pub(super) fn new(config: &AcmedConfig) -> Self {
let (tx, rx) = mpsc::unbounded_channel();
let mut endpoints = HashMap::with_capacity(config.endpoint.len());
for (name, edp) in &config.endpoint {
tracing::debug!("loading endpoint: {name}");
tracing::debug!(name, "loading endpoint");
let client = get_http_client(config.get_global_root_certs(), &edp.root_certificates);
let endpoint = HttpEndpoint { client };
endpoints.insert(name.to_owned(), endpoint);
@ -68,21 +70,22 @@ impl HttpRoutine {
}
}
#[tracing::instrument(skip_all, level = "trace")]
pub(super) async fn run(mut self) {
tracing::trace!("starting the http routine");
while let Some(raw_req) = self.rx.recv().await {
tracing::debug!("new http request: {:?}", raw_req.request);
tracing::debug!(request = ?raw_req.request, "new http request");
match self.endpoints.get(&raw_req.endpoint) {
Some(edp) => {
let ret = edp.client.execute(raw_req.request).await;
let _ = raw_req.tx.send(ret);
}
None => {
tracing::error!("{}: endpoint not found", raw_req.endpoint);
tracing::error!(endpoint = raw_req.endpoint, "endpoint not found");
}
}
}
tracing::warn!("the http routine has stopped");
tracing::error!("the http routine has stopped");
}
}
@ -92,17 +95,15 @@ macro_rules! add_root_cert {
match get_cert_pem(cert_path) {
Ok(cert) => {
$builder = $builder.add_root_certificate(cert);
tracing::debug!("root certificate loaded: {}", cert_path.display());
tracing::debug!(?cert_path, "root certificate loaded");
}
Err(e) => tracing::error!(
"{} unable to load root certificate: {e:#?}",
cert_path.display()
),
Err(e) => tracing::error!(?cert_path, "{e:#?}",),
}
}
};
}
#[tracing::instrument(level = "trace")]
fn get_http_client(base_certs_opt: Option<&[PathBuf]>, end_certs: &[PathBuf]) -> Client {
let useragent = format!(
"{}/{} ({}) {}",

47
src/main.rs

@ -5,7 +5,7 @@ mod log;
use crate::config::AcmedConfig;
use crate::http::HttpRoutine;
use anyhow::{Context, Result};
use anyhow::Result;
use clap::Parser;
use daemonize::Daemonize;
use std::fs::File;
@ -24,19 +24,18 @@ fn main() {
// Initialize the logging system
log::init(args.log_level, !args.log.log_stderr);
tracing::trace!("computed args: {args:?}");
tracing::trace!(?args, "computed args");
// Load the configuration
let cfg = match config::load(args.config.as_path()) {
Ok(cfg) => cfg,
Err(e) => {
tracing::error!("unable to load configuration: {e:#}");
std::process::exit(3);
}
Err(_) => std::process::exit(3),
};
// Initialize the server (PID file and daemon)
init_server(args.foreground, args.pid.get_pid_file());
if init_server(args.foreground, args.pid.get_pid_file()).is_err() {
std::process::exit(3);
}
// Starting ACMEd
tokio::runtime::Builder::new_multi_thread()
@ -58,14 +57,20 @@ async fn start(cnf: AcmedConfig) {
});
// TODO: REMOVE ME
debug_remove_me(http_client).await;
}
#[tracing::instrument(skip_all, level = "trace")]
async fn debug_remove_me(http_client: crate::http::HttpClient) {
use reqwest::{Method, Request, Url};
let rsp = http_client
.send(
"my-ca",
Request::new(Method::GET, Url::parse("https://example.org").unwrap()),
Request::new(Method::GET, Url::parse("https://example.invalid").unwrap()),
)
.await;
tracing::debug!("{rsp:?}");
tracing::debug!(response = ?rsp, "response received");
let rsp = http_client
.send(
"my-ca",
@ -75,33 +80,27 @@ async fn start(cnf: AcmedConfig) {
),
)
.await;
tracing::debug!("{rsp:?}");
tracing::debug!(response = ?rsp, "response received");
}
fn init_server(foreground: bool, pid_file: Option<&Path>) {
#[tracing::instrument(level = "trace", err(Debug))]
fn init_server(foreground: bool, pid_file: Option<&Path>) -> Result<()> {
if !foreground {
let mut daemonize = Daemonize::new();
if let Some(f) = pid_file {
daemonize = daemonize.pid_file(f);
}
if let Err(e) = daemonize.start() {
tracing::error!("{e:#}");
std::process::exit(3);
}
daemonize.start()?
} else if let Some(f) = pid_file {
if let Err(e) = write_pid_file(f) {
tracing::error!("{e:#}");
std::process::exit(3);
}
write_pid_file(f)?
}
Ok(())
}
fn write_pid_file(pid_file: &Path) -> Result<()> {
let data = format!("{}\n", process::id()).into_bytes();
let mut file = File::create(pid_file).with_context(|| format!("{}", pid_file.display()))?;
file.write_all(&data)
.with_context(|| format!("{}", pid_file.display()))?;
file.sync_all()
.with_context(|| format!("{}", pid_file.display()))?;
let mut file = File::create(pid_file)?;
file.write_all(&data)?;
file.sync_all()?;
Ok(())
}
Loading…
Cancel
Save