initial matching

This commit is contained in:
Robin Appelman 2024-07-21 01:17:23 +02:00
commit 246b4552f9
31 changed files with 87489 additions and 43394 deletions

383
Cargo.lock generated
View file

@ -2,6 +2,389 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "clap"
version = "4.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8d93d855ce6a0aa87b8473ef9169482f40abaa2e9e0993024c35c902cbd5920"
dependencies = [
"bitflags",
"clap_derive",
"clap_lex",
"is-terminal",
"once_cell",
"strsim",
"termcolor",
]
[[package]]
name = "clap_derive"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "clap_lex"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "033f6b7a4acb1f358c742aaca805c939ee73b4c6209ae4318ec7aca81c42e646"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "cloud-log-analyser"
version = "0.1.0"
dependencies = [
"clap",
"cloud-log-analyser-data",
"log",
"regex",
"serde",
"serde_json",
"thiserror",
]
[[package]]
name = "cloud-log-analyser-data"
version = "0.1.0"
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "is-terminal"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b"
dependencies = [
"hermit-abi",
"libc",
"windows-sys",
]
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "libc"
version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "os_str_bytes"
version = "6.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn 1.0.109",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "serde"
version = "1.0.204"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.204"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
]
[[package]]
name = "serde_json"
version = "1.0.120"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
[[package]]
name = "thiserror"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "winapi-util"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
dependencies = [
"windows-sys",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"

View file

@ -4,3 +4,10 @@ version = "0.1.0"
edition = "2021"
[dependencies]
thiserror = "1.0.63"
serde = { version = "1.0.204", features = ["derive"] }
serde_json = "1.0.120"
regex = "1.10.5"
log = "0.4.22"
clap = { version = "=4.1.3", features = ["derive"] }
cloud-log-analyser-data = { version = "0.1.0", path = "./data" }

7
data/Cargo.lock generated Normal file
View file

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "cloud-log-analyser-data"
version = "0.1.0"

8
data/Cargo.toml Normal file
View file

@ -0,0 +1,8 @@
[package]
name = "cloud-log-analyser-data"
description = "static data for cloud-log-analyser"
version = "0.1.0"
edition = "2021"
[dependencies]

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

18
data/src/data.rs Normal file
View file

@ -0,0 +1,18 @@
mod server_24;
mod server_25;
mod server_26;
mod server_27;
mod server_28;
mod server_29;
pub fn get_statements(name: &str, version: u32) -> &[crate::LoggingStatement] {
match (name, version) {
("server", 24) => server_24::STATEMENTS,
("server", 25) => server_25::STATEMENTS,
("server", 26) => server_26::STATEMENTS,
("server", 27) => server_27::STATEMENTS,
("server", 28) => server_28::STATEMENTS,
("server", 29) => server_29::STATEMENTS,
_ => &[],
}
}

11009
data/src/data/server_24.rs Normal file

File diff suppressed because it is too large Load diff

14327
data/src/data/server_25.rs Normal file

File diff suppressed because it is too large Load diff

14729
data/src/data/server_26.rs Normal file

File diff suppressed because it is too large Load diff

15211
data/src/data/server_27.rs Normal file

File diff suppressed because it is too large Load diff

15631
data/src/data/server_28.rs Normal file

File diff suppressed because it is too large Load diff

15787
data/src/data/server_29.rs Normal file

File diff suppressed because it is too large Load diff

5
data/src/lib.rs Normal file
View file

@ -0,0 +1,5 @@
mod data;
mod types;
pub use data::get_statements;
pub use types::*;

35
data/src/types.rs Normal file
View file

@ -0,0 +1,35 @@
#[derive(Debug, Default, PartialEq, Clone, Copy)]
pub enum LogLevel {
Debug,
Info,
Notice,
Warn,
Error,
Alert,
Critical,
Emergency,
Exception,
#[default]
Unknown,
}
impl From<i64> for LogLevel {
fn from(value: i64) -> Self {
match value {
0 => Self::Debug,
1 => Self::Info,
2 => Self::Warn,
3 => Self::Error,
4 => Self::Critical,
_ => Self::Unknown,
}
}
}
#[derive(Debug, PartialEq)]
pub struct LoggingStatement {
pub level: LogLevel,
pub path: &'static str,
pub line: usize,
pub message_parts: &'static [&'static str],
}

View file

