@autter/runtime-node 1.6.1 → 1.8.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 CHANGED
@@ -242,6 +242,40 @@ when the error was already reported). Errors from another JavaScript realm
242
242
  message and stack. `autterErrorResponse()` reports the same way and also
243
243
  answers the request.
244
244
 
245
+ ### Sample and ignore errors (1.8.0)
246
+
247
+ ```ts
248
+ initAutterServer({
249
+ ...,
250
+ sampleRate: 0.5, // half of captured errors
251
+ ignoreErrors: ["ECONNRESET", /^AbortError$/, /^billing\.declined/],
252
+ });
253
+ ```
254
+
255
+ - `sampleRate` (0..1, default 1): the share of captured errors reported:
256
+ `captureException`, error-level `captureMessage` and `reportOutcome`.
257
+ Never a fatal message, a crash (uncaught exception) or an unhandled
258
+ rejection (which may be one); warnings and info are never sampled. Not
259
+ `traceSampleRate`, which samples healthy traces.
260
+ - `ignoreErrors`: never reported. A string matches when the error's type
261
+ (`error.name`) or message contains it (case-sensitive); a RegExp is tested
262
+ against the type, the message and `"<type>: <message>"`. Every capture
263
+ path, crashes included.
264
+ - A value filtered out is marked captured, so a later hook (error
265
+ middleware, `onRequestError`) does not report it either. A request that
266
+ failed still exports its failed span, which the ingester turns into a
267
+ stackless `HttpServerError` for a 5xx; leave those out with a
268
+ suppression rule.
269
+ - `initAutterLogging` takes the same two options; `registerAutter`
270
+ (`@autter/runtime-next`) passes them through.
271
+
272
+ What the SDK filters never leaves the process and is counted nowhere. For
273
+ volume control that is counted, applies to every SDK and service at once and
274
+ is changed without a deploy, use **suppression rules** in Autter's Runtime
275
+ settings (drop or sample by error type, message, service, environment,
276
+ route, release or source; ingester 1.9.0). The ingester also collapses a
277
+ looping error into one sample a minute with an exact count.
278
+
245
279
  ### Unhandled promise rejections
246
280
 
247
281
  Recorded as errors (severity `error`, `autter.unhandled_rejection: true`, not
@@ -317,11 +351,21 @@ silent loss. While wiring things up, set `debug: true` (or `AUTTER_DEBUG=1`)
317
351
  to see `[autter] exported N span(s)` lines on stderr as batches leave.
318
352
 
319
353
  Note on usage rollups: requests are counted from the `http.server.duration`
320
- metric (100% accurate) and additionally from sampled server spans. At the
321
- default 1% sampling the span contribution is negligible; if you set
322
- `traceSampleRate: 1` in development, expect request counts roughly doubled.
323
- Tail-retained error traces don't distort this: their spans carry
324
- `autter.tail_retained` and the ingester keeps them out of span-fed rollups.
354
+ metric (100% accurate), under their route template: Express routes and,
355
+ from 1.7.0, Next.js routes (`/blog/[slug]`, from the `next.route` Next puts
356
+ on its own spans). The SDK marks its resource `autter.metrics_wired` and
357
+ `autter.metrics_routes`, and each request span whose metric got a route
358
+ `autter.metric_has_route`; an up-to-date ingester then counts that request
359
+ from the metric alone, whatever `traceSampleRate` is. A request whose
360
+ metric has no route (Koa, Fastify or plain `http` without a router
361
+ instrumentation) is also counted from its sampled spans, which keep its
362
+ path. Ingesters up to 1.7.0 count every sampled server span on top of the
363
+ metric (at `traceSampleRate: 1`, about twice the requests), except
364
+ tail-retained error traces (`autter.tail_retained`). Since 1.7.0 the SDK
365
+ also applies the HTTP instrumentation to servers created before
366
+ `initAutterServer` (Next.js creates its server before `instrumentation.ts`
367
+ runs): until then a Next.js app got request spans and metrics only from
368
+ the first request that happened to load `http` again, if ever.
325
369
 
326
370
  ### Privacy: secrets and PII are scrubbed before they leave the process
327
371
 
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
 
5
- var _chunk4MVWIRBIcjs = require('./chunk-4MVWIRBI.cjs');
5
+ var _chunkMOZOUEMAcjs = require('./chunk-MOZOUEMA.cjs');
6
6
 
7
7
  // ../runtime-core/dist/index.js
8
8
  var SENSITIVE_KEY_PATTERNS = [
@@ -974,6 +974,43 @@ function splitFingerprint(attributes) {
974
974
  const { fingerprint, ...rest } = attributes;
975
975
  return { attributes: rest, fingerprint };
976
976
  }
977
+ function testPattern(pattern, type, message) {
978
+ if (typeof pattern === "string") {
979
+ return pattern !== "" && (message.includes(pattern) || type.includes(pattern));
980
+ }
981
+ if (!(pattern instanceof RegExp)) return false;
982
+ const re = pattern.global || pattern.sticky ? new RegExp(pattern.source, pattern.flags.replace(/[gy]/g, "")) : pattern;
983
+ return re.test(message) || type !== "" && (re.test(type) || re.test(`${type}: ${message}`));
984
+ }
985
+ function isIgnoredError(patterns, type, message) {
986
+ if (!_optionalChain([patterns, 'optionalAccess', _13 => _13.length])) return false;
987
+ for (const pattern of patterns) {
988
+ try {
989
+ if (testPattern(pattern, type, message)) return true;
990
+ } catch (e15) {
991
+ }
992
+ }
993
+ return false;
994
+ }
995
+ function effectiveSampleRate(rate) {
996
+ return typeof rate === "number" && Number.isFinite(rate) && rate >= 0 && rate < 1 ? rate : null;
997
+ }
998
+ function createErrorFilter(options = {}, random = Math.random) {
999
+ const patterns = Array.isArray(options.ignoreErrors) ? options.ignoreErrors.slice() : [];
1000
+ const rate = effectiveSampleRate(options.sampleRate);
1001
+ if (!patterns.length && rate === null) return () => true;
1002
+ return (input) => {
1003
+ try {
1004
+ if (isIgnoredError(patterns, _nullishCoalesce(input.type, () => ( "")), _nullishCoalesce(input.message, () => ( "")))) return false;
1005
+ if (rate === null || input.crash) return true;
1006
+ const severity = _nullishCoalesce(input.severity, () => ( "error"));
1007
+ if (severity !== "error") return true;
1008
+ return random() < rate;
1009
+ } catch (e16) {
1010
+ return true;
1011
+ }
1012
+ };
1013
+ }
977
1014
 
978
1015
  // src/breadcrumbs.ts
979
1016
  var _api = require('@opentelemetry/api');
@@ -994,7 +1031,7 @@ var _crypto = require('crypto');
994
1031
 
995
1032
  var _fs = require('fs');
996
1033
  var _path = require('path');
997
- var sinkStats = _chunk4MVWIRBIcjs.sharedSlot.call(void 0, "sinks", () => ({ dropped: 0 }));
1034
+ var sinkStats = _chunkMOZOUEMAcjs.sharedSlot.call(void 0, "sinks", () => ({ dropped: 0 }));
998
1035
  function otlpSink(options = {}) {
999
1036
  let context = null;
1000
1037
  let queue = [];
@@ -1070,7 +1107,7 @@ function otlpSink(options = {}) {
1070
1107
  Math.max(1, Math.min(3e3, deadline - Date.now()))
1071
1108
  )
1072
1109
  });
1073
- _chunk4MVWIRBIcjs.observeIngesterResponse.call(void 0, { status: response.status, headers: response.headers, route: "/v1/logs" });
1110
+ _chunkMOZOUEMAcjs.observeIngesterResponse.call(void 0, { status: response.status, headers: response.headers, route: "/v1/logs" });
1074
1111
  if (!response.ok)
1075
1112
  throw new Error(`Runtime log export failed (${response.status})`);
1076
1113
  failure = void 0;
@@ -1120,7 +1157,7 @@ function otlpSink(options = {}) {
1120
1157
  }
1121
1158
  queue.push({ record, bytes });
1122
1159
  queueBytes += bytes;
1123
- _chunk4MVWIRBIcjs.noteCompatFeature.call(void 0, "operation_logging");
1160
+ _chunkMOZOUEMAcjs.noteCompatFeature.call(void 0, "operation_logging");
1124
1161
  scheduleFlush();
1125
1162
  },
