@neat.is/core 0.9.3 → 0.9.5-dev.20260824

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.
@@ -20,7 +20,7 @@ import {
20
20
  startStalenessLoop,
21
21
  touchLastSeen,
22
22
  writeAtomically
23
- } from "./chunk-EDE4XP2M.js";
23
+ } from "./chunk-IVVF37OU.js";
24
24
  import {
25
25
  assertBindAuthority,
26
26
  buildOtelReceiver,
@@ -891,4 +891,4 @@ export {
891
891
  resolveHost,
892
892
  startDaemon
893
893
  };
894
- //# sourceMappingURL=chunk-2D4Y5QHE.js.map
894
+ //# sourceMappingURL=chunk-TGCWMMF6.js.map
package/dist/cli.cjs CHANGED
@@ -5476,6 +5476,64 @@ function latencyPercentiles(hist) {
5476
5476
  return { p50: round(quantile(hist, 0.5)), p95: round(quantile(hist, 0.95)) };
5477
5477
  }
5478
5478
 
5479
+ // src/stacktrace.ts
5480
+ init_cjs_shims();
5481
+ var FRAME_SHAPES = [
5482
+ // `File "<path>", line <N>, in <func>` — the "most recent call last" shape.
5483
+ { re: /File "([^"]+)", line (\d+)(?:, in (\S+))?/, file: 1, line: 2, fn: 3, deepest: "last" },
5484
+ // `at <func> (<path>:<line>:<col>)` — named call frame, most recent first.
5485
+ { re: /\bat\s+(.+?)\s+\((.+?):(\d+):\d+\)/, file: 2, line: 3, fn: 1, deepest: "first" },
5486
+ // `at <path>:<line>:<col>` — anonymous call frame, most recent first.
5487
+ { re: /\bat\s+(.+?):(\d+):\d+/, file: 1, line: 2, deepest: "first" },
5488
+ // `at <qualified.method>(<File.ext>:<line>)` — JVM-style, most recent first.
5489
+ { re: /\bat\s+(.+?)\((\S+\.\w+):(\d+)\)/, file: 2, line: 3, fn: 1, deepest: "first" }
5490
+ ];
5491
+ var VENDOR_MARKERS = [
5492
+ "node_modules",
5493
+ // dependency root
5494
+ "site-packages",
5495
+ // installed-package root
5496
+ "dist-packages",
5497
+ // distro-packaged root
5498
+ "node:"
5499
+ // runtime-internal module scheme (a stdlib/runtime-root frame)
5500
+ ];
5501
+ function matchFrame(line) {
5502
+ for (const shape of FRAME_SHAPES) {
5503
+ const m = shape.re.exec(line);
5504
+ if (!m) continue;
5505
+ const file = m[shape.file];
5506
+ const lineNo = Number(m[shape.line]);
5507
+ if (!file || !Number.isFinite(lineNo)) continue;
5508
+ const fn = shape.fn !== void 0 ? m[shape.fn] : void 0;
5509
+ return { frame: { file, line: lineNo, ...fn ? { fn } : {} }, deepest: shape.deepest };
5510
+ }
5511
+ return null;
5512
+ }
5513
+ function isApplicationFrame(file) {
5514
+ if (file.startsWith("<")) return false;
5515
+ const norm = file.split("\\").join("/");
5516
+ for (const marker of VENDOR_MARKERS) {
5517
+ if (norm.includes(marker)) return false;
5518
+ }
5519
+ return true;
5520
+ }
5521
+ function deepestApplicationFrame(stacktrace) {
5522
+ if (!stacktrace) return null;
5523
+ const appFrames = [];
5524
+ for (const raw of stacktrace.split("\n")) {
5525
+ const matched = matchFrame(raw);
5526
+ if (!matched) continue;
5527
+ if (!isApplicationFrame(matched.frame.file)) continue;
5528
+ appFrames.push(matched);
5529
+ }
5530
+ if (appFrames.length === 0) return null;
5531
+ const orientation = appFrames.some((f) => f.deepest === "last") ? "last" : "first";
5532
+ const oriented = appFrames.filter((f) => f.deepest === orientation);
5533
+ const chosen = orientation === "last" ? oriented[oriented.length - 1] : oriented[0];
5534
+ return chosen ? chosen.frame : null;
5535
+ }
5536
+
5479
5537
  // src/ingest.ts