@ -34,14 +34,10 @@
msrv = (fromTOML (readFile ./Cargo.toml)).package.rust-version;
extractorMsrv = (fromTOML (readFile ./logging-extractor/Cargo.toml)).package.rust-version;
toolchain = rust-bin.stable.latest.default;
msrvToolchain = rust-bin.stable."${msrv}".default;
extractorMsrvToolchain = rust-bin.stable."${extractorMsrv}".default;
naersk' = callPackage naersk {
rustc = toolchain;
cargo = toolchain;
};
naersk' = callPackage naersk {};
msrvNaersk = callPackage naersk {
rustc = msrvToolchain;
cargo = msrvToolchain;
@ -80,12 +76,12 @@
lib.attrsets.genAttrs targets (target:
(cross-naersk'.buildPackage target) nearskOpt)
// {
inherit (pkgs) logging-extractor extracted-logs;
inherit (pkgs) logging-extractor extracted-logs extracted-logs-rust;
check = naersk'.buildPackage (nearskOpt
// {
mode = "check";
});
checkExtractor = naersk'.buildPackage (nearskOpt
extractorCheck = naersk'.buildPackage (nearskOpt
// {
mode = "check";
root = extractorSrc;
@ -111,7 +107,7 @@
releaseMatrix = buildMatrix releaseTargets;
devShells.default = mkShell {
nativeBuildInputs = with pkgs; [toolchain bacon cargo-msrv cargo-insta];
nativeBuildInputs = with pkgs; [cargo rustc bacon cargo-msrv cargo-insta];
};
}
)

View file

@ -35,6 +35,29 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "databake"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a04fbfbecca8f0679c8c06fef907594adcc3e2052e11163a6d30535a1a5604d"
dependencies = [
"databake-derive",
"proc-macro2",
"quote",
]
[[package]]
name = "databake-derive"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4078275de501a61ceb9e759d37bdd3d7210e654dbc167ac1a3678ef4435ed57b"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
[[package]]
name = "encode_unicode"
version = "0.3.6"
@ -89,6 +112,7 @@ name = "logging-extractor"
version = "0.1.0"
dependencies = [
"cc",
"databake",
"insta",
"memchr",
"serde",
@ -261,6 +285,17 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "synstructure"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "test-case"
version = "3.3.1"

View file

@ -19,6 +19,7 @@ walkdir = "2.5.0"
tree-sitter = "0.22.6"
tree-sitter-php = "0.22.7"
memchr = "2.7.4"
databake = { version = "0.1.8", features = ["derive"] }
[build-dependencies]
cc = "1.1.6"

View file

@ -0,0 +1,73 @@
use databake::Bake;
use std::borrow::Cow;
#[derive(Debug, Default, PartialEq, Clone, Copy, Bake)]
#[databake(path = crate)]
pub enum LogLevel {
Debug,
Info,
Notice,
Warn,
Error,
Alert,
Critical,
Emergency,
Exception,
#[default]
Unknown,
}
impl From<crate::LogLevel> for LogLevel {
fn from(value: crate::LogLevel) -> Self {
match value {
crate::LogLevel::Debug => LogLevel::Debug,
crate::LogLevel::Info => LogLevel::Info,
crate::LogLevel::Notice => LogLevel::Notice,
crate::LogLevel::Warn => LogLevel::Warn,
crate::LogLevel::Error => LogLevel::Error,
crate::LogLevel::Alert => LogLevel::Alert,
crate::LogLevel::Critical => LogLevel::Critical,
crate::LogLevel::Emergency => LogLevel::Emergency,
crate::LogLevel::Exception => LogLevel::Exception,
crate::LogLevel::Unknown => LogLevel::Unknown,
}
}
}
#[derive(Debug, PartialEq, Bake)]
#[databake(path = crate)]
pub struct LoggingStatement<'a> {
pub level: LogLevel,
pub path: &'a str,
pub line: usize,
pub message_parts: &'a [&'a str],
}
pub fn bake_statement(output: &mut String, statement: &crate::LoggingStatement) {
let message_parts: Vec<_> = statement.message_parts.iter().map(Cow::as_ref).collect();
let statement = LoggingStatement {
level: statement.level.into(),
path: statement.path,
line: statement.line,
message_parts: &message_parts,
};
output.push_str(&statement.bake(&Default::default()).to_string());
}
#[cfg(feature = "bake")]
mod bake_test {
#[test]
fn test_bake() {
use databake::test_bake;
test_bake!(
crate::LoggingStatement,
const: crate::LoggingStatement {
level: crate::LogLevel::Debug,
path: "foo",
line: 12usize,
message_parts: &["part1", "part2"]
},
cloud_log_analyser,
);
}
}

View file

@ -1,7 +1,8 @@
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
#[derive(Debug, Default, PartialEq)]
#[derive(Debug, Default, PartialEq, Clone, Copy, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum LogLevel {
Debug,
Info,
@ -49,27 +50,8 @@ impl LogLevel {
}
}
impl Serialize for LogLevel {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.as_str().serialize(serializer)
}
}
impl Display for LogLevel {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.as_str().fmt(f)
}
}
impl<'de> Deserialize<'de> for LogLevel {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = <&str>::deserialize(deserializer)?;
Ok(LogLevel::parse(s).unwrap_or_default())
}
}

