-
-
Notifications
You must be signed in to change notification settings - Fork 166
Expand file tree
/
Copy pathmod.rs
More file actions
145 lines (124 loc) · 3.68 KB
/
mod.rs
File metadata and controls
145 lines (124 loc) · 3.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//! Filters
use log::Record;
#[cfg(feature = "config_parsing")]
use serde::{de, Serialize, Serializer};
#[cfg(feature = "config_parsing")]
use serde_value::Value;
#[cfg(feature = "config_parsing")]
use std::collections::BTreeMap;
use std::fmt;
#[cfg(feature = "config_parsing")]
use crate::config::Deserializable;
#[cfg(feature = "threshold_filter")]
pub mod threshold;
/// The trait implemented by log4rs filters.
///
/// Filters are associated with appenders and limit the log events that will be
/// sent to that appender.
pub trait Filter: fmt::Debug + Send + Sync + 'static {
/// Filters a log event.
fn filter(&self, record: &Record) -> Response;
}
#[cfg(feature = "config_parsing")]
impl Deserializable for dyn Filter {
fn name() -> &'static str {
"filter"
}
}
#[derive(PartialEq, Debug)]
/// The response returned by a filter.
pub enum Response {
/// Accept the log event.
///
/// It will be immediately passed to the appender, bypassing any remaining
/// filters.
Accept,
/// Take no action on the log event.
///
/// It will continue on to remaining filters or pass on to the appender if
/// there are none remaining.
Neutral,
/// Reject the log event.
Reject,
}
/// Configuration for a filter.
#[cfg(feature = "config_parsing")]
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct FilterConfig {
/// The filter kind.
pub kind: String,
/// The filter configuration.
pub config: Value,
}
#[cfg(feature = "config_parsing")]
impl<'de> de::Deserialize<'de> for FilterConfig {
fn deserialize<D>(d: D) -> Result<FilterConfig, D::Error>
where
D: de::Deserializer<'de>,
{
let mut map = BTreeMap::<Value, Value>::deserialize(d)?;
let kind = match map.remove(&Value::String("kind".to_owned())) {
Some(kind) => kind.deserialize_into().map_err(|e| e.to_error())?,
None => return Err(de::Error::missing_field("kind")),
};
Ok(FilterConfig {
kind,
config: Value::Map(map),
})
}
}
#[cfg(feature = "config_parsing")]
impl Serialize for FilterConfig {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut map = BTreeMap::new();
map.insert(
Value::String("kind".to_owned()),
Value::String(self.kind.clone()),
);
if let Value::Map(ref config_map) = self.config {
for (key, value) in config_map {
map.insert(key.clone(), value.clone());
}
}
map.serialize(serializer)
}
}
#[cfg(test)]
mod test {
#[cfg(feature = "config_parsing")]
use super::*;
#[cfg(feature = "config_parsing")]
use serde_test::{assert_de_tokens, assert_de_tokens_error, Token};
#[test]
#[cfg(feature = "config_parsing")]
fn test_cfg_deserializer() {
let filter = FilterConfig {
kind: "threshold".to_owned(),
config: Value::Map({
let mut map = BTreeMap::new();
map.insert(
Value::String("level".to_owned()),
Value::String("error".to_owned()),
);
map
}),
};
let mut cfg = vec![
Token::Struct {
name: "FilterConfig",
len: 2,
},
Token::Str("kind"),
Token::Str("threshold"),
Token::Str("level"),
Token::Str("error"),
Token::StructEnd,
];
assert_de_tokens(&filter, &cfg);
cfg[1] = Token::Str("knd");
assert_de_tokens_error::<FilterConfig>(&cfg, "missing field `kind`");
}
}