@kb-labs/gateway-app 2.118.0 → 2.118.1

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/index.js CHANGED
@@ -2697,17 +2697,48 @@ function pumpBidirectional(client, upstream, logger) {
2697
2697
  const pending = [];
2698
2698
  let upstreamOpen = false;
2699
2699
  let closed = false;
2700
- const closeBoth = (code, reason) => {
2700
+ const startedAt = Date.now();
2701
+ let clientToUpstreamMessages = 0;
2702
+ let upstreamToClientMessages = 0;
2703
+ let clientToUpstreamBytes = 0;
2704
+ let upstreamToClientBytes = 0;
2705
+ let droppedMessages = 0;
2706
+ const byteLength = (data) => {
2707
+ if (typeof data === "string") {
2708
+ return Buffer.byteLength(data);
2709
+ }
2710
+ if (Buffer.isBuffer(data)) {
2711
+ return data.byteLength;
2712
+ }
2713
+ if (data instanceof ArrayBuffer) {
2714
+ return data.byteLength;
2715
+ }
2716
+ return data.reduce((total, chunk) => total + chunk.byteLength, 0);
2717
+ };
2718
+ const closeBoth = (code, reason, closeReason = "peer_closed") => {
2701
2719
  if (closed) {
2702
2720
  return;
2703
2721
  }
2704
2722
  closed = true;
2705
2723
  safeClose(client, code, reason);
2706
2724
  safeClose(upstream, code, reason);
2725
+ logger.info("Gateway WebSocket relay closed", {
2726
+ event: "websocket.relay.closed",
2727
+ closeReason,
2728
+ closeCode: code,
2729
+ durationMs: Date.now() - startedAt,
2730
+ clientToUpstreamMessages,
2731
+ upstreamToClientMessages,
2732
+ clientToUpstreamBytes,
2733
+ upstreamToClientBytes,
2734
+ droppedMessages
2735
+ });
2707
2736
  };
2708
2737
  client.on("message", (data, isBinary) => {
2709
2738
  if (upstreamOpen && upstream.readyState === OPEN) {
2710
2739
  upstream.send(data, { binary: isBinary });
2740
+ clientToUpstreamMessages += 1;
2741
+ clientToUpstreamBytes += byteLength(data);
2711
2742
  } else {
2712
2743
  pending.push({ data, binary: isBinary });
2713
2744
  }
@@ -2717,6 +2748,10 @@ function pumpBidirectional(client, upstream, logger) {
2717
2748
  for (const frame of pending) {
2718
2749
  if (upstream.readyState === OPEN) {
2719
2750
  upstream.send(frame.data, { binary: frame.binary });
2751
+ clientToUpstreamMessages += 1;
2752
+ clientToUpstreamBytes += byteLength(frame.data);
2753
+ } else {
2754
+ droppedMessages += 1;
2720
2755
  }
2721
2756
  }
2722
2757
  pending.length = 0;
@@ -2724,6 +2759,10 @@ function pumpBidirectional(client, upstream, logger) {
2724
2759
  upstream.on("message", (data, isBinary) => {
2725
2760
  if (client.readyState === OPEN) {
2726
2761
  client.send(data, { binary: isBinary });
2762
+ upstreamToClientMessages += 1;
2763
+ upstreamToClientBytes += byteLength(data);
2764
+ } else {
2765
+ droppedMessages += 1;
2727
2766
  }
2728
2767
  });
2729
2768
  upstream.on("close", (code, reason) => {
@@ -2734,11 +2773,11 @@ function pumpBidirectional(client, upstream, logger) {
2734
2773
  });
2735
2774
  upstream.on("error", (err) => {
2736
2775
  logger.warn("Upstream WS error", { error: err.message });
2737
- closeBoth(1011);
2776
+ closeBoth(1011, void 0, "upstream_error");
2738
2777
  });
2739
2778
  client.on("error", (err) => {
2740
2779
  logger.warn("Client WS error", { error: err.message });
2741
- closeBoth(1011);
2780
+ closeBoth(1011, void 0, "client_error");
2742
2781
  });
2743
2782
  }
2744
2783
 
@@ -2796,8 +2835,21 @@ function attachGatewayWs(server, cache, jwtConfig, logger, hostRegistry, socketW
2796
2835
  const { search } = new URL(req.url ?? "/", "http://localhost");
2797
2836
  const upstreamUrl = buildUpstreamWsUrl(socketUpstream, pathname, search);
2798
2837
  wss.handleUpgrade(req, socket, head, (clientWs) => {
2799
- const upstreamWs = new WebSocket(upstreamUrl, { headers: forwardWsHeaders(req) });
2800
- pumpBidirectional(clientWs, upstreamWs, logger);
2838
+ const requestId = typeof req.headers["x-request-id"] === "string" ? req.headers["x-request-id"] : randomUUID();
2839
+ const traceId = typeof req.headers["x-trace-id"] === "string" ? req.headers["x-trace-id"] : randomUUID();
2840
+ const connectionId = randomUUID();
2841
+ const connectionLogger = logger.child({
2842
+ requestId,
2843
+ traceId,
2844
+ "network.transport": "websocket",
2845
+ "network.connection_id": connectionId,
2846
+ "http.route": pathname
2847
+ }) ?? logger;
2848
+ connectionLogger.info("Gateway WebSocket relay opened", { event: "websocket.relay.opened" });
2849
+ const upstreamWs = new WebSocket(upstreamUrl, {
2850
+ headers: { ...forwardWsHeaders(req), "x-request-id": requestId, "x-trace-id": traceId }
2851
+ });
2852
+ pumpBidirectional(clientWs, upstreamWs, connectionLogger);
2801
2853
  });
2802
2854
  return;
2803
2855
  }