View file

@ -7,11 +7,13 @@ use std::io::{Read, Write};
use tracing::error;
use walkdir::WalkDir;
mod bake;
pub mod error;
pub mod extractor;
mod level;
pub mod string;
use crate::bake::bake_statement;
pub use level::LogLevel;
#[derive(Debug, PartialEq, Serialize, Deserialize)]
@ -22,13 +24,23 @@ pub struct LoggingStatement<'a> {
message_parts: Vec<Cow<'a, str>>,
}
pub fn extract_dir<W: Write>(root: &str, mut output: W) -> Result<(), Error> {
pub fn extract_dir<W: Write>(root: &str, mut output: W, bake: bool) -> Result<(), Error> {
let mut code_buff = String::with_capacity(32 * 1024 * 1024);
writeln!(&mut output, "[").ok();
if bake {
writeln!(
&mut output,
"pub const STATEMENTS: &[crate::LoggingStatement] = &[\n"
)
.ok();
} else {
writeln!(&mut output, "[").ok();
}
let mut first_line = true;
let mut bake_buff = String::with_capacity(1024 * 1024);
let extractor = LogExtractor::new();
for file in WalkDir::new(root).into_iter().flatten() {
@ -57,13 +69,23 @@ pub fn extract_dir<W: Write>(root: &str, mut output: W) -> Result<(), Error> {
}
first_line = false;
write!(&mut output, "\t").ok();
let _ = serde_json::to_writer(&mut output, &log_item);
if bake {
bake_buff.clear();
bake_statement(&mut bake_buff, &log_item);
writeln!(&mut output, "{bake_buff}").ok();
} else {
let _ = serde_json::to_writer(&mut output, &log_item);
}
}
}
}
}
writeln!(&mut output, "\n]").ok();
if bake {
writeln!(&mut output, "];\n").ok();
} else {
writeln!(&mut output, "\n]").ok();
}
Ok(())
}

View file

