-
Notifications
You must be signed in to change notification settings - Fork 18
Rework for syslog version 5 #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@@ -14,6 +14,6 @@ readme = "README.md" | |||
path = "lib.rs" | |||
|
|||
[dependencies] | |||
hostname = "0.3" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe already bump the version of this crate if this is a breaking change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. I pushed another commit to a bump the version.
I've made several changes and squashed them together. For complete history, see my |
The `syslog` crate underwent extensive API refactoring between versions 3 and 5. This commit rewrites much of `slog-syslog` to fit the new API. It is partially compatible with previous versions of `slog-syslog` (`examples/syslog-unix.rs` still works without modification), but the shape of `Streamer3164` in particular is quite different. There are also some new features: * All `SyslogBuilder` settings are now optional and have sensible defaults. Simply running `SyslogBuilder::new().start()` will yield a usable `Drain` (if there is a syslog daemon on the local machine). * `SyslogBuilder` no longer requires a hostname to be supplied when choosing a transport (TCP, UDP, Unix socket). Instead, the hostname is a separate setting (`SyslogBuilder::hostname`), and if none is provided, it's discovered (if possible) using the `hostname` crate. * `Streamer3164` no longer contains a mutex, and is not thread-safe (that is, it is no longer `Sync`). This improves performance when used with slog-async, which doesn't need the underlying `Drain` to be thread-safe. `slog::Logger` does require the underlying `Drain` to be thread-safe, so `SyslogBuilder::start` now returns a `Streamer3164` wrapped in a `Mutex`, and there's now a `SyslogBuilder::start_single_threaded` method that returns an unwrapped `Streamer3164` instead. * Key-value pairs attached to logging records are now, by default, formatted in a style that resembles RFC 5424 STRUCTURED-DATA. Their formatting can be customized by implementing the `MsgFormat3164` trait.
let mut guard = self.io.borrow_mut(); | ||
let logger = &mut *guard; | ||
|
||
// We need to smuggle errors out of the `Display` implementation for `msg`, below. The `Display::fmt` method takes `&self` rather than `&mut self`, so the obvious way of accomplishing this (`let mut msg_format_result: syslog::Result<()>`) will not work because the closure cannot write to any captured variable (including `msg_format_result`). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is what's going here better than thread_local
reusable buffer that was here bofore?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. Your thread-local reusable buffer was faster than this implementation.
But there's no way to avoid it and still use syslog
version 5. It now uses std::fmt::format
on the input, which allocates a new buffer and writes the whole message into it. If we tried to use a reusable buffer like before, syslog
would just copy the contents of that reusable buffer into the newly-allocated one anyway, negating the performance benefit.
A thread-local reusable buffer would be a good idea, but it would need to be done in the syslog
crate rather than here. Unfortunately, that crate seems abandoned, judging from all the old, unanswered PRs.
So, maybe it would be best to reject this PR and stick with the old implementation. I don't know.
To be honest, several days after I submitted this PR, I gave up on using the syslog
crate entirely. It turns out that it uses the wrong protocol for local syslog over a Unix-domain socket, and it's pretty much impossible to implement correctly because the details of that protocol vary greatly between systems. Some (macOS) use a completely different protocol instead of the BSD local syslog protocol. Some (OpenBSD) don't even use a socket! So, I wrote a syslog logger based on libc
calls for the sloggers
crate instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if you care, but if you're not already a cargo-crev
user you should probably fill a negative package review with unmaintained: true
, and your findings in it.
From the rest of it, it seems that the correct way to go is to take over / have a new syslog
-like crate that is libc
based and re-use it both in sloggers
and here? There could be more users that would benefit from it? Or not?
We can leave this PR hanging for now, I guess.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if you care, but if you're not already a
cargo-crev
user you should probably fill a negative package review withunmaintained: true
, and your findings in it.
I'm sorry, but I don't feel comfortable interfering with someone else's project like that.
From the rest of it, it seems that the correct way to go is to take over / have a new
syslog
-like crate that islibc
based and re-use it both insloggers
and here? There could be more users that would benefit from it? Or not?
Probably not. The POSIX syslog
API is pretty simple and easy to use from Rust. Most of the code I contributed to sloggers
was just an adapter for Slog's different log record format (it has key-value pairs, whereas plain syslog doesn't) and different logger lifecycle (there is only one syslog logger per process, whereas Slog allows there to be many Drain
s at the same time).
But it might be useful to Slog users if they could construct a syslog-based Drain
without all the decoration that sloggers
stacks on top (it automatically applies slog-async, etc). So, I could extract the code I contributed to sloggers
and use that as a new slog-syslog
. Should I do that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But it might be useful to Slog users if they could construct a syslog-based Drain without all the decoration that sloggers stacks on top (it automatically applies slog-async, etc). So, I could extract the code I contributed to sloggers and use that as a new slog-syslog. Should I do that?
Exactly. Please do.
I'm sorry, but I don't feel comfortable interfering with someone else's project like that.
If you can't get a response from the maintainer in reasonable time, it's a clear sign the package is not maintained, especially if there are problem with it. Rather than thinking about the author, think about all the people that could lose their time and maybe even more than time, building on top of stuff that has problems. Anyway ... I don't even fully understand the issues, so it's all up to you. I just think it's worthwhile sharing opinions and finding to help the community.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Good work.
As discussed in PR slog-rs#5, this is based on the [syslog backend that I wrote for sloggers][1] and does not use the `syslog` crate. It is now very different from both slog-syslog 0.12 and PR slog-rs#5. Differences from slog-rs#5 include: * Uses the POSIX syslog API through the `libc` crate. (See “design and rationale” in src/lib.rs, starting at line 52, for details.) This means: * Only works on Unix-like platforms. * Only sends log messages to the local syslog daemon, not to a remote server. * Formats log messages into a reusable thread-local buffer, as in slog-syslog 0.12. * The `Drain` implementation is now called `SyslogDrain` instead of `Streamer3164`, since local syslog doesn't use the RFC3164 protocol. * If the `serde` feature is enabled, logging settings can be loaded from a configuration file. Minimum supported Rust version is 1.27.2, or if the `serde` feature is enabled, 1.31.0. Doc-tests require 1.28.0. Works (except doc-tests) on 1.26.2 if you run the following commands first: ``` cargo generate-lockfile cargo update --package lazy_static --precise 1.3.0 cargo update --package serde --precise 1.0.58 cargo update --package serde_derive --precise 1.0.58 ``` [1]: sile/sloggers#34
Thank you for this, I use this on production Linux machines without any problems. It does not work on macOS however, but this is also true for the original slog-syslog.
I spent a bit of time trying to solve it, but since we use macOS only on dev machines I stopped spending time on this. It works like a charm on Linux though |
@eun-ice As discussed above, this code (i.e. PR #5) doesn't actually work correctly even on Linux. It probably depends on the particular syslogd you're using, but if you use systemd-journald, you'll get malformed log entries if you use this code. Did you try the code in PR #6? I'm not sure whether it'll work any better for you (I don't have a Mac on hand right now to test it with), but it's a completely different and hopefully more compatible implementation. I apparently forgot to close this PR, so I'll go ahead and do that now. |
@argv-minus-one thanks for the heads up, I actually started using and testing this branch before the discussion above happened. |
This PR reworks slog-syslog for version 5 of the
syslog
crate. It is a breaking change.The
syslog
crate underwent extensive API refactoring between versions 3 and 5. This PR rewrites much ofslog-syslog
to fit the new API. It is partially compatible with previous versions ofslog-syslog
(examples/syslog-unix.rs
still works without modification), but the shape ofStreamer3164
in particular is quite different.There are also some new features:
All
SyslogBuilder
settings are now optional and have sensible defaults. Simply runningSyslogBuilder::new().start()
will yield a usableDrain
(if there is a syslog daemon on the local machine).SyslogBuilder
no longer requires a hostname to be supplied when choosing a transport (TCP, UDP, Unix socket). Instead, the hostname is a separate setting (SyslogBuilder::hostname
), and if none is provided, it's discovered (if possible) using thehostname
crate.Streamer3164
no longer contains a mutex, and is not thread-safe (that is, it is no longerSync
). This improves performance when used with slog-async, which doesn't need the underlyingDrain
to be thread-safe.slog::Logger
does require the underlyingDrain
to be thread-safe, soSyslogBuilder::start
now returns aStreamer3164
wrapped in aMutex
, and there's now aSyslogBuilder::start_single_threaded
method that returns an unwrappedStreamer3164
instead.Key-value pairs attached to logging records are now, by default, formatted in a style that resembles RFC 5424 STRUCTURED-DATA. Their formatting can be customized by implementing the
MsgFormat3164
trait.The minimum supported Rust version of
syslog
version 5, and therefore of slog-syslog with this PR, is 1.31. This is newer than Slog's MSRV of 1.26.