1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#[macro_use]
extern crate lazy_static;
extern crate regex;
extern crate serde;

// Used for tests
#[macro_use]
extern crate serde_json;

use serde_json::Value;
use std::fs::File;
use std::io;
use std::io::Write;
use std::io::{BufRead, BufReader};

pub mod filter;
pub mod format;
pub mod line_formats;

use filter::*;
use format::*;

pub fn read_log(
  maybe_file_path: Option<&str>,
  unparsed_filters: Vec<&str>,
  number_of_lines_option: Option<&str>,
) {
  let stdin = io::stdin();
  let reader: Box<dyn BufRead> = match maybe_file_path {
    Some(file_path) => Box::new(BufReader::new(
      File::open(file_path).expect("File should exist"),
    )),
    None => Box::new(stdin.lock()),
  };

  let number_of_lines = number_of_lines_option.map(|n| {
    n.parse::<i32>()
      .expect("'lines' options should be a valid number.")
  });
  let filters = parse_filters(unparsed_filters);

  let mut count: i32 = 0;

  let stdout = io::stdout();
  let mut stdout_lock = stdout.lock();
  for maybe_line in reader.lines() {
    if number_of_lines.is_some() && count > number_of_lines.unwrap() {
      return;
    }
    let line = maybe_line.expect("Line should exist");
    match serde_json::from_str::<Value>(line.as_str()) {
      Err(_e) => write!(stdout_lock, "{}\n", format_not_json(&line)).unwrap_or(()),
      Ok(v) => {
        if v.is_object() {
          if passes_filters(&filters, &v) {
            count += 1;
            write!(stdout_lock, "{}\n", format_message(v)).unwrap_or(())
          }
        } else {
          write!(stdout_lock, "{}\n", format_not_json(&line)).unwrap_or(())
        }
      }
    }
  }
}