Skip to content
51 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Projects have Observability: their requests, logs, traces, metrics and errors, from apps on g1t.page with nothing to set up, and from software anywhere else over OpenTelemetry.1import assert from "node:assert/strict";
2import test from "node:test";
3
4import { fingerprint, messageShape, topFrame } from "./errors.ts";
5import { bucketOf, decode, encode, percentiles, quantile } from "./histogram.ts";
6import { hexId, nanosToMicros, route, severityNumber, severityOf } from "./shape.ts";
7
8test("routes lose their ids, keep their words", () => {
9 assert.equal(route("/users/42/posts"), "/users/:id/posts");
10 assert.equal(route("/o/3f2504e0-4f89-11d3-9a0c-0305e82c3301?x=1"), "/o/:id");
11 assert.equal(route("/blob/4bf92f3577b34da6a3ce/readme"), "/blob/:id/readme");
12 assert.equal(route("/assets/app.css"), "/assets/app.css");
13 assert.equal(route("/"), "/");
14 assert.equal(route("/settings/profile"), "/settings/profile");
15});
16
17test("severities", () => {
18 assert.equal(severityOf(severityNumber("warn")), "warn");
19 assert.equal(severityOf(severityNumber("log")), "info");
20 assert.equal(severityOf(severityNumber("CRITICAL")), "fatal");
21 assert.equal(severityOf(0), "info");
22 assert.equal(severityOf(3), "trace");
23});
24
25test("ids and times", () => {
26 assert.equal(hexId("AAAAAAAAAAAAAAAAAAAAAA==", 32), null);
27 assert.equal(hexId("S/kvNXezTaajzpKdDg5HNg==", 32), "4bf92f3577b34da6a3ce929d0e0e4736");
28 assert.equal(hexId("ABCDEF0123456789", 16), "abcdef0123456789");
29 assert.equal(nanosToMicros("1760000000123456789"), 1_760_000_000_123_456);
30 assert.equal(nanosToMicros("0"), null);
31});
32
33test("percentiles come from bucket counts, within a bucket of the truth", () => {
34 const counts = decode("");
35 for (let i = 1; i <= 100; i++) counts[bucketOf(i)]++;
36 const p = percentiles(counts);
37 assert.ok(p.p50! >= 30 && p.p50! <= 75, `p50 ${p.p50}`);
38 assert.ok(p.p99! >= 75 && p.p99! <= 100, `p99 ${p.p99}`);
39 assert.deepEqual(decode(encode(counts)), counts);
40 assert.equal(quantile(decode(""), 0.5), null);
41});
42
43test("the same error thrown with different ids is one group", async () => {
44 const a = await fingerprint("TypeError", "Cannot read 'name' of user 41", "TypeError\n at load (src/user.ts:10:5)", "api");
45 const b = await fingerprint("TypeError", "Cannot read 'email' of user 977", "TypeError\n at load (src/user.ts:12:9)", "api");
46 const c = await fingerprint("TypeError", "Cannot read 'name' of user 41", "TypeError\n at save (src/user.ts:10:5)", "api");
47 assert.equal(a, b);
48 assert.notEqual(a, c);
49 assert.equal(messageShape('fetch https://x.y/z failed with 503 for "abc"'), 'fetch <url> failed with # for "…"');
50 assert.equal(topFrame("Error\n at f (node_modules/lib/index.js:1:1)\n at g (src/app.ts:4:2)"), "g src/app.ts");
51});