pub struct FileAppender { /* private fields */ }Expand description
Appender that writes formatted log events to a file, appending to it.
The file is opened in append mode (created if it does not exist) and
flushed after every event so log output survives crashes. When a size limit
is configured with FileAppender::builder’s max_size, the current file
is rolled over to a timestamped sibling (e.g. app.log.20260809-102530-1)
once the next line would exceed the limit. A max_files retention policy
(see FileAppenderBuilder::max_files) deletes the oldest rotated files
once the count is exceeded. With FileAppenderBuilder::compressed,
rotated files are gzip-compressed (.gz) on rollover. Write errors are
silently ignored: a logging appender should never crash the application.
Internally synchronized, so it is safe to share between threads even when appenders run outside the global logger lock.
Implementations§
Source§impl FileAppender
impl FileAppender
Sourcepub fn open(path: impl AsRef<Path>, layout: Box<dyn Layout>) -> Result<Self>
pub fn open(path: impl AsRef<Path>, layout: Box<dyn Layout>) -> Result<Self>
Open (or create) path for appending, formatting events with layout.
Examples found in repository?
8fn main() {
9 let log_path = std::env::temp_dir().join("log4rc-file-appender.log");
10
11 Logger::builder(LogLevel::Info)
12 .appender(Box::new(ConsoleAppender::new(Box::new(SimpleLayout))))
13 .appender(Box::new(
14 FileAppender::open(&log_path, Box::new(SimpleLayout))
15 .expect("failed to open log file"),
16 ))
17 .init();
18
19 log4rc::info!("Writing to console and file");
20 log4rc::error!("An error also goes to both");
21 log4rc::debug!("Filtered out at Info level");
22
23 // Read the file back to prove the messages were written to disk.
24 let mut contents = String::new();
25 std::fs::File::open(&log_path)
26 .expect("failed to reopen log file")
27 .read_to_string(&mut contents)
28 .expect("failed to read log file");
29
30 println!("\n--- Contents of {} ---", log_path.display());
31 print!("{contents}");
32 let _ = std::fs::remove_file(&log_path);
33}Sourcepub fn builder(
path: impl AsRef<Path>,
layout: Box<dyn Layout>,
) -> FileAppenderBuilder
pub fn builder( path: impl AsRef<Path>, layout: Box<dyn Layout>, ) -> FileAppenderBuilder
Configure a FileAppender, e.g. with size-based rotation.
Examples found in repository?
10fn main() {
11 let dir = std::env::temp_dir();
12 let prefix = format!("log4rc-rolling-{}", std::process::id());
13 let log_path = dir.join(format!("{prefix}.log"));
14
15 Logger::builder(LogLevel::Info)
16 .appender(Box::new(
17 FileAppender::builder(&log_path, Box::new(SimpleLayout))
18 .max_size(100) // tiny limit so a few messages trigger a roll
19 .max_files(3) // keep only the 3 newest rotated files
20 .compressed() // gzip rotated files
21 .build()
22 .expect("failed to open log file"),
23 ))
24 .init();
25
26 for i in 0..10 {
27 log4rc::info!("This is message number {i:02} with some padding to grow the file");
28 }
29
30 // List the active file plus any rotated siblings.
31 let mut files: Vec<_> = std::fs::read_dir(&dir)
32 .unwrap()
33 .flatten()
34 .map(|e| e.path())
35 .filter(|p| {
36 p.file_name()
37 .and_then(|n| n.to_str())
38 .is_some_and(|n| n.starts_with(&prefix))
39 })
40 .collect();
41 files.sort();
42
43 println!("--- Log files ---");
44 let mut total_lines = 0;
45 for path in &files {
46 let contents = if path.to_string_lossy().ends_with(".gz") {
47 let mut contents = String::new();
48 let file = std::fs::File::open(path).expect("failed to open rotated file");
49 GzDecoder::new(file)
50 .read_to_string(&mut contents)
51 .expect("failed to decompress rotated file");
52 contents
53 } else {
54 std::fs::read_to_string(path).expect("failed to read log file")
55 };
56 let lines = contents.lines().count();
57 total_lines += lines;
58 println!("{} ({} lines):", path.display(), lines);
59 }
60 println!("total lines across files: {total_lines}");
61
62 for path in files {
63 let _ = std::fs::remove_file(path);
64 }
65}