Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce daemonbase and use it for logging. #94

Merged
merged 6 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
661 changes: 386 additions & 275 deletions Cargo.lock

Large diffs are not rendered by default.

8 changes: 2 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,12 @@ readme = "README.md"
arc-swap = "1.0"
bytes = "1"
chrono = "0.4.31"
clap = { version = "3.0", features = [ "cargo" ] }
clap = { version = "~4.4", features = [ "cargo", "derive" ] }
crossbeam-utils = "0.8.4"
fern = "0.6.0"
daemonbase = "0.1.0"
futures = "0.3"
hyper = { version = "0.14.8", features = [ "server", "stream" ] }
log = "0.4"
log-reroute = "0.1.5"
pin-project-lite = "0.2.4"
rand = "0.8.3"
reqwest = { version = "0.11.3", default-features = false, features = ["blocking", "rustls-tls"] }
Expand All @@ -37,9 +36,6 @@ toml = "0.8.2"
url = { version = "2.2", features = ["serde"] }
webpki-roots = "0.25.2"

[target.'cfg(unix)'.dependencies]
syslog = "6.0"

[dev-dependencies]
rand_pcg = "0.3"

Expand Down
133 changes: 29 additions & 104 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
//! file referred to in command line options.

use std::{borrow, error, fmt, fs, io, ops};
use std::cell::RefCell;
use std::path::{Path, PathBuf};
use std::path::Path;
use std::sync::Arc;
use clap::{Arg, ArgMatches, Command};
use clap::{Args as _, FromArgMatches};
use daemonbase::logging;
use daemonbase::config::ConfigPath;
use daemonbase::error::Failed;
use serde::Deserialize;
use toml::Spanned;
use crate::http;
use crate::log::{ExitError, Failed, LogConfig};
use crate::manager::{Manager, TargetSet, UnitSet};


Expand All @@ -39,19 +40,19 @@ pub struct Config {

/// The logging configuration.
#[serde(flatten)]
pub log: LogConfig,
pub log: logging::Config,

/// The HTTP server configuration.
#[serde(flatten)]
pub http: http::Server,
}

impl Config {
/// Initialises everything.
/// Adds the basic arguments to a Clap command.
///
/// This function should be called first thing.
pub fn init() -> Result<(), ExitError> {
LogConfig::init_logging()
/// Returns the command with the arguments added.
pub fn config_args(app: clap::Command) -> clap::Command {
Args::augment_args(app)
}

/// Creates a configuration from a bytes slice with TOML data.
Expand All @@ -66,20 +67,6 @@ impl Config {
res
}

/// Configures a clap app with the arguments to load the configuration.
pub fn config_args(app: Command) -> Command {
let app = app.arg(
Arg::new("config")
.short('c')
.long("config")
.required(true)
.takes_value(true)
.value_name("PATH")
.help("Read base configuration from this file")
);
LogConfig::config_args(app)
}

/// Loads the configuration based on command line options provided.
///
/// The `matches` must be the result of getting argument matches from a
Expand All @@ -91,30 +78,42 @@ impl Config {
/// paths. The manager is necessary to resolve links given in the
/// configuration.
pub fn from_arg_matches(
matches: &ArgMatches,
cur_dir: &Path,
matches: &clap::ArgMatches,
manager: &mut Manager,
) -> Result<Self, Failed> {
let conf_path = cur_dir.join(matches.value_of("config").unwrap());
let conf = match ConfigFile::load(&conf_path) {
let args = Args::from_arg_matches(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear to me why cur_dir is no longer needed here.

Copy link
Member Author

@partim partim Mar 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expansion of relative paths is now done transparently in daemonbase.

matches
).expect("bug in command line arguments parser");
let conf = match ConfigFile::load(&args.config) {
Ok(conf) => conf,
Err(err) => {
eprintln!(
"Failed to read config file '{}': {}",
conf_path.display(),
args.config.display(),
err
);
return Err(Failed)
}
};
let mut res = manager.load(conf)?;
res.log.update_with_arg_matches(matches, cur_dir)?;
res.log.switch_logging(false)?;
res.log.apply_args(&args.log);
Ok(res)
}
}


//------------ Args ----------------------------------------------------------

#[derive(clap::Parser)]
pub struct Args {
#[arg(short, long)]
pub config: ConfigPath,

#[command(flatten)]
pub log: logging::Args,
}


//------------ Source --------------------------------------------------------

/// Description of the source of configuration.
Expand Down Expand Up @@ -370,77 +369,3 @@ impl fmt::Display for ConfigError {

impl error::Error for ConfigError { }


//------------ ConfigPath ----------------------------------------------------

/// A path that encountered in a config file.
///
/// This is a basically a `PathBuf` that, when, deserialized resolves all
/// relative paths from a certain base path so that all relative paths
/// encountered in a config file are automatically resolved relative to the
/// location of the config file.
#[derive(
Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd
)]
#[serde(from = "String")]
pub struct ConfigPath(PathBuf);

impl ConfigPath {
thread_local!(
static BASE_PATH: RefCell<Option<PathBuf>> = const {
RefCell::new(None)
}
);

fn set_base_path(path: PathBuf) {
Self::BASE_PATH.with(|base_path| {
base_path.replace(Some(path));
})
}

fn clear_base_path() {
Self::BASE_PATH.with(|base_path| {
base_path.replace(None);
})
}
}

impl From<PathBuf> for ConfigPath {
fn from(path: PathBuf) -> Self {
Self(path)
}
}

impl From<ConfigPath> for PathBuf {
fn from(path: ConfigPath) -> Self {
path.0
}
}

impl From<String> for ConfigPath {
fn from(path: String) -> Self {
Self::BASE_PATH.with(|base_path| {
ConfigPath(
match base_path.borrow().as_ref() {
Some(base_path) => base_path.join(path.as_str()),
None => path.into()
}
)
})
}
}

impl ops::Deref for ConfigPath {
type Target = Path;

fn deref(&self) -> &Self::Target {
self.0.as_ref()
}
}

impl AsRef<Path> for ConfigPath {
fn as_ref(&self) -> &Path {
self.0.as_ref()
}
}

6 changes: 3 additions & 3 deletions src/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use std::pin::Pin;
use std::sync::{Arc, Mutex, Weak};
use std::task::{Context, Poll};
use arc_swap::ArcSwap;
use daemonbase::error::ExitError;
use futures::pin_mut;
use hyper::{Body, Method, Request, Response, StatusCode};
use hyper::server::accept::Accept;
Expand All @@ -24,7 +25,6 @@ use serde::Deserialize;
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use tokio::net::{TcpListener, TcpStream};
use tokio::runtime::Runtime;
use crate::log::ExitError;
use crate::metrics;


Expand Down Expand Up @@ -64,15 +64,15 @@ impl Server {
Ok(listener) => listener,
Err(err) => {
error!("Fatal: error listening on {}: {}", addr, err);
return Err(ExitError);
return Err(ExitError::default());
}
};
if let Err(err) = listener.set_nonblocking(true) {
error!(
"Fatal: failed to set listener {} to non-blocking: {}.",
addr, err
);
return Err(ExitError);
return Err(ExitError::default());
}
debug!("HTTP server listening on {}", addr);
listeners.push(listener);
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub mod comms;
pub mod config;
pub mod formats;
pub mod http;
pub mod log;
//pub mod log;
partim marked this conversation as resolved.
Show resolved Hide resolved
pub mod manager;
pub mod metrics;
pub mod payload;
Expand Down
Loading
Loading