rust 45 lines · 9 steps

Buffered log scanning in Rust

Two functions stream a log file line by line with buffered reads, aggregating stats and finding the first match without loading the whole file.

Explained by highlit
1use std::fs::File;
2use std::io::{self, BufRead, BufReader};
3use std::path::Path;
4 
5pub struct LogStats {
6 pub total_lines: usize,
7 pub error_lines: usize,
8 pub bytes_scanned: u64,
9}
10 
11pub fn scan_log<P: AsRef<Path>>(path: P) -> io::Result<LogStats> {
12 let file = File::open(path)?;
13 let reader = BufReader::with_capacity(64 * 1024, file);
14 
15 let mut stats = LogStats {
16 total_lines: 0,
17 error_lines: 0,
18 bytes_scanned: 0,
19 };
20 
21 for line in reader.lines() {
22 let line = line?;
23 stats.total_lines += 1;
24 stats.bytes_scanned += line.len() as u64 + 1;
25 
26 if line.contains("ERROR") || line.contains("FATAL") {
27 stats.error_lines += 1;
28 }
29 }
30 
31 Ok(stats)
32}
33 
34pub fn first_match<P: AsRef<Path>>(path: P, needle: &str) -> io::Result<Option<(usize, String)>> {
35 let reader = BufReader::new(File::open(path)?);
36 
37 for (idx, line) in reader.lines().enumerate() {
38 let line = line?;
39 if line.contains(needle) {
40 return Ok(Some((idx + 1, line)));
41 }
42 }
43 
44 Ok(None)
45}
01 / 01
STEP 01

Walkthrough

Space play ←→ step click any line
Three takeaways
  1. 1Buffered readers let you stream large files line by line instead of loading them entirely into memory.
  2. 2Accepting `AsRef<Path>` makes a function callable with `&str`, `String`, or `PathBuf` interchangeably.
  3. 3Propagating `io::Result` with `?` keeps the happy path readable while surfacing every I/O failure.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Buffered log scanning in Rust — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code