-
Notifications
You must be signed in to change notification settings - Fork 56
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
feat: file logging #54
Conversation
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.
Hi @hnidoaht-101, thanks for the PR and welcome to the project!
Apart from the minor issues I've highlighted below, this patch disables the main pulsar logging infrastructure, which uses env_logger.
There are some higher level design decisions I'd like to discuss with @banditopazzo before merging it (BTW, he's currently on holiday, he'll be back early next week):
How to integrate with general pulsar logging
Possible paths forward include:
- Creating a multiplexing logger
- Installing only the log4rs logger
- Avoid installing log4rs as the logger. Write logs directly, maybe reusing log4rs code.
- Check if the
tracing
ecosystem offers a better solution.
Reusing pulsar.ini vs external log4rs config
Reusing the pulsar.ini
would give better consistency, pulsar CLI integration and eventual hot reloading. On the other hand, the external file gives greater flexibility and more features.
Logging of non-threat events
What should a user do if he wants to log also non-threat events? Maybe a work-around would be marking all/some events as threat from the rule-engine.
Logging of application log
What should a user do if he wants to log to file also application logs? I'd reuse systemd, but we may need a way to do it if that's not acceptable. It's probably an uncommon use-case and I would probably handle it in a different module/way.
modules/logger/src/lib.rs
Outdated
|
||
use std::path::PathBuf; | ||
|
||
use log::info; |
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.
For consistency with the rest of the project, remove the use log::info
line and use log::info!()
in the code below.
modules/logger/src/lib.rs
Outdated
@@ -47,27 +54,41 @@ impl TryFrom<&ModuleConfig> for Config { | |||
fn try_from(config: &ModuleConfig) -> Result<Self, Self::Error> { | |||
Ok(Self { | |||
console: config.required("console").unwrap_or(true), | |||
// file: config.required("file")?, | |||
file: config.required("file").unwrap_or(false), |
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.
This should be: config.with_default("file", false)?
See pulsar-core/src/pdk/config.rs
That utility method has the added benefit of returning a config error if the user value is invalid (eg. [logger] file=invalid_value
). By propagating it with ?
we'll cause the logger module to fail and show the error to the user.
modules/logger/src/lib.rs
Outdated
include_str!("../log4rs_conf.yml"), | ||
) { | ||
Ok(it) => it, | ||
Err(err) => println!("{}", err), |
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.
Warning should be logged with log::warn!()
, not println!
. The pre-existing println!
line below is an exception (since this module goal is to output logs about events, we decided it made sense to write them to stdout directly)
An even better solution would be to propagate the error with ?
, causing the module to fail.
modules/logger/src/logging.rs
Outdated
println!( | ||
"Initializing logging according to {:?}", | ||
log_conf_file.to_str().unwrap_or("[??]") | ||
); |
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.
log::info!
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.
uhmm, at this point, I can use println!
only because we start initializing logger here, log::info!
has no effects.
modules/logger/src/logging.rs
Outdated
|
||
if !log_conf_file.exists() { | ||
if let Some(d) = log_conf_file.parent() { | ||
fs::create_dir_all(d).map_err(|e| LoggerError::CreateParentDir(e.to_string()))? |
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.
Don't convert errors to strings, we may lose useful information when things go wrong.
A better solution is to keep the original error and wrap it:
pub enum LoggerError {
#[error("Could not create log file's parent directory: {0}")]
CreateParentDir(PathBuf, #[source] std::io::Error),
...
if let Some(d) = log_conf_file.parent() {
fs::create_dir_all(d).map_err(|e| LoggerError::CreateParentDir(d.to_path_buf(), e))?
};
The same applies to the errors below.
To make things less verbose, we usually choose anyhow
for error management in modules since it allows to just .with_context(|| format!("Could not create log file's parent directory: {d}"))?
In the core modules (pulsar-core
, bpf-common
, etc.) instead, we prefer to use thiserror
.
Since you've already took care of using thiserror for this, I would keep it. If next time you feel lazy, go with anyhow.
pulsar/src/pulsard/mod.rs
Outdated
|
||
mod config; | ||
mod daemon; | ||
mod module_manager; | ||
mod shutdown_signal; |
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.
Please, split this change in a different PR.
Also, I'm not so sure about the need for this since right now we're Linux-only.
@banditopazzo what do you think?
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.
yeah, sorry I didnt notice carefully, this one should belong to another PR. This is minor change I think, the point is I want to handle shutdown signal properly, before that we just handle 2 signal kinds.
hi @MatteoNardi thank for your detailed reviews 💯 I'll update minor issues first. |
Ah, nice catch!
Actually I really wanted to reuse |
For now stick to to the minor issues and let's wait for Bandito's opinion before going forward. I think we wanted to give tracing a try, the first solution which comes to mind would be replacing env_logger with tracing-subscriber and overriding it in the pulsar logger module by tracing-appender using with_default. But I don't want to waste your time on a solution we're not sure about, so let's wait some days. |
@MatteoNardi |
Hi, I think it's better to implement a simple handwritten file logger which doesn't use the log subsystem. This module is called Application and the event logging and separate things, we don't want to mix them. We have planned to take a look at tracing for the application wide logging, if we decide to switch to tracing we will rethink a new solution. |
Got it. I will rework this PR & submit for review again. |
@hnidoaht-101 did you copy the code from https://github.com/polyverse/file-rotation/blob/main/src/asynchronous.rs ? it's an unmaintained crate. why did you change variables and function names? I didn't have time to check in detail the code and in particular if the at this state the code needs an accurate review, if you can't explain the code with better comments, a detailed review will be re scheduled for future |
Yeah sure, will add comment details for code. P/s: im in holidays, be back next week to update, thank for ur review. |
[nitpiking mode on] If pub enum RotationState {
PendingRename(Pin<Box<dyn Future<Output = io::Result<()>> + Send>>),
PendingCreate(Pin<Box<dyn Future<Output = io::Result<fs::File>> + Send>>),
PendingFlush,
Done,
} |
Neat! Thanks @MatteoNardi. 👍 |
As discussed with @banditopazzo, I'm going to close this PR first to rethink a simpler solution instead of using unmaintained version with my own update. |
File logging
This PR is served for #39.
Implementation (Optional)
Following TODO placeholder left in the source code.
I have
cargo fmt
;cargo clippy
;cargo test
and all tests pass;