@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.
@@ -3691,6 +3691,63 @@ function latencyPercentiles(hist) {
3691
3691
  return { p50: round(quantile(hist, 0.5)), p95: round(quantile(hist, 0.95)) };
3692
3692
  }
3693
3693
 
3694
+ // src/stacktrace.ts
3695
+ var FRAME_SHAPES = [
3696
+ // `File "<path>", line <N>, in <func>` — the "most recent call last" shape.
3697
+ { re: /File "([^"]+)", line (\d+)(?:, in (\S+))?/, file: 1, line: 2, fn: 3, deepest: "last" },
3698
+ // `at <func> (<path>:<line>:<col>)` — named call frame, most recent first.
3699
+ { re: /\bat\s+(.+?)\s+\((.+?):(\d+):\d+\)/, file: 2, line: 3, fn: 1, deepest: "first" },
3700
+ // `at <path>:<line>:<col>` — anonymous call frame, most recent first.
3701
+ { re: /\bat\s+(.+?):(\d+):\d+/, file: 1, line: 2, deepest: "first" },
3702
+ // `at <qualified.method>(<File.ext>:<line>)` — JVM-style, most recent first.
3703
+ { re: /\bat\s+(.+?)\((\S+\.\w+):(\d+)\)/, file: 2, line: 3, fn: 1, deepest: "first" }
3704
+ ];
3705
+ var VENDOR_MARKERS = [
3706
+ "node_modules",
3707
+ // dependency root
3708
+ "site-packages",
3709
+ // installed-package root
3710
+ "dist-packages",
3711
+ // distro-packaged root
3712
+ "node:"
3713
+ // runtime-internal module scheme (a stdlib/runtime-root frame)
3714
+ ];
3715
+ function matchFrame(line) {
3716
+ for (const shape of FRAME_SHAPES) {
3717
+ const m = shape.re.exec(line);
3718
+ if (!m) continue;
3719
+ const file = m[shape.file];
3720
+ const lineNo = Number(m[shape.line]);
3721
+ if (!file || !Number.isFinite(lineNo)) continue;
3722
+ const fn = shape.fn !== void 0 ? m[shape.fn] : void 0;
3723
+ return { frame: { file, line: lineNo, ...fn ? { fn } : {} }, deepest: shape.deepest };
3724
+ }
3725
+ return null;
3726
+ }
3727
+ function isApplicationFrame(file) {
3728
+ if (file.startsWith("<")) return false;
3729
+ const norm = file.split("\\").join("/");
3730
+ for (const marker of VENDOR_MARKERS) {
3731
+ if (norm.includes(marker)) return false;
3732
+ }
3733
+ return true;
3734
+ }
3735
+ function deepestApplicationFrame(stacktrace) {
3736
+ if (!stacktrace) return null;
3737
+ const appFrames = [];
3738
+ for (const raw of stacktrace.split("\n")) {
3739
+ const matched = matchFrame(raw);
3740
+ if (!matched) continue;
3741
+ if (!isApplicationFrame(matched.frame.file)) continue;
3742
+ appFrames.push(matched);
3743
+ }
3744
+ if (appFrames.length === 0) return null;
3745
+ const orientation = appFrames.some((f) => f.deepest === "last") ? "last" : "first";
3746
+ const oriented = appFrames.filter((f) => f.deepest === orientation);
3747
+ const chosen = orientation === "last" ? oriented[oriented.length - 1] : oriented[0];
3748
+ return chosen ? chosen.frame : null;
3749
+ }
3750
+
3694
3751
  // src/ingest.ts
3695
3752
  var HOUR_MS = 60 * 60 * 1e3;
3696
3753
  var DAY_MS = 24 * HOUR_MS;
@@ -4542,29 +4599,71 @@ async function appendConnectorIncident(errorsPath, input) {
4542
4599
  await fs7.mkdir(path8.dirname(errorsPath), { recursive: true });
4543
4600
  await fs7.appendFile(errorsPath, JSON.stringify(ev) + "\n", "utf8");
4544
4601
  }
