Skip to content

Commit

Permalink
2
Browse files Browse the repository at this point in the history
  • Loading branch information
SpriteOvO committed Apr 2, 2024
1 parent 15ba14c commit b0452a2
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 22 deletions.
75 changes: 66 additions & 9 deletions spdlog/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ mod source;

pub(crate) mod deser;

use std::{collections::HashMap, convert::Infallible};
use std::{
cell::RefCell,
collections::{hash_map::Entry, HashMap},
convert::Infallible,
};

pub use registry::*;
use serde::{de::DeserializeOwned, Deserialize};
pub use source::*;

use crate::{sync::*, Result};
use crate::{sync::*, Logger, LoggerBuilder, LoggerParams, Result};

// TODO: Builder?
#[derive(PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -57,25 +61,78 @@ pub trait Configurable: Sized {

// #[derive(Deserialize)]
// #[serde(deny_unknown_fields)]
// pub(super) struct Logger(#[serde(deserialize_with =
// struct Logger(#[serde(deserialize_with =
// "crate::config::deser::logger")] crate::Logger);

#[derive(PartialEq, Debug, Deserialize)]
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct ConfigView {
loggers: HashMap<String, toml::Value>,
struct ConfigView {
loggers: HashMap<String, LoggerParams>,
}

#[derive(Debug, Hash, Eq, PartialEq)]
enum LoggerKind {
Default,
Named(String),
}

#[derive(PartialEq, Debug)]
pub struct Config {
view: ConfigView, // Stores the config values only, build lazily
view: ConfigView, // Stores the config values only, build loggers lazily
built: RefCell<HashMap<LoggerKind, Weak<Logger>>>,
}
// TODO: But only build once! For later acquires, return the built `Arc<Logger>`
// Stores `Weak`?

impl Config {
pub fn acquire_default_logger(&self) -> Option<Result<Arc<Logger>>> {
self.acquire_logger_inner(LoggerKind::Default)
}

pub fn acquire_logger<S>(&self, name: S) -> Option<Result<Arc<Logger>>>
where
S: AsRef<str>,
{
self.acquire_logger_inner(LoggerKind::Named(name.as_ref().into()))
}
}

impl Config {
fn acquire_logger_inner(&self, logger_kind: LoggerKind) -> Option<Result<Arc<Logger>>> {
let logger_name = match &logger_kind {
LoggerKind::Default => "default",
LoggerKind::Named(name) => name,
};
let logger_params = self.view.loggers.get(logger_name)?;

// TODO: Factually unnecessary clone in the argument of `build_config`, could be
// avoided with some effort
Some((|| match self.built.borrow_mut().entry(logger_kind) {
Entry::Occupied(mut entry) => match entry.get().upgrade() {
None => {
let new = Arc::new(LoggerBuilder::build_config(logger_params.clone())?);
entry.insert(Arc::downgrade(&new));
Ok(new)
}
Some(built) => Ok(built),
},
Entry::Vacant(entry) => {
let new = Arc::new(LoggerBuilder::build_config(logger_params.clone())?);
entry.insert(Arc::downgrade(&new));
Ok(new)
}
})())
}
}

// TODO: temp code
impl Config {
// TODO: Remember to remove me
pub fn new_for_test(inputs: &str) -> Result<Self> {
let view = toml::from_str(inputs).unwrap();
Ok(Self { view })
Ok(Self {
view,
built: RefCell::new(HashMap::new()),
})
}
}

Expand Down
1 change: 0 additions & 1 deletion spdlog/src/config/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ mod erased_serde_ext {
use erased_serde_ext::*;

type ComponentDeser<C> = fn(de: &mut dyn ErasedDeserializer) -> Result<C>;

type RegisteredComponents<C> = HashMap<&'static str, ComponentDeser<C>>;

pub struct Registry {
Expand Down
26 changes: 14 additions & 12 deletions spdlog/src/logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,20 @@ use crate::{
fn check_logger_name(name: impl AsRef<str>) -> StdResult<(), SetLoggerNameError> {
let name = name.as_ref();

if name.chars().any(|ch| {
ch == ','
|| ch == '='
|| ch == '*'
|| ch == '?'
|| ch == '$'
|| ch == '{'
|| ch == '}'
|| ch == '"'
|| ch == '\''
|| ch == ';'
}) || name.starts_with(' ')
if name.to_ascii_lowercase() == "default"
|| name.chars().any(|ch| {
ch == ','
|| ch == '='
|| ch == '*'
|| ch == '?'
|| ch == '$'
|| ch == '{'
|| ch == '}'
|| ch == '"'
|| ch == '\''
|| ch == ';'
})
|| name.starts_with(' ')
|| name.ends_with(' ')
{
Err(SetLoggerNameError::new(name))
Expand Down
48 changes: 48 additions & 0 deletions spdlog/tests/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use std::{
fs,
path::{Path, PathBuf},
sync::Arc,
};

use once_cell::sync::Lazy;
use spdlog::{
config::{self, Config},
formatter::{pattern, PatternFormatter},
};

include!(concat!(
env!("OUT_DIR"),
"/test_utils/common_for_integration_test.rs"
));
use test_utils::*;

static TEMP_DIR: Lazy<PathBuf> = Lazy::new(|| {
let temp_dir = PathBuf::from(env!("OUT_DIR"))
.join("dev")
.join("integration-test-config");
fs::create_dir_all(&temp_dir).unwrap();
temp_dir
});

#[test]
fn test_config_full() {
let path = TEMP_DIR.join("file-sink.log");
let inputs = format!(
r#"
[loggers.default]
sinks = [
{{ name = "$ConfigMockSink1", arg = 114 }},
{{ name = "$ConfigMockSink2", arg = 514 }},
{{ name = "$ConfigMockSink3", arg = 1919 }},
{{ name = "FileSink", path = "{}", formatter = {{ name = "PatternFormatter", template = "Meow! {{payload}}{{eol}}" }} }}
]
flush_level_filter = "Equal(Info)" # TODO: reconsider the syntax
[loggers.network]
sinks = [ {{ name = "$ConfigMockSink2", arg = 810 }} ]
# TODO: flush_period = "10s"
"#,
path.display()
);
let config = Config::new_for_test(&inputs).unwrap();
}

0 comments on commit b0452a2

Please sign in to comment.