Skip to content
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

Add syslog supports #2537

Merged
merged 26 commits into from
Nov 17, 2024
Merged

Add syslog supports #2537

merged 26 commits into from
Nov 17, 2024

Conversation

tisonkun
Copy link
Contributor

This refers to #413.

Hello world works locally:

2024-11-12 19:19:52.264557+0800 0x27405d0  Default     0x0                  27738  0    test-aae182a0654f64e3: Hello, nix!

I'd like to send this patch early for any necessary alignments.

Signed-off-by: tison <[email protected]>
Signed-off-by: tison <[email protected]>
@tisonkun tisonkun changed the title Wrap syslog Add syslog supports Nov 12, 2024
@SteveLauC SteveLauC self-requested a review November 12, 2024 11:25
@tisonkun
Copy link
Contributor Author

@SteveLauC I'd like to learn the following things:

  1. How are the feature flags structured in this crate?
  2. What is the convention to convert type (integers, strings) across the language boundary?
  3. How do you typically test a wrapper?
  4. Is it OK that I support syslog for macos only for now? I have only macos at hand recently, and cannot programming without really test them out.

@SteveLauC
Copy link
Member

Hi, thanks for the PR!

How are the feature flags structured in this crate?

I am not quite sure I understand the question, you mean how to pick a feature? Putting these interfaces under the feature syslog feature looks good

What is the convention to convert type (integers, strings) across the language boundary?

