diff --git a/src/main.rs b/src/main.rs index 2fe1484..9345f12 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,14 +1,18 @@ -use chrono::{DateTime, Local}; -use chrono::{Datelike, Month, NaiveDate, NaiveDateTime, NaiveTime, TimeZone}; +use std::str::FromStr; + +use tokio_postgres::{Client, Config, NoTls, Statement}; + +use tokio::net::{TcpListener, TcpStream}; + +use std::net::SocketAddr; +use std::sync::Arc; + +use structopt::StructOpt; + +use std::collections::HashSet; + use futures_util::FutureExt; use futures_util::StreamExt; -use std::collections::HashSet; -use std::net::SocketAddr; -use std::str::FromStr; -use std::sync::Arc; -use structopt::StructOpt; -use tokio::net::{TcpListener, TcpStream}; -use tokio_postgres::{Client, Config, NoTls, Statement}; type Error = Box; @@ -88,6 +92,8 @@ async fn main() -> Result<(), Error> { } } +use chrono::{DateTime, FixedOffset, Local}; + async fn handle_peer_and_error( stream: TcpStream, peer: SocketAddr, @@ -112,57 +118,44 @@ async fn handle_peer( let ip = peer.ip(); let mut lines = FramedRead::new(stream, LinesCodec::new()); - while let Some(line) = lines.next().await.transpose()? { - let ParsedLine { - prio, - rcvtime, - logtime, - service, - entry, - } = parse_line(&line)?; - if !blacklist.contains(service) { - db.execute( - &insert_statement, - &[&prio, &ip, &rcvtime, &logtime, &service, &entry], - ) - .await?; + loop { + match lines.next().await.transpose()? { + Some(line) => { + let (prio, now, date, service, log) = parse_line(&line)?; + if !blacklist.contains(service) { + db.execute( + &insert_statement, + &[&prio, &ip, &now, &date, &service, &log], + ) + .await?; + } + } + None => break, } } Ok(()) } -struct ParsedLine<'a> { - prio: i16, - rcvtime: DateTime, - logtime: DateTime, - // maybe this would be more correct, but i don't want to redo the database rn - //logtime: NaiveDateTime, - service: &'a str, - entry: &'a str, -} -#[test] -fn tst_timeparse() { - let input = "Jul 8 01:20:30"; - let year = 2022; - let parsed = parse_log_date(year, input).unwrap(); - assert_eq!( - parsed, - NaiveDateTime::parse_from_str("2022-07-08 01:20:30", "%Y-%m-%d %H:%M:%S").unwrap() - ) -} - -fn parse_log_date(year: i32, input: &'_ str) -> Result { - let mut parts = input.split(" ").map(|p| p.trim()).filter(|p| p.len() > 0); - let month = Month::from_str(parts.next().ok_or("no month")?) - .map_err(|e| format!("month parsing error: {:?}", e))?; - let day: u32 = parts.next().ok_or("no day")?.parse()?; - let date = - NaiveDate::from_ymd_opt(year, month.number_from_month(), day).ok_or("invalid day+moth")?; - let time = NaiveTime::parse_from_str(parts.next().ok_or("no time")?, "%H:%M:%S")?; - Ok(NaiveDateTime::new(date, time)) -} - -fn parse_line(line: &'_ str) -> Result, Error> { +/** parses a line, returning + * ( prio + * , time the log was recieved + * , time the log was written according to logger + * , name of the service that wrote the log + * , log entry + * ) + */ +fn parse_line( + line: &'_ str, +) -> Result< + ( + i16, + DateTime, + DateTime, + &'_ str, + &'_ str, + ), + Error, +> { let mut prio_and_remainder = line.splitn(2, '>'); let prio = prio_and_remainder .next() @@ -177,11 +170,13 @@ fn parse_line(line: &'_ str) -> Result, Error> { .expect("splitn should always return a second part"); let (date, line) = line.split_at(16); - let rcvtime = chrono::Local::now(); - // we need to prepend the current year and add timezone, as that is not stated in the logfile - let logtime = parse_log_date(rcvtime.date_naive().year(), date) - .map_err(|e| format!("could not parse logtime {}{} {}", date, line, e))?; - let logtime = TimeZone::from_local_datetime(&Local, &logtime).unwrap(); + // we need to prepend the current year and timezone, as that is not stated in the logfile + let now = chrono::Local::now(); + let mut base = format!("{}", now.format("%Y %z ")); + base.push_str(date); + + let date = DateTime::parse_from_str(&base, "%Y %z %b %e %H:%M:%S ") + .map_err(|e| format!("could not parse {}{} {}", date, line, e))?; let mut parts = line.splitn(2, ':'); @@ -192,12 +187,6 @@ fn parse_line(line: &'_ str) -> Result, Error> { .ok_or("could not split pid from service")? .trim(); - let entry = parts.next().ok_or("could not parse logfile")?.trim(); - Ok(ParsedLine { - prio, - rcvtime, - logtime, - service, - entry, - }) + let log = parts.next().ok_or("could not parse logfile")?.trim(); + Ok((prio, now, date, service, log)) }