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
66
67
68
#[macro_use]
extern crate lazy_static;
extern crate regex;
extern crate serde;

// Used for tests
#[cfg_attr(test, 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<&String>,
  unparsed_filters: Vec<&str>,
  number_of_lines: Option<&u64>,
) {
  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 filters = parse_filters(unparsed_filters);

  let mut count: u64 = 0;

  let stdout = io::stdout();
  let mut stdout_lock = stdout.lock();
  let mut formatter = Formatter::new();
  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");
    let output = match serde_json::from_str::<Value>(line.as_str()) {
      Err(_e) => Some(formatter.format_not_json(&line)),
      Ok(v) => {
        if v.is_object() {
          if passes_filters(&filters, &v) {
            Some(formatter.format_message(v))
          } else {
            None
          }
        } else {
          Some(formatter.format_not_json(&line))
        }
      }
    };

    if output.is_some() {
      writeln!(stdout_lock, "{}", output.unwrap()).unwrap_or(());
      count += 1;
    }
  }
}