Logging #26

Open
leon wants to merge 33 commits from Logging into main
4 changed files with 167 additions and 159 deletions
Showing only changes of commit a787dd93e5 - Show all commits

View File

@ -7,6 +7,7 @@ edition = "2021"
[dependencies]
getset = { version = "0.1.2", default-features = false }
once_cell = { version = "1.19.0", default-features = false, features = ["std"] }
[lints.rust]
unsafe_code = "forbid"

65
config/src/db.rs Normal file
View File

@ -0,0 +1,65 @@
/*!
* This module contains everything related to [`DbConfig`].
*/
#![allow(clippy::module_name_repetitions)]
use getset::Getters;
/**
* A immutable record of all the information needed to connect to the SQL database.
*/
#[allow(clippy::module_name_repetitions)]
#[derive(Clone, PartialEq, Eq, Getters, Debug)]
#[getset(get = "pub")]
pub struct DbConfig
{
/// Database connection address.
/// Is an option to allow constructing a default config during compile time.<br>
addr: String,
/// Database connection port.<br>
port: u16,
}
impl Default for DbConfig
{
fn default() -> Self
{
Self {
addr: String::from("localhost"),
port: 6969
}
}
}
/**
* Builder for [`DbConfig`].
*/
#[derive(Default, Debug)]
pub struct DbConfigBuilder(DbConfig);
impl DbConfigBuilder
{
/// Get a new [`DbConfigBuilder`]
#[must_use]
pub fn new() -> Self
{
Self::default()
}
/// Set the address to the location of the database.
#[must_use]
pub fn set_addr(mut self, addr: impl Into<String>) -> Self
{
self.0.addr = addr.into();
self
}
/// Set the port to the port the database uses.
#[must_use]
pub fn set_port(mut self, port: impl Into<u16>) -> Self
{
self.0.port = port.into();
self
}
}

View File

