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. | 1 | import assert from "node:assert/strict"; |
| 2 | import test from "node:test"; | |
| 3 | ||
| 4 | import { OTLP_DOOR, readLogs, readMetrics, readTraces } from "./normalize.ts"; | |
| 5 | import { projectOfToken } from "./ingest.ts"; | |
| 6 | ||
| 7 | const resource = (attrs: Record<string, string>) => ({ attributes: Object.entries(attrs).map(([key, v]) => ({ key, value: { stringValue: v } })) }); | |
| 8 | ||
| 9 | test("a server span is a request, filed under its service and environment", () => { | |
| 10 | const batch = readTraces( | |
| 11 | { | |
| 12 | resourceSpans: [ | |
| 13 | { | |
| 14 | resource: resource({ "service.name": "billing", "deployment.environment.name": "production", "vcs.ref.head.revision": "abc123" }), | |
| 15 | scopeSpans: [ | |
| 16 | { | |
| 17 | spans: [ | |
| 18 | { | |
| 19 | traceId: "4bf92f3577b34da6a3ce929d0e0e4736", | |
| 20 | spanId: "00f067aa0ba902b7", | |
| 21 | name: "POST", | |
| 22 | kind: 2, | |
| 23 | startTimeUnixNano: "1760000000000000000", | |
| 24 | endTimeUnixNano: "1760000000120000000", | |
| 25 | attributes: [ | |
| 26 | { key: "http.request.method", value: { stringValue: "POST" } }, | |
| 27 | { key: "url.path", value: { stringValue: "/invoices/12345" } }, | |
| 28 | { key: "http.response.status_code", value: { intValue: "502" } }, | |
| 29 | ], | |
| 30 | events: [{ name: "exception", timeUnixNano: "1760000000100000000", attributes: [{ key: "exception.type", value: { stringValue: "UpstreamError" } }] }], | |
| 31 | status: { code: 2, message: "upstream refused" }, | |
| 32 | }, | |
| 33 | // Ids of zeros are no ids: the span is dropped. | |
| 34 | { traceId: "00000000000000000000000000000000", spanId: "0000000000000000", startTimeUnixNano: "1" }, | |
| 35 | ], | |
| 36 | }, | |
| 37 | ], | |
| 38 | }, | |
| 39 | ], | |
| 40 | }, | |
| 41 | OTLP_DOOR, | |
| 42 | 100, | |
| 43 | ); | |
| 44 | assert.equal(batch.spans.length, 1); | |
| 45 | const span = batch.spans[0]; | |
| 46 | assert.equal(span.service, "billing"); | |
| 47 | assert.equal(span.environment, "production"); | |
| 48 | assert.equal(span.commit_sha, "abc123"); | |
| 49 | assert.equal(span.start_us, 1_760_000_000_000_000); | |
| 50 | assert.equal(span.duration_us, 120_000); | |
| 51 | assert.equal(span.status, "error"); | |
| 52 | assert.equal(batch.requests.length, 1); | |
| 53 | assert.equal(batch.requests[0].route, "/invoices/:id"); | |
| 54 | assert.equal(batch.requests[0].status, 502); | |
| 55 | assert.equal(batch.requests[0].outcome, "error"); | |
| 56 | assert.equal(batch.errors[0].name, "UpstreamError"); | |
| 57 | }); | |
| 58 | ||
| 59 | test("an app on g1t.page has its requests counted from its tail events, not its SDK's spans", () => { | |
| 60 | const batch = readTraces( | |
| 61 | { | |
| 62 | resourceSpans: [ | |
| 63 | { | |
| 64 | resource: resource({ "service.name": "web", "g1t.deployment.id": "dep_1" }), | |
| 65 | scopeSpans: [{ spans: [{ traceId: "4bf92f3577b34da6a3ce929d0e0e4736", spanId: "00f067aa0ba902b7", kind: "SPAN_KIND_SERVER" as never, startTimeUnixNano: "1760000000000000000" }] }], | |
| 66 | }, | |
| 67 | ], | |
| 68 | }, | |
| 69 | OTLP_DOOR, | |
| 70 | 0, | |
| 71 | ); | |
| 72 | assert.equal(batch.spans[0].kind, "server"); | |
| 73 | assert.equal(batch.spans[0].deployment_id, "dep_1"); | |
| 74 | assert.equal(batch.requests.length, 0); | |
| 75 | }); | |
| 76 | ||
| 77 | test("log records keep their severity, body and trace", () => { | |
| 78 | const batch = readLogs( | |
| 79 | { | |
| 80 | resourceLogs: [ | |
| 81 | { | |
| 82 | resource: resource({ "service.name": "worker" }), | |
| 83 | scopeLogs: [ | |
| 84 | { | |
| 85 | logRecords: [ | |
| 86 | { timeUnixNano: "1760000000000000000", severityText: "warning", body: { stringValue: "slow" } }, | |
| 87 | { observedTimeUnixNano: "1760000000000000000", severityNumber: 17, body: { kvlistValue: { values: [{ key: "a", value: { intValue: "1" } }] } }, attributes: [{ key: "exception.type", value: { stringValue: "Boom" } }] }, | |
| 88 | ], | |
| 89 | }, | |
| 90 | ], | |
| 91 | }, | |
| 92 | ], | |
| 93 | }, | |
| 94 | OTLP_DOOR, | |
| 95 | 0, | |
| 96 | ); | |
| 97 | assert.equal(batch.logs[0].severity, "warn"); | |
| 98 | assert.equal(batch.logs[0].body, "slow"); | |
| 99 | assert.equal(batch.logs[1].severity, "error"); | |
| 100 | assert.equal(batch.logs[1].body, '{"a":1}'); | |
| 101 | assert.equal(batch.errors.length, 1); | |
| 102 | }); | |
| 103 | ||
| 104 | test("metrics of each kind become points", () => { | |
| 105 | const batch = readMetrics( | |
| 106 | { | |
| 107 | resourceMetrics: [ | |
| 108 | { | |
| 109 | resource: resource({ "service.name": "api" }), | |
| 110 | scopeMetrics: [ | |
| 111 | { | |
| 112 | metrics: [ | |
| 113 | { name: "queue.depth", gauge: { dataPoints: [{ timeUnixNano: "1760000000000000000", asInt: "7" }] } }, | |
| 114 | { name: "jobs", sum: { aggregationTemporality: 2, isMonotonic: true, dataPoints: [{ timeUnixNano: "1760000000000000000", asDouble: 3 }] } }, | |
| 115 | { name: "latency", unit: "ms", histogram: { dataPoints: [{ timeUnixNano: "1760000000000000000", count: "4", sum: 40, explicitBounds: [10], bucketCounts: ["2", "2"] }] } }, | |
| 116 | ], | |
| 117 | }, | |
| 118 | ], | |
| 119 | }, | |
| 120 | ], | |
| 121 | }, | |
| 122 | OTLP_DOOR, | |
| 123 | 0, | |
| 124 | ); | |
| 125 | assert.deepEqual(batch.metrics.map((m) => [m.name, m.kind, m.value]), [["queue.depth", "gauge", 7], ["jobs", "sum", 3], ["latency", "histogram", 10]]); | |
| 126 | assert.equal(batch.metrics[1].monotonic, true); | |
| 127 | assert.deepEqual(batch.metrics[2].counts, [2, 2]); | |
| 128 | }); | |
| 129 | ||
| 130 | test("a token names its project", () => { | |
| Merge main into rm-agents: mirroring removal, open signups, free-tier limits, the g1t CLI and runner fixes, with the agent removal kept. The CLI's table of operations is regenerated from the API without the agent, customize and AI credit operations; no CLI command used them. | 131 | assert.equal(projectOfToken("g1to_prj_01jb2k7x9hfq0b3zj0f5s2m8ra_abcdef0123"), "prj_01jb2k7x9hfq0b3zj0f5s2m8ra"); |
| 132 | // Only a project id as g1t makes them: anything else never reaches a store. | |
| 133 | assert.equal(projectOfToken("g1to_prj_01J9ZK3_abcdef0123"), null); | |
| 134 | assert.equal(projectOfToken("g1to_anything-at-all_abcdef0123"), null); | |
| 135 | assert.equal(projectOfToken("g1to_prj_01jb2k7x9hfq0b3zj0f5s2m8rax_abcdef0123"), null); | |
| 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. | 136 | assert.equal(projectOfToken("g1t_prj_x_y"), null); |
| 137 | assert.equal(projectOfToken("g1to_nounderscore"), null); | |
| 138 | }); |
This file's history is long; its oldest lines are credited to the oldest commit read.