1126
1163
  flush,
@@ -1248,7 +1285,7 @@ function formatPretty(event, color = false) {
1248
1285
  }
1249
1286
  function consoleSink(options = {}) {
1250
1287
  const format = _nullishCoalesce(options.format, () => ( (process.env.NODE_ENV === "production" ? "json" : "pretty")));
1251
- const color = _nullishCoalesce(options.color, () => ( (_optionalChain([process, 'access', _13 => _13.stdout, 'optionalAccess', _14 => _14.isTTY]) === true && !process.env.NO_COLOR)));
1288
+ const color = _nullishCoalesce(options.color, () => ( (_optionalChain([process, 'access', _14 => _14.stdout, 'optionalAccess', _15 => _15.isTTY]) === true && !process.env.NO_COLOR)));
1252
1289
  const write = _nullishCoalesce(options.write, () => ( ((line) => console.log(line))));
1253
1290
  return {
1254
1291
  name: "console",
@@ -1293,14 +1330,14 @@ function fileSink(options = {}) {
1293
1330
  index = sameDay.length ? sameDay[sameDay.length - 1].index : 0;
1294
1331
  try {
1295
1332
  currentBytes = _fs.statSync.call(void 0, _path.join.call(void 0, dir, fileName(day, index))).size;
1296
- } catch (e15) {
1333
+ } catch (e17) {
1297
1334
  currentBytes = 0;
1298
1335
  }
1299
1336
  prune();
1300
1337
  };
1301
1338
  const disable = (error) => {
1302
1339
  disabled = true;
1303
- const code = _nullishCoalesce(_optionalChain([error, 'optionalAccess', _15 => _15.code]), () => ( "error"));
1340
+ const code = _nullishCoalesce(_optionalChain([error, 'optionalAccess', _16 => _16.code]), () => ( "error"));
1304
1341
  console.warn(
1305
1342
  `[autter-runtime] local runtime files disabled (${code} writing ${dir}); set logging.file: false to silence`
1306
1343
  );
@@ -1363,7 +1400,7 @@ function memorySink() {
1363
1400
  }
1364
1401
 
1365
1402
  // src/logger.ts
1366
- var shared = _chunk4MVWIRBIcjs.sharedSlot.call(void 0, "logger", () => ({
1403
+ var shared = _chunkMOZOUEMAcjs.sharedSlot.call(void 0, "logger", () => ({
1367
1404
  local: new (0, _async_hooks.AsyncLocalStorage)(),
1368
1405
  config: null,
1369
1406
  sinks: [],
@@ -1373,7 +1410,7 @@ var local = shared.local;
1373
1410
  var extraSinks = shared.extraSinks;
1374
1411
  var fallbackConsole = null;
1375
1412
  function redact(attributes) {
1376
- return _nullishCoalesce(_optionalChain([shared, 'access', _16 => _16.config, 'optionalAccess', _17 => _17.redact, 'call', _18 => _18(attributes)]), () => ( redactAttributes(attributes)));
1413
+ return _nullishCoalesce(_optionalChain([shared, 'access', _17 => _17.config, 'optionalAccess', _18 => _18.redact, 'call', _19 => _19(attributes)]), () => ( redactAttributes(attributes)));
1377
1414
  }
1378
1415
  var safe = (attributes = {}) => boundContext(attributes, redact);
1379
1416
  var merge = (current, next) => mergeContext(current, next, redact);
@@ -1412,12 +1449,12 @@ function traceAttributes(state) {
1412
1449
  }
1413
1450
  function emit(level, message, attributes, extra = {}, options = {}) {
1414
1451
  const state = options.state !== void 0 ? _nullishCoalesce(options.state, () => ( void 0)) : local.getStore();
1415
- if (_optionalChain([state, 'optionalAccess', _19 => _19.sealed])) return;
1452
+ if (_optionalChain([state, 'optionalAccess', _20 => _20.sealed])) return;
1416
1453
  const summary = extra["autter.event.type"] === "operation";
1417
1454
  if (!summary) recordLogBreadcrumb(level, message, attributes, state);
1418
- if (!summary && LEVEL_SEVERITY[level] < LEVEL_SEVERITY[_nullishCoalesce(_optionalChain([shared, 'access', _20 => _20.config, 'optionalAccess', _21 => _21.options, 'optionalAccess', _22 => _22.minLevel]), () => ( "debug"))])
1455
+ if (!summary && LEVEL_SEVERITY[level] < LEVEL_SEVERITY[_nullishCoalesce(_optionalChain([shared, 'access', _21 => _21.config, 'optionalAccess', _22 => _22.options, 'optionalAccess', _23 => _23.minLevel]), () => ( "debug"))])
1419
1456
  return;
1420
- if (!summary && state && _optionalChain([shared, 'access', _23 => _23.config, 'optionalAccess', _24 => _24.options, 'optionalAccess', _25 => _25.inline]) !== false) {
1457
+ if (!summary && state && _optionalChain([shared, 'access', _24 => _24.config, 'optionalAccess', _25 => _25.options, 'optionalAccess', _26 => _26.inline]) !== false) {
1421
1458
  const { "exception.stacktrace": _stack, ...inlineAttrs } = userContext(
1422
1459
  attributes,
1423
1460
  redact
@@ -1425,8 +1462,8 @@ function emit(level, message, attributes, extra = {}, options = {}) {
1425
1462
  appendInlineLog(state.inline, level, message, inlineAttrs, redact);
1426
1463
  if (level === "debug" || level === "info") return;
1427
1464
  }
1428
- const span = _nullishCoalesce(options.span, () => ( _optionalChain([_api.trace, 'access', _26 => _26.getActiveSpan, 'call', _27 => _27(), 'optionalAccess', _28 => _28.spanContext, 'call', _29 => _29()])));
1429
- const user = merge(_nullishCoalesce(_optionalChain([state, 'optionalAccess', _30 => _30.attributes]), () => ( {})), attributes);
1465
+ const span = _nullishCoalesce(options.span, () => ( _optionalChain([_api.trace, 'access', _27 => _27.getActiveSpan, 'call', _28 => _28(), 'optionalAccess', _29 => _29.spanContext, 'call', _30 => _30()])));
1466
+ const user = merge(_nullishCoalesce(_optionalChain([state, 'optionalAccess', _31 => _31.attributes]), () => ( {})), attributes);
1430
1467
  const exceptions = Object.fromEntries(
1431
1468
  Object.entries(user).filter(([key]) => key.startsWith("exception."))
1432
1469
  );
@@ -1437,8 +1474,8 @@ function emit(level, message, attributes, extra = {}, options = {}) {
1437
1474
  ...operationAttributes(state),
1438
1475
  ...user
1439
1476
  };
1440
- const enrichers = _optionalChain([shared, 'access', _31 => _31.config, 'optionalAccess', _32 => _32.options, 'optionalAccess', _33 => _33.enrich]);
1441
- if (summary && state && _optionalChain([enrichers, 'optionalAccess', _34 => _34.length])) {
1477
+ const enrichers = _optionalChain([shared, 'access', _32 => _32.config, 'optionalAccess', _33 => _33.options, 'optionalAccess', _34 => _34.enrich]);
1478
+ if (summary && state && _optionalChain([enrichers, 'optionalAccess', _35 => _35.length])) {
1442
1479
  const event2 = { level, message, attributes: raw };
1443
1480
  for (const enrich of enrichers) {
1444
1481
  try {
@@ -1447,7 +1484,7 @@ function emit(level, message, attributes, extra = {}, options = {}) {
1447
1484
  res: state.res,
1448
1485
  operation: { id: state.id, name: state.name, kind: state.kind }
1449
1486
  });
1450
- } catch (e16) {
1487
+ } catch (e18) {
1451
1488
  }
1452
1489
  }
1453
1490
  }
@@ -1460,7 +1497,7 @@ function emit(level, message, attributes, extra = {}, options = {}) {
1460
1497
  for (const sink of activeSinks()) {
1461
1498
  try {
1462
1499
  sink.write(event);
1463
- } catch (e17) {
1500
+ } catch (e19) {
1464
1501
  }
1465
1502
  }
1466
1503
  }
@@ -1469,7 +1506,7 @@ function configureRuntimeLogger(next) {
1469
1506
  shared.sinks = defaultSinks(next);
1470
1507
  for (const sink of shared.sinks) {
1471
1508
  try {
1472
- _optionalChain([sink, 'access', _35 => _35.start, 'optionalCall', _36 => _36({
1509
+ _optionalChain([sink, 'access', _36 => _36.start, 'optionalCall', _37 => _37({
1473
1510
  endpoint: next.endpoint,
1474
1511
  apiKey: next.apiKey,
1475
1512
  service: next.service,
@@ -1477,7 +1514,7 @@ function configureRuntimeLogger(next) {
1477
1514
  ...next.release ? { release: next.release } : {},
1478
1515
  ...next.distro ? { distro: next.distro } : {}
1479
1516
  })]);
1480
- } catch (e18) {
1517
+ } catch (e20) {
1481
1518
  }
1482
1519
  }
1483
1520
  }
@@ -1498,25 +1535,25 @@ function notifyException(error, attributes = {}) {
1498
1535
  type: isError(error) ? error.name : "Error",
1499
1536
  attributes: { ...attributes, ...errorAttributes(error) },
1500
1537
  ...state ? { operationId: state.id } : {},
1501
- ..._optionalChain([state, 'optionalAccess', _37 => _37.requestId]) ? { requestId: state.requestId } : {}
1538
+ ..._optionalChain([state, 'optionalAccess', _38 => _38.requestId]) ? { requestId: state.requestId } : {}
1502
1539
  };
1503
1540
  for (const sink of [...shared.sinks, ...extraSinks]) {
1504
1541
  try {
1505
- _optionalChain([sink, 'access', _38 => _38.exception, 'optionalCall', _39 => _39(record)]);
1506
- } catch (e19) {
1542
+ _optionalChain([sink, 'access', _39 => _39.exception, 'optionalCall', _40 => _40(record)]);
1543
+ } catch (e21) {
1507
1544
  }
1508
1545
  }
1509
1546
  }
1510
1547
  function runtimeLogStats() {
1511
1548
  return {
1512
- buffered: shared.sinks.reduce((sum, sink) => sum + (_nullishCoalesce(_optionalChain([sink, 'access', _40 => _40.buffered, 'optionalCall', _41 => _41()]), () => ( 0))), 0),
1549
+ buffered: shared.sinks.reduce((sum, sink) => sum + (_nullishCoalesce(_optionalChain([sink, 'access', _41 => _41.buffered, 'optionalCall', _42 => _42()]), () => ( 0))), 0),
1513
1550
  dropped: sinkStats.dropped
1514
1551
  };
1515
1552
  }
1516
1553
  async function flushRuntimeLogs() {
1517
1554
  if (!shared.config) return;
1518
1555
  const results = await Promise.allSettled(
1519
- shared.sinks.map((sink) => Promise.resolve().then(() => _optionalChain([sink, 'access', _42 => _42.flush, 'optionalCall', _43 => _43()])))
1556
+ shared.sinks.map((sink) => Promise.resolve().then(() => _optionalChain([sink, 'access', _43 => _43.flush, 'optionalCall', _44 => _44()])))
1520
1557
  );
1521
1558
  const failed = results.find((result) => result.status === "rejected");
1522
1559
  if (failed) throw failed.reason;
@@ -1524,7 +1561,7 @@ async function flushRuntimeLogs() {
1524
1561
  async function shutdownRuntimeLogger() {
1525
1562
  const active = shared.sinks;
1526
1563
  const results = await Promise.allSettled(
1527
- active.map((sink) => Promise.resolve().then(() => _optionalChain([sink, 'access', _44 => _44.shutdown, 'optionalCall', _45 => _45()])))
1564
+ active.map((sink) => Promise.resolve().then(() => _optionalChain([sink, 'access', _45 => _45.shutdown, 'optionalCall', _46 => _46()])))
1528
1565
  );
1529
1566
  shared.config = null;
1530
1567
  shared.sinks = [];
@@ -1565,7 +1602,7 @@ var runtimeLogger = createRuntimeLogger();
1565
1602
  function captureExceptionAsLog(error, attributes = {}) {
1566
1603
  const isErr = isError(error);
1567
1604
  const message = isErr ? error.message : String(error);
1568
- const stack = isErr && error.stack ? error.stack : _nullishCoalesce(_optionalChain([new Error(), 'access', _46 => _46.stack, 'optionalAccess', _47 => _47.split, 'call', _48 => _48("\n"), 'access', _49 => _49.filter, 'call', _50 => _50((line, i) => i === 0 || !/captureException/.test(line)), 'access', _51 => _51.join, 'call', _52 => _52("\n")]), () => ( ""));
1605
+ const stack = isErr && error.stack ? error.stack : _nullishCoalesce(_optionalChain([new Error(), 'access', _47 => _47.stack, 'optionalAccess', _48 => _48.split, 'call', _49 => _49("\n"), 'access', _50 => _50.filter, 'call', _51 => _51((line, i) => i === 0 || !/captureException/.test(line)), 'access', _52 => _52.join, 'call', _53 => _53("\n")]), () => ( ""));
1569
1606
  noteOperationError(error);
1570
1607
  emit(
1571
1608
  "error",
@@ -1619,7 +1656,7 @@ function operationHandle(state) {
1619
1656
  setContext: (attrs) => {
1620
1657
  if (!state.sealed) {
1621
1658
  state.attributes = merge(state.attributes, attrs);
1622
- _optionalChain([_api.trace, 'access', _53 => _53.getActiveSpan, 'call', _54 => _54(), 'optionalAccess', _55 => _55.setAttributes, 'call', _56 => _56(traceAttributes(state))]);
1659
+ _optionalChain([_api.trace, 'access', _54 => _54.getActiveSpan, 'call', _55 => _55(), 'optionalAccess', _56 => _56.setAttributes, 'call', _57 => _57(traceAttributes(state))]);
1623
1660
  }
1624
1661
  },
1625
1662
  outcome: (status, message) => setOutcome(state, status, message),
@@ -1679,7 +1716,7 @@ function emitSummary(state, options = {}) {
1679
1716
  }
1680
1717
  function reportExplicitFailure(state) {
1681
1718
  if (state.outcome === "failed" && state.explicitOutcome && !state.errorThrown)
1682
- _optionalChain([shared, 'access', _57 => _57.config, 'optionalAccess', _58 => _58.reportOutcome, 'call', _59 => _59(state.name, _nullishCoalesce(state.message, () => ( "Operation failed")), {
1719
+ _optionalChain([shared, 'access', _58 => _58.config, 'optionalAccess', _59 => _59.reportOutcome, 'call', _60 => _60(state.name, _nullishCoalesce(state.message, () => ( "Operation failed")), {
1683
1720
  ...traceAttributes(state),
1684
1721
  "autter.outcome.stack": _nullishCoalesce(state.reportingStack, () => ( ""))
1685
1722
  })]);
@@ -1687,7 +1724,7 @@ function reportExplicitFailure(state) {
1687
1724
  function startOperation(name, fn, attributes, options, internal = {}) {
1688
1725
  const parent = _nullishCoalesce(internal.forkParent, () => ( local.getStore()));
1689
1726
  const carrier = options.from ? parseCarrier(options.from) : null;
1690
- const traceparent = _optionalChain([carrier, 'optionalAccess', _60 => _60.traceparent]) ? parseTraceparent(carrier.traceparent) : null;
1727
+ const traceparent = _optionalChain([carrier, 'optionalAccess', _61 => _61.traceparent]) ? parseTraceparent(carrier.traceparent) : null;
1691
1728
  const linked = internal.forkParent !== void 0 || parent && !parent.sealed;
1692
1729
  const state = newState(
1693
1730
  name,
@@ -1699,7 +1736,7 @@ function startOperation(name, fn, attributes, options, internal = {}) {
1699
1736
  ...traceparent ? { parentTraceId: traceparent.traceId } : {}
1700
1737
  } : {
1701
1738
  ...linked && parent ? { parentId: parent.id, base: parent.attributes } : {},
1702
- ..._optionalChain([parent, 'optionalAccess', _61 => _61.requestId]) ? { requestId: parent.requestId } : {}
1739
+ ..._optionalChain([parent, 'optionalAccess', _62 => _62.requestId]) ? { requestId: parent.requestId } : {}
1703
1740
  }
1704
1741
  );
1705
1742
  if (linked && parent) state.breadcrumbs = parent.breadcrumbs ??= new BreadcrumbTrail();
@@ -1713,16 +1750,16 @@ function startOperation(name, fn, attributes, options, internal = {}) {
1713
1750
  thrown = error;
1714
1751
  noteOperationError(error, true, state);
1715
1752
  rememberThrownBreadcrumbs(error, state);
1716
- _optionalChain([shared, 'access', _62 => _62.config, 'optionalAccess', _63 => _63.captureThrown, 'optionalCall', _64 => _64(error)]);
1753
+ _optionalChain([shared, 'access', _63 => _63.config, 'optionalAccess', _64 => _64.captureThrown, 'optionalCall', _65 => _65(error)]);
1717
1754
  throw error;
1718
1755
  } finally {
1719
- _optionalChain([_api.trace, 'access', _65 => _65.getActiveSpan, 'call', _66 => _66(), 'optionalAccess', _67 => _67.setAttributes, 'call', _68 => _68({
1756
+ _optionalChain([_api.trace, 'access', _66 => _66.getActiveSpan, 'call', _67 => _67(), 'optionalAccess', _68 => _68.setAttributes, 'call', _69 => _69({
1720
1757
  ...traceAttributes(state),
1721
1758
  "autter.operation.outcome": state.outcome,
1722
1759
  "autter.operation.kind": state.kind
1723
1760
  })]);
1724
1761
  if (state.outcome === "failed" && !thrown)
1725
- _optionalChain([shared, 'access', _69 => _69.config, 'optionalAccess', _70 => _70.reportOutcome, 'call', _71 => _71(
1762
+ _optionalChain([shared, 'access', _70 => _70.config, 'optionalAccess', _71 => _71.reportOutcome, 'call', _72 => _72(
1726
1763
  state.name,
1727
1764
  _nullishCoalesce(state.message, () => ( "Operation failed")),
1728
1765
  {
@@ -1743,14 +1780,14 @@ function startOperation(name, fn, attributes, options, internal = {}) {
1743
1780
  }
1744
1781
  }
1745
1782
  ] : [];
1746
- const promise = _optionalChain([shared, 'access', _72 => _72.config, 'optionalAccess', _73 => _73.run]) ? shared.config.run(state.name, run, traceAttributes(state), links) : run();
1783
+ const promise = _optionalChain([shared, 'access', _73 => _73.config, 'optionalAccess', _74 => _74.run]) ? shared.config.run(state.name, run, traceAttributes(state), links) : run();
1747
1784
  if (!options.waitUntil) return promise;
1748
1785
  const waitUntil = options.waitUntil;
1749
1786
  return promise.finally(() => {
1750
1787
  try {
1751
1788
  waitUntil(flushRuntimeLogs().catch(() => {
1752
1789
  }));
1753
- } catch (e20) {
1790
+ } catch (e22) {
1754
1791
  }
1755
1792
  });
1756
1793
  }
@@ -1766,7 +1803,7 @@ var runtimeContext = {
1766
1803
  const state = currentOperation();
1767
1804
  if (!state) return;
1768
1805
  state.attributes = merge(state.attributes, attributes);
1769
- _optionalChain([_api.trace, 'access', _74 => _74.getActiveSpan, 'call', _75 => _75(), 'optionalAccess', _76 => _76.setAttributes, 'call', _77 => _77(traceAttributes(state))]);
1806
+ _optionalChain([_api.trace, 'access', _75 => _75.getActiveSpan, 'call', _76 => _76(), 'optionalAccess', _77 => _77.setAttributes, 'call', _78 => _78(traceAttributes(state))]);
1770
1807
  },
1771
1808
  /** Set the outcome explicitly (wins over status/thrown-error rules). */
1772
1809
  outcome(status, message) {
@@ -1789,11 +1826,11 @@ var runtimeContext = {
1789
1826
  },
1790
1827
  /** Current operation id. */
1791
1828
  get id() {
1792
- return _optionalChain([local, 'access', _78 => _78.getStore, 'call', _79 => _79(), 'optionalAccess', _80 => _80.id]);
1829
+ return _optionalChain([local, 'access', _79 => _79.getStore, 'call', _80 => _80(), 'optionalAccess', _81 => _81.id]);
1793
1830
  },
1794
1831
  /** Current request id (inherited by child operations and forks). */
1795
1832
  get requestId() {
1796
- return _optionalChain([local, 'access', _81 => _81.getStore, 'call', _82 => _82(), 'optionalAccess', _83 => _83.requestId]);
1833
+ return _optionalChain([local, 'access', _82 => _82.getStore, 'call', _83 => _83(), 'optionalAccess', _84 => _84.requestId]);
1797
1834
  },
1798
1835
  /**
1799
1836
  * Run `fn` as a child operation whose parent link is captured NOW, so it
@@ -1807,7 +1844,7 @@ var runtimeContext = {
1807
1844
  carrier() {
1808
1845
  const state = local.getStore();
1809
1846
  if (!state) return void 0;
1810
- const span = _optionalChain([_api.trace, 'access', _84 => _84.getActiveSpan, 'call', _85 => _85(), 'optionalAccess', _86 => _86.spanContext, 'call', _87 => _87()]);
1847
+ const span = _optionalChain([_api.trace, 'access', _85 => _85.getActiveSpan, 'call', _86 => _86(), 'optionalAccess', _87 => _87.spanContext, 'call', _88 => _88()]);
1811
1848
  const traceparent = span ? formatTraceparent(span.traceId, span.spanId, (span.traceFlags & 1) === 1) : void 0;
1812
1849
  return createCarrier({
1813
1850
  op: state.id,
@@ -1820,7 +1857,7 @@ var runtimeContext = {
1820
1857
  // src/breadcrumbs.ts
1821
1858
  var INVALID_TRACE_ID = "00000000000000000000000000000000";
1822
1859
  var MAX_TRACE_TRAILS = 200;
1823
- var trails = _chunk4MVWIRBIcjs.sharedSlot.call(void 0, "breadcrumbs", () => ({
1860
+ var trails = _chunkMOZOUEMAcjs.sharedSlot.call(void 0, "breadcrumbs", () => ({
1824
1861
  byTrace: /* @__PURE__ */ new Map(),
1825
1862
  process: new BreadcrumbTrail(),
1826
1863
  thrown: /* @__PURE__ */ new WeakMap()
@@ -1829,14 +1866,14 @@ var byTrace = trails.byTrace;
1829
1866
  var processTrail = trails.process;
1830
1867
  var thrownTrails = trails.thrown;
1831
1868
  function redact2(attributes) {
1832
- return _nullishCoalesce(_optionalChain([loggerConfigured, 'call', _88 => _88(), 'optionalAccess', _89 => _89.redact, 'call', _90 => _90(attributes)]), () => ( redactAttributes(attributes)));
1869
+ return _nullishCoalesce(_optionalChain([loggerConfigured, 'call', _89 => _89(), 'optionalAccess', _90 => _90.redact, 'call', _91 => _91(attributes)]), () => ( redactAttributes(attributes)));
1833
1870
  }
1834
1871
  function trailFor(create, state = local.getStore()) {
1835
1872
  if (state) {
1836
1873
  if (!state.breadcrumbs && create) state.breadcrumbs = new BreadcrumbTrail();
1837
1874
  return state.breadcrumbs;
1838
1875
  }
1839
- const traceId = _optionalChain([_api.trace, 'access', _91 => _91.getActiveSpan, 'call', _92 => _92(), 'optionalAccess', _93 => _93.spanContext, 'call', _94 => _94(), 'access', _95 => _95.traceId]);
1876
+ const traceId = _optionalChain([_api.trace, 'access', _92 => _92.getActiveSpan, 'call', _93 => _93(), 'optionalAccess', _94 => _94.spanContext, 'call', _95 => _95(), 'access', _96 => _96.traceId]);
1840
1877
  if (traceId && traceId !== INVALID_TRACE_ID) {
1841
1878
  let trail = byTrace.get(traceId);
1842
1879
  if (!trail && create) {
@@ -1855,9 +1892,9 @@ function addBreadcrumb(input) {
1855
1892
  try {
1856
1893
  const crumb = normalizeBreadcrumb(input, redact2);
1857
1894
  if (!crumb) return;
1858
- _optionalChain([trailFor, 'call', _96 => _96(true), 'optionalAccess', _97 => _97.add, 'call', _98 => _98(crumb)]);
1859
- _chunk4MVWIRBIcjs.noteCompatFeature.call(void 0, "breadcrumbs");
1860
- } catch (e21) {
1895
+ _optionalChain([trailFor, 'call', _97 => _97(true), 'optionalAccess', _98 => _98.add, 'call', _99 => _99(crumb)]);
1896
+ _chunkMOZOUEMAcjs.noteCompatFeature.call(void 0, "breadcrumbs");
1897
+ } catch (e23) {
1861
1898
  }
1862
1899
  }
1863
1900
  function recordLogBreadcrumb(level, message, attributes, state) {
@@ -1873,8 +1910,8 @@ function recordLogBreadcrumb(level, message, attributes, state) {
1873
1910
  }
1874
1911
  }
1875
1912
  const crumb = normalizeBreadcrumb({ type: "log", level, message, data }, redact2);
1876
- if (crumb) _optionalChain([trailFor, 'call', _99 => _99(true, state), 'optionalAccess', _100 => _100.add, 'call', _101 => _101(crumb)]);
1877
- } catch (e22) {
1913
+ if (crumb) _optionalChain([trailFor, 'call', _100 => _100(true, state), 'optionalAccess', _101 => _101.add, 'call', _102 => _102(crumb)]);
1914
+ } catch (e24) {
1878
1915
  }
1879
1916
  }
1880
1917
  function attributeBudget() {
@@ -1891,10 +1928,10 @@ function breadcrumbEventAttributes(scrub, error) {
1891
1928
  try {
1892
1929
  const thrown = error !== null && typeof error === "object" ? thrownTrails.get(error) : void 0;
1893
1930
  const trail = _nullishCoalesce(thrown, () => ( trailFor(false)));
1894
- if (!_optionalChain([trail, 'optionalAccess', _102 => _102.size])) return {};
1931
+ if (!_optionalChain([trail, 'optionalAccess', _103 => _103.size])) return {};
1895
1932
  const json = breadcrumbsAttribute(trail.list(), scrub, attributeBudget());
1896
1933
  return json ? { [BREADCRUMBS_ATTRIBUTE]: json } : {};
1897
- } catch (e23) {
1934
+ } catch (e25) {
1898
1935
  return {};
1899
1936
  }
1900
1937
  }
@@ -1949,4 +1986,5 @@ function breadcrumbEventAttributes(scrub, error) {
1949
1986
 
1950
1987
 
1951
1988
 
1952
- exports.redactAttributes = redactAttributes; exports.redactText = redactText; exports.makeRedactor = makeRedactor; exports.CODE_PATTERN = CODE_PATTERN; exports.RuntimeError = RuntimeError; exports.defineRuntimeErrors = defineRuntimeErrors; exports.isError = isError; exports.isRuntimeErrorLike = isRuntimeErrorLike; exports.errorCodeOf = errorCodeOf; exports.errorAttributes = errorAttributes; exports.errorInternal = errorInternal; exports.toClientError = toClientError; exports.responseStatusOf = responseStatusOf; exports.isSummary = isSummary; exports.DEFAULT_REQUEST_ID_HEADER = DEFAULT_REQUEST_ID_HEADER; exports.resolveRequestId = resolveRequestId; exports.normalizeRoutePath = normalizeRoutePath; exports.compileIgnore = compileIgnore; exports.requestOutcome = requestOutcome; exports.parseUserAgent = parseUserAgent; exports.sanitizeBreadcrumbs = sanitizeBreadcrumbs; exports.fingerprintValues = fingerprintValues; exports.fingerprintEventAttributes = fingerprintEventAttributes; exports.splitFingerprint = splitFingerprint; exports.addBreadcrumb = addBreadcrumb; exports.breadcrumbEventAttributes = breadcrumbEventAttributes; exports.otlpSink = otlpSink; exports.consoleSink = consoleSink; exports.fileSink = fileSink; exports.memorySink = memorySink; exports.local = local; exports.currentOperation = currentOperation; exports.configureRuntimeLogger = configureRuntimeLogger; exports.addRuntimeSink = addRuntimeSink; exports.notifyException = notifyException; exports.runtimeLogStats = runtimeLogStats; exports.flushRuntimeLogs = flushRuntimeLogs; exports.shutdownRuntimeLogger = shutdownRuntimeLogger; exports.noteOperationError = noteOperationError; exports.recordOperationAiUsage = recordOperationAiUsage; exports.createRuntimeLogger = createRuntimeLogger; exports.runtimeLogger = runtimeLogger; exports.captureExceptionAsLog = captureExceptionAsLog; exports.createRequestState = createRequestState; exports.emitSummary = emitSummary; exports.reportExplicitFailure = reportExplicitFailure; exports.withRuntimeOperation = withRuntimeOperation; exports.runInBackground = runInBackground; exports.runtimeContext = runtimeContext;
1989
+
1990
+ exports.redactAttributes = redactAttributes; exports.redactText = redactText; exports.makeRedactor = makeRedactor; exports.CODE_PATTERN = CODE_PATTERN; exports.RuntimeError = RuntimeError; exports.defineRuntimeErrors = defineRuntimeErrors; exports.isError = isError; exports.isRuntimeErrorLike = isRuntimeErrorLike; exports.errorCodeOf = errorCodeOf; exports.errorAttributes = errorAttributes; exports.errorInternal = errorInternal; exports.toClientError = toClientError; exports.responseStatusOf = responseStatusOf; exports.isSummary = isSummary; exports.DEFAULT_REQUEST_ID_HEADER = DEFAULT_REQUEST_ID_HEADER; exports.resolveRequestId = resolveRequestId; exports.normalizeRoutePath = normalizeRoutePath; exports.compileIgnore = compileIgnore; exports.requestOutcome = requestOutcome; exports.parseUserAgent = parseUserAgent; exports.sanitizeBreadcrumbs = sanitizeBreadcrumbs; exports.fingerprintValues = fingerprintValues; exports.fingerprintEventAttributes = fingerprintEventAttributes; exports.splitFingerprint = splitFingerprint; exports.createErrorFilter = createErrorFilter; exports.addBreadcrumb = addBreadcrumb; exports.breadcrumbEventAttributes = breadcrumbEventAttributes; exports.otlpSink = otlpSink; exports.consoleSink = consoleSink; exports.fileSink = fileSink; exports.memorySink = memorySink; exports.local = local; exports.currentOperation = currentOperation; exports.configureRuntimeLogger = configureRuntimeLogger; exports.addRuntimeSink = addRuntimeSink; exports.notifyException = notifyException; exports.runtimeLogStats = runtimeLogStats; exports.flushRuntimeLogs = flushRuntimeLogs; exports.shutdownRuntimeLogger = shutdownRuntimeLogger; exports.noteOperationError = noteOperationError; exports.recordOperationAiUsage = recordOperationAiUsage; exports.createRuntimeLogger = createRuntimeLogger; exports.runtimeLogger = runtimeLogger; exports.captureExceptionAsLog = captureExceptionAsLog; exports.createRequestState = createRequestState; exports.emitSummary = emitSummary; exports.reportExplicitFailure = reportExplicitFailure; exports.withRuntimeOperation = withRuntimeOperation; exports.runInBackground = runInBackground; exports.runtimeContext = runtimeContext;
@@ -5,7 +5,7 @@
5
5
 
6
6
 
7
7
 
8
- var _chunk4MVWIRBIcjs = require('./chunk-4MVWIRBI.cjs');
8
+ var _chunkMOZOUEMAcjs = require('./chunk-MOZOUEMA.cjs');
9
9
 
10
10
  // src/doctor.ts
11
11
  var _fs = require('fs');
@@ -30,19 +30,19 @@ function installedSdks(cwd) {
30
30
  }
31
31
  if (_path.dirname.call(void 0, dir) === dir) break;
32
32
  }
33
- if (!found.has(_chunk4MVWIRBIcjs.SDK_IDENTITY.name)) found.set(_chunk4MVWIRBIcjs.SDK_IDENTITY.name, _chunk4MVWIRBIcjs.SDK_IDENTITY.version);
33
+ if (!found.has(_chunkMOZOUEMAcjs.SDK_IDENTITY.name)) found.set(_chunkMOZOUEMAcjs.SDK_IDENTITY.name, _chunkMOZOUEMAcjs.SDK_IDENTITY.version);
34
34
  return [...found].map(([name, version]) => ({ name, version }));
35
35
  }
36
36
  function featuresInUse(sdks) {
37
- return _chunk4MVWIRBIcjs.COMPAT_MANIFEST.features.filter(
37
+ return _chunkMOZOUEMAcjs.COMPAT_MANIFEST.features.filter(
38
38
  (feature) => sdks.some((sdk) => {
39
39
  const min = feature.sdks[sdk.name];
40
- return min !== void 0 && _chunk4MVWIRBIcjs.versionAtLeast.call(void 0, sdk.version, min) === true;
40
+ return min !== void 0 && _chunkMOZOUEMAcjs.versionAtLeast.call(void 0, sdk.version, min) === true;
41
41
  })
42
42
  ).map((feature) => feature.id);
43
43
  }
44
44
  async function checkKey(endpoint, key, timeoutMs) {
45
- const res = await _chunk4MVWIRBIcjs.compatRequest.call(void 0, "POST", `${endpoint}/v1/traces`, {
45
+ const res = await _chunkMOZOUEMAcjs.compatRequest.call(void 0, "POST", `${endpoint}/v1/traces`, {
46
46
  body: JSON.stringify({ resourceSpans: [] }),
47
47
  headers: { authorization: `Bearer ${key}` },
48
48
  unref: false,
@@ -62,10 +62,10 @@ async function runDoctor(options = {}) {
62
62
  const features = _optionalChain([options, 'access', _ => _.features, 'optionalAccess', _2 => _2.length]) ? options.features : featuresInUse(sdks);
63
63
  const routes = [
64
64
  ...new Set(
65
- features.map((id) => _optionalChain([_chunk4MVWIRBIcjs.COMPAT_MANIFEST, 'access', _3 => _3.features, 'access', _4 => _4.find, 'call', _5 => _5((f) => f.id === id), 'optionalAccess', _6 => _6.route])).filter((route) => Boolean(route))
65
+ features.map((id) => _optionalChain([_chunkMOZOUEMAcjs.COMPAT_MANIFEST, 'access', _3 => _3.features, 'access', _4 => _4.find, 'call', _5 => _5((f) => f.id === id), 'optionalAccess', _6 => _6.route])).filter((route) => Boolean(route))
66
66
  )
67
67
  ];
68
- const { info, error } = await _chunk4MVWIRBIcjs.fetchIngesterCompat.call(void 0, endpoint, { probeRoutes: routes, unref: false, timeoutMs });
68
+ const { info, error } = await _chunkMOZOUEMAcjs.fetchIngesterCompat.call(void 0, endpoint, { probeRoutes: routes, unref: false, timeoutMs });
69
69
  const issues = [];
70
70
  const seen = /* @__PURE__ */ new Set();
71
71
  const add = (issue) => {
@@ -75,15 +75,15 @@ async function runDoctor(options = {}) {
75
75
  issues.push(issue);
76
76
  }
77
77
  };
78
- _chunk4MVWIRBIcjs.evaluateCompat.call(void 0, { features, ingester: info }).forEach(add);
78
+ _chunkMOZOUEMAcjs.evaluateCompat.call(void 0, { features, ingester: info }).forEach(add);
79
79
  for (const sdk of sdks) {
80
80
  if (_optionalChain([options, 'access', _7 => _7.features, 'optionalAccess', _8 => _8.length])) {
81
- _chunk4MVWIRBIcjs.evaluateCompat.call(void 0, { features: options.features, ingester: null, sdk }).forEach(add);
81
+ _chunkMOZOUEMAcjs.evaluateCompat.call(void 0, { features: options.features, ingester: null, sdk }).forEach(add);
82
82
  }
83
83
  }
84
84
  const key = options.key ? await checkKey(endpoint, options.key, timeoutMs) : void 0;
85
85
  const featureRows = features.flatMap((id) => {
86
- const feature = _chunk4MVWIRBIcjs.COMPAT_MANIFEST.features.find((f) => f.id === id);
86
+ const feature = _chunkMOZOUEMAcjs.COMPAT_MANIFEST.features.find((f) => f.id === id);
87
87
  if (!feature) return [];
88
88
  const bad = issues.some((issue) => issue.feature === id);
89
89
  const known = _optionalChain([info, 'optionalAccess', _9 => _9.version]) != null || feature.route !== void 0 && _optionalChain([info, 'optionalAccess', _10 => _10.routes, 'optionalAccess', _11 => _11[feature.route]]) !== void 0;
@@ -153,7 +153,7 @@ Checks that your Autter SDKs, ingester and ClickHouse schema versions match.
153
153
  Options:
154
154
  --endpoint <url> Ingester base URL (default: $AUTTER_ENDPOINT, $OTEL_EXPORTER_OTLP_ENDPOINT, or ${DEFAULT_ENDPOINT})
155
155
  --key <key> Also verify an ingest key (default: $AUTTER_RUNTIME_KEY)
156
- --features <a,b> Only check these features (${_chunk4MVWIRBIcjs.COMPAT_MANIFEST.features.map((f) => f.id).join(", ")})
156
+ --features <a,b> Only check these features (${_chunkMOZOUEMAcjs.COMPAT_MANIFEST.features.map((f) => f.id).join(", ")})
157
157
  --json Machine-readable output
158
158
  --timeout <ms> Per-request timeout (default 5000)
159
159
 
@@ -119,6 +119,57 @@ var compat_manifest_default = {
119
119
  ingester: "1.6.0",
120
120
  migrations: [],
121
121
  sdks: { "@autter/runtime-browser": "1.6.0", "@autter/runtime-next": "1.6.0", "@autter/runtime-node": "1.6.0" }
122
+ },
123
+ {
124
+ id: "sourcemap_upload_keys",
125
+ title: "Upload-only keys for source maps (autter_rtu_)",
126
+ ingester: "1.7.0",
127
+ migrations: [],
128
+ route: "/v1/sourcemaps",
129
+ sdks: {}
130
+ },
131
+ {
132
+ id: "source_map_verify",
133
+ title: "Source map check by debug id (autter-runtime sourcemaps verify)",
134
+ ingester: "1.7.0",
135
+ migrations: ["0017-source-maps-debug-id"],
136
+ route: "/v1/sourcemaps/check",
137
+ sdks: {}
138
+ },
139
+ {
140
+ id: "ingest_drop_counts",
141
+ title: "Rejected and dropped records per repository",
142
+ ingester: "1.8.0",
143
+ migrations: ["0018-runtime-ingest-drops"],
144
+ sdks: {}
145
+ },
146
+ {
147
+ id: "telemetry_sender_via",
148
+ title: "How each service's telemetry arrives (SDK, OpenTelemetry Collector or browser relay)",
149
+ ingester: "1.8.0",
150
+ migrations: ["0019-sdk-versions-via"],
151
+ sdks: {}
152
+ },
153
+ {
154
+ id: "frame_resolution_counts",
155
+ title: "Resolved and unresolved browser frames per occurrence",
156
+ ingester: "1.8.0",
157
+ migrations: ["0020-occurrence-frame-resolution"],
158
+ sdks: {}
159
+ },
160
+ {
161
+ id: "ingest_suppression",
162
+ title: "Suppression rules: drop or sample matching errors at ingest",
163
+ ingester: "1.9.0",
164
+ migrations: [],
165
+ sdks: {}
166
+ },
167
+ {
168
+ id: "loop_collapse",
169
+ title: "Loop collapse: a looping error stored as one sample a minute with an exact count",
170
+ ingester: "1.9.0",
171
+ migrations: ["0021-occurrence-collapsed-count"],
172
+ sdks: {}
122
173
  }
123
174
  ]
124
175
  };
@@ -464,7 +515,7 @@ import { request as httpsRequest } from "https";
464
515
  // package.json
465
516
  var package_default = {
466
517
  name: "@autter/runtime-node",
467
- version: "1.6.1",
518
+ version: "1.8.0",
468
519
  description: "Autter Runtime for Node.js: request wide events, coded errors, operation logging, same-origin browser relay and a curated OpenTelemetry server tracker",
469
520
  license: "MIT",
470
521
  type: "module",