refactor(prettify-log): regex performance

This commit is contained in:
2025-02-06 14:39:39 +00:00
parent 132724faa1
commit 26719f232c
4 changed files with 30 additions and 25 deletions

View File

@@ -137,10 +137,10 @@
virtualisation.vmVariant.virtualisation = { virtualisation.vmVariant.virtualisation = {
qemu.options = [ qemu.options = [
"-nographic" "-nographic"
"-display" "curses" "-display curses"
"-append" "console=ttyS0" "-append console=ttyS0"
"-serial" "mon:stdio" "-serial mon:stdio"
"-vga" "qxl" "-vga qxl"
]; ];
forwardPorts = [ forwardPorts = [
{ from = "host"; host.port = 40500; guest.port = 22; } { from = "host"; host.port = 40500; guest.port = 22; }

View File

@@ -225,6 +225,7 @@ dependencies = [
"atty", "atty",
"colored_json", "colored_json",
"float-cmp", "float-cmp",
"once_cell",
"predicates", "predicates",
"regex", "regex",
"serde", "serde",

View File

@@ -6,6 +6,7 @@ edition = "2021"
[dependencies] [dependencies]
atty = "0.2.14" atty = "0.2.14"
colored_json = "5.0.0" colored_json = "5.0.0"
once_cell = "1.20.2"
regex = "1.11.1" regex = "1.11.1"
serde = "1.0.217" serde = "1.0.217"
serde_json = "1.0.138" serde_json = "1.0.138"

View File

@@ -2,7 +2,8 @@ use std::io::{self, BufRead};
use std::env; use std::env;
use serde_json::Value; use serde_json::Value;
use colored_json::{ColorMode, ToColoredJson}; use colored_json::{ColorMode, ToColoredJson};
use regex::Regex; use regex::{Regex, Captures};
use once_cell::sync::Lazy;
/// Finds the first '{' and tries to match nested braces until the corresponding '}'. /// Finds the first '{' and tries to match nested braces until the corresponding '}'.
fn find_json_block(line: &str) -> Option<(usize, usize)> { fn find_json_block(line: &str) -> Option<(usize, usize)> {
@@ -23,6 +24,10 @@ fn find_json_block(line: &str) -> Option<(usize, usize)> {
None None
} }
static RE: Lazy<Regex> = Lazy::new(|| {
Regex::new(r"(?i)(^|[^A-Za-z])(?P<kw>ERROR|DEBUG|INFO|LOG|EXCEPTION|WARNING|NOTICE|HINT|FATAL|DETAIL|STATEMENT)(:)").unwrap()
});
/// Applies color to known log keywords (e.g. ERROR, DEBUG) without coloring the colon. /// Applies color to known log keywords (e.g. ERROR, DEBUG) without coloring the colon.
/// Captures the preceding boundary, the keyword, and the colon, then colors only the keyword. /// Captures the preceding boundary, the keyword, and the colon, then colors only the keyword.
fn colorize_keywords(line: &str) -> String { fn colorize_keywords(line: &str) -> String {
@@ -34,26 +39,24 @@ fn colorize_keywords(line: &str) -> String {
let cyan = "\x1b[36m"; let cyan = "\x1b[36m";
let reset = "\x1b[0m"; let reset = "\x1b[0m";
let patterns = vec![ RE.replace_all(line, |caps: &Captures| {
(Regex::new(r"(?i)(^|[^A-Za-z])(ERROR)(:)").unwrap(), format!("$1{red}$2{reset}$3", red=red, reset=reset)), let prefix = caps.get(1).unwrap().as_str();
(Regex::new(r"(?i)(^|[^A-Za-z])(DEBUG)(:)").unwrap(), format!("$1{blue}$2{reset}$3", blue=blue, reset=reset)), let keyword = caps.name("kw").unwrap().as_str();
(Regex::new(r"(?i)(^|[^A-Za-z])(INFO)(:)").unwrap(), format!("$1{green}$2{reset}$3", green=green, reset=reset)), let suffix = caps.get(3).unwrap().as_str();
(Regex::new(r"(?i)(^|[^A-Za-z])(LOG)(:)").unwrap(), format!("$1{green}$2{reset}$3", green=green, reset=reset)), let key = match keyword.to_lowercase().as_str() {
(Regex::new(r"(?i)(^|[^A-Za-z])(EXCEPTION)(:)").unwrap(), format!("$1{magenta}$2{reset}$3", magenta=magenta, reset=reset)), "error" => format!("{}{}{}{}", prefix, red, keyword, reset),
(Regex::new(r"(?i)(^|[^A-Za-z])(WARNING)(:)").unwrap(), format!("$1{yellow}$2{reset}$3", yellow=yellow, reset=reset)), "debug" => format!("{}{}{}{}", prefix, blue, keyword, reset),
(Regex::new(r"(?i)(^|[^A-Za-z])(NOTICE)(:)").unwrap(), format!("$1{cyan}$2{reset}$3", cyan=cyan, reset=reset)), "info" | "log"
(Regex::new(r"(?i)(^|[^A-Za-z])(HINT)(:)").unwrap(), format!("$1{cyan}$2{reset}$3", cyan=cyan, reset=reset)), => format!("{}{}{}{}", prefix, green, keyword, reset),
(Regex::new(r"(?i)(^|[^A-Za-z])(FATAL)(:)").unwrap(), format!("$1{magenta}$2{reset}$3", magenta=magenta, reset=reset)), "exception" | "fatal"
(Regex::new(r"(?i)(^|[^A-Za-z])(DETAIL)(:)").unwrap(), format!("$1{cyan}$2{reset}$3", cyan=cyan, reset=reset)), => format!("{}{}{}{}", prefix, magenta, keyword, reset),
(Regex::new(r"(?i)(^|[^A-Za-z])(STATEMENT)(:)").unwrap(), format!("$1{cyan}$2{reset}$3", cyan=cyan, reset=reset)), "warning" => format!("{}{}{}{}", prefix, yellow, keyword, reset),
]; "notice" | "hint" | "detail" | "statement"
=> format!("{}{}{}{}", prefix, cyan, keyword, reset),
let mut out = String::from(line); _ => caps[0].to_string(),
for (re, replacement) in patterns { };
// Replace all occurrences key + suffix
out = re.replace_all(&out, replacement.as_str()).to_string(); }).to_string()
}
out
} }
fn conditionally_colorize_keywords<'a>(line: &'a str, force_color: bool) -> String { fn conditionally_colorize_keywords<'a>(line: &'a str, force_color: bool) -> String {