Skip to content

Instantly share code, notes, and snippets.

@tokland
Created April 29, 2021 08:06
Show Gist options
  • Save tokland/bef28cd748841334aa49a79987196ca3 to your computer and use it in GitHub Desktop.
Save tokland/bef28cd748841334aa49a79987196ca3 to your computer and use it in GitHub Desktop.
Get some simple stats from a HAR file
import _ from "lodash";
import fs from "fs";
import crypto from "crypto";
import { Har } from "har-format";
function getMd5(data: string) {
return crypto.createHash("md5").update(data).digest("hex");
}
interface Request {
index: number;
method: string;
url: string;
time: number;
reqSize: number;
resSize: number;
requestHash: string;
responseHash: string;
}
function getRequestHash(req: Request) {
return getMd5([req.method, req.url, req.responseHash].join("-"));
}
function requestToString(req: Request): string {
const prefix = `${req.index} ${req.method} ${req.url.replace(/\?.*$/, "")}`;
return [
`${prefix} [${req.time.toFixed(0)} ms]`,
req.method === "POST" ? `[req=${(req.reqSize / 1024).toFixed(1)} Kb]` : "",
`[res=${(req.resSize / 1024).toFixed(2)} Kb] [${req.responseHash.slice(0, 8)}]`,
]
.filter(Boolean)
.join(" ");
}
function getRequestsFromHar(har: Har): Request[] {
return har.log.entries.map(
(entry, index): Request => {
const { request, response } = entry;
return {
index,
method: request.method,
url: request.url,
time: entry.time,
reqSize: request.postData?.text?.length || 0,
resSize: response.content.size,
requestHash: getMd5(request.postData?.text || ""),
responseHash: getMd5(response.content.text || ""),
};
}
);
}
function printRequest(req: Request): void {
console.log(requestToString(req));
}
function checkHar(harPath: string) {
const contents = fs.readFileSync(harPath, "utf8");
const har = JSON.parse(contents) as Har;
const requests = getRequestsFromHar(har);
console.log("= By time");
_(requests)
.sortBy(request => request.time)
.takeRight(10)
.each(printRequest);
console.log("\n= By size");
_(requests)
.sortBy(request => request.resSize)
.takeRight(10)
.each(printRequest);
const totalSize = _(requests)
.map(req => req.resSize)
.sum();
const totalTime = _(requests)
.map(req => req.time)
.sum();
console.log("\n= By request hash + time");
_(requests)
.groupBy(getRequestHash)
.toPairs()
.sortBy(([_hash, reqs]) => {
/* return reqs.length */
return _(reqs)
.map(req => req.time)
.sum();
})
.takeRight(10)
.each(([hash, reqs]) => {
console.log(hash.slice(0, 8));
reqs.forEach(req => {
console.log(" " + requestToString(req));
});
});
console.log(
`\ntotalSize=${(totalSize / 1e6).toFixed(0)} Mb, totalTime=${(totalTime / 1000).toFixed(
2
)} s`
);
}
const [harPath] = process.argv.slice(2);
checkHar(harPath);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment