syslog_rs/sync/syslog_sync.rs
1/*-
2 * syslog-rs - a syslog client translated from libc to rust
3 *
4 * Copyright 2025 Aleksandr Morozov
5 *
6 * The syslog-rs crate can be redistributed and/or modified
7 * under the terms of either of the following licenses:
8 *
9 * 1. the Mozilla Public License Version 2.0 (the “MPL”) OR
10 *
11 * 2. The MIT License (MIT)
12 *
13 * 3. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016
14 */
15
16use std::{fmt, marker::PhantomData, sync::{Arc, Mutex}};
17
18use crate::
19{
20 DefaultLocalSyslogDestination, LogFacility, LogStat, Priority, SyslogDestination, error::SyRes,
21 formatters::{DefaultSyslogFormatter, SyslogFormatter},
22 sync::{LogItems, SyStream, SyStreamPri, SyStreamSyslogApi, syslog_sync_internal::SyslogSocketLockless}
23};
24
25/// A public trait which defines the public interface for the `dyn` syslog instance.
26pub trait DynSyslog: Send + Sync
27{
28 /// Connects the current instance to the syslog server (destination).
29 fn connectlog(&self) -> SyRes<()>;
30
31 /// Sets the logmask to filter out the syslog calls.
32 ///
33 /// See macroses [LOG_MASK] and [LOG_UPTO] to generate mask
34 ///
35 /// # Example
36 ///
37 /// LOG_MASK!(Priority::LOG_EMERG) | LOG_MASK!(Priority::LOG_ERROR)
38 ///
39 /// or
40 ///
41 /// ~(LOG_MASK!(Priority::LOG_INFO))
42 /// LOG_UPTO!(Priority::LOG_ERROR)
43 fn setlogmask(&self, logmask: i32) -> SyRes<i32>;
44
45 /// Closes connection to the syslog server (destination).
46 fn closelog(&self) -> SyRes<()>;
47
48 /// Similar to libc, syslog() sends data to syslog server.
49 ///
50 /// # Arguments
51 ///
52 /// * `pri` - a priority [Priority]
53 ///
54 /// * `fmt` - a formatter string which should be sent to syslog/file.
55 ///
56 /// # Returns
57 ///
58 /// A [SyRes] is returned which may describe an error.
59 fn syslog(&self, pri: Priority, fmt: String) -> SyRes<()>;
60
61 /// This function can be used to update the facility name, for example
62 /// after fork().
63 ///
64 /// # Arguments
65 ///
66 /// * `ident` - an [Option] optional new identity (up to 48 UTF8 chars)
67 /// If set to [Option::None] would request the program name from OS.
68 fn change_identity(&self, ident: Option<&str>) -> SyRes<()>;
69
70 /// Updates the instance's socket. `tap_data` [TapTypeData] should be of
71 /// the same variant (type) as current.
72 fn reconnect(&self) -> SyRes<()>;
73}
74
75/// A public trait which defines the public interface for the `dyn` syslog instance.
76pub trait MutDynSyslog
77{
78 /// Connects the current instance to the syslog server (destination).
79 fn connectlog(&mut self) -> SyRes<()>;
80
81 /// Sets the logmask to filter out the syslog calls.
82 ///
83 /// See macroses [LOG_MASK] and [LOG_UPTO] to generate mask
84 ///
85 /// # Example
86 ///
87 /// LOG_MASK!(Priority::LOG_EMERG) | LOG_MASK!(Priority::LOG_ERROR)
88 ///
89 /// or
90 ///
91 /// ~(LOG_MASK!(Priority::LOG_INFO))
92 /// LOG_UPTO!(Priority::LOG_ERROR)
93 fn setlogmask(&mut self, logmask: i32) -> SyRes<i32>;
94
95 /// Closes connection to the syslog server (destination).
96 fn closelog(&mut self) -> SyRes<()>;
97
98 /// Similar to libc, syslog() sends data to syslog server.
99 ///
100 /// # Arguments
101 ///
102 /// * `pri` - a priority [Priority]
103 ///
104 /// * `fmt` - a formatter string which should be sent to syslog/file.
105 ///
106 /// # Returns
107 ///
108 /// A [SyRes] is returned which may describe an error.
109 fn syslog(&mut self, pri: Priority, fmt: String) -> SyRes<()>;
110
111 /// This function can be used to update the facility name, for example
112 /// after fork().
113 ///
114 /// # Arguments
115 ///
116 /// * `ident` - an [Option] optional new identity (up to 48 UTF8 chars)
117 /// If set to [Option::None] would request the program name from OS.
118 fn change_identity(&mut self, ident: Option<&str>) -> SyRes<()>;
119
120 /// Updates the instance's socket. `tap_data` [TapTypeData] should be of
121 /// the same variant (type) as current.
122 fn reconnect(&mut self) -> SyRes<()>;
123}
124
125/// Exposed only to allow constraint on the generic type. Should not be implemented on the
126/// user's side.
127pub trait SyslogType: fmt::Debug
128{
129 type LockItemsBase;
130
131 type LockItems;
132
133 type LockStreamBase<D: SyslogDestination>;
134
135 type LockStream<D: SyslogDestination>;
136
137 type MoveLockType;
138
139 fn wrap_items(items: Self::LockItemsBase) -> Self::LockItems;
140 fn wrap_stream<D: SyslogDestination>(stream: Self::LockStreamBase<D>) -> Self::LockStream<D>;
141}
142
143/// A main sync syslog client instance.
144///
145/// # Generics
146///
147/// * `F` - a syslog message formatter. See dir `src/formatters` for available or define one
148/// yourself. A default is [DefaultSyslogFormatter].
149///
150/// * `D` - a destination server/file. See file `src/syslog_provider.rs` for available
151/// transports. A default is [DefaultLocalSyslogDestination].
152///
153/// * `SL` - a client type. Sets the mechanism how the resources are shared. There are 3 types
154/// of syslog. See info below. Default is [SyShared].
155///
156/// # Client types
157///
158/// * [SyShared] - is a single FD descriptor which is protected by Mutex. This type can be
159/// clonned, moved between threads.
160///
161/// * [SyThreadLocal] - is a thread local/lockless type which should be used only in the
162/// single thread applications or with [std::thread_local] only! Can be enabled with
163/// feature `build_with_thread_local`.
164///
165/// * [SyQueued] - is a buffering/fast type which uses a separate thread to access the
166/// socket's/file's FD. This type can be clonned, moved between threads. Can be
167/// enabled with feature `build_with_queue`. Also, it can be used to use the same
168/// connection/file from async and sync code, see `examples/example_sync_async.rs`.
169///
170/// Feature `build_with_queue` without any async features uses a `crossbeam` MPSC. If
171/// any feature which enables `async` i.e `build_async_tokio`, `build_async_smol`,
172/// `build_async_interface`, the MPSC provider will be switch to either Smoll's, Tokio's,
173/// or which you will define.
174///
175/// # Examples
176///
177/// Full default:
178///
179/// ```ignore
180/// pub static SYSLOG: LazyLock<Syslog> = LazyLock::new(||
181/// {
182/// #[cfg(target_family = "unix")]
183/// let syslog_provider =
184/// SyslogLocal::new();
185///
186/// #[cfg(target_family = "windows")]
187/// let syslog_provider =
188/// WindowsEvent::new();
189///
190/// Syslog::openlog(
191/// Some("example"),
192/// LogStat::LOG_CONS | LogStat::LOG_PID,
193/// LogFacility::LOG_DAEMON,
194/// syslog_provider
195/// )
196/// .unwrap()
197/// }
198/// );
199/// ```
200///
201/// Custom i.e queued
202///
203/// ```ignore
204/// pub static SYSLOG: LazyLock<Syslog<DefaultSyslogFormatter, DefaultLocalSyslogDestination, SyQueued<DefaultQueueAdapter, DefaultSyslogFormatter, DefaultLocalSyslogDestination>>> =
205/// LazyLock::new(||
206/// {
207/// #[cfg(target_family = "unix")]
208/// let syslog_provider =
209/// SyslogLocal::new();
210///
211/// #[cfg(target_family = "windows")]
212/// let syslog_provider =
213/// WindowsEvent::new();
214///
215/// Syslog
216/// ::<_, _, SyQueued<DefaultQueueAdapter, _, _>>
217/// ::openlog_with(
218/// Some("example_sync_queue"),
219/// LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID,
220/// LogFacility::LOG_DAEMON,
221/// syslog_provider
222/// )
223/// .unwrap()
224/// }
225/// );
226/// ```
227///
228#[derive(Debug)]
229pub struct Syslog<F = DefaultSyslogFormatter, D = DefaultLocalSyslogDestination, SL = SyShared>
230where
231 F: SyslogFormatter,
232 D: SyslogDestination,
233 SL: SyslogType
234{
235 /// An identification i.e program name, thread name
236 log_items: SL::LockItems,
237
238 /// A stream (unixdatagram, udp, tcp)
239 stream: SL::LockStream<D>,
240
241 _p: PhantomData<F>,
242
243 _p_not_ss: SL::MoveLockType
244}
245
246impl Syslog
247{
248 /// Opens a default connection to the local syslog server with default formatter.
249 ///
250 /// In order to access the syslog API, use the [SyslogApi].
251 ///
252 /// # Arguments
253 ///
254 /// * `ident` - A program name which will appear on the logs. If none, will be determined
255 /// automatically.
256 ///
257 /// * `logstat` - [LogStat] an instance config.
258 ///
259 /// * `facility` - [LogFacility] a syslog facility.
260 ///
261 /// * `net_tap_prov` - a [SyslogLocal] instance with configuration.
262 ///
263 /// # Returns
264 ///
265 /// A [SyRes] is returned ([Result]) with:
266 ///
267 /// * [Result::Ok] - with instance
268 ///
269 /// * [Result::Err] - with error description.
270 pub
271 fn openlog(ident: Option<&str>, logstat: LogStat, facility: LogFacility,
272 net_tap_prov: DefaultLocalSyslogDestination) -> SyRes<Self>
273 {
274 return Ok(
275 Self
276 {
277 log_items:
278 <SyShared as SyslogType>
279 ::wrap_items(
280 <SyShared as SyslogType>::LockItemsBase::new(ident, 0xff, logstat, facility)
281 ),
282 stream:
283 <SyShared as SyslogType>
284 ::wrap_stream(
285 <SyShared as SyslogType>::LockStreamBase::<DefaultLocalSyslogDestination>::new(logstat, net_tap_prov)?,
286 ),
287 _p:
288 PhantomData,
289 _p_not_ss:
290 PhantomData
291 }
292 );
293 }
294}
295
296#[cfg(feature = "build_with_thread_local")]
297pub mod build_with_thread_local
298{
299 use super::*;
300
301 /// A threal local syslog which is completely lockless! It can be used in signle threaded
302 /// applications or with the [thread_local] functionality.
303 ///
304 /// ```ignore
305 /// thread_local!
306 /// {
307 /// // Could add pub to make it public to whatever Foo already is public to.
308 /// static SYSLOG: RefCell<Syslog<DefaultSyslogFormatter, SyslogLocal, SyThreadLocal>> =
309 /// RefCell::new(
310 /// Syslog
311 /// ::<_, _, SyThreadLocal>
312 //// ::openlog_with(Some("test"), LogStat::LOG_PID, LogFacility::LOG_DAEMON, SyslogLocal::new())
313 /// .unwrap()
314 /// );
315 /// }
316 /// ```
317 ///
318 /// A stream is availble via [SyStreamApi].
319 ///
320 /// ```ignore
321 /// let _ = write!(SYSLOG.stream(Priority::LOG_DEBUG), "test {} 123 stream test ", d);
322 /// ```
323 ///
324 /// The instances will be completly separated and have own FD.
325 ///
326 /// # Generics
327 ///
328 /// * `D` - a [SyslogDestination] instance which is either:
329 /// [SyslogLocal], [crate::syslog_provider::SyslogFile], [crate::syslog_provider::SyslogNet],
330 /// [crate::syslog_provider::SyslogTls]. By default a `SyslogLocal` is selected.
331 ///
332 /// * `F` - a [SyslogFormatter] which sets the instance which would
333 /// format the message.
334 ///
335 #[derive(Debug)]
336 pub struct SyThreadLocal;
337
338 impl SyslogType for SyThreadLocal
339 {
340 type LockItemsBase = LogItems;
341 type LockItems = Self::LockItemsBase;
342
343 type LockStreamBase<D: SyslogDestination> = SyslogSocketLockless<D>;
344 type LockStream<D: SyslogDestination> = Self::LockStreamBase<D>;
345
346 type MoveLockType = PhantomData<*const ()>;
347
348 fn wrap_items(items: Self::LockItemsBase) -> Self::LockItems
349 {
350 items
351 }
352
353 fn wrap_stream<D: SyslogDestination>(stream: Self::LockStreamBase<D>) -> Self::LockStream<D>
354 {
355 stream
356 }
357 }
358
359 impl<F, D> MutDynSyslog for Syslog<F, D, SyThreadLocal>
360 where
361 F: SyslogFormatter,
362 D: SyslogDestination,
363 {
364 #[inline]
365 fn connectlog(&mut self) -> SyRes<()>
366 {
367 self.connectlog()
368 }
369
370 #[inline]
371 fn setlogmask(&mut self, logmask: i32) -> SyRes<i32>
372 {
373 self.setlogmask(logmask)
374 }
375
376 #[inline]
377 fn closelog(&mut self) -> SyRes<()>
378 {
379 self.closelog()
380 }
381
382 fn syslog(&mut self, pri: Priority, fmt: String) -> SyRes<()>
383 {
384 self.syslog(pri, fmt.into())
385 }
386
387 fn change_identity(&mut self, ident: Option<&str>) -> SyRes<()>
388 {
389 self.change_identity(ident)
390 }
391
392 fn reconnect(&mut self) -> SyRes<()>
393 {
394 self.reconnect()
395 }
396 }
397
398 impl<F, D> Syslog<F, D, SyThreadLocal>
399 where
400 F: SyslogFormatter,
401 D: SyslogDestination,
402 {
403 pub
404 fn make_dyn(self) -> Box<dyn MutDynSyslog>
405 {
406 Box::new(self)
407 }
408
409 /// Opens a default connection to the local syslog server with default formatter.
410 ///
411 /// # Arguments
412 ///
413 /// * `ident` - A program name which will appear on the logs. If none, will be determined
414 /// automatically.
415 ///
416 /// * `logstat` - [LogStat] an instance config.
417 ///
418 /// * `facility` - [LogFacility] a syslog facility.
419 ///
420 /// * `net_tap_prov` - a [SyslogLocal] instance with configuration.
421 ///
422 /// # Returns
423 ///
424 /// A [SyRes] is returned ([Result]) with:
425 ///
426 /// * [Result::Ok] - with instance
427 ///
428 /// * [Result::Err] - with error description.
429 pub
430 fn openlog_with(ident: Option<&str>, logstat: LogStat, facility: LogFacility, net_tap_prov: D) -> SyRes<Self>
431 {
432 return Ok(
433 Self
434 {
435 log_items:
436 <SyThreadLocal as SyslogType>
437 ::wrap_items(
438 <SyThreadLocal as SyslogType>::LockItems::new(ident, 0xff, logstat, facility)
439 ),
440 stream:
441 <SyThreadLocal as SyslogType>
442 ::wrap_stream(
443 <SyThreadLocal as SyslogType>::LockStream::new(logstat, net_tap_prov)?
444 ),
445 _p:
446 PhantomData,
447 _p_not_ss:
448 PhantomData
449 }
450 );
451 }
452 }
453
454 impl<F, D> Syslog<F, D, SyThreadLocal>
455 where
456 F: SyslogFormatter,
457 D: SyslogDestination,
458 {
459 /// Connects the current instance to the syslog server (destination).
460 #[inline]
461 pub
462 fn connectlog(&mut self) -> SyRes<()>
463 {
464 return
465 self
466 .stream
467 .connectlog();
468 }
469
470 /// Sets the logmask to filter out the syslog calls.
471 ///
472 /// See macroses [LOG_MASK] and [LOG_UPTO] to generate mask
473 ///
474 /// # Example
475 ///
476 /// LOG_MASK!(Priority::LOG_EMERG) | LOG_MASK!(Priority::LOG_ERROR)
477 ///
478 /// or
479 ///
480 /// ~(LOG_MASK!(Priority::LOG_INFO))
481 /// LOG_UPTO!(Priority::LOG_ERROR)
482 #[inline]
483 pub
484 fn setlogmask(&mut self, logmask: i32) -> SyRes<i32>
485 {
486 return Ok(
487 self
488 .log_items
489 .set_logmask(logmask)
490 );
491 }
492
493 /// Closes connection to the syslog server (destination).
494 #[inline]
495 pub
496 fn closelog(&mut self) -> SyRes<()>
497 {
498 return
499 self
500 .stream
501 .disconnectlog();
502 }
503
504 /// Similar to libc, syslog() sends data to syslog server.
505 ///
506 /// # Arguments
507 ///
508 /// * `pri` - a priority [Priority]
509 ///
510 /// * `fmt` - a formatter [SyslogFormatter] message. In C exists a functions with
511 /// variable argumets amount. In Rust you should create your
512 /// own macros like format!() or use format!()]. The [String] and ref `'static`
513 /// [str] can be passed directly.
514 ///
515 /// # Returns
516 ///
517 /// A [SyRes] is returned which may describe an error.
518 #[inline]
519 pub
520 fn syslog(&mut self, pri: Priority, fmt: F) -> SyRes<()>
521 {
522 let Some((formatted_msg, logstat)) =
523 self.log_items.vsyslog1_msg::<F, D>(pri, &fmt)
524 else { return Ok(()) };
525
526 self.stream.vsyslog1(logstat, formatted_msg)
527 }
528
529 /// This function can be used to update the facility name, for example
530 /// after fork().
531 ///
532 /// # Arguments
533 ///
534 /// * `ident` - an [Option] optional new identity (up to 48 UTF8 chars)
535 /// If set to [Option::None] would request the program name from OS.
536 #[inline]
537 pub
538 fn change_identity(&mut self, ident: Option<&str>) -> SyRes<()>
539 {
540 self.log_items.set_identity(ident);
541
542 return Ok(());
543 }
544
545 /// Re-opens the connection to the syslog server. Can be used to
546 /// rotate logs(handle SIGHUP).
547 ///
548 /// # Returns
549 ///
550 /// A [Result] is retured as [SyRes].
551 ///
552 /// * [Result::Ok] - with empty inner type.
553 ///
554 /// * [Result::Err] - an error code and description
555 #[inline]
556 pub
557 fn reconnect(&mut self) -> SyRes<()>
558 {
559 return
560 self
561 .stream
562 .reconnectlog();
563 }
564
565 /// Updates the instance's socket. `tap_data` [TapTypeData] should be of
566 /// the same variant (type) as current.
567 #[inline]
568 pub
569 fn update_tap_data(&mut self, tap_data: D) -> SyRes<()>
570 {
571 return
572 self
573 .stream
574 .update_tap_data(tap_data.clone());
575 }
576 }
577
578 impl<F, D> Syslog<F, D, SyThreadLocal>
579 where
580 F: SyslogFormatter,
581 D: SyslogDestination,
582 {
583 /// Returns the streamable [SyStream] instance which can be used with [write!].
584 ///
585 /// It implements both [std::fmt::Write] and [std::io::Write].
586 ///
587 /// # Example
588 ///
589 /// ```ignore
590 /// let log =
591 /// SingleSyslog::openlog(
592 /// Some("test1"),
593 /// LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID,
594 /// LogFacility::LOG_DAEMON,
595 /// SyslogLocal::new()
596 /// ).unwrap();
597 ///
598 /// write!(log.get_stream::<SyStreamPriDebug>(), "test stream singlesyslog {}", i).unwrap();
599 /// ```
600 pub
601 fn get_stream<'t, PRI>(&'t mut self) -> SyStream<'t, PRI, D, F, &'t mut Self>
602 where PRI: SyStreamPri
603 {
604 SyStream
605 {
606 s: Some(self),
607 _p: PhantomData,
608 _p1: PhantomData,
609 _p2: PhantomData
610 }
611 }
612 }
613
614 impl<F, D> SyStreamSyslogApi<F, D>
615 for &mut Syslog<F, D, SyThreadLocal>
616 where
617 F: SyslogFormatter,
618 D: SyslogDestination,
619 {
620 type SYSLOG<'t> = &'t mut Syslog<F, D, SyThreadLocal>;
621
622 fn syslog<'t>(syslog: Self::SYSLOG<'t>, pri: Priority, fmt: F) -> SyRes<()>
623 {
624 syslog.syslog(pri, fmt)
625 }
626 }
627}
628
629#[cfg(feature = "build_with_thread_local")]
630pub use self::build_with_thread_local::SyThreadLocal;
631
632// ---- SYSLOG SHARED
633
634/// A `sync`, shared instance of the syslog client which is shared between many
635/// threads. Previously a mutex was used, but since the v5.0.0 a CoW experimental
636/// approach is used. The `CoW` creates clones of the instance without holding
637/// a long mutex locks. When writing, the instance does not hold a long lock on
638/// updated item. Only exclusive lock locks the readers, because the instance is
639/// updated and not usable anyway.
640///
641/// If the program has fixed amount of threads, probably the `syslog_threadlocal`
642/// will be better alternative. It has the same functionality, but avoids
643/// any sync locks by working in current thread.
644///
645/// # Traits
646///
647/// For this isntance a [SyslogApi] and [SyStreamApi] are implemented.
648///
649/// # Examples
650///
651/// ```ignore
652/// let log =
653/// Syslog::openlog(
654/// Some("test1"),
655/// LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID,
656/// LogFacility::LOG_DAEMON,
657/// SyslogLocal::new()
658/// );
659/// ```
660///
661/// ```ignore
662/// let log =
663/// Syslog
664/// ::<DefaultSyslogFormatter, SyslogLocal, SyShared>
665/// ::openlog_with(
666/// Some("test1"),
667/// LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID,
668/// LogFacility::LOG_DAEMON,
669/// SyslogLocal::new()
670/// );
671/// ```
672///
673/// ```ignore
674/// pub static SYSLOG3: LazyLock<Syslog<DefaultSyslogFormatter, SyslogLocal, SyShared>> =
675/// LazyLock::new(||
676/// {
677/// Syslog
678/// ::<DefaultSyslogFormatter, SyslogLocal, SyShared>
679/// ::openlog_with(
680/// Some("test1"),
681/// LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID,
682/// LogFacility::LOG_DAEMON,
683/// SyslogLocal::new()
684/// )
685/// .unwrap()
686/// }
687/// );
688/// ```
689/// # Streaming
690///
691/// A stream is availble via [SyStreamApi].
692///
693/// ```ignore
694/// let _ = write!(SYSLOG.stream(Priority::LOG_DEBUG), "test {} 123 stream test ", d);
695/// ```
696///
697/// # Generics
698///
699/// * `F` - a [SyslogFormatter] which sets the instance which would
700/// format the message.
701///
702/// * `D` - a [SyslogDestination] instance which is either:
703/// [SyslogLocal], [SyslogFile], [SyslogNet], [SyslogTls]. By
704/// default a `SyslogLocal` is selected.
705#[derive(Debug)]
706pub struct SyShared;
707
708impl SyslogType for SyShared
709{
710 type LockItemsBase = LogItems;
711 type LockItems = Arc<Mutex<Self::LockItemsBase>>;
712
713 type LockStreamBase<D: SyslogDestination> = SyslogSocketLockless<D>;
714 type LockStream<D: SyslogDestination> = Arc<Mutex<Self::LockStreamBase<D>>>;
715
716 type MoveLockType = PhantomData<()>;
717
718 fn wrap_items(items: Self::LockItemsBase) -> Self::LockItems
719 {
720 Arc::new(Mutex::new(items))
721 }
722
723 fn wrap_stream<D: SyslogDestination>(stream: Self::LockStreamBase<D>) -> Self::LockStream<D>
724 {
725 Arc::new(Mutex::new(stream))
726 }
727}
728
729impl<F, D> Clone for Syslog<F, D, SyShared>
730where
731 F: SyslogFormatter,
732 D: SyslogDestination,
733{
734 fn clone(&self) -> Self
735 {
736 Self
737 {
738 log_items:
739 self.log_items.clone(),
740 stream:
741 self.stream.clone(),
742 _p:
743 PhantomData,
744 _p_not_ss:
745 PhantomData,
746 }
747 }
748}
749
750impl<F, D> DynSyslog for Syslog<F, D, SyShared>
751where
752 F: SyslogFormatter,
753 D: SyslogDestination,
754{
755 #[inline]
756 fn connectlog(&self) -> SyRes<()>
757 {
758 self.connectlog()
759 }
760
761 #[inline]
762 fn setlogmask(&self, logmask: i32) -> SyRes<i32>
763 {
764 self.setlogmask(logmask)
765 }
766
767 #[inline]
768 fn closelog(&self) -> SyRes<()>
769 {
770 self.closelog()
771 }
772
773 fn syslog(&self, pri: Priority, fmt: String) -> SyRes<()>
774 {
775 self.syslog(pri, fmt.into())
776 }
777
778 fn change_identity(&self, ident: Option<&str>) -> SyRes<()>
779 {
780 self.change_identity(ident)
781 }
782
783 fn reconnect(&self) -> SyRes<()>
784 {
785 self.reconnect()
786 }
787}
788
789
790impl<F, D> Syslog<F, D, SyShared>
791where
792 F: SyslogFormatter,
793 D: SyslogDestination,
794{
795 pub
796 fn make_dyn(self) -> Box<dyn DynSyslog + Send + Sync>
797 {
798 Box::new(self)
799 }
800
801 /// Opens a special connection to the destination syslog server with specific formatter.
802 ///
803 /// All struct generic should be specified before calling this function.
804 ///
805 /// In order to access the syslog API, use the [SyslogApi].
806 ///
807 /// # Arguments
808 ///
809 /// * `ident` - A program name which will appear on the logs. If none, will be determined
810 /// automatically.
811 ///
812 /// * `logstat` - [LogStat] an instance config.
813 ///
814 /// * `facility` - [LogFacility] a syslog facility.
815 ///
816 /// * `net_tap_prov` - a destination server. A specific `D` instance which contains infomation
817 /// about the destination server. See `syslog_provider.rs`.
818 ///
819 /// # Returns
820 ///
821 /// A [SyRes] is returned ([Result]) with:
822 ///
823 /// * [Result::Ok] - with instance
824 ///
825 /// * [Result::Err] - with error description.
826 pub
827 fn openlog_with(ident: Option<&str>, logstat: LogStat, facility: LogFacility, net_tap_prov: D) -> SyRes<Self>
828 {
829 return Ok(
830 Self
831 {
832 log_items:
833 <SyShared as SyslogType>
834 ::wrap_items(
835 <SyShared as SyslogType>::LockItemsBase::new(ident, 0xff, logstat, facility)
836 ),
837 stream:
838 <SyShared as SyslogType>
839 ::wrap_stream(
840 <SyShared as SyslogType>::LockStreamBase::<D>::new(logstat, net_tap_prov)?,
841 ),
842 _p:
843 PhantomData,
844 _p_not_ss:
845 PhantomData
846 }
847 );
848 }
849
850 /// Just initializes the instance from other instance. For example, in the crate which uses
851 /// this type of logging.
852 ///
853 /// Will work only if `F` and `D` are same.
854 pub
855 fn attach(other: &Syslog<F, D, SyShared>) -> SyRes<Self>
856 {
857 Ok(other.clone())
858 }
859}
860
861impl<F, D> Syslog<F, D, SyShared>
862where
863 F: SyslogFormatter,
864 D: SyslogDestination,
865{
866 /// Connects the current instance to the syslog server (destination).
867 pub
868 fn connectlog(&self) -> SyRes<()>
869 {
870 return
871 self
872 .stream
873 .lock()
874 .unwrap()
875 .connectlog();
876 }
877
878 /// Sets the logmask to filter out the syslog calls.
879 ///
880 /// See macroses [LOG_MASK] and [LOG_UPTO] to generate mask
881 ///
882 /// # Example
883 ///
884 /// LOG_MASK!(Priority::LOG_EMERG) | LOG_MASK!(Priority::LOG_ERROR)
885 ///
886 /// or
887 ///
888 /// ~(LOG_MASK!(Priority::LOG_INFO))
889 /// LOG_UPTO!(Priority::LOG_ERROR)
890 pub
891 fn setlogmask(&self, logmask: i32) -> SyRes<i32>
892 {
893 let pri =
894 self
895 .log_items
896 .lock()
897 .unwrap()
898 .set_logmask(logmask);
899
900 return Ok(pri);
901 }
902
903 /// Closes connection to the syslog server (destination).
904 pub
905 fn closelog(&self) -> SyRes<()>
906 {
907 return
908 self
909 .stream
910 .lock()
911 .unwrap()
912 .disconnectlog();
913 }
914
915 /// Similar to libc, syslog() sends data to syslog server.
916 ///
917 /// # Arguments
918 ///
919 /// * `pri` - a priority [Priority]
920 ///
921 /// * `fmt` - a formatter [SyslogFormatter] message. In C exists a functions with
922 /// variable argumets amount. In Rust you should create your
923 /// own macros like format!() or use format!()]. The [String] and ref `'static`
924 /// [str] can be passed directly.
925 ///
926 /// # Returns
927 ///
928 /// A [SyRes] is returned which may describe an error.
929 #[inline]
930 pub
931 fn syslog(&self, pri: Priority, fmt: F) -> SyRes<()>
932 {
933 let Some((formatted_msg, logstat)) =
934 self.log_items.lock().unwrap().vsyslog1_msg::<F, D>(pri, &fmt)
935 else { return Ok(()) };
936
937 self.stream.lock().unwrap().vsyslog1(logstat, formatted_msg)
938 }
939
940 /// This function can be used to update the facility name, for example
941 /// after fork().
942 ///
943 /// # Arguments
944 ///
945 /// * `ident` - an [Option] optional new identity (up to 48 UTF8 chars)
946 /// If set to [Option::None] would request the program name from OS.
947 pub
948 fn change_identity(&self, ident: Option<&str>) -> SyRes<()>
949 {
950 self
951 .log_items
952 .lock()
953 .unwrap()
954 .set_identity(ident);
955
956 return Ok(());
957 }
958
959 /// Re-opens the connection to the syslog server. Can be used to
960 /// rotate logs(handle SIGHUP).
961 ///
962 /// # Returns
963 ///
964 /// A [Result] is retured as [SyRes].
965 ///
966 /// * [Result::Ok] - with empty inner type.
967 ///
968 /// * [Result::Err] - an error code and description
969 pub
970 fn reconnect(&self) -> SyRes<()>
971 {
972 return
973 self
974 .stream
975 .lock()
976 .unwrap()
977 .reconnectlog();
978 }
979
980 /// Updates the instance's socket. `tap_data` [TapTypeData] should be of
981 /// the same variant (type) as current.
982 pub
983 fn update_tap_data(&self, tap_data: D) -> SyRes<()>
984 {
985 return
986 self
987 .stream
988 .lock()
989 .unwrap()
990 .update_tap_data(tap_data);
991 }
992}
993
994impl<F, D> Syslog<F, D, SyShared>
995where
996 F: SyslogFormatter,
997 D: SyslogDestination,
998{
999 /// Returns the streamable [SyStream] instance which can be used with [write!].
1000 ///
1001 /// It implements both [std::fmt::Write] and [std::io::Write].
1002 ///
1003 /// # Example
1004 ///
1005 /// ```ignore
1006 /// let log =
1007 /// SingleSyslog::openlog(
1008 /// Some("test1"),
1009 /// LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID,
1010 /// LogFacility::LOG_DAEMON,
1011 /// SyslogLocal::new()
1012 /// ).unwrap();
1013 ///
1014 /// write!(log.get_stream::<SyStreamPriDebug>(), "test stream singlesyslog {}", i).unwrap();
1015 /// ```
1016 pub
1017 fn get_stream<'t, PRI>(&'t self) -> SyStream<'t, PRI, D, F, &'t Self>
1018 where PRI: SyStreamPri
1019 {
1020 SyStream
1021 {
1022 s: Some(self),
1023 _p: PhantomData,
1024 _p1: PhantomData,
1025 _p2: PhantomData
1026 }
1027 }
1028}
1029
1030impl<F: SyslogFormatter, D: SyslogDestination> SyStreamSyslogApi<F, D>
1031for &Syslog<F, D, SyShared>
1032{
1033 type SYSLOG<'t> = &'t Syslog<F, D, SyShared>;
1034
1035 fn syslog<'t>(syslog: Self::SYSLOG<'t>, pri: Priority, fmt: F) -> SyRes<()>
1036 {
1037 syslog.syslog(pri, fmt)
1038 }
1039}
1040
1041// --- QUEUE
1042
1043
1044#[cfg(feature = "build_with_queue")]
1045pub mod build_with_queue
1046{
1047 use std::{sync::{Arc, Mutex, Weak, atomic::{AtomicBool, Ordering}}, thread};
1048
1049 use crate::{DefaultLocalSyslogDestination, SyslogDestination, formatters::{DefaultSyslogFormatter, SyslogFormatter}, map_error, sy_sync_queue::{SyCmd, SyslogInternal, SyslogQueueChanSnd, SyslogQueueChannel, SyslogQueueOneChanRcv}, sync::DefaultQueueAdapter};
1050
1051 use super::*;
1052
1053 /// A queued syslog client which uses a separate thread to send messages to upstream.
1054 ///
1055 /// # Generics
1056 ///
1057 /// * `F` - a syslog message formatter. See dir `src/formatters` for available or define one
1058 /// yourself. A default is [DefaultSyslogFormatter].
1059 ///
1060 /// * `D` - a destination server/file. See file `src/syslog_provider.rs` for available
1061 /// transports. A default is [DefaultLocalSyslogDestination].
1062 ///
1063 /// * `S` - a queue mechanism. A default is [DefaultLocalSyslogDestination]. If you don't
1064 /// need any special queue mechanism, use the default.
1065 #[derive(Debug, Clone)]
1066 pub struct SyQueued<S = DefaultQueueAdapter, F = DefaultSyslogFormatter, D = DefaultLocalSyslogDestination>
1067 where
1068 F: SyslogFormatter,
1069 D: SyslogDestination,
1070 S: SyslogQueueChannel<F, D>,
1071
1072 {
1073 /// Control flag
1074 run_control: Weak<AtomicBool>,
1075
1076 /// commands channel
1077 pub(crate) tasks: S::ChannelSnd,
1078
1079 /// process thread
1080 thread: Arc<Mutex<Option<thread::JoinHandle<()>>>>,
1081 }
1082
1083 impl<F, DD, S> SyslogType for SyQueued<S, F, DD>
1084 where F: SyslogFormatter, DD: SyslogDestination, S: SyslogQueueChannel<F, DD>
1085 {
1086 type LockItemsBase = ();
1087 type LockItems = Self::LockItemsBase;
1088
1089 type LockStreamBase<D: SyslogDestination> = SyQueued<S, F, DD>;
1090 type LockStream<D: SyslogDestination> = Self::LockStreamBase<D>;
1091
1092 type MoveLockType = PhantomData<()>;
1093
1094 fn wrap_items(items: Self::LockItemsBase) -> Self::LockItems
1095 {
1096 items
1097 }
1098
1099 fn wrap_stream<D: SyslogDestination>(stream: Self::LockStreamBase<D>) -> Self::LockStream<D>
1100 {
1101 stream
1102 }
1103 }
1104
1105 unsafe impl<F, D, S> Send for SyQueued<S, F, D>
1106 where F: SyslogFormatter, D: SyslogDestination, S: SyslogQueueChannel<F, D>
1107 {}
1108
1109 impl<F, D, S> Drop for SyQueued<S, F, D>
1110 where F: SyslogFormatter, D: SyslogDestination, S: SyslogQueueChannel<F, D>
1111 {
1112 fn drop(&mut self)
1113 {
1114 if let Some(ctrl) = self.run_control.upgrade()
1115 {
1116 ctrl.store(false, Ordering::SeqCst);
1117
1118 if let Err(_e) = self.tasks.q_send_blocking(SyCmd::form_stop())
1119 {
1120
1121 }
1122
1123 let join_handle = self.thread.lock().unwrap().take().unwrap();
1124
1125 let _ = join_handle.join();
1126 }
1127 }
1128 }
1129
1130 impl<F, D, S> Clone for Syslog<F, D, SyQueued<S, F, D>>
1131 where F: SyslogFormatter, D: SyslogDestination, S: SyslogQueueChannel<F, D>
1132 {
1133 fn clone(&self) -> Self
1134 {
1135 Self
1136 {
1137 log_items:
1138 self.log_items.clone(),
1139 stream:
1140 self.stream.clone(),
1141 _p:
1142 PhantomData,
1143 _p_not_ss:
1144 PhantomData
1145 }
1146 }
1147 }
1148
1149 impl<F, D, S> DynSyslog for Syslog<F, D, SyQueued<S, F, D>>
1150 where
1151 F: SyslogFormatter,
1152 D: SyslogDestination,
1153 S: SyslogQueueChannel<F, D>
1154 {
1155 #[inline]
1156 fn connectlog(&self) -> SyRes<()>
1157 {
1158 self.connectlog()
1159 }
1160
1161 #[inline]
1162 fn setlogmask(&self, logmask: i32) -> SyRes<i32>
1163 {
1164 self.setlogmask(logmask)
1165 }
1166
1167 #[inline]
1168 fn closelog(&self) -> SyRes<()>
1169 {
1170 self.closelog()
1171 }
1172
1173 fn syslog(&self, pri: Priority, fmt: String) -> SyRes<()>
1174 {
1175 self.syslog(pri, fmt.into())
1176 }
1177
1178 fn change_identity(&self, ident: Option<&str>) -> SyRes<()>
1179 {
1180 self.change_identity(ident)
1181 }
1182
1183 fn reconnect(&self) -> SyRes<()>
1184 {
1185 self.reconnect()
1186 }
1187 }
1188
1189 impl<F, D, S> Syslog<F, D, SyQueued<S, F, D>>
1190 where
1191 F: SyslogFormatter,
1192 D: SyslogDestination,
1193 S: SyslogQueueChannel<F, D>
1194 {
1195 /// Converts the current instance into dyncamic object. See [DynSyslog] for the interface.
1196 pub
1197 fn make_dyn(self) -> Box<dyn DynSyslog + Send + Sync>
1198 {
1199 Box::new(self)
1200 }
1201
1202 /// Opens a default connection to the local syslog server with default formatter with
1203 /// provided generics.
1204 ///
1205 /// # Arguments
1206 ///
1207 /// * `ident` - A program name which will appear on the logs. If none, will be determined
1208 /// automatically.
1209 ///
1210 /// * `logstat` - [LogStat] an instance config.
1211 ///
1212 /// * `facility` - [LogFacility] a syslog facility.
1213 ///
1214 /// * `net_tap_prov` - a [SyslogLocal] instance with configuration.
1215 ///
1216 /// # Returns
1217 ///
1218 /// A [SyRes] is returned ([Result]) with:
1219 ///
1220 /// * [Result::Ok] - with instance
1221 ///
1222 /// * [Result::Err] - with error description.
1223 pub
1224 fn openlog_with(ident: Option<&str>, logstat: LogStat, facility: LogFacility, net_tap_prov: D) -> SyRes<Self>
1225 {
1226 // creating internal syslog struct
1227
1228 let log_items =
1229 LogItems::new(ident, 0xff, logstat, facility);
1230
1231 let stream =
1232 SyslogSocketLockless::<D>::new(logstat, net_tap_prov)?;
1233
1234 let (inst, sender, run_ctrl) =
1235 SyslogInternal::<F, D, S>::new(log_items, stream)?;
1236
1237
1238 let thr_name: String = "syslog_queue/0".into();
1239
1240 // initiate a thread
1241 let thread_hnd =
1242 thread::Builder::new()
1243 .name(thr_name.clone())
1244 .spawn(move || SyslogInternal::<F, D, S>::thread_worker(inst))
1245 .map_err(|e|
1246 map_error!("{} thread spawn failed. {}", thr_name, e)
1247 )?;
1248
1249 let sy_q =
1250 SyQueued
1251 {
1252 run_control:
1253 run_ctrl,
1254 tasks:
1255 sender,
1256 thread:
1257 Arc::new(Mutex::new(Some(thread_hnd))),
1258 };
1259
1260 return Ok(
1261 Self
1262 {
1263 log_items:
1264 (),
1265 stream:
1266 sy_q,
1267 _p:
1268 PhantomData,
1269 _p_not_ss:
1270 PhantomData
1271 }
1272 );
1273 }
1274 }
1275
1276 impl<F, D, S> Syslog<F, D, SyQueued<S, F, D>>
1277 where
1278 F: SyslogFormatter,
1279 D: SyslogDestination,
1280 S: SyslogQueueChannel<F, D>
1281 {
1282 /// Connects the current instance to the syslog server (destination).
1283 pub
1284 fn connectlog(&self) -> SyRes<()>
1285 {
1286 let (sy_cmd, loopback) =
1287 SyCmd::form_connectlog();
1288
1289 self.stream.tasks.q_send_blocking(sy_cmd)?;
1290
1291 return
1292 loopback
1293 .recv_once_blocking()?;
1294 }
1295
1296 /// Sets the logmask to filter out the syslog calls.
1297 ///
1298 /// See macroses [LOG_MASK] and [LOG_UPTO] to generate mask
1299 ///
1300 /// # Example
1301 ///
1302 /// LOG_MASK!(Priority::LOG_EMERG) | LOG_MASK!(Priority::LOG_ERROR)
1303 ///
1304 /// or
1305 ///
1306 /// ~(LOG_MASK!(Priority::LOG_INFO))
1307 /// LOG_UPTO!(Priority::LOG_ERROR)
1308 pub
1309 fn setlogmask(&self, logmask: i32) -> SyRes<i32>
1310 {
1311 let (sy_cmd, loopback) =
1312 SyCmd::form_logmask(logmask);
1313
1314 self.stream.tasks.q_send_blocking(sy_cmd)?;
1315
1316 return
1317 loopback
1318 .recv_once_blocking();
1319 }
1320
1321 /// Closes connection to the syslog server (destination).
1322 pub
1323 fn closelog(&self) -> SyRes<()>
1324 {
1325 let (sy_cmd, loopback) =
1326 SyCmd::form_disconnectlog();
1327
1328 // send stop
1329 self.stream.tasks.q_send_blocking(sy_cmd)?;
1330
1331 return
1332 loopback
1333 .recv_once_blocking()?;
1334 }
1335
1336 /// Similar to libc, syslog() sends data to syslog server.
1337 ///
1338 /// # Arguments
1339 ///
1340 /// * `pri` - a priority [Priority]
1341 ///
1342 /// * `fmt` - a formatter [SyslogFormatter] message. In C exists a functions with
1343 /// variable argumets amount. In Rust you should create your
1344 /// own macros like format!() or use format!()]. The [String] and ref `'static`
1345 /// [str] can be passed directly.
1346 ///
1347 /// # Returns
1348 ///
1349 /// A [SyRes] is returned which may describe an error.
1350 pub
1351 fn syslog(&self, pri: Priority, fmt: F) -> SyRes<()>
1352 {
1353 // even if the thread is in a process of termination, there is
1354 // no need to sync access to the run_control field as even if
1355 // syslog thread will terminate before someone push something on the
1356 // queue, it will be left in the queue until the end of program's time.
1357
1358 let sy_cmd = SyCmd::form_syslog(pri, fmt);
1359
1360 return self.stream.tasks.q_send_blocking(sy_cmd);
1361 }
1362
1363 /// This function can be used to update the facility name, for example
1364 /// after fork().
1365 ///
1366 /// # Arguments
1367 ///
1368 /// * `ident` - an [Option] optional new identity (up to 48 UTF8 chars)
1369 /// If set to [Option::None] would request the program name from OS.
1370 pub
1371 fn change_identity(&self, ident: Option<&str>) -> SyRes<()>
1372 {
1373 let sy_cmd =
1374 SyCmd::form_change_ident(ident.map(|v| v.to_string()));
1375
1376 return
1377 self.stream.tasks.q_send_blocking(sy_cmd);
1378 }
1379
1380 /// Re-opens the connection to the syslog server. Can be used to
1381 /// rotate logs(handle SIGHUP).
1382 ///
1383 /// # Returns
1384 ///
1385 /// A [Result] is retured as [SyRes].
1386 ///
1387 /// * [Result::Ok] - with empty inner type.
1388 ///
1389 /// * [Result::Err] - an error code and description
1390 pub
1391 fn reconnect(&self) -> SyRes<()>
1392 {
1393 return
1394 self.stream.tasks.q_send_blocking(SyCmd::form_reconnect());
1395 }
1396
1397 /// Updates the instance's socket. `tap_data` [TapTypeData] should be of
1398 /// the same variant (type) as current.
1399 pub
1400 fn update_tap_data(&self, tap_data: D) -> SyRes<()>
1401 {
1402 let (tap_data_cmd, loopback) = SyCmd::form_update_tap(tap_data);
1403
1404 self.stream.tasks.q_send_blocking(tap_data_cmd)?;
1405
1406 return
1407 loopback
1408 .recv_once_blocking()?;
1409 }
1410 }
1411
1412 impl<F, D, S> Syslog<F, D, SyQueued<S, F, D>>
1413 where
1414 F: SyslogFormatter,
1415 D: SyslogDestination,
1416 S: SyslogQueueChannel<F, D>
1417 {
1418 /// Returns the streamable [SyStream] instance which can be used with [write!].
1419 ///
1420 /// It implements both [std::fmt::Write] and [std::io::Write].
1421 ///
1422 /// # Example
1423 ///
1424 /// ```ignore
1425 /// let log =
1426 /// SingleSyslog::openlog(
1427 /// Some("test1"),
1428 /// LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID,
1429 /// LogFacility::LOG_DAEMON,
1430 /// SyslogLocal::new()
1431 /// ).unwrap();
1432 ///
1433 /// write!(log.get_stream::<SyStreamPriDebug>(), "test stream singlesyslog {}", i).unwrap();
1434 /// ```
1435 pub
1436 fn get_stream<'t, PRI>(&'t self) -> SyStream<'t, PRI, D, F, &'t Self>
1437 where PRI: SyStreamPri
1438 {
1439 SyStream
1440 {
1441 s: Some(self),
1442 _p: PhantomData,
1443 _p1: PhantomData,
1444 _p2: PhantomData
1445 }
1446 }
1447 }
1448
1449 impl<F, D, S> SyStreamSyslogApi<F, D>
1450 for &Syslog<F, D, SyQueued<S, F, D>>
1451 where F: SyslogFormatter, D: SyslogDestination, S: SyslogQueueChannel<F, D>
1452 {
1453 type SYSLOG<'t> = &'t Syslog<F, D, SyQueued<S, F, D>>;
1454
1455 fn syslog<'t>(syslog: Self::SYSLOG<'t>, pri: Priority, fmt: F) -> SyRes<()>
1456 {
1457 syslog.syslog(pri, fmt)
1458 }
1459 }
1460
1461
1462 /// A queued implementation for ASYNC.
1463 #[cfg(feature = "async_enabled")]
1464 pub mod syslog_async_queue
1465 {
1466 use crate::error::SyRes;
1467 use crate::sy_sync_queue::{SyCmd, SyslogQueueChanSnd, SyslogQueueChannel, SyslogQueueOneChanRcv};
1468 use crate::{Priority, Syslog};
1469 use crate::{formatters::SyslogFormatter, SyslogDestination, SyQueued};
1470 use crate::a_sync::syslog_trait::AsyncSyslogQueueApi;
1471
1472 impl<F: SyslogFormatter, D: SyslogDestination, S: SyslogQueueChannel<F, D>> AsyncSyslogQueueApi<F, D>
1473 for Syslog<F, D, SyQueued<S, F, D>>
1474 {
1475 async
1476 fn a_connectlog(&mut self) -> SyRes<()>
1477 {
1478 let (sy_cmd, loopback) =
1479 SyCmd::form_connectlog();
1480
1481 self.stream.tasks.q_send(sy_cmd).await?;
1482
1483 return
1484 loopback
1485 .recv_once()
1486 .await?;
1487 }
1488
1489 /// Sets the logmask to filter out the syslog calls. This function behaves
1490 /// differently as it behaves in syslog_sync.rs or syslog_async.rs.
1491 /// It may return an error if: syslog thread had exit and some thread calls
1492 /// this function. Or something happened with channel.
1493 /// This function blocks until the previous mask is received.
1494 ///
1495 /// See macroses [LOG_MASK] and [LOG_UPTO] to generate mask
1496 ///
1497 /// # Example
1498 ///
1499 /// LOG_MASK!(Priority::LOG_EMERG) | LOG_MASK!(Priority::LOG_ERROR)
1500 ///
1501 /// or
1502 ///
1503 /// ~(LOG_MASK!(Priority::LOG_INFO))
1504 /// LOG_UPTO!(Priority::LOG_ERROR)
1505 async
1506 fn a_setlogmask(&self, logmask: i32) -> SyRes<i32>
1507 {
1508 let (sy_cmd, loopback) =
1509 SyCmd::form_logmask(logmask);
1510
1511 self.stream.tasks.q_send(sy_cmd).await?;
1512
1513 return
1514 loopback
1515 .recv_once()
1516 .await;
1517 }
1518
1519 /// Closes connection to the syslog server
1520 async
1521 fn a_closelog(&self) -> SyRes<()>
1522 {
1523 let (sy_cmd, loopback) =
1524 SyCmd::form_disconnectlog();
1525
1526 // send stop
1527 self.stream.tasks.q_send(sy_cmd).await?;
1528
1529 return
1530 loopback
1531 .recv_once()
1532 .await?;
1533 }
1534
1535 /// Similar to libc, syslog() sends data to syslog server, but asynchroniously.
1536 ///
1537 /// # Arguments
1538 ///
1539 /// * `pri` - a priority [Priority]
1540 ///
1541 /// * `fmt` - a program's message to be sent as payload. The message is encoded with the
1542 /// [SyslogFormatter] and may be different for different formatters.
1543 #[inline]
1544 async
1545 fn a_syslog(&self, pri: Priority, fmt: F) -> SyRes<()>
1546 {
1547 let sy_cmd = SyCmd::form_syslog(pri, fmt);
1548
1549 return self.stream.tasks.q_send(sy_cmd).await;
1550 }
1551
1552
1553 /// Performs the reconnection to the syslog server or file re-open.
1554 ///
1555 /// # Returns
1556 ///
1557 /// A [Result] is retured as [SyRes].
1558 ///
1559 /// * [Result::Ok] - with empty inner type.
1560 ///
1561 /// * [Result::Err] - an error code and description
1562 async
1563 fn a_reconnect(&self) -> SyRes<()>
1564 {
1565 return
1566 self.stream.tasks.q_send(SyCmd::form_reconnect()).await;
1567 }
1568
1569 async
1570 fn a_change_identity(&self, ident: &str) -> SyRes<()>
1571 {
1572 let sy_cmd =
1573 SyCmd::form_change_ident(Some(ident.to_string()));
1574
1575 return
1576 self.stream.tasks.q_send(sy_cmd).await;
1577 }
1578
1579 /// Updates the inner instance destionation i.e path to file
1580 /// or server address. The type of destination can not be changed.
1581 ///
1582 /// This function disconnects from syslog server if previously was
1583 /// connected (and reconnects if was connected previously).
1584 ///
1585 /// # Arguments
1586 ///
1587 /// * `new_tap` - a consumed instance of type `D` [SyslogDestination]
1588 ///
1589 /// # Returns
1590 ///
1591 /// A [SyRes] is returned. An error may be returned if:
1592 ///
1593 /// * connection to server was failed
1594 ///
1595 /// * incorrect type
1596 ///
1597 /// * disconnect frm server failed
1598 async
1599 fn a_update_tap_data(&self, new_tap: D) -> SyRes<()>
1600 {
1601 let (tap_data_cmd, loopback) = SyCmd::form_update_tap(new_tap);
1602
1603 self.stream.tasks.q_send(tap_data_cmd).await?;
1604
1605 return
1606 loopback
1607 .recv_once()
1608 .await?;
1609 }
1610 }
1611 }
1612}
1613
1614#[cfg(feature = "build_with_queue")]
1615pub use self::build_with_queue::SyQueued;