@autter/runtime-node 1.6.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -5
- package/dist/{chunk-4MVWIRBI.cjs → chunk-GYTQLITW.cjs} +38 -1
- package/dist/{chunk-7OTD2YPT.cjs → chunk-HKVFURYT.cjs} +11 -11
- package/dist/{chunk-5KISVAVB.js → chunk-KA4AOZX2.js} +1 -1
- package/dist/{chunk-HRDELHZP.js → chunk-LG52CW3V.js} +38 -1
- package/dist/{chunk-L5ENELB2.js → chunk-QUC6OUE7.js} +1 -1
- package/dist/{chunk-UXTIMS3G.cjs → chunk-RV4MJNM2.cjs} +7 -7
- package/dist/cli.cjs +8 -8
- package/dist/cli.js +2 -2
- package/dist/index.cjs +236 -175
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +72 -11
- package/dist/testing.cjs +8 -8
- package/dist/testing.js +2 -2
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -198,8 +198,9 @@ type RuntimeContextHandle = typeof runtimeContext;
|
|
|
198
198
|
* call)
|
|
199
199
|
* successful traces : 1% (head sampling, configurable)
|
|
200
200
|
* request metrics : aggregated every 60 s, keyed by route
|
|
201
|
-
* template (Express routes
|
|
202
|
-
* out of the box — see
|
|
201
|
+
* template (Express and Next.js routes
|
|
202
|
+
* detected out of the box — see
|
|
203
|
+
* captureRequestRoute, route-label.ts)
|
|
203
204
|
* operation / request summaries: 100% (withRuntimeOperation,
|
|
204
205
|
* autterRequests, … — one wide
|
|
205
206
|
* record per unit of work, never
|
package/dist/index.d.ts
CHANGED
|
@@ -198,8 +198,9 @@ type RuntimeContextHandle = typeof runtimeContext;
|
|
|
198
198
|
* call)
|
|
199
199
|
* successful traces : 1% (head sampling, configurable)
|
|
200
200
|
* request metrics : aggregated every 60 s, keyed by route
|
|
201
|
-
* template (Express routes
|
|
202
|
-
* out of the box — see
|
|
201
|
+
* template (Express and Next.js routes
|
|
202
|
+
* detected out of the box — see
|
|
203
|
+
* captureRequestRoute, route-label.ts)
|
|
203
204
|
* operation / request summaries: 100% (withRuntimeOperation,
|
|
204
205
|
* autterRequests, … — one wide
|
|
205
206
|
* record per unit of work, never
|
package/dist/index.js
CHANGED
|
@@ -45,10 +45,10 @@ import {
|
|
|
45
45
|
splitFingerprint,
|
|
46
46
|
toClientError,
|
|
47
47
|
withRuntimeOperation
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-KA4AOZX2.js";
|
|
49
49
|
import {
|
|
50
50
|
runDoctor
|
|
51
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-QUC6OUE7.js";
|
|
52
52
|
import {
|
|
53
53
|
COMPAT_MANIFEST,
|
|
54
54
|
CountingExporter,
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
sharedSlot,
|
|
71
71
|
telemetryStats,
|
|
72
72
|
unregisterFlushTargets
|
|
73
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-LG52CW3V.js";
|
|
74
74
|
|
|
75
75
|
// src/relay.ts
|
|
76
76
|
var IpWindow = class {
|
|
@@ -441,6 +441,9 @@ function createBrowserRelayHandler(opts) {
|
|
|
441
441
|
}
|
|
442
442
|
|
|
443
443
|
// src/server.ts
|
|
444
|
+
import { errorMonitor } from "events";
|
|
445
|
+
import { createRequire } from "module";
|
|
446
|
+
import { join } from "path";
|
|
444
447
|
import { ServerResponse } from "http";
|
|
445
448
|
import { randomUUID } from "crypto";
|
|
446
449
|
import {
|
|
@@ -450,7 +453,7 @@ import {
|
|
|
450
453
|
SpanStatusCode,
|
|
451
454
|
TraceFlags
|
|
452
455
|
} from "@opentelemetry/api";
|
|
453
|
-
import { getRPCMetadata as
|
|
456
|
+
import { getRPCMetadata as getRPCMetadata3, RPCType as RPCType3 } from "@opentelemetry/core";
|
|
454
457
|
import {
|
|
455
458
|
AggregationTemporalityPreference,
|
|
456
459
|
OTLPMetricExporter
|
|
@@ -1276,6 +1279,40 @@ function installUnhandledRejectionCapture(capture, mode = unhandledRejectionsMod
|
|
|
1276
1279
|
};
|
|
1277
1280
|
}
|
|
1278
1281
|
|
|
1282
|
+
// src/route-label.ts
|
|
1283
|
+
import { getRPCMetadata as getRPCMetadata2, RPCType as RPCType2 } from "@opentelemetry/core";
|
|
1284
|
+
var ours = /* @__PURE__ */ new WeakMap();
|
|
1285
|
+
var RAW_PATH_SPAN_TYPES = /* @__PURE__ */ new Set(["BaseServer.renderToResponse"]);
|
|
1286
|
+
function noteFrameworkRoute(parent, attributes) {
|
|
1287
|
+
const route = attributes?.["next.route"];
|
|
1288
|
+
if (typeof route !== "string" || !route.startsWith("/")) return;
|
|
1289
|
+
if (RAW_PATH_SPAN_TYPES.has(String(attributes?.["next.span_type"] ?? ""))) return;
|
|
1290
|
+
const rpc = getRPCMetadata2(parent);
|
|
1291
|
+
if (!rpc || rpc.type !== RPCType2.HTTP) return;
|
|
1292
|
+
const mine = ours.get(rpc);
|
|
1293
|
+
if (rpc.route !== void 0 && rpc.route !== mine) return;
|
|
1294
|
+
if (mine !== void 0 && mine.includes("[") && !route.includes("[")) return;
|
|
1295
|
+
if (mine !== void 0 && (route === `${mine}/route` || route === `${mine}/page`)) return;
|
|
1296
|
+
rpc.route = route;
|
|
1297
|
+
ours.set(rpc, route);
|
|
1298
|
+
}
|
|
1299
|
+
var RouteLabelSampler = class {
|
|
1300
|
+
constructor(delegate) {
|
|
1301
|
+
this.delegate = delegate;
|
|
1302
|
+
}
|
|
1303
|
+
delegate;
|
|
1304
|
+
shouldSample(ctx, traceId, spanName, spanKind, attributes, links) {
|
|
1305
|
+
try {
|
|
1306
|
+
noteFrameworkRoute(ctx, attributes);
|
|
1307
|
+
} catch {
|
|
1308
|
+
}
|
|
1309
|
+
return this.delegate.shouldSample(ctx, traceId, spanName, spanKind, attributes, links);
|
|
1310
|
+
}
|
|
1311
|
+
toString() {
|
|
1312
|
+
return `RouteLabel(${this.delegate.toString()})`;
|
|
1313
|
+
}
|
|
1314
|
+
};
|
|
1315
|
+
|
|
1279
1316
|
// src/server.ts
|
|
1280
1317
|
var S = sharedSlot("server", () => ({
|
|
1281
1318
|
active: null,
|
|
@@ -1597,17 +1634,33 @@ function recordError(span, err) {
|
|
|
1597
1634
|
function redactWithActive(attributes) {
|
|
1598
1635
|
return S.redactor(attributes);
|
|
1599
1636
|
}
|
|
1600
|
-
function
|
|
1637
|
+
function patchLoadedHttpModules() {
|
|
1638
|
+
try {
|
|
1639
|
+
const load = createRequire(join(process.cwd(), "autter-runtime-http.cjs"));
|
|
1640
|
+
load("http");
|
|
1641
|
+
load("https");
|
|
1642
|
+
} catch {
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
var METRIC_ROUTE_ATTR = "autter.metric_has_route";
|
|
1646
|
+
function captureRequestRoute(span, response) {
|
|
1601
1647
|
if (!(response instanceof ServerResponse)) return;
|
|
1602
|
-
const rpcMetadata =
|
|
1603
|
-
if (rpcMetadata?.type !==
|
|
1648
|
+
const rpcMetadata = getRPCMetadata3(context2.active());
|
|
1649
|
+
if (rpcMetadata?.type !== RPCType3.HTTP) return;
|
|
1650
|
+
let failed = false;
|
|
1651
|
+
response.on(errorMonitor, () => {
|
|
1652
|
+
failed = true;
|
|
1653
|
+
});
|
|
1604
1654
|
const setRoute = () => {
|
|
1605
1655
|
if (rpcMetadata.route) return;
|
|
1606
1656
|
const route = expressRouteOf(response.req);
|
|
1607
1657
|
if (route) rpcMetadata.route = route;
|
|
1608
1658
|
};
|
|
1609
1659
|
response.prependListener("finish", setRoute);
|
|
1610
|
-
response.prependListener("close",
|
|
1660
|
+
response.prependListener("close", () => {
|
|
1661
|
+
setRoute();
|
|
1662
|
+
if (rpcMetadata.route && !failed) span.setAttribute(METRIC_ROUTE_ATTR, true);
|
|
1663
|
+
});
|
|
1611
1664
|
if (S.hookRequests) startHookRequest(response);
|
|
1612
1665
|
}
|
|
1613
1666
|
function structuredErrorAttributes(error) {
|
|
@@ -1656,8 +1709,14 @@ function initAutterServer(options) {
|
|
|
1656
1709
|
"telemetry.distro.version": distro.version,
|
|
1657
1710
|
// Tells the ingester request metrics arrive on the metrics pipe, so
|
|
1658
1711
|
// it must not also fold our server spans into usage rollups (that
|
|
1659
|
-
// would double-count every sampled request)
|
|
1660
|
-
"autter.metrics_wired": true
|
|
1712
|
+
// would double-count every sampled request)...
|
|
1713
|
+
"autter.metrics_wired": true,
|
|
1714
|
+
// ...for the requests whose metric carries their route: those
|
|
1715
|
+
// request spans say so (`autter.metric_has_route`, see
|
|
1716
|
+
// captureRequestRoute). Ingesters honour metrics_wired only with
|
|
1717
|
+
// this, so an older SDK, whose Next.js metrics have no route, keeps
|
|
1718
|
+
// its span-fed per-route counts.
|
|
1719
|
+
"autter.metrics_routes": true
|
|
1661
1720
|
});
|
|
1662
1721
|
const rootSampler = new TraceIdRatioBasedSampler(options.traceSampleRate ?? 0.01);
|
|
1663
1722
|
const headSampler = new ParentBasedSampler({
|
|
@@ -1674,6 +1733,7 @@ function initAutterServer(options) {
|
|
|
1674
1733
|
const retainTraces = retainOnError || slowThresholdMs > 0;
|
|
1675
1734
|
let sampler = retainTraces ? new RecordUnsampledSampler(headSampler) : headSampler;
|
|
1676
1735
|
if (options.llmTracing !== false) sampler = new LlmAwareSampler(sampler);
|
|
1736
|
+
sampler = new RouteLabelSampler(sampler);
|
|
1677
1737
|
const errorTraceBuffer = retainTraces ? new ErrorTraceRetentionProcessor(
|
|
1678
1738
|
new BatchSpanProcessor(traceExporter(), { scheduledDelayMillis: 2e3 }),
|
|
1679
1739
|
retainOnError,
|
|
@@ -1712,11 +1772,12 @@ function initAutterServer(options) {
|
|
|
1712
1772
|
) })
|
|
1713
1773
|
],
|
|
1714
1774
|
instrumentations: [
|
|
1715
|
-
new HttpInstrumentation({ responseHook:
|
|
1775
|
+
new HttpInstrumentation({ responseHook: captureRequestRoute }),
|
|
1716
1776
|
...options.instrumentations ?? []
|
|
1717
1777
|
]
|
|
1718
1778
|
});
|
|
1719
1779
|
sdk.start();
|
|
1780
|
+
patchLoadedHttpModules();
|
|
1720
1781
|
const stopMemoryMetrics = options.memoryMetrics === false ? null : startMemoryMetrics();
|
|
1721
1782
|
noteCompatFeature("endpoint_latency");
|
|
1722
1783
|
if (stopMemoryMetrics) noteCompatFeature("memory_metrics");
|
package/dist/testing.cjs
CHANGED
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
var
|
|
6
|
-
require('./chunk-
|
|
5
|
+
var _chunkRV4MJNM2cjs = require('./chunk-RV4MJNM2.cjs');
|
|
6
|
+
require('./chunk-GYTQLITW.cjs');
|
|
7
7
|
|
|
8
8
|
// src/testing.ts
|
|
9
9
|
function captureRuntime() {
|
|
10
|
-
const sink =
|
|
11
|
-
const remove =
|
|
10
|
+
const sink = _chunkRV4MJNM2cjs.memorySink.call(void 0, );
|
|
11
|
+
const remove = _chunkRV4MJNM2cjs.addRuntimeSink.call(void 0, sink);
|
|
12
12
|
return {
|
|
13
13
|
get events() {
|
|
14
14
|
return [...sink.events];
|
|
15
15
|
},
|
|
16
16
|
get operations() {
|
|
17
|
-
return sink.events.filter(
|
|
17
|
+
return sink.events.filter(_chunkRV4MJNM2cjs.isSummary);
|
|
18
18
|
},
|
|
19
19
|
get logs() {
|
|
20
|
-
return sink.events.filter((event) => !
|
|
20
|
+
return sink.events.filter((event) => !_chunkRV4MJNM2cjs.isSummary.call(void 0, event));
|
|
21
21
|
},
|
|
22
22
|
get exceptions() {
|
|
23
23
|
return [...sink.exceptions];
|
|
@@ -98,7 +98,7 @@ var OperationExpectation = class {
|
|
|
98
98
|
}
|
|
99
99
|
};
|
|
100
100
|
function expectOperation(source, name) {
|
|
101
|
-
const events = Array.isArray(source) ? source.filter(
|
|
101
|
+
const events = Array.isArray(source) ? source.filter(_chunkRV4MJNM2cjs.isSummary) : source.operations;
|
|
102
102
|
const matches = events.filter((event2) => {
|
|
103
103
|
const actual = String(_nullishCoalesce(event2.attributes["autter.operation.name"], () => ( "")));
|
|
104
104
|
return typeof name === "string" ? actual === name : name.test(actual);
|
|
@@ -118,4 +118,4 @@ function expectOperation(source, name) {
|
|
|
118
118
|
|
|
119
119
|
|
|
120
120
|
|
|
121
|
-
exports.captureRuntime = captureRuntime; exports.expectOperation = expectOperation; exports.memorySink =
|
|
121
|
+
exports.captureRuntime = captureRuntime; exports.expectOperation = expectOperation; exports.memorySink = _chunkRV4MJNM2cjs.memorySink;
|
package/dist/testing.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autter/runtime-node",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Autter Runtime for Node.js: request wide events, coded errors, operation logging, same-origin browser relay and a curated OpenTelemetry server tracker",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|