Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1 @@
/target
/target/
16 changes: 12 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 8 additions & 23 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,24 +1,9 @@
[package]
name = "elb-log-parser"
version = "0.2.7"
edition = "2024"
authors = ["Jihyeon Kim <[email protected]>"]
description = "Simple AWS ELB log parser which parses Classic LB and ALB logs into JSONs."
license = "AGPL-3.0-or-later"
repository = "https://github.com/simnalamburt/elb-log-parser"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[workspace]
members = ["elb-log-parser", "libelb-log-parser"]
resolver = "3"

[dependencies]
regex = "1"
regex-automata = "0.4"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
walkdir = "2"
flate2 = "1"

anyhow = { version = "1", features = ["backtrace"] }
thiserror = "2"
clap = { version = "4.0.22", features = ["derive"] }
clap_complete = "4.5.33"
crossbeam-channel = "0.5.15"
[workspace.package]
authors = ["Jihyeon Kim <[email protected]>"]
edition = "2024"
license = "Apache-2.0 OR MIT"
repository = "https://github.com/simnalamburt/sample-rust-apps"
21 changes: 21 additions & 0 deletions elb-log-parser/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "elb-log-parser"
description = "Simple AWS ELB log parser which parses Classic LB and ALB logs into JSONs."
version = "0.2.7"

authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true

[dependencies]
libelb-log-parser = { path = "../libelb-log-parser", version = "0.0.0" }

serde_json = "1"
walkdir = "2"
flate2 = "1"

anyhow = { version = "1", features = ["backtrace"] }
clap = { version = "4.0.22", features = ["derive"] }
clap_complete = "4.5.33"
crossbeam-channel = "0.5.15"
12 changes: 3 additions & 9 deletions src/main.rs → elb-log-parser/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
mod alb;
mod classic_lb;
mod parse;

use std::fs::{File, metadata};
use std::io::{BufRead, BufReader, IsTerminal, Write, stderr, stdin, stdout};
use std::thread;
Expand All @@ -13,9 +9,7 @@ use crossbeam_channel::unbounded;
use flate2::read::MultiGzDecoder;
use walkdir::{DirEntry, WalkDir};

use crate::alb::LogParser as ALBLogParser;
use crate::classic_lb::LogParser as ClassicLBLogParser;
use crate::parse::{LBLogParser, ParseLogError};
use libelb_log_parser::{ALBLogParser, ClassicLBLogParser, LBLogParser, LBType, ParseLogError};

#[derive(Parser)]
#[command(
Expand Down Expand Up @@ -130,8 +124,8 @@ fn walkdir<T: LBLogParser>(path: &str, config: Config) -> Result<()> {

let file = File::open(path)?;
let reader: Box<dyn BufRead> = match T::TYPE {
Type::Alb => Box::new(BufReader::new(MultiGzDecoder::new(file))),
Type::ClassicLb => Box::new(BufReader::new(file)),
LBType::Alb => Box::new(BufReader::new(MultiGzDecoder::new(file))),
LBType::ClassicLb => Box::new(BufReader::new(file)),
};
for_each_parsed_lines::<T>(reader, config, |log| {
let json = serde_json::to_string(&log)?;
Expand Down
18 changes: 18 additions & 0 deletions libelb-log-parser/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "libelb-log-parser"
description = "Simple AWS ELB log parser."
version = "0.0.0"

authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true

[dependencies]
regex = "1"
regex-automata = "0.4"
serde = { version = "1", features = ["derive"] }
thiserror = "2"

[dev-dependencies]
serde_json = "1"
10 changes: 5 additions & 5 deletions src/alb.rs → libelb-log-parser/src/alb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::cell::RefCell;
use regex::bytes::{CaptureLocations, Regex};
use serde::Serialize;

use crate::parse::{LBLogParser, ParseLogError, bytes_ser, optional_bytes_ser};
use crate::parse::{LBLogParser, LBType, ParseLogError, bytes_ser, optional_bytes_ser};

#[derive(Serialize)]
pub struct Log<'a> {
Expand Down Expand Up @@ -75,9 +75,9 @@ pub struct Log<'a> {
/// Optional TID (Traceability ID) field, added in May 2024
///
/// ###### References
/// - https://github.com/simnalamburt/elb-log-parser/issues/11
/// - https://dev.classmethod.jp/articles/alb-accesslog-traceabilityid/
/// - https://repost.aws/knowledge-center/trace-elb-x-amzn-trace-id
/// - <https://github.com/simnalamburt/elb-log-parser/issues/11>
/// - <https://dev.classmethod.jp/articles/alb-accesslog-traceabilityid/>
/// - <https://repost.aws/knowledge-center/trace-elb-x-amzn-trace-id>
#[serde(
skip_serializing_if = "Option::is_none",
serialize_with = "optional_bytes_ser"
Expand All @@ -94,7 +94,7 @@ impl LBLogParser for LogParser {
type Log<'input> = self::Log<'input>;

const EXT: &'static str = ".log.gz";
const TYPE: crate::Type = crate::Type::Alb;
const TYPE: LBType = LBType::Alb;

// https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-log-entry-format
const REGEX: &'static str = r#"(?x)
Expand Down
4 changes: 2 additions & 2 deletions src/classic_lb.rs → libelb-log-parser/src/classic_lb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::cell::RefCell;
use regex::bytes::{CaptureLocations, Regex};
use serde::Serialize;

use crate::parse::{LBLogParser, ParseLogError, bytes_ser};
use crate::parse::{LBLogParser, LBType, ParseLogError, bytes_ser};

#[derive(Serialize)]
pub struct Log<'a> {
Expand Down Expand Up @@ -54,7 +54,7 @@ impl LBLogParser for LogParser {
type Log<'input> = self::Log<'input>;

const EXT: &'static str = ".log";
const TYPE: crate::Type = crate::Type::ClassicLb;
const TYPE: LBType = LBType::ClassicLb;

// https://docs.aws.amazon.com/en_us/elasticloadbalancing/latest/classic/access-log-collection.html#access-log-entry-syntax
const REGEX: &'static str = r#"(?x)
Expand Down
9 changes: 9 additions & 0 deletions libelb-log-parser/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
mod alb;
mod classic_lb;
mod parse;

pub use crate::parse::{LBLogParser, LBType, ParseLogError};
pub use crate::{
alb::{Log as ALBLog, LogParser as ALBLogParser},
classic_lb::{Log as ClassicLBLog, LogParser as ClassicLBLogParser},
};
12 changes: 8 additions & 4 deletions src/parse.rs → libelb-log-parser/src/parse.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
use serde::{Serialize, Serializer, ser};
use thiserror::Error;

use crate::Type;

#[derive(Error, Clone, Debug)]
pub enum ParseLogError {
#[error("Invalid log line: {}", String::from_utf8_lossy(.0))]
InvalidLogFormat(Vec<u8>),
}

pub(crate) trait LBLogParser {
#[derive(Clone)]
pub enum LBType {
Alb,
ClassicLb,
}

pub trait LBLogParser {
type Log<'input>: Serialize;

const EXT: &'static str;
const TYPE: Type;
const TYPE: LBType;
const REGEX: &'static str;

fn new() -> Self;
Expand Down