fboxrec 0.1.0 → 0.3.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/dist/index.d.mts CHANGED
@@ -94,7 +94,13 @@ declare function start(userConfig?: UserConfig): void;
94
94
  declare function trigger(reason?: string): string | null;
95
95
  /** Record a custom timeline event (e.g. flightbox.addEvent('cache.miss', { key })). */
96
96
  declare function addEvent(name: string, data?: Record<string, unknown>): void;
97
- /** Disarms recording, stops samplers and watchdogs. Module patches remain but degrade to no-ops. */
97
+ /**
98
+ * Disarms recording: stops samplers/watchdogs/timers, removes the process
99
+ * listeners, and restores the module patches (console, http server/client,
100
+ * fetch, pg). A patch that other tooling wrapped after start() can't be
101
+ * spliced out safely; it stays in place but passes straight through.
102
+ * start() may be called again afterwards.
103
+ */
98
104
  declare function stop(): void;
99
105
  declare const _default: {
100
106
  start: typeof start;
package/dist/index.d.ts CHANGED
@@ -94,7 +94,13 @@ declare function start(userConfig?: UserConfig): void;
94
94
  declare function trigger(reason?: string): string | null;
95
95
  /** Record a custom timeline event (e.g. flightbox.addEvent('cache.miss', { key })). */
96
96
  declare function addEvent(name: string, data?: Record<string, unknown>): void;
97
- /** Disarms recording, stops samplers and watchdogs. Module patches remain but degrade to no-ops. */
97
+ /**
98
+ * Disarms recording: stops samplers/watchdogs/timers, removes the process
99
+ * listeners, and restores the module patches (console, http server/client,
100
+ * fetch, pg). A patch that other tooling wrapped after start() can't be
101
+ * spliced out safely; it stays in place but passes straight through.
102
+ * start() may be called again afterwards.
103
+ */
98
104
  declare function stop(): void;
99
105
  declare const _default: {
100
106
  start: typeof start;
package/dist/index.mjs CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  start,
5
5
  stop,
6
6
  trigger
7
- } from "./chunk-HCJF2ASP.mjs";
7
+ } from "./chunk-4DHWBXXW.mjs";
8
8
  export {
9
9
  addEvent,
10
10
  index_default as default,
package/dist/register.cjs CHANGED
@@ -677,7 +677,7 @@ var FORMAT_VERSION = 1;
677
677
  var MAX_DECOMPRESSED_BYTES = 1024 * 1024 * 1024;
678
678
 
679
679
  // src/dump/serializer.ts
680
- var FLIGHTBOX_VERSION = "0.1.0";
680
+ var FLIGHTBOX_VERSION = "0.3.0";
681
681
  var DUMP_GZIP_LEVEL = 1;
682
682
  var dumpCounter = 0;
683
683
  function buildIncident(opts) {
@@ -1468,8 +1468,9 @@ function startWatchdog(agent) {
1468
1468
  // src/instrumentations/http-server.ts
1469
1469
  var http = __toESM(require("http"));
1470
1470
  var import_node_crypto2 = require("crypto");
1471
- var patched = false;
1472
1471
  var agentRef;
1472
+ var active2 = false;
1473
+ var saved = null;
1473
1474
  function tokenMatches(supplied, expected) {
1474
1475
  const a = (0, import_node_crypto2.createHash)("sha256").update(supplied).digest();
1475
1476
  const b = (0, import_node_crypto2.createHash)("sha256").update(expected).digest();
@@ -1511,12 +1512,12 @@ function handleFlightboxEndpoint(agent, req, res) {
1511
1512
  }
1512
1513
  function instrumentHttpServer(agent) {
1513
1514
  agentRef = agent;
1514
- if (patched) return;
1515
- patched = true;
1515
+ active2 = true;
1516
+ if (saved) return;
1516
1517
  const orig = http.Server.prototype.emit;
1517
1518
  const flightboxEmit = function(event) {
1518
1519
  const args = arguments;
1519
- if (event !== "request") {
1520
+ if (!active2 || event !== "request") {
1520
1521
  return orig.apply(this, args);
1521
1522
  }
1522
1523
  const agent2 = agentRef;
@@ -1569,13 +1570,15 @@ function instrumentHttpServer(agent) {
1569
1570
  }
1570
1571
  return requestStorage.run(ctx, () => orig.apply(this, args));
1571
1572
  };
1572
- http.Server.prototype.emit = flightboxEmit;
1573
+ saved = { orig, wrapper: flightboxEmit };
1574
+ http.Server.prototype.emit = saved.wrapper;
1573
1575
  }
1574
1576
 
1575
1577
  // src/instrumentations/http-client.ts
1576
1578
  var import_node_module = require("module");
1577
- var patched2 = false;
1578
1579
  var agentRef2;
1580
+ var active3 = false;
1581
+ var liveWraps = /* @__PURE__ */ new Map();
1579
1582
  function extractTarget(args) {
1580
1583
  let method = "GET";
1581
1584
  let host = "";
@@ -1607,10 +1610,12 @@ function extractTarget(args) {
1607
1610
  return { method: String(method).toUpperCase(), host: String(host), path: String(path8) };
1608
1611
  }
1609
1612
  var nodeRequire = (0, import_node_module.createRequire)(process.cwd() + "/noop.js");
1610
- function wrapModule(mod) {
1611
- const origRequest = mod.request.bind(mod);
1613
+ function wrapModule(key, mod) {
1614
+ const rawRequest = mod.request;
1615
+ const rawGet = mod.get;
1616
+ const origRequest = rawRequest.bind(mod);
1612
1617
  const tracedRequest = function(...args) {
1613
- if (isShedding()) return origRequest(...args);
1618
+ if (!active3 || isShedding()) return origRequest(...args);
1614
1619
  const agent = agentRef2;
1615
1620
  let spanId = 0n;
1616
1621
  let requestId = 0n;
@@ -1657,18 +1662,27 @@ function wrapModule(mod) {
1657
1662
  }
1658
1663
  return req;
1659
1664
  };
1660
- mod.request = tracedRequest;
1661
- mod.get = function(...args) {
1665
+ const tracedGet = function(...args) {
1662
1666
  const req = tracedRequest(...args);
1663
1667
  req.end();
1664
1668
  return req;
1665
1669
  };
1670
+ mod.request = tracedRequest;
1671
+ mod.get = tracedGet;
1672
+ liveWraps.set(key, () => {
1673
+ let clear = true;
1674
+ if (mod.request === tracedRequest) mod.request = rawRequest;
1675
+ else clear = false;
1676
+ if (mod.get === tracedGet) mod.get = rawGet;
1677
+ else clear = false;
1678
+ return clear;
1679
+ });
1666
1680
  }
1667
1681
  function wrapFetch() {
1668
1682
  const origFetch = globalThis.fetch;
1669
1683
  if (typeof origFetch !== "function") return;
1670
- globalThis.fetch = async function flightboxFetch(input, init) {
1671
- if (isShedding()) return origFetch(input, init);
1684
+ const wrapper = async function flightboxFetch(input, init) {
1685
+ if (!active3 || isShedding()) return origFetch(input, init);
1672
1686
  const agent = agentRef2;
1673
1687
  let spanId = 0n;
1674
1688
  let requestId = 0n;
@@ -1721,22 +1735,35 @@ function wrapFetch() {
1721
1735
  throw err;
1722
1736
  }
1723
1737
  };
1738
+ globalThis.fetch = wrapper;
1739
+ liveWraps.set("fetch", () => {
1740
+ if (globalThis.fetch === wrapper) {
1741
+ globalThis.fetch = origFetch;
1742
+ return true;
1743
+ }
1744
+ return false;
1745
+ });
1724
1746
  }
1725
1747
  function instrumentHttpClient(agent) {
1726
1748
  agentRef2 = agent;
1727
- if (patched2) return;
1728
- patched2 = true;
1729
- try {
1730
- wrapModule(nodeRequire("node:http"));
1731
- } catch {
1749
+ active3 = true;
1750
+ if (!liveWraps.has("http")) {
1751
+ try {
1752
+ wrapModule("http", nodeRequire("node:http"));
1753
+ } catch {
1754
+ }
1732
1755
  }
1733
- try {
1734
- wrapModule(nodeRequire("node:https"));
1735
- } catch {
1756
+ if (!liveWraps.has("https")) {
1757
+ try {
1758
+ wrapModule("https", nodeRequire("node:https"));
1759
+ } catch {
1760
+ }
1736
1761
  }
1737
- try {
1738
- wrapFetch();
1739
- } catch {
1762
+ if (!liveWraps.has("fetch")) {
1763
+ try {
1764
+ wrapFetch();
1765
+ } catch {
1766
+ }
1740
1767
  }
1741
1768
  }
1742
1769
 
@@ -1756,17 +1783,21 @@ function paramShapes(values) {
1756
1783
  return values.slice(0, 32).map((v) => v === null ? "null" : Array.isArray(v) ? "array" : typeof v);
1757
1784
  }
1758
1785
  var agentRef3;
1786
+ var active4 = false;
1787
+ var queryPatch = null;
1788
+ var connectPatch = null;
1759
1789
  function instrumentPg(agent) {
1760
1790
  agentRef3 = agent;
1761
1791
  const recorder = {
1762
1792
  record: ((...args) => agentRef3.recorder.record(...args))
1763
1793
  };
1794
+ active4 = true;
1764
1795
  const pg = loadPg();
1765
1796
  if (!pg?.Client?.prototype?.query) return false;
1766
- if (!pg.Client.prototype.query.__flightbox) {
1797
+ if (!queryPatch && !pg.Client.prototype.query.__flightbox) {
1767
1798
  const origQuery = pg.Client.prototype.query;
1768
1799
  const wrappedQuery = function(...args) {
1769
- if (isShedding()) return origQuery.apply(this, args);
1800
+ if (!active4 || isShedding()) return origQuery.apply(this, args);
1770
1801
  let spanId = 0n;
1771
1802
  let requestId = 0n;
1772
1803
  let tStart = 0n;
@@ -1839,13 +1870,14 @@ function instrumentPg(agent) {
1839
1870
  return out;
1840
1871
  };
1841
1872
  wrappedQuery.__flightbox = true;
1873
+ queryPatch = { proto: pg.Client.prototype, orig: origQuery, wrapper: wrappedQuery };
1842
1874
  pg.Client.prototype.query = wrappedQuery;
1843
1875
  }
1844
1876
  const Pool = pg.Pool;
1845
- if (Pool?.prototype?.connect && !Pool.prototype.connect.__flightbox) {
1877
+ if (Pool?.prototype?.connect && !connectPatch && !Pool.prototype.connect.__flightbox) {
1846
1878
  const origConnect = Pool.prototype.connect;
1847
1879
  const wrappedConnect = function(cb) {
1848
- if (isShedding()) return origConnect.call(this, cb);
1880
+ if (!active4 || isShedding()) return origConnect.call(this, cb);
1849
1881
  const tStart = nowMono();
1850
1882
  const requestId = currentRequestId();
1851
1883
  const record = () => {
@@ -1872,6 +1904,7 @@ function instrumentPg(agent) {
1872
1904
  return out;
1873
1905
  };
1874
1906
  wrappedConnect.__flightbox = true;
1907
+ connectPatch = { proto: Pool.prototype, orig: origConnect, wrapper: wrappedConnect };
1875
1908
  Pool.prototype.connect = wrappedConnect;
1876
1909
  }
1877
1910
  return true;
@@ -1881,24 +1914,28 @@ function instrumentPg(agent) {
1881
1914
  var import_node_util = require("util");
1882
1915
  var LEVELS = ["log", "info", "warn", "error", "debug"];
1883
1916
  var FORMAT_OPTS = { depth: 2, maxArrayLength: 20, maxStringLength: LIMITS.log };
1884
- var patched3 = false;
1885
1917
  var agentRef4;
1918
+ var active5 = false;
1919
+ var patches = /* @__PURE__ */ new Map();
1886
1920
  function instrumentConsole(agent) {
1887
1921
  agentRef4 = agent;
1888
- if (patched3) return;
1889
- patched3 = true;
1922
+ active5 = true;
1890
1923
  for (const level of LEVELS) {
1891
- const orig = console[level].bind(console);
1892
- console[level] = function flightboxConsole(...args) {
1924
+ if (patches.has(level)) continue;
1925
+ const orig = console[level];
1926
+ const bound = orig.bind(console);
1927
+ const wrapper = function flightboxConsole(...args) {
1893
1928
  try {
1894
- if (!isShedding()) {
1929
+ if (active5 && !isShedding()) {
1895
1930
  const msg = capScrub((0, import_node_util.formatWithOptions)(FORMAT_OPTS, ...args), LIMITS.log);
1896
1931
  agentRef4.recorder.record(8 /* Log */, { level, msg });
1897
1932
  }
1898
1933
  } catch {
1899
1934
  }
1900
- orig(...args);
1935
+ bound(...args);
1901
1936
  };
1937
+ patches.set(level, { orig, wrapper });
1938
+ console[level] = wrapper;
1902
1939
  }
1903
1940
  }
1904
1941