diff --git a/02-filter-a-log-file/chains_parser/parser.js b/02-filter-a-log-file/chains_parser/parser.js index c0cdad3..e54d7ae 100644 --- a/02-filter-a-log-file/chains_parser/parser.js +++ b/02-filter-a-log-file/chains_parser/parser.js @@ -9,7 +9,7 @@ import format from "date-fns/format/index.js"; program .option("--min ", "The lowest count to print. Stop at this.", 1) .option("--errors", "Show the errors so you can fix them.", false) - .requiredOption("--outfile ", "Save to file rather than stdout.") + .requiredOption("--output ", "Save to file rather than stdout.") .requiredOption("--domain ", "Domain for the log. Gets removed as a refer.") .requiredOption("--input ", "Input file glob.") .description("Processes different web server logs to determine request chain frequency.") @@ -276,6 +276,6 @@ const output_json = async (stats, data, domain, min, outfile) => { const [by_date, stats] = await parse_logs_glob(OPTS.input, OPTS.errors); -output_json(stats, by_date, OPTS.domain, OPTS.min, OPTS.outfile); +output_json(stats, by_date, OPTS.domain, OPTS.min, OPTS.output); console.log(stats); diff --git a/02-filter-a-log-file/chains_parser/reporter.js b/02-filter-a-log-file/chains_parser/reporter.js index d7d80b2..32d5884 100644 --- a/02-filter-a-log-file/chains_parser/reporter.js +++ b/02-filter-a-log-file/chains_parser/reporter.js @@ -4,11 +4,14 @@ import readline from "readline"; import { program } from "commander"; import glob from "fast-glob"; import format from "date-fns/format/index.js"; +import asciichart from "asciichart"; program .option("--min ", "The lowest count to print. Stop at this.", 1) .option("--errors", "Show the errors so you can fix them.", false) .option("--outfile ", "Save to file rather than stdout.") + .option("--max-days ", "Only display charts for entries with at least this many days.", 10) + .option("--height ", "Height of the ascii graph.", 5) .requiredOption("--input ", "Input file glob.") .description("Loads the output of a chain parser and produces a report.") .version(0.1); @@ -18,6 +21,10 @@ const OPTS = program.opts(); OPTS.min = parseInt(OPTS.min); assert(!isNaN(OPTS.min), `min must be a number, you have ${OPTS.min}`); +OPTS.height = parseInt(OPTS.height); +assert(!isNaN(OPTS.height), `height must be a number, you have ${OPTS.height}`); + + const sort_request_chains = (chains, min) => { const converted = []; @@ -36,14 +43,24 @@ const sort_request_chains = (chains, min) => { const { stats, domain, result, generated_on} = JSON.parse(fs.readFileSync(OPTS.input)); -const dates = Object.keys(result).sort(); +const sorted = []; +const keys = Object.keys(result).sort(); + +const by_chain = {}; -for(let key of dates) { - console.log(`--- ${key} ---`); +for(let key of keys) { + const chain = sort_request_chains(result[key], OPTS.min); - const stats = sort_request_chains(result[key], OPTS.min); + for(let [count, urls] of chain) { + const series = by_chain[urls] || []; + series.push(count); + by_chain[urls] = series; + } +} - for(let [count, chain] of stats) { - console.log(count, "\t", chain); +for(let [chain, counts] of Object.entries(by_chain)) { + if(counts.length > OPTS.maxDays) { + console.log(chain); + console.log(asciichart.plot(counts, {height: OPTS.height})); } } diff --git a/02-filter-a-log-file/package-lock.json b/02-filter-a-log-file/package-lock.json index f686e90..1fedba7 100644 --- a/02-filter-a-log-file/package-lock.json +++ b/02-filter-a-log-file/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "BSD", "dependencies": { + "asciichart": "^1.5.25", "ava": "^4.3.1", "commander": "^9.4.0", "date-fns": "^2.29.1", @@ -159,6 +160,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/asciichart": { + "version": "1.5.25", + "resolved": "https://registry.npmjs.org/asciichart/-/asciichart-1.5.25.tgz", + "integrity": "sha512-PNxzXIPPOtWq8T7bgzBtk9cI2lgS4SJZthUHEiQ1aoIc3lNzGfUvIvo9LiAnq26TACo9t1/4qP6KTGAUbzX9Xg==" + }, "node_modules/ava": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/ava/-/ava-4.3.1.tgz", @@ -1929,6 +1935,11 @@ "resolved": "https://registry.npmjs.org/arrify/-/arrify-3.0.0.tgz", "integrity": "sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==" }, + "asciichart": { + "version": "1.5.25", + "resolved": "https://registry.npmjs.org/asciichart/-/asciichart-1.5.25.tgz", + "integrity": "sha512-PNxzXIPPOtWq8T7bgzBtk9cI2lgS4SJZthUHEiQ1aoIc3lNzGfUvIvo9LiAnq26TACo9t1/4qP6KTGAUbzX9Xg==" + }, "ava": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/ava/-/ava-4.3.1.tgz", diff --git a/02-filter-a-log-file/package.json b/02-filter-a-log-file/package.json index b9e990c..7d999e4 100644 --- a/02-filter-a-log-file/package.json +++ b/02-filter-a-log-file/package.json @@ -10,6 +10,7 @@ "author": "", "license": "BSD", "dependencies": { + "asciichart": "^1.5.25", "ava": "^4.3.1", "commander": "^9.4.0", "date-fns": "^2.29.1",