Skip to content

Instantly share code, notes, and snippets.

@nemtsov
Created April 14, 2025 13:31
Show Gist options
  • Save nemtsov/d0b88e33101276a7cd9cb54daaabdf23 to your computer and use it in GitHub Desktop.
Save nemtsov/d0b88e33101276a7cd9cb54daaabdf23 to your computer and use it in GitHub Desktop.
#!/usr/bin/env node
const readline = require("readline");
const outputAsTSV = process.argv.includes("--tsv");
const fields = [
"timestamp",
"level",
"tx_id",
"duration",
"planning",
"waiting",
"size",
"session_type",
"protocol",
"driver_lib",
"client_address",
"server_address",
"user",
"client_ip",
"uri",
"db",
"operation",
"query",
"params",
"runtime",
"error",
"source_ip",
"source_type",
];
const logRegex =
/^(?<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}\+\d{4})\s+(?<level>\w+)\s+transaction id:(?<tx_id>-?\d+)\s+-\s+(?<duration>\d+)\s+ms: \(planning: (?<planning>\d+), waiting: (?<waiting>\d+)\)\s+-\s+(?<size>\d+)\s+B\s+-\s+(?<session_type>\S+)\s+(?<protocol>\S+)\s+(?:(?<driver_lib>[^\s/]+(?:\/[^\s/]+)?)\/(?<client_address>\d{1,3}(?:\.\d{1,3}){3}:\d+)\s+server\/(?<server_address>\d{1,3}(?:\.\d{1,3}){3}:\d+)>?\s+(?<user><[^>]*>)|(?<client_ip>\d{1,3}(?:\.\d{1,3}){3})\s+(?<uri>\S+)\s+(?<db>\S+))\s+-\s+(?<operation>\S+)\s+-\s+(?<query>[\s\S]*?)\s+-\s+(?<params>\{[\s\S]*?\})?\s+-\s+runtime=(?<runtime>\S+)\s+-\s+\{\}(?:\s+-\s+(?<error>[\s\S]*?))?(?=\n\d{4}-\d{2}-\d{2}|\n*$)$/gms;
let buffer = "";
const rl = readline.createInterface({
input: process.stdin,
terminal: false,
});
if (outputAsTSV) {
process.stdout.write(fields.join("\t") + "\n");
}
rl.on("line", (line) => {
buffer += line + "\n";
if (!/ - \{\}(?:\s+-\s+.+)?\s*$/.test(line)) {
return;
}
const matches = [...buffer.matchAll(logRegex)];
for (const match of matches) {
const g = match.groups;
const parsed = {
timestamp: g.timestamp,
level: g.level,
tx_id: Number(g.tx_id),
duration: Number(g.duration),
planning: Number(g.planning),
waiting: Number(g.waiting),
size: Number(g.size),
session_type: g.session_type,
protocol: g.protocol,
driver_lib: g.driver_lib,
client_address: g.client_address,
server_address: g.server_address,
user: g.user,
client_ip: g.client_ip,
uri: g.uri,
db: g.db,
operation: g.operation,
query: g.query.replace(/\s+/g, " ").trim(),
params: g.params ? g.params.trim() : null,
runtime: g.runtime,
error: g.error ? g.error.trim() : null,
};
if (outputAsTSV) {
const row = fields.map((f) => parsed[f] ?? "").join("\t");
process.stdout.write(row + "\n");
} else {
process.stdout.write(JSON.stringify(parsed) + "\n");
}
}
buffer = "";
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment