1use serde::Serialize;
2use serde_json::{json, Map, Value};
3use std::str::FromStr;
4use std::fmt::Display;
5use time::format_description;
6use crate::{constants::{CRITICAL_ENABLED_KEY, CRITICAL_TEXT_KEY, DEBUG_ENABLED_KEY, DEBUG_TEXT_KEY, ENABLED_KEY, FATAL_ENABLED_KEY, FATAL_TEXT_KEY, INFO_ENABLED_KEY, INFO_TEXT_KEY, LOG_MESSAGE_FORMAT_KEY, PATTERN_KEY, TIMESTAMP_FORMAT_KEY, WARNING_ENABLED_KEY, WARNING_TEXT_KEY}, utils::{check_message_pattern, remove_quotes}};
7
8
9
10pub (crate) const PLAIN_TEXT_FORMAT: &str = "plain_text";
11pub (crate) const JSON_FORMAT: &str = "json";
12pub (crate) const JSON_PRETTY_FORMAT: &str = "json_pretty";
13
14
15pub (crate) const VALID_LOG_MESSAGE_FORMATS: [&str; 3] = [
16 PLAIN_TEXT_FORMAT,
17 JSON_FORMAT,
18 JSON_PRETTY_FORMAT
19];
20
21
22const CONFIGURABLE_KEYS: [&str; 13] = [
23 ENABLED_KEY,
24 TIMESTAMP_FORMAT_KEY,
25 DEBUG_ENABLED_KEY,
26 INFO_ENABLED_KEY,
27 WARNING_ENABLED_KEY,
28 CRITICAL_ENABLED_KEY,
29 DEBUG_TEXT_KEY,
30 INFO_TEXT_KEY,
31 WARNING_TEXT_KEY,
32 CRITICAL_TEXT_KEY,
33 FATAL_TEXT_KEY,
34 LOG_MESSAGE_FORMAT_KEY,
35 PATTERN_KEY,
36];
37
38#[derive(Serialize, Clone, Copy)]
40pub enum LogMsgType {
41 DebugMsgType,
42 InfoMsgType,
43 WarningMsgType,
44 CriticalMsgType,
45 FatalMsgType,
46}
47
48impl PartialEq for LogMsgType {
50 fn eq(&self, other: &Self) -> bool {
51 *self as i32 == *other as i32
52 }
53}
54
55pub const LOG_MSG_TYPE_NUM: usize = LogMsgType::FatalMsgType as usize + 1usize;
57
58pub (crate) enum LogMessageFormat {
60 PlainText,
61 Json,
62 JsonPretty
63}
64
65pub (crate) struct LogMessageFormatErr {
67 message: String
68}
69
70impl Display for LogMessageFormatErr {
72 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73 write!(f, "{}", self.message)
74 }
75}
76
77impl FromStr for LogMessageFormat {
79 type Err = LogMessageFormatErr;
80
81 fn from_str(s: &str) -> Result<Self, Self::Err> {
82 let s_lowecase = s.to_lowercase();
83 if s_lowecase == PLAIN_TEXT_FORMAT {
84 Ok(LogMessageFormat::PlainText)
85 } else if s_lowecase == JSON_FORMAT {
86 Ok(LogMessageFormat::Json)
87 } else if s_lowecase == JSON_PRETTY_FORMAT {
88 Ok(LogMessageFormat::JsonPretty)
89 } else {
90 Err(LogMessageFormatErr {message: format!("<{}> is not a valid log message format, valid are ({})",
91 s_lowecase, VALID_LOG_MESSAGE_FORMATS.join(", "))})
92 }
93 }
94}
95
96pub struct LogHandlerBase {
98 name: String,
99 enabled: bool,
100 timestamp_format: String,
101 msg_types_enabled: [bool; LOG_MSG_TYPE_NUM],
102 msg_types_text: [String; LOG_MSG_TYPE_NUM],
103 message_format: String,
104 pattern: String,
105 appname: String,
106 appver: String
107}
108
109impl LogHandlerBase {
111 pub fn new (name: String,
123 enabled: bool,
124 timestamp_format: String,
125 msg_types_enabled: [bool; LOG_MSG_TYPE_NUM],
126 msg_types_text: [String; LOG_MSG_TYPE_NUM],
127 message_format: String,
128 pattern: String,
129 appname: String,
130 appver: String) -> Self {
131 Self {
132 name,
133 enabled,
134 timestamp_format,
135 msg_types_enabled,
136 msg_types_text,
137 message_format,
138 pattern,
139 appname,
140 appver
141 }
142 }
143
144 pub fn get_name(&self) ->&String {
146 &self.name
147 }
148
149 pub fn is_enabled(&self) ->bool {
151 self.enabled.clone()
152 }
153
154 pub fn is_msg_type_enabled(&self, msg_type: &LogMsgType) -> bool {
157 let idx = *msg_type as usize;
158 let mut result = false;
159 if idx < self.msg_types_enabled.len() {
160 result = self.msg_types_enabled[idx].clone();
161 }
162
163 result
164 }
165
166 pub fn get_timestamp_format(&self) ->&String {
168 &self.timestamp_format
169 }
170
171 pub fn get_pattern(&self) ->&String {
173 &self.pattern
174 }
175
176 pub fn get_appname(&self) ->&String {
178 &self.appname
179 }
180
181 pub fn get_appver(&self) ->&String {
183 &self.appver
184 }
185
186 pub fn get_msg_types_text(&self) -> &[String; LOG_MSG_TYPE_NUM] {
188 &self.msg_types_text
189 }
190
191 pub fn get_message_format(&self) -> &String {
193 &self.message_format
194 }
195
196 pub fn is_abaseconfig(&self, key: &str) -> bool {
198 CONFIGURABLE_KEYS.contains(&key)
199 }
200
201 pub fn set_config(&mut self, key: &str, value: &Value) -> Result<Option<String>, String> {
205 let mut error = String::new();
206 if ENABLED_KEY == key {
207 match value.as_bool() {
208 Some(val) => {
209 self.enabled = val;
210 },
211 None => {
212 error = format!("{} needs a boolean value", key);
213 }
214 }
215 } else if TIMESTAMP_FORMAT_KEY == key {
216 match value.as_str() {
217 Some(val) => {
218 let no_quotes_value = remove_quotes(val);
219 if let Err(parse_error) = format_description::parse(&no_quotes_value) {
220 error = format!("{}", parse_error);
221 } else {
222 self.timestamp_format = no_quotes_value;
223 }
224 },
225 None => {
226 error = format!("{} needs a string value", key);
227 }
228 }
229 } else if DEBUG_ENABLED_KEY == key {
230 match value.as_bool() {
231 Some(val) => {
232 self.msg_types_enabled[LogMsgType::DebugMsgType as usize] = val;
233 },
234 None => {
235 error = format!("{} needs a boolean value", key);
236 }
237 }
238 } else if INFO_ENABLED_KEY == key {
239 match value.as_bool() {
240 Some(val) => {
241 self.msg_types_enabled[LogMsgType::InfoMsgType as usize] = val;
242 },
243 None => {
244 error = format!("{} needs a boolean value", key);
245 }
246 }
247 } else if WARNING_ENABLED_KEY == key {
248 match value.as_bool() {
249 Some(val) => {
250 self.msg_types_enabled[LogMsgType::WarningMsgType as usize] = val;
251 },
252 None => {
253 error = format!("{} needs a boolean value", key);
254 }
255 }
256 } else if CRITICAL_ENABLED_KEY == key {
257 match value.as_bool() {
258 Some(val) => {
259 self.msg_types_enabled[LogMsgType::CriticalMsgType as usize] = val;
260 },
261 None => {
262 error = format!("{} needs a boolean value", key);
263 }
264 }
265 } else if DEBUG_TEXT_KEY == key {
266 match value.as_str() {
267 Some(val) => {
268 self.msg_types_text[LogMsgType::DebugMsgType as usize] = String::from(val);
269 },
270 None => {
271 error = format!("{} needs a string value", key);
272 }
273 }
274 } else if INFO_TEXT_KEY == key{
275 match value.as_str() {
276 Some(val) => {
277 self.msg_types_text[LogMsgType::InfoMsgType as usize] = String::from(val);
278 },
279 None => {
280 error = format!("{} needs a string value", key);
281 }
282 }
283 } else if WARNING_TEXT_KEY == key{
284 match value.as_str() {
285 Some(val) => {
286 self.msg_types_text[LogMsgType::WarningMsgType as usize] = String::from(val);
287 },
288 None => {
289 error = format!("{} needs a string value", key);
290 }
291 }
292 } else if CRITICAL_TEXT_KEY == key{
293 match value.as_str() {
294 Some(val) => {
295 self.msg_types_text[LogMsgType::CriticalMsgType as usize] = String::from(val);
296 },
297 None => {
298 error = format!("{} needs a string value", key);
299 }
300 }
301 } else if FATAL_TEXT_KEY == key {
302 match value.as_str() {
303 Some(val) => {
304 self.msg_types_text[LogMsgType::FatalMsgType as usize] = String::from(val);
305 },
306 None => {
307 error = format!("{} needs a string value", key);
308 }
309 }
310 } else if LOG_MESSAGE_FORMAT_KEY == key {
311 match value.as_str() {
312 Some(val) => {
313 match val.parse::<LogMessageFormat>() {
314 Ok(_) => {
315 self.message_format = String::from(val);
316 },
317 Err(parse_error) => {
318 error = format!("{}", parse_error);
319 }
320 }
321 },
322 None => {
323 error = format!("{} needs a string value", key);
324 }
325 }
326 } else if PATTERN_KEY == key {
327 match value.as_str() {
328 Some(val) => {
329 if let Err(check_error) = check_message_pattern(&val.to_string()) {
330 error = check_error;
331 } else {
332 self.pattern = String::from(val);
333 }
334 },
335 None => {
336 error = format!("{} needs a string value", key);
337 }
338 }
339
340 } else {
341 error = format!("{} is not a valid configuration key", key);
342 }
343
344 if error.len() > 0 {
345 Err(error)
346 } else {
347 Ok(None)
348 }
349 }
350
351 pub fn get_config(&self) -> Map<String, Value> {
353 let mut config = Map::new();
354 config.insert(String::from("name"), json!(self.name));
355 config.insert(String::from(ENABLED_KEY), json!(self.enabled));
356 config.insert(String::from(TIMESTAMP_FORMAT_KEY), json!(format!("\"{}\"", self.timestamp_format)));
357 config.insert(String::from(DEBUG_ENABLED_KEY), json!(self.msg_types_enabled[LogMsgType::DebugMsgType as usize]));
358 config.insert(String::from(INFO_ENABLED_KEY), json!(self.msg_types_enabled[LogMsgType::InfoMsgType as usize]));
359 config.insert(String::from(WARNING_ENABLED_KEY), json!(self.msg_types_enabled[LogMsgType::WarningMsgType as usize]));
360 config.insert(String::from(CRITICAL_ENABLED_KEY), json!(self.msg_types_enabled[LogMsgType::CriticalMsgType as usize]));
361 config.insert(String::from(FATAL_ENABLED_KEY), json!(self.msg_types_enabled[LogMsgType::FatalMsgType as usize]));
362
363 config.insert(String::from(DEBUG_TEXT_KEY), json!(self.msg_types_text[LogMsgType::DebugMsgType as usize]));
364 config.insert(String::from(INFO_TEXT_KEY), json!(self.msg_types_text[LogMsgType::InfoMsgType as usize]));
365 config.insert(String::from(WARNING_TEXT_KEY), json!(self.msg_types_text[LogMsgType::WarningMsgType as usize]));
366 config.insert(String::from(CRITICAL_TEXT_KEY), json!(self.msg_types_text[LogMsgType::CriticalMsgType as usize]));
367 config.insert(String::from(FATAL_TEXT_KEY), json!(self.msg_types_text[LogMsgType::FatalMsgType as usize]));
368
369 config.insert(String::from(PATTERN_KEY), json!(self.pattern));
370 config.insert(String::from(LOG_MESSAGE_FORMAT_KEY), json!(self.get_message_format()));
371 config.insert(String::from("appname"), json!(self.appname));
372 config.insert(String::from("appver"), json!(self.appver));
373
374 config
375 }
376}