@ -1,168 +1,21 @@
/*!
* A singleton, thread-safe struct used for accessing
* Containing all singleton and thread-safe structs related to configuring `WANessa`.
*/
use std::path::Path;
use std::path::PathBuf;
use std::sync::RwLock;
pub mod log;
pub mod db;
use std::cmp::Ordering;
use crate::db::DbConfig;
use crate::log::LogSettings;
use crate::LogVerbosity::Warning;
use std::sync::{Arc, RwLock};
use getset::Getters;
use getset::Setters;
use once_cell::sync::Lazy;
/**
* Represents a valid `WANessa` configuration. Intended as a read-only singleton.
* See [`DEFAULTS`]
*/
#[derive(Clone, PartialEq, Eq, Getters, Setters, Debug)]
#[getset(get = "pub", set = "pub")]
#[allow(clippy::struct_excessive_bools)] // False positive, since this is a config struct.
pub struct Config {
/// See [`LogVerbosity`].<br>
/// Default: [`Warning`]
log_verbosity: LogVerbosity,
/// Logs UTC time and date of message, if true.<br>
/// Default: `false`
log_time: bool,
/// Time and date format.<br>
/// Defaults to `%F/%T:%f`.<br>
/// See [chrono](https://docs.rs/chrono/latest/chrono/format/strftime/index.html).<br>
/// Default example : `2001-12-31/23:59:33:26490000`
#[getset(skip)]
log_time_format: Option<String>,
/// Logs location in code, where the message was logged, if true.<br>
/// Default: `false`
log_location: bool,
/// If `Some(path)` tries to also write the log to `path` in addition to stderr/stderr.<br>
/// Default: [None]
#[getset(skip)]
log_path: Option<PathBuf>,
/// Logs to standard out, if true.<br>
/// Default: `true`
log_stdout: bool,
/// Logs to standard err, if true.<br>
/// Default: `true`
log_stderr: bool,
/// Database connection address.
/// Is an option to allow constructing a default config during compile time.<br>
/// Default: `localhost`.
#[getset(skip)]
db_addr: Option<String>,
/// Database connection port.<br>
/// Default: `6969` (nice).
db_port: u16,
}
// TODO: replace default with parsed settings from files+flags
impl Config {
/// Getter for [`Self::db_addr`].
#[must_use]
pub fn db_addr(&self) -> &str {
self.db_addr.as_ref().map_or("localhost", |addr| addr)
}
/// Singelton [`DbConfig`].
pub static DB_CONFIG: Lazy<Arc<DbConfig>> = Lazy::new(|| Arc::new(DbConfig::default()));
/// Setter for [`Self::db_addr`].
pub fn set_db_addr(&mut self, db_addr: impl Into<String>) {
self.db_addr = Some(db_addr.into());
}
/// Getter for [`Self::log_time_format`].
#[must_use]
pub fn log_time_format(&self) -> &str {
self.log_time_format.as_ref().map_or("%F-%T:%f", |fmt| fmt)
}
/// Setter for [`Self::log_time_format`].
pub fn set_log_time_format(&mut self, format: impl Into<String>) {
self.log_time_format = Some(format.into());
}
/// Getter for [`Self::log_path`].
#[must_use]
pub fn log_path(&self) -> Option<&Path> {
self.log_path.as_deref()
}
/// Setter for [`Self::log_path`].
pub fn set_log_path(&mut self, log_path: impl Into<Option<PathBuf>>) {
self.log_path = log_path.into();
}
}
/// See [`DEFAULTS`].
impl Default for Config {
/// See [`DEFAULTS`].
fn default() -> Self {
DEFAULTS
}
}
/**
* Default configuration.
* ```rust
* # use config::Config;
* # use config::LogVerbosity::Warning;
* let mut defaults = Config::default();
*
* defaults.set_log_verbosity(Warning);
* defaults.set_log_time(false);
* assert_eq!(defaults.log_time_format(), "%F-%T:%f");
* defaults.set_log_location(false);
* defaults.set_log_stdout(true);
* defaults.set_log_stderr(true);
* defaults.set_log_path(None);
* assert_eq!(defaults.db_addr(), "localhost");
* defaults.set_db_port(6969);
*
* # assert_eq!(defaults,config::DEFAULTS)
* ```
*/
pub const DEFAULTS: Config = Config {
log_verbosity: Warning,
log_time: false,
log_time_format: None,
log_location: false,
log_stdout: true,
log_stderr: true,
log_path: None,
db_addr: None,
db_port: 6969,
};
/// Configuration singleton.
pub static CONFIG: RwLock<Config> = RwLock::new(DEFAULTS);
/**
* Each level includes the previous ones.
*/
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum LogVerbosity {
/// Critical Errors, may lead to crashes or deactivating certain features.
Error = 10,
/// Very minor and recovered errors, such as invalid configs.
Warning = 20,
/// Very verbose and detailed. Basically gives a step-by-step instruction on what is currently done.
Information = 30,
/// Very technical and even more verbose.
/// May contain secrets and private information.
/// **Do not use in production environments!**
Debugging = 40,
}
impl PartialOrd for LogVerbosity {
/// Some operator overloading of comparison symbols (==, <,>=, etc.) as syntactic sugar.
/// See [`PartialOrd`].
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for LogVerbosity {
/// Some operator overloading of comparison symbols (==, <,>=, etc.) as syntactic sugar.
/// See [`Ord`].
fn cmp(&self, other: &Self) -> Ordering {
(*self as usize).cmp(&(*other as usize))
}
}
/// Singelton [`LogSettings`].
pub static LOG_SETTINGS: Lazy<RwLock<LogSettings>> = Lazy::new(|| RwLock::new(LogSettings::default()));

89
config/src/log.rs Normal file
View File

@ -0,0 +1,89 @@
/*!
* This module contains everything related to [`LogSettings`].
*/
#![allow(clippy::module_name_repetitions)]
use std::cmp::Ordering;
use crate::log::LogVerbosity::Warning;
use std::path::PathBuf;
use getset::Getters;
use getset::Setters;
/**
* All settings relating to how the project logs information.
*/
#[allow(clippy::struct_excessive_bools)]
#[derive(Clone, PartialEq, Eq, Getters, Setters, Debug)]
#[getset(get = "pub", set = "pub")]
pub struct LogSettings
{
/// See [`LogVerbosity`].<br>
verbosity: LogVerbosity,
/// Logs UTC time and date of message, if true.<br>
time: bool,
/// Time and date format.<br>
/// See [chrono](https://docs.rs/chrono/latest/chrono/format/strftime/index.html).<br>
time_format: String,
/// Logs location in code, where the message was logged, if true.<br>
location: bool,
/// If `Some(path)` tries to also write the log to `path` in addition to stderr/stderr.<br>
path: Option<PathBuf>,
/// Logs to standard out, if true.<br>
stdout: bool,
/// Logs to standard err, if true.<br>
stderr: bool,
}
impl Default for LogSettings
{
fn default() -> Self
{
Self {
verbosity: Warning,
time: false,
time_format: String::from("%F-%T:%f"),
location: false,
stdout: true,
stderr: true,
path: None,
}
}
}
/**
* Each level includes the previous ones.
*/
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum LogVerbosity {
/// Critical Errors, may lead to crashes or deactivating certain features.
Error = 10,
/// Very minor and recovered errors, such as invalid configs.
Warning = 20,
/// Very verbose and detailed. Basically gives a step-by-step instruction on what is currently done.
Information = 30,
/// Very technical and even more verbose.
/// May contain secrets and private information.
/// **Do not use in production environments!**
Debugging = 40,
}
impl PartialOrd for LogVerbosity {
/// Some operator overloading of comparison symbols (==, <,>=, etc.) as syntactic sugar.
/// See [`PartialOrd`].
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for LogVerbosity {
/// Some operator overloading of comparison symbols (==, <,>=, etc.) as syntactic sugar.
/// See [`Ord`].
fn cmp(&self, other: &Self) -> Ordering {
(*self as usize).cmp(&(*other as usize))
}
}