@neat.is/core 0.9.1 → 0.9.2-dev.20260822

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/dist/cli.cjs CHANGED
@@ -526,11 +526,42 @@ async function decodeProtobufBody(buf) {
526
526
  const { reshapeGrpcRequest: reshapeGrpcRequest2 } = await Promise.resolve().then(() => (init_otel_grpc(), otel_grpc_exports));
527
527
  return reshapeGrpcRequest2(decoded);
528
528
  }
529
+ function decompressorForEncoding(encoding) {
530
+ switch (encoding) {
531
+ case "gzip":
532
+ case "x-gzip":
533
+ return import_node_zlib.default.createGunzip();
534
+ case "deflate":
535
+ return import_node_zlib.default.createInflate();
536
+ default:
537
+ return null;
538
+ }
539
+ }
529
540
  async function buildOtelReceiver(opts) {
530
541
  const app = (0, import_fastify.default)({
531
542
  logger: false,
532
543
  bodyLimit: opts.bodyLimit ?? 16 * 1024 * 1024
533
544
  });
545
+ app.addHook("preParsing", (req, _reply, payload, done) => {
546
+ const encoding = (req.headers["content-encoding"] ?? "").toString().trim().toLowerCase();
547
+ if (encoding === "" || encoding === "identity") {
548
+ done(null, payload);
549
+ return;
550
+ }
551
+ const decompressor = decompressorForEncoding(encoding);
552
+ if (!decompressor) {
553
+ done(null, payload);
554
+ return;
555
+ }
556
+ const tracked = decompressor;
557
+ tracked.receivedEncodedLength = 0;
558
+ payload.on("data", (chunk) => {
559
+ tracked.receivedEncodedLength = (tracked.receivedEncodedLength ?? 0) + chunk.length;
560
+ });
561
+ payload.on("error", (err) => decompressor.destroy(err));
562
+ payload.pipe(decompressor);
563
+ done(null, decompressor);
564
+ });
534
565
  const REJECT_WARN_INTERVAL_MS = 6e4;
535
566
  let lastRejectWarnAt = 0;
536
567
  const warnRejectedOtlp = () => {
@@ -728,13 +759,14 @@ async function listenSteppingOtlp(app, requestedPort, host) {
728
759
  }
729
760
  }
730
761
  }
731
- var import_node_path54, import_node_url3, import_fastify, import_protobufjs, ENV_ATTR_CANONICAL, ENV_ATTR_COMPAT, ENV_FALLBACK, exportTraceServiceRequestType, exportTraceServiceResponseType, cachedProtobufResponseBody, OTLP_STEP_ATTEMPTS, OTLP_STEP_STRIDE;
762
+ var import_node_path54, import_node_url3, import_node_zlib, import_fastify, import_protobufjs, ENV_ATTR_CANONICAL, ENV_ATTR_COMPAT, ENV_FALLBACK, exportTraceServiceRequestType, exportTraceServiceResponseType, cachedProtobufResponseBody, OTLP_STEP_ATTEMPTS, OTLP_STEP_STRIDE;
732
763
  var init_otel = __esm({
733
764
  "src/otel.ts"() {
734
765
  "use strict";
735
766
  init_cjs_shims();
736
767
  import_node_path54 = __toESM(require("path"), 1);
737
768
  import_node_url3 = require("url");
769
+ import_node_zlib = __toESM(require("zlib"), 1);
738
770
  import_fastify = __toESM(require("fastify"), 1);
739
771
  import_protobufjs = __toESM(require("protobufjs"), 1);
740
772
  init_auth();
@@ -5542,6 +5574,14 @@ function grpcStatusCodeFromAttrs(attrs) {
5542
5574
  }
5543
5575
  return void 0;
5544
5576
  }
5577
+ function spanRecordsError(span) {
5578
+ if (span.statusCode === 2) return true;
5579
+ const grpc2 = grpcStatusCodeFromAttrs(span.attributes);
5580
+ if (grpc2 !== void 0 && grpc2 !== 0) return true;
5581
+ const httpStatus = httpResponseStatusFromAttrs(span.attributes);
5582
+ if (httpStatus !== void 0 && httpStatus >= 500) return true;
5583
+ return false;
5584
+ }
5545
5585
  function nonHttpFailureMessageFromAttrs(attrs) {
5546
5586
  const grpc2 = grpcStatusCodeFromAttrs(attrs);
5547
5587
  if (grpc2 !== void 0 && grpc2 !== 0) {
@@ -6340,6 +6380,21 @@ async function recordExceptionIncident(ctx, span, ts) {
6340
6380
  };
6341
6381
  await appendErrorEvent(ctx, ev);
6342
6382
  }
6383
+ async function recordGrpcFailureIncident(ctx, span, ts) {
6384
+ const attrs = sanitizeAttributes(span.attributes);
6385
+ const ev = {
6386
+ id: `${span.traceId}:${span.spanId}`,
6387
+ timestamp: ts,
6388
+ service: span.service,
6389
+ traceId: span.traceId,
6390
+ spanId: span.spanId,
6391
+ errorType: "grpc-failure",
6392
+ errorMessage: incidentMessage(span),
6393
+ ...Object.keys(attrs).length > 0 ? { attributes: attrs } : {},
6394
+ affectedNode: incidentAffectedNode(span, ctx.graph, ctx.scanPath)
6395
+ };
6396
+ await appendErrorEvent(ctx, ev);
6397
+ }
6343
6398
  async function advance4xxBurst(ctx, span, affectedNode, ts, nowMs, status2) {
6344
6399
  const { threshold, windowMs } = loadIncidentThresholdsFromEnv();
6345
6400
  if (!ctx.burstState) ctx.burstState = /* @__PURE__ */ new Map();
@@ -6410,7 +6465,7 @@ async function handleSpan(ctx, span) {
6410
6465
  warnUnidentifiedSpan(ctx.project ?? DEFAULT_PROJECT);
6411
6466
  }
6412
6467
  const sourceId = ensureServiceNode(ctx.graph, span.service, env);
6413
- const isError = span.statusCode === 2;
6468
+ const isError = spanRecordsError(span);
6414
6469
  const durationMs = span.durationNanos > 0n && !spanIsStreaming(span) ? Number(span.durationNanos) / 1e6 : void 0;
6415
6470
  const sourceServiceNode = ctx.graph.getNodeAttributes(sourceId);
6416
6471
  const callSite = callSiteFromSpan(span, sourceServiceNode, ctx.scanPath);
@@ -6646,10 +6701,13 @@ async function handleSpan(ctx, span) {
6646
6701
  }
6647
6702
  if (span.statusCode !== 2) {
6648
6703
  const status2 = httpResponseStatus(span);
6704
+ const grpcStatus = grpcStatusCodeFromAttrs(span.attributes);
6649
6705
  if (span.exception) {
6650
6706
  await recordExceptionIncident(ctx, span, ts);
6651
6707
  } else if (status2 !== void 0 && status2 >= 500) {
6652
6708
  await recordFailingResponseIncident(ctx, span, sourceId, ts, status2, 1);
6709
+ } else if (grpcStatus !== void 0 && grpcStatus !== 0) {
6710
+ await recordGrpcFailureIncident(ctx, span, ts);
6653
6711
  } else if (status2 !== void 0 && status2 >= 400 && spanMintsObservedEdge(span.kind)) {
6654
6712
  await advance4xxBurst(ctx, span, sourceId, ts, nowMs, status2);
6655
6713
  }