1use std::{borrow::Cow, env::{self, VarError}, str::FromStr};
17
18#[cfg(feature = "build_sync")]
19use crate::{LogFacility, LogStat, Priority, };
20#[cfg(feature = "build_ext_file")]
21use crate::SyslogFile;
22#[cfg(feature = "build_ext_tls")]
23use crate::SyslogTls;
24#[cfg(feature = "build_ext_net")]
25use crate::{SyslogNetTcp, SyslogNetUdp};
26#[cfg(feature = "build_with_queue")]
27use crate::{SyQueued, sy_sync_queue::SyslogQueueChannel};
28#[cfg(feature = "build_with_thread_local")]
29use crate::{MutDynSyslog, SyThreadLocal};
30
31use crate::{
32 DynSyslog, LOG_UPTO, SyShared, Syslog, SyslogDestination, SyslogLocal,
33 error::{SyRes},
34 formatters::
35 {
36 DEFAULT_SYSLOG_FORMATTER_TYPE, FormatFile, FormatRfc3146, FormatRfc5424, SyslogFormatter,
37 SyslogFormatters
38 },
39 map_error, throw_error
40};
41
42
43pub const LOGGER_TYPE_LOCAL: &'static str = "local";
46
47pub const LOGGER_TYPE_UDP: &'static str = "udp";
51
52pub const LOGGER_TYPE_TCP: &'static str = "tcp";
56
57pub const LOGGER_TYPE_TLS: &'static str = "tls";
61
62pub const LOGGER_TYPE_FILE: &'static str = "file";
64
65pub const SYSLOG_LOGGER_DST_URI: &'static str = "SYSLOG_LOGGER_DST_URI";
67
68pub const SYSLOG_LOGGER_LOG_FACILITY: &'static str = "SYSLOG_LOGGER_LOG_FACILITY";
70
71pub const SYSLOG_LOGGER_LOG_FORMATTER: &'static str = "SYSLOG_LOGGER_LOG_FORMATTER";
77
78pub const SYSLOG_LOGGER_LOG_IDENTITY: &'static str = "SYSLOG_LOGGER_LOG_IDENTITY";
82
83pub const SYSLOG_LOGGER_LOG_UPTO: &'static str = "SYSLOG_LOGGER_LOG_UPTO";
87
88#[cfg(not(feature = "logger_lazy"))]
89mod logger_cells
90{
91 #[cfg(feature = "build_with_thread_local")]
92 use std::cell::RefCell;
93 use std::sync::OnceLock;
94
95 use crate::DynSyslog;
96 #[cfg(feature = "build_with_thread_local")]
97 use crate::MutDynSyslog;
98
99 pub(crate) static LOGGER: OnceLock<Box<dyn DynSyslog + Send + Sync>> = OnceLock::new();
101
102 #[cfg(feature = "build_with_thread_local")]
103 thread_local!
104 {
105 pub(super) static LOGGER_LOCAL: RefCell<Option<Box<dyn MutDynSyslog>>> = RefCell::new(None);
107 }
108}
109
110#[cfg(feature = "logger_lazy")]
113mod logger_lazy
114{
115 use std::sync::LazyLock;
116
117 use crate::{DynSyslog, SyShared, logger::internal_init_event_log};
118
119 pub(crate) static LOGGER: LazyLock<Option<Box<dyn DynSyslog + Send + Sync>>> =
120 LazyLock::new(
121 ||
122 {
123 match internal_init_event_log::<SyShared>(None)
124 {
125 Ok(sy) => sy,
126 Err(e) =>
127 {
128 if cfg!(feature = "logger_lazy_silence_panic")
129 {
130 None
131 }
132 else
133 {
134 panic!("{}", e);
135 }
136 }
137 }
138 }
139 );
140}
141
142fn derive_suffix(suffix: Option<&str>, env_name: &'static str) -> Cow<'static, str>
143{
144 if let Some(su) = suffix
145 {
146 Cow::Owned([env_name, "_", su].concat())
147 }
148 else
149 {
150 Cow::Borrowed(env_name)
151 }
152}
153
154#[derive(Debug)]
155struct EnvVars
156{
157 logger_type_res: String,
158 logger_facility: LogFacility,
159 logger_formatter: SyslogFormatters,
160 logger_identity: Option<String>,
161 logger_upto: Option<Priority>,
162}
163
164impl EnvVars
165{
166 fn read_env(env_sufix: Option<&str>) -> SyRes<Option<Self>>
167 {
168 let logger_type_res =
169 match env::var(derive_suffix(env_sufix, SYSLOG_LOGGER_DST_URI).as_ref())
170 {
171 Ok(val) =>
172 val,
173 Err(VarError::NotPresent) =>
174 return Ok(None),
175 Err(VarError::NotUnicode(_e)) =>
176 throw_error!("{} is not unicode", SYSLOG_LOGGER_DST_URI)
177 };
178
179 let logger_facility=
180 match env::var(derive_suffix(env_sufix, SYSLOG_LOGGER_LOG_FACILITY).as_ref())
181 {
182 Ok(val) =>
183 LogFacility::from_str(&val)?,
184 Err(VarError::NotPresent) =>
185 LogFacility::LOG_DAEMON,
186 Err(VarError::NotUnicode(_e)) =>
187 throw_error!("{} is not unicode", SYSLOG_LOGGER_LOG_FACILITY)
188 };
189
190 let logger_formatter =
191 match env::var(derive_suffix(env_sufix, SYSLOG_LOGGER_LOG_FORMATTER).as_ref())
192 {
193 Ok(val) =>
194 SyslogFormatters::from_str(&val)?,
195 Err(VarError::NotPresent) =>
196 DEFAULT_SYSLOG_FORMATTER_TYPE,
197 Err(VarError::NotUnicode(_e)) =>
198 throw_error!("{} is not unicode", SYSLOG_LOGGER_LOG_FORMATTER)
199 };
200
201 let logger_identity =
202 match env::var(derive_suffix(env_sufix, SYSLOG_LOGGER_LOG_IDENTITY).as_ref())
203 {
204 Ok(val) =>
205 Some(val),
206 Err(VarError::NotPresent) =>
207 None,
208 Err(VarError::NotUnicode(_e)) =>
209 throw_error!("{} is not unicode", SYSLOG_LOGGER_LOG_IDENTITY)
210 };
211
212
213 let logger_upto =
214 match env::var(derive_suffix(env_sufix, SYSLOG_LOGGER_LOG_UPTO).as_ref())
215 {
216 Ok(val) =>
217 Some(Priority::from_str(&val)?),
218 Err(VarError::NotPresent) =>
219 None,
220 Err(VarError::NotUnicode(_e)) =>
221 throw_error!("{} is not unicode", SYSLOG_LOGGER_LOG_IDENTITY)
222 };
223
224 return Ok(
225 Some(
226 Self
227 {
228 logger_type_res, logger_facility, logger_formatter, logger_identity, logger_upto
229 }
230 )
231 );
232 }
233}
234
235#[derive(Debug, PartialEq, Eq)]
236enum LoggerDst<'a>
237{
238 LoLocal{ dst_path: Option<&'a str> },
239
240 #[cfg(feature = "build_ext_net")]
241 LoUdp{ dst_host: &'a str },
242
243 #[cfg(feature = "build_ext_net")]
244 LoTcp{ dst_host: &'a str },
245
246 #[cfg(feature = "build_ext_tls")]
247 LoTls
248 {
249 dst_host: &'a str,
250 serv_name: &'a str,
251 root_cert_path: &'a str,
252 },
253
254 #[cfg(feature = "build_ext_file")]
255 LoFile{ dst_path: &'a str }
256}
257
258impl<'a> LoggerDst<'a>
259{
260 fn from_str(lo_sch: &'a str) -> SyRes<Self>
261 {
262 let (dst_type, payload) =
263 lo_sch
264 .split_once("#")
265 .ok_or_else(||
266 map_error!("{} incorrect format, expected type#dst:extras", SYSLOG_LOGGER_DST_URI)
267 )?;
268
269 let res =
270 match dst_type.to_lowercase().as_str()
271 {
272 LOGGER_TYPE_LOCAL =>
273 {
274 let dst_path = payload.trim();
275
276 if dst_path.is_empty() == false
277 {
278 Self::LoLocal{ dst_path: Some(dst_path) }
279 }
280 else
281 {
282 Self::LoLocal{ dst_path: None }
283 }
284 },
285
286 #[cfg(feature = "build_ext_net")]
287 LOGGER_TYPE_UDP =>
288 {
289 let dst_host = payload.trim();
290
291 Self::LoUdp{ dst_host }
292 },
293
294 #[cfg(not(feature = "build_ext_net"))]
295 LOGGER_TYPE_UDP =>
296 throw_error!("cannot use UDP, crate compiled without `build_ext_net`!"),
297
298 #[cfg(feature = "build_ext_net")]
299 LOGGER_TYPE_TCP => {
301 let dst_host = payload.trim();
302
303 Self::LoTcp{ dst_host }
304 },
305
306 #[cfg(not(feature = "build_ext_net"))]
307 LOGGER_TYPE_TCP =>
308 throw_error!("cannot use UDP, crate compiled without `build_ext_net`!"),
309
310 #[cfg(feature = "build_ext_tls")]
311 LOGGER_TYPE_TLS =>
312 {
313 let (dst_host, payload) =
314 payload
315 .split_once("#")
316 .map(|c| (c.0.trim(), c.1))
317 .ok_or_else(||
318 map_error!("SYSLOG_LOGGER_DST_URI incorrect format, expected type#dst:extras")
319 )?;
320
321 let (serv_name, root_cert_path) =
322 payload
323 .split_once("#")
324 .map(|c| (c.0.trim(), c.1))
325 .ok_or_else(||
326 map_error!("SYSLOG_LOGGER_DST_URI incorrect format, expected type#dst:extras")
327 )?;
328
329 Self::LoTls{ dst_host, serv_name, root_cert_path }
330 },
331
332 #[cfg(not(feature = "build_ext_tls"))]
333 LOGGER_TYPE_TLS =>
334 throw_error!("cannot use UDP, crate compiled without `build_ext_tls`!"),
335
336 #[cfg(feature = "build_ext_file")]
337 LOGGER_TYPE_FILE =>
338 {
339 let dst_path = payload.trim();
340
341 Self::LoFile{ dst_path }
342 },
343
344 #[cfg(not(feature = "build_ext_file"))]
345 LOGGER_TYPE_FILE =>
346 throw_error!("cannot use UDP, crate compiled without `build_ext_file`!"),
347
348 n =>
349 throw_error!("SYSLOG_LOGGER_DST_URI unknown syslog dest type: {}", n)
350 };
351
352 return Ok(res);
353 }
354}
355
356
357trait LoggerDynRet
358{
359 type RetType;
360
361 fn openlog_with<F, D>(ident: Option<String>, logstat: LogStat, facility: LogFacility, net_tap_prov: D) -> SyRes<Self::RetType>
362 where
363 F: SyslogFormatter,
364 D: SyslogDestination;
365
366 fn set_prio(syslog_inst: &mut Self::RetType, opt_prio: Option<Priority>) -> SyRes<()>;
367}
368
369impl LoggerDynRet for SyShared
370{
371 type RetType = Box<dyn DynSyslog + Send + Sync>;
372
373 fn openlog_with<F, D>(ident: Option<String>, logstat: LogStat, facility: LogFacility, net_tap_prov: D) -> SyRes<Self::RetType>
374 where
375 F: SyslogFormatter,
376 D: SyslogDestination,
377 {
378 Syslog
379 ::<F, D, Self>
380 ::openlog_with(ident.as_ref().map(|d| d.as_str()),
381 logstat, facility, net_tap_prov)
382 .map(|sy| sy.make_dyn())
383 }
384
385 fn set_prio(syslog_inst: &mut Self::RetType, opt_prio: Option<Priority>) -> SyRes<()>
386 {
387 if let Some(prio) = opt_prio
388 {
389 syslog_inst.setlogmask(LOG_UPTO!(prio))?;
390 }
391
392 return Ok(());
393 }
394}
395
396#[cfg(feature = "build_with_thread_local")]
397impl LoggerDynRet for SyThreadLocal
398{
399 type RetType = Box<dyn MutDynSyslog>;
400
401 fn openlog_with<F, D>(ident: Option<String>, logstat: LogStat, facility: LogFacility, net_tap_prov: D) -> SyRes<Self::RetType>
402 where
403 F: SyslogFormatter,
404 D: SyslogDestination,
405 {
406 Syslog
407 ::<F, D, Self>
408 ::openlog_with(ident.as_ref().map(|d| d.as_str()),
409 logstat, facility, net_tap_prov)
410 .map(|sy| sy.make_dyn())
411 }
412
413 fn set_prio(syslog_inst: &mut Self::RetType, opt_prio: Option<Priority>) -> SyRes<()>
414 {
415 if let Some(prio) = opt_prio
416 {
417 syslog_inst.setlogmask(LOG_UPTO!(prio))?;
418 }
419
420 return Ok(());
421 }
422}
423
424#[cfg(all(not(feature = "logger_lazy")))]
478pub
479fn init_event_log(env_suffix: Option<&str>) -> SyRes<()>
480{
481 let Some(syslog) = internal_init_event_log::<SyShared>(env_suffix)?
482 else { return Ok(()) };
483
484 logger_cells::LOGGER.set(syslog).map_err(|_e| map_error!("duplicate call to init_event_log()"))?;
485
486 return Ok(());
487}
488
489#[cfg(all(feature = "build_with_thread_local", not(feature = "logger_lazy")))]
543pub
544fn init_thread_local_event_log(env_suffix: Option<&str>) -> SyRes<()>
545{
546 let Some(syslog) = internal_init_event_log::<SyThreadLocal>(env_suffix)?
547 else { return Ok(()) };
548
549 logger_cells::LOGGER_LOCAL.set(Some(syslog));
550
551 return Ok(());
552}
553
554
555
556#[cfg(not(feature = "logger_lazy"))]
563pub
564fn attach_event_log_shared<F, D>(sy: &Syslog<F, D, SyShared>) -> SyRes<()>
565where
566 F: SyslogFormatter,
567 D: SyslogDestination,
568{
569 let clonned_sy = sy.clone().make_dyn();
570
571 logger_cells::LOGGER
572 .set(clonned_sy)
573 .map_err(|_e|
574 map_error!("syslog instance has been already initialized!")
575 )
576}
577
578#[cfg(all(feature = "build_with_queue", not(feature = "logger_lazy")))]
585pub
586fn attach_event_log_queued<F, D, S>(sy: &Syslog<F, D, SyQueued<S, F, D>>) -> SyRes<()>
587where
588 F: SyslogFormatter,
589 D: SyslogDestination,
590 S: SyslogQueueChannel<F, D>
591{
592 let clonned_sy = sy.clone().make_dyn();
593
594 logger_cells::LOGGER
595 .set(clonned_sy)
596 .map_err(|_e|
597 map_error!("syslog instance has been already initialized!")
598 )
599}
600
601fn internal_init_event_log<OUT: LoggerDynRet>(env_suffix: Option<&str>) -> SyRes<Option<OUT::RetType>> {
603 let Some(envs) = EnvVars::read_env(env_suffix)?
604 else { return Ok(None) };
605
606 let dst = LoggerDst::from_str(&envs.logger_type_res)?;
607
608 match dst
609 {
610 LoggerDst::LoLocal{ dst_path } =>
611 {
612 let tap =
613 if let Some(dst_path) = dst_path
614 {
615 SyslogLocal::new_custom_path(dst_path, false)?
616 }
617 else
618 {
619 SyslogLocal::new()
620 };
621
622 let mut syslog_inst =
623 match envs.logger_formatter
624 {
625 SyslogFormatters::FormatRfc3146 =>
626 {
627 OUT::
628 openlog_with
629 ::<FormatRfc3146, SyslogLocal>(envs.logger_identity,
630 LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, envs.logger_facility, tap)?
631 },
632 SyslogFormatters::FormatRfc5424 =>
633 {
634 OUT::
635 openlog_with
636 ::<FormatRfc5424, SyslogLocal>(envs.logger_identity,
637 LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, envs.logger_facility, tap)?
638 },
639 SyslogFormatters::FormatFile =>
640 {
641 OUT::
642 openlog_with
643 ::<FormatFile, SyslogLocal>(envs.logger_identity,
644 LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, envs.logger_facility, tap)?
645 },
646 };
647
648 OUT::set_prio(&mut syslog_inst, envs.logger_upto)?;
649
650 return Ok(Some(syslog_inst));
651 },
652 #[cfg(feature = "build_ext_net")]
653 LoggerDst::LoUdp{ dst_host } =>
654 {
655 let tap = SyslogNetUdp::new(dst_host, None)?;
656
657 let mut syslog_inst =
658 match envs.logger_formatter
659 {
660 SyslogFormatters::FormatRfc3146 =>
661 {
662 OUT::
663 openlog_with
664 ::<FormatRfc3146, SyslogNetUdp>(envs.logger_identity,
665 LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, envs.logger_facility, tap)?
666 },
667 SyslogFormatters::FormatRfc5424 =>
668 {
669 OUT::
670 openlog_with
671 ::<FormatRfc5424, SyslogNetUdp>(envs.logger_identity,
672 LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, envs.logger_facility, tap)?
673 },
674 SyslogFormatters::FormatFile =>
675 {
676 OUT::
677 openlog_with
678 ::<FormatFile, SyslogNetUdp>(envs.logger_identity,
679 LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, envs.logger_facility, tap)?
680 }
681 };
682
683 OUT::set_prio(&mut syslog_inst, envs.logger_upto)?;
684
685 return Ok(Some(syslog_inst));
686 },
687 #[cfg(feature = "build_ext_net")]
688 LoggerDst::LoTcp{ dst_host } => {
690 let tap = SyslogNetTcp::new(dst_host, None, None)?;
691
692 let mut syslog_inst =
693 match envs.logger_formatter
694 {
695 SyslogFormatters::FormatRfc3146 =>
696 {
697 OUT::
698 openlog_with
699 ::<FormatRfc3146, SyslogNetTcp>(envs.logger_identity,
700 LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, envs.logger_facility, tap)?
701 },
702 SyslogFormatters::FormatRfc5424 =>
703 {
704 OUT::
705 openlog_with
706 ::<FormatRfc5424, SyslogNetTcp>(envs.logger_identity,
707 LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, envs.logger_facility, tap)?
708 },
709 SyslogFormatters::FormatFile =>
710 {
711 OUT::
712 openlog_with
713 ::<FormatFile, SyslogNetTcp>(envs.logger_identity,
714 LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, envs.logger_facility, tap)?
715 }
716 };
717
718 OUT::set_prio(&mut syslog_inst, envs.logger_upto)?;
719
720 return Ok(Some(syslog_inst));
721 },
722
723 #[cfg(feature = "build_ext_tls")]
724 LoggerDst::LoTls{ dst_host, serv_name, root_cert_path } =>
725 {
726 let tap = SyslogTls::new2(dst_host, None, serv_name, root_cert_path, None)?;
727
728 let mut syslog_inst =
729 match envs.logger_formatter
730 {
731 SyslogFormatters::FormatRfc3146 =>
732 {
733 OUT::
734 openlog_with
735 ::<FormatRfc3146, SyslogTls>(envs.logger_identity,
736 LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, envs.logger_facility, tap)?
737 },
738 SyslogFormatters::FormatRfc5424 =>
739 {
740 OUT::
741 openlog_with
742 ::<FormatRfc5424, SyslogTls>(envs.logger_identity,
743 LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID,envs. logger_facility, tap)?
744 },
745 SyslogFormatters::FormatFile =>
746 {
747 OUT::
748 openlog_with
749 ::<FormatFile, SyslogTls>(envs.logger_identity,
750 LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, envs.logger_facility, tap)?
751 }
752 };
753
754 OUT::set_prio(&mut syslog_inst, envs.logger_upto)?;
755
756 return Ok(Some(syslog_inst));
757 },
758
759 #[cfg(feature = "build_ext_file")]
760 LoggerDst::LoFile{ dst_path } =>
761 {
762 let tap = SyslogFile::new(dst_path);
763
764 let mut syslog_inst =
765 match envs.logger_formatter
766 {
767 SyslogFormatters::FormatRfc3146 =>
768 {
769 OUT::
770 openlog_with
771 ::<FormatRfc3146, SyslogFile>(envs.logger_identity,
772 LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, envs.logger_facility, tap)?
773 },
774 SyslogFormatters::FormatRfc5424 =>
775 {
776 OUT::
777 openlog_with
778 ::<FormatRfc5424, SyslogFile>(envs.logger_identity,
779 LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, envs.logger_facility, tap)?
780 },
781 SyslogFormatters::FormatFile =>
782 {
783 OUT::
784 openlog_with
785 ::<FormatFile, SyslogFile>(envs.logger_identity,
786 LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, envs.logger_facility, tap)?
787 }
788 };
789
790 OUT::set_prio(&mut syslog_inst, envs.logger_upto)?;
791
792 return Ok(Some(syslog_inst));
793 }
794 }
795}
796
797#[cfg(all(feature = "build_with_thread_local", not(feature = "logger_lazy")))]
799pub
800fn logger_log(pri: Priority, msg: String)
801{
802 if let Some(logger) = logger_cells::LOGGER.get()
803 {
804 let _ = logger.syslog(pri, msg);
805 }
806 else
807 {
808 logger_cells::LOGGER_LOCAL
809 .with_borrow_mut(
810 |b|
811 {
812 let Some(logger) = b
813 else { return; };
814
815 let _ = logger.syslog(pri, msg);
816 }
817 );
818 }
819}
820
821#[cfg(all(not(feature = "build_with_thread_local"), not(feature = "logger_lazy")))]
822pub
823fn logger_log(pri: Priority, msg: String)
824{
825 let Some(logger) = logger_cells::LOGGER.get()
826 else { return; };
827
828 let _ = logger.syslog(pri, msg);
829}
830
831#[cfg(all(feature = "logger_lazy"))]
832pub
833fn logger_log(pri: Priority, msg: String)
834{
835 let Some(logger) = logger_lazy::LOGGER.as_ref()
836 else { return; };
837
838 let _ = logger.syslog(pri, msg);
839}
840
841#[macro_export]
843macro_rules! logger_dbg
844{
845 ($($arg:tt)*) => (
846 $crate::logger::logger_log($crate::Priority::LOG_DEBUG, format!($($arg)*))
847 )
848}
849
850#[macro_export]
852macro_rules! logger_info
853{
854 ($($arg:tt)*) => (
855 $crate::logger::logger_log($crate::Priority::LOG_INFO, format!($($arg)*))
856 )
857}
858
859#[macro_export]
861macro_rules! logger_error
862{
863 ($($arg:tt)*) => (
864 $crate::logger::logger_log($crate::Priority::LOG_ERR, format!($($arg)*))
865 )
866}
867
868#[macro_export]
870macro_rules! logger_warn
871{
872 ($($arg:tt)*) => (
873 $crate::logger::logger_log($crate::Priority::LOG_WARNING, format!($($arg)*))
874 )
875}
876
877#[macro_export]
879macro_rules! logger_emerg
880{
881 ($($arg:tt)*) => (
882 $crate::logger::logger_log($crate::Priority::LOG_EMERG, format!($($arg)*))
883 )
884}
885
886#[macro_export]
888macro_rules! logger_custom
889{
890 ($prio:expr, $($arg:tt)*) => (
891 $crate::logger::logger_log($prio, format!($($arg)*))
892 )
893}
894
895
896#[test]
897fn test_parsing_logger()
898{
899 let res = LoggerDst::from_str("local#").unwrap();
900 assert_eq!(res, LoggerDst::LoLocal { dst_path: None });
901
902 let res = LoggerDst::from_str("local#/var/run/syslogcustom").unwrap();
903 assert_eq!(res, LoggerDst::LoLocal { dst_path: Some("/var/run/syslogcustom") });
904
905 #[cfg(feature = "build_ext_net")]
906 {
907 let res = LoggerDst::from_str("udp#127.0.0.1:80").unwrap();
908 assert_eq!(res, LoggerDst::LoUdp { dst_host: "127.0.0.1:80" });
909
910 let res = LoggerDst::from_str("udp#[fe00:::0]:80").unwrap();
911 assert_eq!(res, LoggerDst::LoUdp { dst_host: "[fe00:::0]:80" });
912
913 let res = LoggerDst::from_str("udp#www.mydomain.tdl:80").unwrap();
914 assert_eq!(res, LoggerDst::LoUdp { dst_host: "www.mydomain.tdl:80" });
915
916
917 let res = LoggerDst::from_str("tcp#127.0.0.1:80").unwrap();
918 assert_eq!(res, LoggerDst::LoTcp { dst_host: "127.0.0.1:80" });
919
920 let res = LoggerDst::from_str("tcp#[fe00:::0]:80").unwrap();
921 assert_eq!(res, LoggerDst::LoTcp { dst_host: "[fe00:::0]:80" });
922
923 let res = LoggerDst::from_str("tcp#www.mydomain.tdl:80").unwrap();
924 assert_eq!(res, LoggerDst::LoTcp { dst_host: "www.mydomain.tdl:80" });
925 }
926
927
928 #[cfg(feature = "build_ext_tls")]
929 {
930 let res = LoggerDst::from_str("tls#127.0.0.1:80#servername#/tmp/a1.crt").unwrap();
931 assert_eq!(res, LoggerDst::LoTls { dst_host: "127.0.0.1:80", serv_name: "servername", root_cert_path: "/tmp/a1.crt" });
932
933 let res = LoggerDst::from_str("tls#[fe00:::0]:80#servername#/tmp/a1.crt").unwrap();
934 assert_eq!(res, LoggerDst::LoTls { dst_host: "[fe00:::0]:80", serv_name: "servername", root_cert_path: "/tmp/a1.crt" });
935
936 let res = LoggerDst::from_str("tls#www.mydomain.tdl#servername#/tmp/a1.crt").unwrap();
937 assert_eq!(res, LoggerDst::LoTls { dst_host: "www.mydomain.tdl", serv_name: "servername", root_cert_path: "/tmp/a1.crt" });
938 }
939
940 #[cfg(feature = "build_ext_file")]
941 {
942 let res = LoggerDst::from_str("file#/tmp/file1.txt").unwrap();
943 assert_eq!(res, LoggerDst::LoFile { dst_path: "/tmp/file1.txt" });
944 }
945}
946
947#[test]
948fn test_env_set()
949{
950 unsafe { env::set_var(SYSLOG_LOGGER_DST_URI, "file#/tmp/test_log1.txt") };
951 unsafe { env::set_var(SYSLOG_LOGGER_LOG_FACILITY, "LOG_DAEMON") };
952 unsafe { env::set_var(SYSLOG_LOGGER_LOG_FORMATTER, "FILE") };
953 unsafe { env::set_var(SYSLOG_LOGGER_LOG_IDENTITY, "test_logger_file") };
954
955 let re = EnvVars::read_env(None).unwrap().unwrap();
956
957 assert_eq!(re.logger_type_res.as_str(), "file#/tmp/test_log1.txt");
958 assert_eq!(re.logger_facility, LogFacility::LOG_DAEMON);
959 assert_eq!(re.logger_formatter, SyslogFormatters::FormatFile);
960 assert_eq!(re.logger_identity.as_ref().map(|v| v.as_str()), Some("test_logger_file"));
961}
962
963#[test]
964fn test_env_set_suffix()
965{
966 let suf_xio = Some("XIO");
967 unsafe { env::set_var(derive_suffix(suf_xio, SYSLOG_LOGGER_DST_URI).as_ref(), "file#/tmp/xio_out.txt") };
968 unsafe { env::set_var(derive_suffix(suf_xio, SYSLOG_LOGGER_LOG_FACILITY).as_ref(), "LOG_DAEMON") };
969 unsafe { env::set_var(derive_suffix(suf_xio, SYSLOG_LOGGER_LOG_FORMATTER).as_ref(), "FILE") };
970 unsafe { env::set_var(derive_suffix(suf_xio, SYSLOG_LOGGER_LOG_IDENTITY).as_ref(), "xio_rs") };
971
972 let suf_so9 = Some("SOCKET9");
973 unsafe { env::set_var(derive_suffix(suf_so9, SYSLOG_LOGGER_DST_URI).as_ref(), "file#/tmp/socket9_out.txt") };
974 unsafe { env::set_var(derive_suffix(suf_so9, SYSLOG_LOGGER_LOG_FACILITY).as_ref(), "LOG_DAEMON") };
975 unsafe { env::set_var(derive_suffix(suf_so9, SYSLOG_LOGGER_LOG_FORMATTER).as_ref(), "FILE") };
976 unsafe { env::set_var(derive_suffix(suf_so9, SYSLOG_LOGGER_LOG_IDENTITY).as_ref(), "socket9") };
977
978 let re = EnvVars::read_env(suf_so9).unwrap().unwrap();
979
980 assert_eq!(re.logger_type_res.as_str(), "file#/tmp/socket9_out.txt");
981 assert_eq!(re.logger_facility, LogFacility::LOG_DAEMON);
982 assert_eq!(re.logger_formatter, SyslogFormatters::FormatFile);
983 assert_eq!(re.logger_identity.as_ref().map(|v| v.as_str()), Some("socket9"));
984}
985
986#[test]
987fn test_env_set2()
988{
989 unsafe { env::remove_var(SYSLOG_LOGGER_DST_URI) };
990 unsafe { env::set_var(SYSLOG_LOGGER_LOG_FACILITY, "LOG_DAEMON") };
991 unsafe { env::set_var(SYSLOG_LOGGER_LOG_FORMATTER, "FILE") };
992 unsafe { env::set_var(SYSLOG_LOGGER_LOG_IDENTITY, "test_logger_file") };
993
994 let re = EnvVars::read_env(None).unwrap();
995 assert_eq!(re.is_none(), true);
996}