Do you mean the conversion between the Nix wrapper types and the C types used by the libc crate?

  • For bitflags, we use the libc_bitflag! macro, the LogFlag type proposed in this PR looks good at first glance.
  • For enum, libc_enum! will be used. Types Severity and Facility fall into this category.
  • If a C string is needed (string with a tailing NUL), trait NixPath can be used to fill the gap. You can use it for the void openlog(const char *ident argument.
  • The priority argument of syslog() and vsyslog() should be constructed by ORing enum Severity and enum Facility, we can probably impl std::ops::BitOr<Output = c_int> for these 2 types, but this is not that fault-resilient, perhaps we should define another wrapper type here🤔
  • Regarding the format void syslog(int priority, const char *format, ...); argument, do you think we should implement syslog as a macro similar to println!?

How do you typically test a wrapper?

A few tests to ensure the wrapper would work should be sufficient.

Is it OK that I support syslog for macos only for now?

Yeah, it is ok.

@SteveLauC
Copy link
Member

BTW, a changelog is needed, please see CONTRIBUTING.md on how to add one.

@tisonkun
Copy link
Contributor Author

@SteveLauC Thanks for your information! All updated.

For enum, libc_enum! will be used. Types Severity and Facility fall into this category.

Updated.

If a C string is needed (string with a tailing NUL), trait NixPath can be used to fill the gap. You can use it for the void openlog(const char *ident argument.

Updated.

The priority argument of syslog() and vsyslog() should be constructed by ORing enum Severity and enum Facility, we can probably impl std::ops::BitOr<Output = c_int> for these 2 types, but this is not that fault-resilient, perhaps we should define another wrapper type here🤔

Reasonable. Priority struct added.

Regarding the format void syslog(int priority, const char *format, ...); argument, do you think we should implement syslog as a macro similar to println!?

No. As stated at #413 (comment), I think we just simply use Rust's formatting function and pass the formatted string. This is also how Python wraps syslog functionalities.

A few tests to ensure the wrapper would work should be sufficient.

Included.

@tisonkun
Copy link
Contributor Author

This patch doesn't wrap vsyslog and setlogmark.

For vsyslog, it's a variant of syslog for ergonomically coding in C, irrelevant to Rust.

For setlogmark, libc doesn't export LOG_MASK and/or LOG_UPTO, make it hard to wrap reasonable code. I temporarily added the wrapper but later revert it. IMO it's less used and we can revisit this function when there is a real-world necessity.

@tisonkun
Copy link
Contributor Author

LOG_MASK and LOG_UPTO may be easy to add:

#[macro_export]
macro_rules! LOG_MASK 
{
    ($($arg:tt)*) => (
        (1 << $($arg)*)
    )
}

#[macro_export]
macro_rules! LOG_UPTO 
{
    ($($arg:tt)*) => (
        ((1 << (($($arg)*) + 1)) - 1)
    )
}

But I'd like to wait for this patch getting review and perhaps did it in a followup so that we don't push everything at once.

Cargo.toml Outdated Show resolved Hide resolved
Cargo.toml Show resolved Hide resolved
src/syslog.rs Outdated Show resolved Hide resolved
src/syslog.rs Outdated Show resolved Hide resolved
src/syslog.rs Show resolved Hide resolved
changelog/2537.added.md Outdated Show resolved Hide resolved
src/syslog.rs Show resolved Hide resolved
@tisonkun

This comment was marked as resolved.

Signed-off-by: tison <[email protected]>
Signed-off-by: tison <[email protected]>
Signed-off-by: tison <[email protected]>
Signed-off-by: tison <[email protected]>
@tisonkun tisonkun requested a review from SteveLauC November 16, 2024 05:43
@tisonkun
Copy link
Contributor Author

tisonkun commented Nov 16, 2024

@SteveLauC test on unix and updated.

I have an idea to implement setlogmask, but not sure if we can export libc::c_int or we have other better types:

pub fn setlogmask(maskpri: libc::c_int) -> libc::c_int {
    let mask = unsafe { libc::setlogmask(maskpri) };
    mask
}

pub fn log_mask(pri: Severity) -> libc::c_int {
    1 << (pri as libc::c_int)
}

pub fn log_upto(pri: Severity) -> libc::c_int {
    (1 << ((pri as libc::c_int) + 1)) - 1
}

Also related test ideas - https://stackoverflow.com/questions/56049852/python-2-7-setlogmask0-not-disabling-syslog

src/lib.rs Outdated Show resolved Hide resolved
test/test.rs Outdated Show resolved Hide resolved
Signed-off-by: tison <[email protected]>
src/syslog.rs Outdated
Comment on lines 7 to 13
/// Logging options of subsequent [`syslog`] calls can be set by calling [`openlog`].
///
/// The parameter `ident` is a string that will be prepended to every message. The `logopt`
/// argument specifies logging options. The `facility` parameter encodes a default facility to be
/// assigned to all messages that do not have an explicit facility encoded.
pub fn openlog<S>(
ident: Option<&S>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This interface should be good for UNIXs other than Linux, since Linux would store the ident pointer as-is (will be used during whole process lifetime), we need to add a separate interface for Linux, and gate this with #[cfg(not(target_os = "linux"))].

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And thanks for adding the Option here! I didn't catch it in my first round of review.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest we remove the ident param for now.

It's not easy to just add Option<&'static str> because it may not end with nul and I don't know how to achieve this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't observe the ident on macos and linux, perhaps this is because the allocated string is collected 🤣

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe Option<&'static CStr>. Let me try.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nix does not pursue uniform interfaces across OSes, if they are different, let them be different. I suggest keeping the original interface for non-Linux platforms as they are not constrained by this limit and adding a separate interface for Linux

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you send a patch to this PR or just edit this PR with the suggested change?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you send a patch to this PR

Yeah, let me send a commit

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See 596280b

src/syslog.rs Show resolved Hide resolved
src/syslog.rs Show resolved Hide resolved
Signed-off-by: tison <[email protected]>
@tisonkun tisonkun requested a review from SteveLauC November 16, 2024 07:50
src/syslog.rs Outdated Show resolved Hide resolved
Co-authored-by: SteveLauC <[email protected]>
@tisonkun
Copy link
Contributor Author

@SteveLauC test on unix and updated.

I have an idea to implement setlogmask, but not sure if we can export libc::c_int or we have other better types:

pub fn setlogmask(maskpri: libc::c_int) -> libc::c_int {
    let mask = unsafe { libc::setlogmask(maskpri) };
    mask
}

pub fn log_mask(pri: Severity) -> libc::c_int {
    1 << (pri as libc::c_int)
}

pub fn log_upto(pri: Severity) -> libc::c_int {
    (1 << ((pri as libc::c_int) + 1)) - 1
}

Also related test ideas - https://stackoverflow.com/questions/56049852/python-2-7-setlogmask0-not-disabling-syslog

@SteveLauC Here is an open question on whether to include setlogmask in this PR.

@SteveLauC
Copy link
Member

Regarding the setlogmask() interface, I think we can implement it in the following way:

/// System log priority mask.
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct LogMask(libc::c_int);

/// Set the process-wide priority mask to `mask` and return the previous mask 
/// value. 
/// 
/// Calls to `syslog()` with a priority level not set in `mask` are ignored. The 
/// default is to log all priorities.
/// 
/// If the `mask` argument is `None`, the current logmask is not modified, this
/// can be used to query the current log mask.
pub fn setlogmask(mask: Option<LogMask>) -> LogMask {
    let mask = match mask {
        Some(mask) => mask.0,
        None => 0,
    };
    
    let prev_mask = unsafe {
        libc::setlogmask(mask)
    };
    
    LogMask(prev_mask)
}

impl LogMask {
    /// Creates a mask of all priorities up to and including `priority`.
    #[doc(alias("LOG_UPTO"))]
    pub fn up_to(priority: Severity) -> Self {
        todo!()
    }
    
    /// Creates a mask for the specified priority.
    #[doc(alias("LOG_MASK"))]
    pub fn of_priority(priority: Severity)  -> Self {
        todo!()
    }
    
    /// Returns if the mask for the specified `priority` is set.
    pub fn contains(&self, priority: Severity) -> bool {
        todo!()
    }
}

impl std::ops::BitOr for LogMask {
    type Output = Self;
    fn bitor(self, rhs: Self) -> Self::Output {
        Self(self.0 | rhs.0)
    }
}

Though I think the C macros LOG_MASK and LOG_UPTO should be added to the libc crate first, so perhaps we can include these things in the next PR?

@SteveLauC SteveLauC linked an issue Nov 17, 2024 that may be closed by this pull request
@tisonkun
Copy link
Contributor Author

Though I think the C macros LOG_MASK and LOG_UPTO should be added to the libc crate first, so perhaps we can include these things in the next PR?

Yes. Let's review this PR as is now.

@SteveLauC Thanks for your following commits!

@tisonkun tisonkun requested a review from SteveLauC November 17, 2024 10:03
Copy link
Member

@SteveLauC SteveLauC left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks for the PR, let's merge it! 🚀

@SteveLauC SteveLauC added this pull request to the merge queue Nov 17, 2024
Merged via the queue into nix-rust:master with commit 47c0f42 Nov 17, 2024
39 checks passed
@tisonkun tisonkun deleted the wrap-syslog branch November 17, 2024 10:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add syslog APIs
2 participants