@ -6,6 +6,7 @@ use std::io::stdout;
fn main() -> Result<(), Error> {
let root = args().nth(1).expect("no root provided");
let mode = args().nth(2).unwrap_or_else(|| "json".into());
let root = canonicalize(&root).map_err(|err| Error::RealPath {
path: root.into(),
err,
@ -14,5 +15,5 @@ fn main() -> Result<(), Error> {
let stdout = stdout();
extract_dir(root, stdout)
extract_dir(root, stdout, mode == "rust")
}

View file

@ -5,7 +5,7 @@ use test_case::test_case;
fn snapshot_test(name: &str) {
let root = format!("test-data/{name}");
let mut output = Vec::<u8>::with_capacity(1024 * 1024);
extract_dir(&root, &mut output).unwrap();
extract_dir(&root, &mut output, false).unwrap();
let output: Vec<LoggingStatement> = serde_json::from_slice(&output).unwrap();
insta::assert_json_snapshot!(output)

View file

@ -7,8 +7,10 @@
url,
major,
sha256,
}:
stdenvNoCC.mkDerivation rec {
mode ? "json",
}: let
ext = if mode == "rust" then "rs" else "json";
in stdenvNoCC.mkDerivation rec {
pname = "extractor-logs-${name}-${major}";
inherit version;
@ -19,11 +21,11 @@ stdenvNoCC.mkDerivation rec {
nativeBuildInputs = [logging-extractor];
buildPhase = ''
logging-extractor . > logs.json
logging-extractor . ${mode} > logs.${ext}
'';
installPhase = ''
mkdir -p $out/${name}/${major}
cp logs.json $out/${name}/${major}
mkdir -p $out
cp logs.* $out/${name}_${major}.${ext}
'';
}

View file

@ -5,16 +5,21 @@ final: prev: let
inherit (prev.lib.lists) flatten;
packages = prev.lib.traceValSeq (importJSON ./versions.json);
loggingFor = name:
loggingFor = mode: name:
mapAttrs (major: data: (final.callPackage ./extracted-logs.nix {
inherit (data) url sha256 version;
inherit name major;
inherit name major mode;
}));
in {
logging-extractor = final.callPackage ./logging-extractor.nix {};
extracted-logs-parts = mapAttrs loggingFor packages;
extracted-logs-parts = mapAttrs (loggingFor "json") packages;
extracted-logs-parts-rust = mapAttrs (loggingFor "rust") packages;
extracted-logs = symlinkJoin {
name = "extracted-logs";
paths = flatten (map attrValues (attrValues final.extracted-logs-parts));
};
extracted-logs-rust = symlinkJoin {
name = "extracted-logs";
paths = flatten (map attrValues (attrValues final.extracted-logs-parts-rust));
};
}

View file

@ -1,3 +1,45 @@
use crate::matcher::Matcher;
use clap::Parser;
use cloud_log_analyser_data::get_statements;
use serde::Deserialize;
use std::borrow::Cow;
mod matcher;
#[derive(Debug, Parser)]
enum Args {
Log(LogCommand),
}
#[derive(Debug, Parser)]
struct LogCommand {
line: String,
}
#[derive(Deserialize)]
struct LogLine<'a> {
version: &'a str,
level: i64,
message: Cow<'a, str>,
}
fn main() {
println!("Hello, world!");
let args = Args::parse();
match args {
Args::Log(LogCommand { line }) => {
let parsed_line: LogLine = serde_json::from_str(&line).unwrap();
let major = parsed_line.version.split(".").next().unwrap();
let major = major.parse().unwrap();
let statements = get_statements("server", major);
let matcher = Matcher::new(statements);
let index = matcher.match_log(parsed_line.level.into(), parsed_line.message.as_ref());
if let Some(index) = index {
let statement = &statements[index];
println!("match found: {} line {}", statement.path, statement.line);
} else {
eprintln!("No match found");
}
}
}
}

129
src/matcher.rs Normal file
View file

@ -0,0 +1,129 @@
use cloud_log_analyser_data::{LogLevel, LoggingStatement};
use regex::{escape, Regex, RegexBuilder};
pub struct LogMatch {
level: LogLevel,
pattern: Regex,
pattern_length: usize,
}
impl LogMatch {
pub fn new(statement: &LoggingStatement) -> LogMatch {
LogMatch {
level: statement.level,
pattern: build_pattern(statement.message_parts),
pattern_length: statement.message_parts.iter().copied().map(str::len).sum(),
}
}
}
pub struct Matcher {
matches: Vec<LogMatch>,
}
impl Matcher {
pub fn new(statements: &[LoggingStatement]) -> Matcher {
Matcher {
matches: statements.iter().map(LogMatch::new).collect(),
}
}
pub fn match_log(&self, level: LogLevel, message: &str) -> Option<usize> {
let mut best_match = None;
let mut best_length = 0;
for (i, log_match) in self.matches.iter().enumerate() {
if (log_match.level == level
|| log_match.level == LogLevel::Exception
|| level == LogLevel::Unknown)
&& log_match.pattern.is_match(message)
&& log_match.pattern_length > best_length
{
best_match = Some(i);
best_length = log_match.pattern_length;
}
}
best_match
}
}
fn build_pattern<'a>(parts: &[&str]) -> Regex {
let mut pattern = String::with_capacity(128);
for part in parts {
pattern.push_str(&escape(part));
pattern.push_str("(.*)");
}
RegexBuilder::new(&pattern)
.build()
.expect("Failed to build regex")
}
#[test]
fn test_build_pattern() {
let regex = build_pattern(["foobar", "asd"]);
assert!(regex.is_match("foobar with asd and more"));
assert!(regex.is_match("foobarasd"));
assert!(!regex.is_match("fooasd"));
}
#[test]
fn test_matcher() {
let statements = &[
LoggingStatement {
line: 68,
level: LogLevel::Exception,
path: "foo",
message_parts: vec!["Not allowed to rename a shared album".into()],
},
LoggingStatement {
line: 69,
level: LogLevel::Error,
path: "bar",
message_parts: vec![
"You are not allowed to edit link shares that you don".into(),
"'".into(),
"t own".into(),
],
},
LoggingStatement {
line: 69,
level: LogLevel::Error,
path: "asd",
message_parts: vec![
"Unsupported query value for mimetype: ".into(),
", only values in the format \"mime/type\" or \"mime/%\" are supported".into(),
],
},
LoggingStatement {
line: 68,
level: LogLevel::Exception,
path: "short",
message_parts: vec!["Not allowed to rename".into()],
},
];
let matcher = Matcher::new(statements);
assert_eq!(
Some(0),
matcher.match_log(LogLevel::Error, "Not allowed to rename a shared album")
);
assert_eq!(
Some(3),
matcher.match_log(LogLevel::Error, "Not allowed to rename an album")
);
assert_eq!(
Some(1),
matcher.match_log(
LogLevel::Error,
"You are not allowed to edit link shares that you don't own"
)
);
assert_eq!(
None,
matcher.match_log(
LogLevel::Info,
"You are not allowed to edit link shares that you don't own"
)
);
assert_eq!(Some(2), matcher.match_log(LogLevel::Error, "Unsupported query value for mimetype: %/text, only values in the format \"mime/type\" or \"mime/%\" are supported"));
}