syslog_rs/lib.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
16//! syslog-rs
17//!
18//! <img src="https://cdn.4neko.org/syslog_logo.webp" width="280"/> <img src="https://cdn.4neko.org/source_avail.webp" width="280"/> <img src="https://cdn.4neko.org/mit_mpl_eupl_2.webp" width="280"/>
19//!
20//! An implementation of the syslog from glibc/libc like it was designed in
21//! in both system libraries. The API is almost compatible with what is in
22//! libc/glibc.
23//!
24//! ## Supports
25//!
26//! * GNU/Linux RFC3164 (UTF-8 by default)
27//! * *BSD and OSX RFC5424 (BOM UTF-8 by default)
28//!
29//! Directories:
30//! * a_sync - all async code
31//! * formatters - syslog message formatter.
32//! * sync - all sync code
33//! * src - all common code for both sync and async.
34//!
35//! Features:
36//! * feature = `build_with_thread_local` enables the lockless syslog client for single threaded or `thread_local` instances.
37//! * feature = "build_sync" a base feature which enables all SYNC code. Just enabling the `use_sync`
38//! would enable only basic SharedSyslog.
39//! * feature = "build_async_tokio" a Tokio based async IO. Includes the tokio and tokio-rustls deps.
40//! * feature = "build_async_smol" for synchronious with async processing (use syslog_rs::sy_async_queue::{Syslog};)
41//! * feature = "build_async_interface" for asynchronious interface only without any realisations.
42//! * feature = "build_with_queue" a Smol based async IO. Includes the smol and futures-rustls dep.
43//! moves the syslog client to separate thread and by default uses
44//! crossbeam-channel to receive messages.
45//! Depending on which async procvider is selected, the channel realization
46//! will be switched suring compilation. In this case, an async code can be
47//! attached to the sync queue which allows to write to the same syslog
48//! connection with the same setup.
49//! * feature = "build_ext_net" adds the networking support! (TCP, UDP)
50//! * feature = "build_ext_tls" adds the TLS support over network (TCP).
51//! * feature = "build_ext_file" writing directly to file.
52//!
53//! --
54//! * feature = "udp_truncate_1024_bytes" - Forces truncation of the (whole) syslog message to 1024
55//! * feature = udp_truncate_1440_bytes - Forces truncation of the (whole) syslog message to 1440
56//! * feature = tcp_truncate_1024_bytes - Forces truncation of the (whole) syslog message to 1024
57//! * feature = tcp_truncate_2048_bytes - Forces truncation of the (whole) syslog message to 2048
58//! * feature = tcp_truncate_4096_bytes - Forces truncation of the (whole) syslog message to 4096
59//! * feature = tcp_truncate_max_bytes - Forces truncation of the (whole) syslog message to 8192 (max)
60//! * feature = dgram_sysctl_failure_panic - BSD only! By default, if crate fails to obtain a sysctl net.local.dgram.maxdgram,
61//! it returns a default value 2048. If this feature is enabled, then it will panic.
62//!
63//! `build_async_tokio` and `build_async_smol` cannot be used together.
64//!
65//! `build_with_queue` behaves differently if enabled ine of the async providers.
66//!
67//! # Usage
68//!
69//! syslog-rs = {version = "5.0", default-features = false, features = ["build_sync", "build_ext_net", "udp_truncate_1440_bytes"]}
70//!
71//! By default, the following features are enabled: `build_sync`, `truncate_default`
72//!
73//! ```ignore
74//! use std::{sync::LazyLock, thread};
75//! use std::time::Duration;
76//!
77//! use syslog_rs::formatters::DefaultSyslogFormatter;
78//! use syslog_rs::{SyslogApi, SyncSyslog};
79//! use syslog_rs::{LogFacility, LogStat, Priority, SyslogLocal};
80//!
81//! pub static SYSLOG: LazyLock<SyncSyslog> = LazyLock::new(||
82//! {
83//! SyncSyslog::openlog(
84//! Some("example"),
85//! LogStat::LOG_CONS | LogStat::LOG_PID,
86//! LogFacility::LOG_DAEMON, SyslogLocal::new()
87//! )
88//! .unwrap()
89//! }
90//! );
91//!
92//! pub static SYSLOG2: LazyLock<SyncSyslog<DefaultSyslogFormatter, SyslogLocal>> = LazyLock::new(||
93//! {
94//! SyncSyslog
95//! ::<_, _>
96//! ::openlog_with(
97//! None,
98//! LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID,
99//! LogFacility::LOG_DAEMON, SyslogLocal::new()
100//! )
101//! .unwrap()
102//! }
103//! );
104//!
105//! pub static SYSLOG3: LazyLock<SyncSyslog<DefaultSyslogFormatter, SyslogLocal>> = LazyLock::new(||
106//! {
107//! SyncSyslog
108//! ::<_, _>
109//! ::openlog_with(
110//! None,
111//! LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID,
112//! LogFacility::LOG_DAEMON, SyslogLocal::new()
113//! )
114//! .unwrap()
115//! }
116//! );
117//!
118//! macro_rules! logdebug
119//! {
120//! ($($arg:tt)*) => (
121//! SYSLOG.syslog(Priority::LOG_DEBUG, format!($($arg)*).into())
122//! )
123//! }
124//!
125//! macro_rules! logdebug2
126//! {
127//! ($($arg:tt)*) => (
128//! SYSLOG2.syslog(Priority::LOG_DEBUG, format!($($arg)*).into())
129//! )
130//! }
131//!
132//! pub fn main()
133//! {
134//! logdebug2!("test program name!");
135//!
136//!
137//! logdebug!("test message1!");
138//!
139//! SYSLOG.change_identity(Some("example2")).unwrap();
140//!
141//! logdebug!("test message from new ident");
142//!
143//! let new_syslog =
144//! SyncSyslog
145//! ::<DefaultSyslogFormatter, SyslogLocal>
146//! ::openlog_with(
147//! None,
148//! LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID,
149//! LogFacility::LOG_DAEMON, SyslogLocal::new()
150//! )
151//! .unwrap();
152//!
153//! let c_new_syslog = new_syslog.clone();
154//! let thread_hndl =
155//! std::thread::spawn(move ||
156//! {
157//! logdebug!("message from thread 1");
158//! std::thread::sleep(Duration::from_nanos(1000));
159//! logdebug!("message from thread 2");
160//! std::thread::sleep(Duration::from_nanos(1000));
161//! logdebug!("message from thread 3");
162//! std::thread::sleep(Duration::from_nanos(1000));
163//! logdebug!("message from thread 4");
164//!
165//! c_new_syslog.syslog(Priority::LOG_DEBUG, "test".into());
166//! }
167//! );
168//!
169//! let _ = thread_hndl.join();
170//!
171//! logdebug!("joined");
172//! thread::sleep(Duration::from_micros(10));
173//!
174//! return;
175//! }
176//! ```
177//!
178//! ```ignore
179//! use syslog_rs::sy_async::AsyncSyslog;
180//! use tokio::sync::OnceCell;
181//! use tokio::time::{Duration, sleep};
182//!
183//! use syslog_rs::{LogFacility, LogStat, Priority, SyslogLocal};
184//!
185//!
186//! pub static SYSLOG: OnceCell<AsyncSyslog> = OnceCell::const_new();
187//!
188//!
189//!
190//!
191//! macro_rules! logdebug
192//! {
193//! ($($arg:tt)*) => (
194//! SYSLOG.get().unwrap().syslog(Priority::LOG_DEBUG, format!($($arg)*)).await
195//! )
196//! }
197//!
198//! #[tokio::main]
199//! async fn main()
200//! {
201//! let syslog =
202//! AsyncSyslog::openlog(
203//! Some("example"),
204//! LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID,
205//! LogFacility::LOG_DAEMON,
206//! SyslogLocal::new()
207//! )
208//! .await
209//! .unwrap();
210//!
211//!
212//! SYSLOG.get_or_init(|| async { syslog }).await;
213//!
214//!
215//! logdebug!("test message async start!");
216//!
217//! SYSLOG.get().unwrap().vsyslog(Priority::LOG_DEBUG, "test 2").await;
218//!
219//! sleep(Duration::from_micros(10)).await;
220//!
221//! SYSLOG.get().unwrap().change_identity("new_identity").await.unwrap();
222//!
223//! logdebug!("test message new identity!");
224//!
225//! sleep(Duration::from_micros(10)).await;
226//!
227//! logdebug!("test 123!");
228//! logdebug!("test 123123! end ");
229//! return;
230//! }
231//!
232//! ```
233
234// make sure that the smol and tokio are not used together.
235#[cfg(all(feature = "build_async_tokio", feature = "build_async_smol"))]
236compile_error!("use_async_tokio and use_async_smol can not be used at the same time");
237
238// make sure that the build_async_interface and either async_embedded are not used together.
239#[cfg(all(feature = "build_async_interface", feature = "async_embedded"))]
240compile_error!("build_async_interface and either tokio/smol can not be used at the same time");
241
242//-- REEXPORT --
243#[macro_use]
244extern crate bitflags;
245pub extern crate chrono;
246pub extern crate nix;
247extern crate socket2;
248
249extern crate instance_copy_on_write;
250
251// -- TLS --
252
253#[cfg(all(feature = "build_sync", feature = "build_ext_tls"))]
254extern crate rustls;
255
256#[cfg(all(feature = "build_async_tokio", feature = "build_ext_tls"))]
257extern crate tokio_rustls;
258
259#[cfg(all(feature = "build_async_smol", feature = "build_ext_tls"))]
260extern crate futures_rustls;
261
262// -- ASYNC --
263
264#[cfg(feature = "build_async_tokio")]
265extern crate tokio;
266
267#[cfg(feature = "build_async_smol")]
268extern crate smol;
269
270// -- SYNC --
271#[cfg(feature = "build_with_queue")]
272extern crate crossbeam_channel;
273
274#[cfg(feature = "build_sync")]
275extern crate crossbeam_utils;
276
277/// A sync syslog realization including shared and queued syslog client.
278#[cfg(feature = "build_sync")]
279pub mod sync;
280
281/// An async interface and/or realisations. The main async syslog struct is located there.
282#[cfg(feature = "async_enabled")]
283pub mod a_sync;
284
285/// A message formatters i.e RFC5424 and other. Also a message formatter interface.
286pub mod formatters;
287
288pub mod syslog_provider;
289
290/// A syslog destnation. i.e local, remote, remote TLS, local file. Needed to initialize the
291/// (both sync and async) instances.
292pub use syslog_provider::*;
293
294/// A common things for the sockets managment.
295pub mod socket;
296
297/// A common code which holds all flags and macroses.
298#[macro_use]
299pub mod common;
300
301/// Unified error interface.
302#[macro_use]
303pub mod error;
304
305
306//-- NON EXPORT
307/// A portable code which is different for different OSes.
308mod portable;
309
310/// Public use of the type of the tap.
311pub use socket::TapType;
312
313/// A (prev SyslogShared) single shared (between threads) a sync type of the syslog client.
314#[cfg(feature = "build_sync")]
315pub use sync::syslog_sync_shared::SyncSyslog;
316
317#[cfg(feature = "build_sync")]
318pub use sync::syslog_trait::SyslogApi;
319
320/// A streamable sync instance (both).
321#[cfg(feature = "build_sync")]
322pub use sync::SyStreamApi;
323
324
325/// A `sy_async` is a shortcut to the file `syslog_async.rs` in dir `a_sync`.
326#[cfg(feature = "async_enabled")]
327pub use a_sync::syslog_async as sy_async;
328
329/// A main async syslog instance.
330#[cfg(feature = "async_enabled")]
331pub use sy_async::AsyncSyslog;
332
333/// A shortcut for the internals of the `async_syslog` and IO for user implementation.
334#[cfg(feature = "build_async_interface")]
335pub use a_sync::syslog_async_internal::{AsyncSyslogInternal, AsyncSyslogInternalIO};
336
337/// A shortcut to the trait `AsyncMutex` which unifies the mutex realiztion of different
338/// exec environments.
339#[cfg(feature = "build_async_interface")]
340pub use a_sync::syslog_async_internal::AsyncMutex;
341
342/// Use this trait to access queue interface for async code.
343#[cfg(all(feature = "async_enabled", feature = "build_with_queue"))]
344pub use a_sync::syslog_trait::AsyncSyslogQueueApi;
345
346
347/// A shortcut to the file `syslog_sync_queue.rs` in dir `sync`.
348#[cfg(feature = "build_with_queue")]
349pub use sync::syslog_sync_queue as sy_sync_queue;
350
351/// A (previosuly SyslogQueue) queued sync type of the syslog client. Also async queue.
352#[cfg(feature = "build_with_queue")]
353pub use sync::syslog_sync_queue::QueuedSyslog;
354
355#[cfg(feature = "build_with_thread_local")]
356pub use sync::syslog_threadlocal::SingleSyslog;
357
358/// A shortcut use of all in the `common.rs`.
359pub use common::*;