log4rs_routing_appender/route/pattern/
mod.rs1use log4rs::file::{Deserialize, Deserializers};
38use log::Record;
39use serde::de;
40use serde_value::Value;
41use std::collections::BTreeMap;
42use std::error::Error;
43use std::fmt;
44
45use route::{Appender, Cache, Entry, Route};
46use route::pattern::template::Template;
47
48mod parser;
49mod template;
50
51#[derive(Deserialize)]
53#[serde(deny_unknown_fields)]
54pub struct PatternRouterConfig {
55 pattern: AppenderConfig,
56}
57
58pub struct PatternRouter {
60 deserializers: Deserializers,
61 kind: String,
62 config: Template,
63}
64
65impl fmt::Debug for PatternRouter {
66 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
67 fmt.debug_struct("PatternRouter").finish()
68 }
69}
70
71impl Route for PatternRouter {
72 fn route(&self, _: &Record, cache: &mut Cache) -> Result<Appender, Box<Error + Sync + Send>> {
73 match cache.entry(self.config.key()) {
74 Entry::Occupied(e) => Ok(e.into_value()),
75 Entry::Vacant(e) => {
76 let appender = self.deserializers
77 .deserialize(&self.kind, self.config.expand()?)?;
78 Ok(e.insert(appender))
79 }
80 }
81 }
82}
83
84pub struct PatternRouterDeserializer;
97
98impl Deserialize for PatternRouterDeserializer {
99 type Trait = Route;
100 type Config = PatternRouterConfig;
101
102 fn deserialize(
103 &self,
104 config: PatternRouterConfig,
105 deserializers: &Deserializers,
106 ) -> Result<Box<Route>, Box<Error + Sync + Send>> {
107 Ok(Box::new(PatternRouter {
108 deserializers: deserializers.clone(),
109 kind: config.pattern.kind,
110 config: Template::new(&config.pattern.config)?,
111 }))
112 }
113}
114
115struct AppenderConfig {
116 kind: String,
117 config: Value,
118}
119
120impl<'de> de::Deserialize<'de> for AppenderConfig {
121 fn deserialize<D>(d: D) -> Result<AppenderConfig, D::Error>
122 where
123 D: de::Deserializer<'de>,
124 {
125 let mut map = BTreeMap::<Value, Value>::deserialize(d)?;
126
127 let kind = match map.remove(&Value::String("kind".to_owned())) {
128 Some(kind) => kind.deserialize_into().map_err(|e| e.to_error())?,
129 None => return Err(de::Error::missing_field("kind")),
130 };
131
132 Ok(AppenderConfig {
133 kind: kind,
134 config: Value::Map(map),
135 })
136 }
137}