typestar

tail-log.js in JavaScript

Summarize an access log from a file or stdin.

#!/usr/bin/env node
// Summarize an access log read from a file or stdin.
import { readFileSync } from "node:fs";

const LINE = /"(?:GET|POST) (\S+)[^"]*" (\d{3}) (\d+)/;

function summarize(text) {
  const statuses = new Map();
  const paths = new Map();
  let bytes = 0;
  for (const line of text.split("\n")) {
    const match = line.match(LINE);
    if (!match) continue;
    const [, path, status, size] = match;
    statuses.set(status, (statuses.get(status) ?? 0) + 1);
    paths.set(path, (paths.get(path) ?? 0) + 1);
    bytes += Number(size);
  }
  return { statuses, paths, bytes };
}

const source = process.argv[2];
const text = readFileSync(source ?? 0, "utf8");
const { statuses, paths, bytes } = summarize(text);

console.log("status codes:", Object.fromEntries(statuses));
console.log("top paths:");
const top = [...paths].sort((a, b) => b[1] - a[1]).slice(0, 3);
for (const [path, hits] of top) {
  console.log(`  ${String(hits).padStart(4)}  ${path}`);
}
console.log(`${bytes.toLocaleString()} bytes served`);

How it works

  1. A regex pulls path, status, and byte size per line.
  2. Maps tally statuses and path frequencies.
  3. The top paths and total bytes print as a report.

Keywords and builtins used here

The run, in numbers

Lines
32
Characters to type
990
Tokens
283
Three-star pace
110 tpm

At the three-star pace of 110 tokens a minute, this run takes about 154 seconds.

Type this snippet

Step 1 of 1 in Encore, step 16 of 16 in Functions & patterns.

← Previous