Skip to content
134 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import test from "node:test";
3
4import { OTLP_DOOR, readLogs, readMetrics, readTraces } from "./normalize.ts";
5import { projectOfToken } from "./ingest.ts";
6
7const resource = (attrs: Record<string, string>) => ({ attributes: Object.entries(attrs).map(([key, v]) => ({ key, value: { stringValue: v } })) });
8
9test("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
59test("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
77test("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
104test("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
130test("a token names its project", () => {
131 assert.equal(projectOfToken("g1to_prj_01J9ZK3_abcdef0123"), "prj_01J9ZK3");
132 assert.equal(projectOfToken("g1t_prj_x_y"), null);
133 assert.equal(projectOfToken("g1to_nounderscore"), null);
134});