]>
git.proxmox.com Git - proxmox-backup.git/blob - src/tools/file_logger.rs
4 /// Log messages with optional automatically added timestamps into files
6 /// Logs messages to file, and optionally to standard output.
11 /// #[macro_use] extern crate proxmox_backup;
12 /// # use anyhow::{bail, format_err, Error};
13 /// use proxmox_backup::tools::{FileLogger, FileLogOptions};
15 /// # std::fs::remove_file("test.log");
16 /// let options = FileLogOptions {
19 /// ..Default::default()
21 /// let mut log = FileLogger::new("test.log", options).unwrap();
22 /// flog!(log, "A simple log: {}", "Hello!");
25 #[derive(Debug, Default)]
26 /// Options to control the behavior of a ['FileLogger'] instance
27 pub struct FileLogOptions
{
28 /// Open underlying log file in append mode, useful when multiple concurrent processes
29 /// want to log to the same file (e.g., HTTP access log). Note that it is only atomic
30 /// for writes smaller than the PIPE_BUF (4k on Linux).
31 /// Inside the same process you may need to still use an mutex, for shared access.
33 /// Open underlying log file as readable
35 /// If set, ensure that the file is newly created or error out if already existing.
37 /// Duplicate logged messages to STDOUT, like tee
39 /// Prefix messages logged to the file with the current local time as RFC 3339
40 pub prefix_time
: bool
,
44 pub struct FileLogger
{
46 options
: FileLogOptions
,
49 /// Log messages to [FileLogger](tools/struct.FileLogger.html)
52 ($log
:expr
, $
($arg
:tt
)*) => ({
53 $log
.log(format
!($
($arg
)*));
58 pub fn new
<P
: AsRef
<std
::path
::Path
>>(
60 options
: FileLogOptions
,
61 ) -> Result
<Self, Error
> {
62 let file
= std
::fs
::OpenOptions
::new()
65 .append(options
.append
)
66 .create_new(options
.exclusive
)
67 .create(!options
.exclusive
)
70 Ok(Self { file, options }
)
73 pub fn log
<S
: AsRef
<str>>(&mut self, msg
: S
) {
74 let msg
= msg
.as_ref();
76 if self.options
.to_stdout
{
77 let mut stdout
= std
::io
::stdout();
78 stdout
.write_all(msg
.as_bytes()).unwrap();
79 stdout
.write_all(b
"\n").unwrap();
82 let now
= proxmox
::tools
::time
::epoch_i64();
83 let rfc3339
= proxmox
::tools
::time
::epoch_to_rfc3339(now
).unwrap();
85 let line
= if self.options
.prefix_time
{
86 format
!("{}: {}\n", rfc3339
, msg
)
90 self.file
.write_all(line
.as_bytes()).unwrap();
94 impl std
::io
::Write
for FileLogger
{
95 fn write(&mut self, buf
: &[u8]) -> Result
<usize, std
::io
::Error
> {
96 if self.options
.to_stdout
{
97 let _
= std
::io
::stdout().write(buf
);
102 fn flush(&mut self) -> Result
<(), std
::io
::Error
> {
103 if self.options
.to_stdout
{
104 let _
= std
::io
::stdout().flush();