4545
- function incidentAffectedNode(span, graph, scanPath) {
4602
+ function landIncidentCallSite(span, callSite, trusted, graph) {
4603
+ const relPath = graph ? reconcileObservedRelPath(graph, span.service, callSite.relPath) : callSite.relPath;
4604
+ const canonicalService = serviceNodeName(graph, span) ?? span.service;
4605
+ const recovered = !trusted;
4606
+ if (graph) {
4607
+ const fusedFileId = fileId3(canonicalService, relPath);
4608
+ if (graph.hasNode(fusedFileId)) {
4609
+ const node = landObservedSymbol(
4610
+ graph,
4611
+ fusedFileId,
4612
+ canonicalService,
4613
+ relPath,
4614
+ { ...callSite, relPath },
4615
+ false
4616
+ );
4617
+ return {
4618
+ affectedNode: node,
4619
+ ...recovered ? {
4620
+ codeFilepath: relPath,
4621
+ ...callSite.line !== void 0 ? { codeLineno: callSite.line } : {}
4622
+ } : {}
4623
+ };
4624
+ }
4625
+ if (recovered) return null;
4626
+ }
4627
+ return { affectedNode: fileId3(span.service, relPath) };
4628
+ }
4629
+ function serviceNodeName(graph, span) {
4630
+ if (!graph) return void 0;
4631
+ const sid = resolveFusedServiceId(graph, span.service, span.env);
4632
+ if (!graph.hasNode(sid)) return void 0;
4633
+ const node = graph.getNodeAttributes(sid);
4634
+ return typeof node.name === "string" ? node.name : void 0;
4635
+ }
4636
+ function stacktraceCallSite(span, serviceNode, scanPath) {
4637
+ const frame = deepestApplicationFrame(span.exception?.stacktrace);
4638
+ if (!frame) return null;
4639
+ const relPath = relPathForRuntimeFile(frame.file, serviceNode, scanPath);
4640
+ if (!relPath) return null;
4641
+ return { relPath, line: frame.line, ...frame.fn ? { fn: frame.fn } : {} };
4642
+ }
4643
+ function incidentLocus(span, graph, scanPath) {
4546
4644
  const sid = graph ? resolveFusedServiceId(graph, span.service, span.env) : serviceId(span.service, span.env);
4547
4645
  const serviceNode = graph && graph.hasNode(sid) ? graph.getNodeAttributes(sid) : void 0;
4548
4646
  const callSite = callSiteFromSpan(span, serviceNode, scanPath);
4549
4647
  if (callSite) {
4550
- const relPath = graph ? reconcileObservedRelPath(graph, span.service, callSite.relPath) : callSite.relPath;
4551
- const canonicalService = serviceNode && typeof serviceNode.name === "string" ? serviceNode.name : span.service;
4552
- if (graph) {
4553
- const fusedFileId = fileId3(canonicalService, relPath);
4554
- if (graph.hasNode(fusedFileId)) {
4555
- return landObservedSymbol(
4556
- graph,
4557
- fusedFileId,
4558
- canonicalService,
4559
- relPath,
4560
- { ...callSite, relPath },
4561
- false
4562
- );
4563
- }
4648
+ const landed = landIncidentCallSite(span, callSite, true, graph);
4649
+ if (landed) return landed;
4650
+ } else {
4651
+ const recovered = stacktraceCallSite(span, serviceNode, scanPath);
4652
+ if (recovered) {
4653
+ const landed = landIncidentCallSite(span, recovered, false, graph);
4654
+ if (landed) return landed;
4564
4655
  }
4565
- return fileId3(span.service, relPath);
4566
4656
  }
4567
- return sid;
4657
+ return { affectedNode: sid };
4658
+ }
4659
+ function incidentAffectedNode(span, graph, scanPath) {
4660
+ return incidentLocus(span, graph, scanPath).affectedNode;
4661
+ }
4662
+ function withRecoveredCodeAttrs(attrs, locus) {
4663
+ if (locus.codeFilepath === void 0) return attrs;
4664
+ attrs[CODE_FILEPATH_ATTR] = locus.codeFilepath;
4665
+ if (locus.codeLineno !== void 0) attrs[CODE_LINENO_ATTR] = locus.codeLineno;
4666
+ return attrs;
4568
4667
  }
4569
4668
  function sanitizeAttributes(attrs) {
4570
4669
  const out = {};
@@ -4577,7 +4676,8 @@ function sanitizeAttributes(attrs) {
4577
4676
  function buildErrorEventForReceiver(span, graph, scanPath) {
4578
4677
  if (span.statusCode !== 2) return null;
4579
4678
  const ts = span.startTimeIso ?? (/* @__PURE__ */ new Date()).toISOString();
4580
- const attrs = sanitizeAttributes(span.attributes);
4679
+ const locus = incidentLocus(span, graph, scanPath);
4680
+ const attrs = withRecoveredCodeAttrs(sanitizeAttributes(span.attributes), locus);
4581
4681
  return {
4582
4682
  id: `${span.traceId}:${span.spanId}`,
4583
4683
  timestamp: ts,
@@ -4588,7 +4688,7 @@ function buildErrorEventForReceiver(span, graph, scanPath) {
4588
4688
  ...span.exception?.type ? { exceptionType: span.exception.type } : {},
4589
4689
  ...span.exception?.stacktrace ? { exceptionStacktrace: span.exception.stacktrace } : {},
4590
4690
  ...Object.keys(attrs).length > 0 ? { attributes: attrs } : {},
4591
- affectedNode: incidentAffectedNode(span, graph, scanPath)
4691
+ affectedNode: locus.affectedNode
4592
4692
  };
4593
4693
  }
4594
4694
  function makeErrorSpanWriter(errorsPath, graph, scanPath) {
@@ -4622,7 +4722,8 @@ async function recordFailingResponseIncident(ctx, span, affectedNode, timestamp,
4622
4722
  await appendErrorEvent(ctx, ev);
4623
4723
  }
4624
4724
  async function recordExceptionIncident(ctx, span, ts) {
4625
- const attrs = sanitizeAttributes(span.attributes);
4725
+ const locus = incidentLocus(span, ctx.graph, ctx.scanPath);
4726
+ const attrs = withRecoveredCodeAttrs(sanitizeAttributes(span.attributes), locus);
4626
4727
  const ev = {
4627
4728
  id: `${span.traceId}:${span.spanId}`,
4628
4729
  timestamp: ts,
@@ -4633,7 +4734,7 @@ async function recordExceptionIncident(ctx, span, ts) {
4633
4734
  ...span.exception?.type ? { exceptionType: span.exception.type } : {},
4634
4735
  ...span.exception?.stacktrace ? { exceptionStacktrace: span.exception.stacktrace } : {},
4635
4736
  ...Object.keys(attrs).length > 0 ? { attributes: attrs } : {},
4636
- affectedNode: incidentAffectedNode(span, ctx.graph, ctx.scanPath)
4737
+ affectedNode: locus.affectedNode
4637
4738
  };
4638
4739
  await appendErrorEvent(ctx, ev);
4639
4740
  }
@@ -4936,7 +5037,8 @@ async function handleSpan(ctx, span) {
4936
5037
  if (span.statusCode === 2) {
4937
5038
  stitchTrace(ctx.graph, sourceId, ts);
4938
5039
  if (ctx.writeErrorEventInline !== false) {
4939
- const attrs = sanitizeAttributes(span.attributes);
5040
+ const locus = incidentLocus(span, ctx.graph, ctx.scanPath);
5041
+ const attrs = withRecoveredCodeAttrs(sanitizeAttributes(span.attributes), locus);
4940
5042
  const ev = {
4941
5043
  id: `${span.traceId}:${span.spanId}`,
4942
5044
  timestamp: ts,
@@ -4948,10 +5050,11 @@ async function handleSpan(ctx, span) {
4948
5050
  ...span.exception?.stacktrace ? { exceptionStacktrace: span.exception.stacktrace } : {},
4949
5051
  ...Object.keys(attrs).length > 0 ? { attributes: attrs } : {},
4950
5052
  // Attribute to where the failure originated — the symbol / file / service
4951
- // the throwing span named (incidentAffectedNode, ADR-191) the same
4952
- // source-based attribution the durable receiver write uses, not the
4953
- // outbound edge target this span happened to mint.
4954
- affectedNode: incidentAffectedNode(span, ctx.graph, ctx.scanPath)
5053
+ // the throwing span named (incidentAffectedNode / ADR-191, extended to
5054
+ // recover the locus from the stacktrace when the span stamped no code.*
5055
+ // attrs, ADR-216) the same source-based attribution the durable
5056
+ // receiver write uses, not the outbound edge target this span minted.
5057
+ affectedNode: locus.affectedNode
4955
5058
  };
4956
5059
  await appendErrorEvent(ctx, ev);
4957
5060
  }
@@ -21695,4 +21798,4 @@ export {
21695
21798
  deprovisionConnector,
21696
21799
  buildApi
21697
21800
  };
21698
- //# sourceMappingURL=chunk-EDE4XP2M.js.map
21801
+ //# sourceMappingURL=chunk-IVVF37OU.js.map