5480
5538
  var HOUR_MS = 60 * 60 * 1e3;
5481
5539
  var DAY_MS = 24 * HOUR_MS;
@@ -6327,29 +6385,71 @@ async function appendConnectorIncident(errorsPath, input) {
6327
6385
  await import_node_fs8.promises.mkdir(import_node_path9.default.dirname(errorsPath), { recursive: true });
6328
6386
  await import_node_fs8.promises.appendFile(errorsPath, JSON.stringify(ev) + "\n", "utf8");
6329
6387
  }
6330
- function incidentAffectedNode(span, graph, scanPath) {
6388
+ function landIncidentCallSite(span, callSite, trusted, graph) {
6389
+ const relPath = graph ? reconcileObservedRelPath(graph, span.service, callSite.relPath) : callSite.relPath;
6390
+ const canonicalService = serviceNodeName(graph, span) ?? span.service;
6391
+ const recovered = !trusted;
6392
+ if (graph) {
6393
+ const fusedFileId = (0, import_types8.fileId)(canonicalService, relPath);
6394
+ if (graph.hasNode(fusedFileId)) {
6395
+ const node = landObservedSymbol(
6396
+ graph,
6397
+ fusedFileId,
6398
+ canonicalService,
6399
+ relPath,
6400
+ { ...callSite, relPath },
6401
+ false
6402
+ );
6403
+ return {
6404
+ affectedNode: node,
6405
+ ...recovered ? {
6406
+ codeFilepath: relPath,
6407
+ ...callSite.line !== void 0 ? { codeLineno: callSite.line } : {}
6408
+ } : {}
6409
+ };
6410
+ }
6411
+ if (recovered) return null;
6412
+ }
6413
+ return { affectedNode: (0, import_types8.fileId)(span.service, relPath) };
6414
+ }
6415
+ function serviceNodeName(graph, span) {
6416
+ if (!graph) return void 0;
6417
+ const sid = resolveFusedServiceId(graph, span.service, span.env);
6418
+ if (!graph.hasNode(sid)) return void 0;
6419
+ const node = graph.getNodeAttributes(sid);
6420
+ return typeof node.name === "string" ? node.name : void 0;
6421
+ }
6422
+ function stacktraceCallSite(span, serviceNode, scanPath) {
6423
+ const frame = deepestApplicationFrame(span.exception?.stacktrace);
6424
+ if (!frame) return null;
6425
+ const relPath = relPathForRuntimeFile(frame.file, serviceNode, scanPath);
6426
+ if (!relPath) return null;
6427
+ return { relPath, line: frame.line, ...frame.fn ? { fn: frame.fn } : {} };
6428
+ }
6429
+ function incidentLocus(span, graph, scanPath) {
6331
6430
  const sid = graph ? resolveFusedServiceId(graph, span.service, span.env) : (0, import_types8.serviceId)(span.service, span.env);
6332
6431
  const serviceNode = graph && graph.hasNode(sid) ? graph.getNodeAttributes(sid) : void 0;
6333
6432
  const callSite = callSiteFromSpan(span, serviceNode, scanPath);
6334
6433
  if (callSite) {
6335
- const relPath = graph ? reconcileObservedRelPath(graph, span.service, callSite.relPath) : callSite.relPath;
6336
- const canonicalService = serviceNode && typeof serviceNode.name === "string" ? serviceNode.name : span.service;
6337
- if (graph) {
6338
- const fusedFileId = (0, import_types8.fileId)(canonicalService, relPath);
6339
- if (graph.hasNode(fusedFileId)) {
6340
- return landObservedSymbol(
6341
- graph,
6342
- fusedFileId,
6343
- canonicalService,
6344
- relPath,
6345
- { ...callSite, relPath },
6346
- false
6347
- );
6348
- }
6434
+ const landed = landIncidentCallSite(span, callSite, true, graph);
6435
+ if (landed) return landed;
6436
+ } else {
6437
+ const recovered = stacktraceCallSite(span, serviceNode, scanPath);
6438
+ if (recovered) {
6439
+ const landed = landIncidentCallSite(span, recovered, false, graph);
6440
+ if (landed) return landed;
6349
6441
  }
6350
- return (0, import_types8.fileId)(span.service, relPath);
6351
6442
  }
6352
- return sid;
6443
+ return { affectedNode: sid };
6444
+ }
6445
+ function incidentAffectedNode(span, graph, scanPath) {
6446
+ return incidentLocus(span, graph, scanPath).affectedNode;
6447
+ }
6448
+ function withRecoveredCodeAttrs(attrs, locus) {
6449
+ if (locus.codeFilepath === void 0) return attrs;
6450
+ attrs[CODE_FILEPATH_ATTR] = locus.codeFilepath;
6451
+ if (locus.codeLineno !== void 0) attrs[CODE_LINENO_ATTR] = locus.codeLineno;
6452
+ return attrs;
6353
6453
  }
6354
6454
  function sanitizeAttributes(attrs) {
6355
6455
  const out = {};
@@ -6362,7 +6462,8 @@ function sanitizeAttributes(attrs) {
6362
6462
  function buildErrorEventForReceiver(span, graph, scanPath) {
6363
6463
  if (span.statusCode !== 2) return null;
6364
6464
  const ts = span.startTimeIso ?? (/* @__PURE__ */ new Date()).toISOString();
6365
- const attrs = sanitizeAttributes(span.attributes);
6465
+ const locus = incidentLocus(span, graph, scanPath);
6466
+ const attrs = withRecoveredCodeAttrs(sanitizeAttributes(span.attributes), locus);
6366
6467
  return {
6367
6468
  id: `${span.traceId}:${span.spanId}`,
6368
6469
  timestamp: ts,
@@ -6373,7 +6474,7 @@ function buildErrorEventForReceiver(span, graph, scanPath) {
6373
6474
  ...span.exception?.type ? { exceptionType: span.exception.type } : {},
6374
6475
  ...span.exception?.stacktrace ? { exceptionStacktrace: span.exception.stacktrace } : {},
6375
6476
  ...Object.keys(attrs).length > 0 ? { attributes: attrs } : {},
6376
- affectedNode: incidentAffectedNode(span, graph, scanPath)
6477
+ affectedNode: locus.affectedNode
6377
6478
  };
6378
6479
  }
6379
6480
  function makeErrorSpanWriter(errorsPath, graph, scanPath) {
@@ -6407,7 +6508,8 @@ async function recordFailingResponseIncident(ctx, span, affectedNode, timestamp,
6407
6508
  await appendErrorEvent(ctx, ev);
6408
6509
  }
6409
6510
  async function recordExceptionIncident(ctx, span, ts) {
6410
- const attrs = sanitizeAttributes(span.attributes);
6511
+ const locus = incidentLocus(span, ctx.graph, ctx.scanPath);
6512
+ const attrs = withRecoveredCodeAttrs(sanitizeAttributes(span.attributes), locus);
6411
6513
  const ev = {
6412
6514
  id: `${span.traceId}:${span.spanId}`,
6413
6515
  timestamp: ts,
@@ -6418,7 +6520,7 @@ async function recordExceptionIncident(ctx, span, ts) {
6418
6520
  ...span.exception?.type ? { exceptionType: span.exception.type } : {},
6419
6521
  ...span.exception?.stacktrace ? { exceptionStacktrace: span.exception.stacktrace } : {},
6420
6522
  ...Object.keys(attrs).length > 0 ? { attributes: attrs } : {},
6421
- affectedNode: incidentAffectedNode(span, ctx.graph, ctx.scanPath)
6523
+ affectedNode: locus.affectedNode
6422
6524
  };
6423
6525
  await appendErrorEvent(ctx, ev);
6424
6526
  }
@@ -6721,7 +6823,8 @@ async function handleSpan(ctx, span) {
6721
6823
  if (span.statusCode === 2) {
6722
6824
  stitchTrace(ctx.graph, sourceId, ts);
6723
6825
  if (ctx.writeErrorEventInline !== false) {
6724
- const attrs = sanitizeAttributes(span.attributes);
6826
+ const locus = incidentLocus(span, ctx.graph, ctx.scanPath);
6827
+ const attrs = withRecoveredCodeAttrs(sanitizeAttributes(span.attributes), locus);
6725
6828
  const ev = {
6726
6829
  id: `${span.traceId}:${span.spanId}`,
6727
6830
  timestamp: ts,
@@ -6733,10 +6836,11 @@ async function handleSpan(ctx, span) {
6733
6836
  ...span.exception?.stacktrace ? { exceptionStacktrace: span.exception.stacktrace } : {},
6734
6837
  ...Object.keys(attrs).length > 0 ? { attributes: attrs } : {},
6735
6838
  // Attribute to where the failure originated — the symbol / file / service
6736
- // the throwing span named (incidentAffectedNode, ADR-191) the same
6737
- // source-based attribution the durable receiver write uses, not the
6738
- // outbound edge target this span happened to mint.
6739
- affectedNode: incidentAffectedNode(span, ctx.graph, ctx.scanPath)
6839
+ // the throwing span named (incidentAffectedNode / ADR-191, extended to
6840
+ // recover the locus from the stacktrace when the span stamped no code.*
6841
+ // attrs, ADR-216) the same source-based attribution the durable
6842
+ // receiver write uses, not the outbound edge target this span minted.
6843
+ affectedNode: locus.affectedNode
6740
6844
  };
6741
6845
  await appendErrorEvent(ctx, ev);
6742
6846
  }
@@ -24312,7 +24416,7 @@ var OTEL_ENV = {
24312
24416
  key: "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT",
24313
24417
  value: "http://localhost:4318/projects/<project>/v1/traces"
24314
24418
  };
24315
- function serviceNodeName(pkg, serviceDir) {
24419
+ function serviceNodeName2(pkg, serviceDir) {
24316
24420
  return pkg.name ?? import_node_path81.default.basename(serviceDir);
24317
24421
  }
24318
24422
  function projectToken(pkg, serviceDir, project) {
@@ -24696,7 +24800,7 @@ async function planNext(serviceDir, pkg, manifestPath, nextConfigPath, project)
24696
24800
  }
24697
24801
  dependencyEdits.push({ file: manifestPath, kind: "add", name: inst.pkg, version: inst.version });
24698
24802
  }
24699
- const svcName = serviceNodeName(pkg, serviceDir);
24803
+ const svcName = serviceNodeName2(pkg, serviceDir);
24700
24804
  const projectName = projectToken(pkg, serviceDir, project);
24701
24805
  const registrations = nonBundled.map((i) => i.registration);
24702
24806
  const generatedFiles = [];
@@ -24795,7 +24899,7 @@ async function queueEnvNeat(serviceDir, pkg, project, generatedFiles) {
24795
24899
  generatedFiles.push({
24796
24900
  file: envNeatFile,
24797
24901
  contents: renderEnvNeat(
24798
- serviceNodeName(pkg, serviceDir),
24902
+ serviceNodeName2(pkg, serviceDir),
24799
24903
  projectToken(pkg, serviceDir, project)
24800
24904
  ),
24801
24905
  skipIfExists: true
@@ -24805,7 +24909,7 @@ async function queueEnvNeat(serviceDir, pkg, project, generatedFiles) {
24805
24909
  function renderFrameworkOtelInitForPkg(template, pkg, serviceDir, project) {
24806
24910
  return renderFrameworkOtelInit(
24807
24911
  template,
24808
- serviceNodeName(pkg, serviceDir),
24912
+ serviceNodeName2(pkg, serviceDir),
24809
24913
  projectToken(pkg, serviceDir, project)
24810
24914
  );
24811
24915
  }
@@ -25185,7 +25289,7 @@ async function plan(serviceDir, opts) {
25185
25289
  } catch {
25186
25290
  return { ...empty, libOnly: true };
25187
25291
  }
25188
- const svcName = serviceNodeName(pkg, serviceDir);
25292
+ const svcName = serviceNodeName2(pkg, serviceDir);
25189
25293
  const projectName = projectToken(pkg, serviceDir, project);
25190
25294
  const registrations = nonBundled.map((i) => i.registration);
25191
25295
  const generatedFiles = [];