@lensmcp/node-instrumentation 1.21.3 → 1.21.5
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/index.d.ts +3 -0
- package/index.js +1 -1
- package/lib/active-work.d.ts +46 -0
- package/lib/active-work.js +1 -0
- package/lib/emit.d.ts +6 -2
- package/lib/emit.js +3 -3
- package/lib/install.js +1 -1
- package/lib/tap-bullmq.js +1 -1
- package/lib/tap-event-loop.d.ts +3 -0
- package/lib/tap-event-loop.js +1 -0
- package/lib/tap-stdout.js +3 -2
- package/package.json +2 -2
package/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export type { FloodGuard, FloodGuardOptions, FloodAdmit } from './lib/flood-guar
|
|
|
5
5
|
export { installRequireHook } from './lib/require-hook';
|
|
6
6
|
export type { ModuleTap } from './lib/require-hook';
|
|
7
7
|
export { tapEgress } from './lib/tap-egress';
|
|
8
|
+
export { tapEventLoop, stopEventLoopTapForTests } from './lib/tap-event-loop';
|
|
8
9
|
export { tapFs } from './lib/tap-fs';
|
|
9
10
|
export { tapExec } from './lib/tap-exec';
|
|
10
11
|
export { pgTap } from './lib/tap-pg';
|
|
@@ -13,3 +14,5 @@ export { bullmqTap } from './lib/tap-bullmq';
|
|
|
13
14
|
export { nestTap, installChildAppBridge } from './lib/tap-nest';
|
|
14
15
|
export type { CapturedChildApp } from './lib/tap-nest';
|
|
15
16
|
export { installLensmcpNodeInstrumentation } from './lib/install';
|
|
17
|
+
export { activeWorkSnapshot, beginActiveWork, installActiveWorkProbe, resetActiveWorkForTests } from './lib/active-work';
|
|
18
|
+
export type { ActiveWorkSnapshot } from './lib/active-work';
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var i=Object.defineProperty;var o=(t,r)=>i(t,"name",{value:r,configurable:!0});var n=Object.defineProperty,e=o((t,r)=>n(t,"name",{value:r,configurable:!0}),"e");Object.defineProperty(exports,"__esModule",{value:!0}),exports.resetActiveWorkForTests=exports.installActiveWorkProbe=exports.beginActiveWork=exports.activeWorkSnapshot=exports.installLensmcpNodeInstrumentation=exports.installChildAppBridge=exports.nestTap=exports.bullmqTap=exports.redisTap=exports.pgTap=exports.tapExec=exports.tapFs=exports.stopEventLoopTapForTests=exports.tapEventLoop=exports.tapEgress=exports.installRequireHook=exports.createEventFloodGuard=exports.maybeRotateEventFile=exports.EVENT_MAX_FILES=exports.EVENT_MAX_BYTES=exports.EVENT_FILE=exports.PROJECT=exports.isLensWriting=exports.lensEmit=void 0;var emit_1=require("./lib/emit");Object.defineProperty(exports,"lensEmit",{enumerable:!0,get:e(function(){return emit_1.lensEmit},"get")}),Object.defineProperty(exports,"isLensWriting",{enumerable:!0,get:e(function(){return emit_1.isLensWriting},"get")}),Object.defineProperty(exports,"PROJECT",{enumerable:!0,get:e(function(){return emit_1.PROJECT},"get")}),Object.defineProperty(exports,"EVENT_FILE",{enumerable:!0,get:e(function(){return emit_1.EVENT_FILE},"get")}),Object.defineProperty(exports,"EVENT_MAX_BYTES",{enumerable:!0,get:e(function(){return emit_1.EVENT_MAX_BYTES},"get")}),Object.defineProperty(exports,"EVENT_MAX_FILES",{enumerable:!0,get:e(function(){return emit_1.EVENT_MAX_FILES},"get")}),Object.defineProperty(exports,"maybeRotateEventFile",{enumerable:!0,get:e(function(){return emit_1.maybeRotateEventFile},"get")});var flood_guard_1=require("./lib/flood-guard");Object.defineProperty(exports,"createEventFloodGuard",{enumerable:!0,get:e(function(){return flood_guard_1.createEventFloodGuard},"get")});var require_hook_1=require("./lib/require-hook");Object.defineProperty(exports,"installRequireHook",{enumerable:!0,get:e(function(){return require_hook_1.installRequireHook},"get")});var tap_egress_1=require("./lib/tap-egress");Object.defineProperty(exports,"tapEgress",{enumerable:!0,get:e(function(){return tap_egress_1.tapEgress},"get")});var tap_event_loop_1=require("./lib/tap-event-loop");Object.defineProperty(exports,"tapEventLoop",{enumerable:!0,get:e(function(){return tap_event_loop_1.tapEventLoop},"get")}),Object.defineProperty(exports,"stopEventLoopTapForTests",{enumerable:!0,get:e(function(){return tap_event_loop_1.stopEventLoopTapForTests},"get")});var tap_fs_1=require("./lib/tap-fs");Object.defineProperty(exports,"tapFs",{enumerable:!0,get:e(function(){return tap_fs_1.tapFs},"get")});var tap_exec_1=require("./lib/tap-exec");Object.defineProperty(exports,"tapExec",{enumerable:!0,get:e(function(){return tap_exec_1.tapExec},"get")});var tap_pg_1=require("./lib/tap-pg");Object.defineProperty(exports,"pgTap",{enumerable:!0,get:e(function(){return tap_pg_1.pgTap},"get")});var tap_redis_1=require("./lib/tap-redis");Object.defineProperty(exports,"redisTap",{enumerable:!0,get:e(function(){return tap_redis_1.redisTap},"get")});var tap_bullmq_1=require("./lib/tap-bullmq");Object.defineProperty(exports,"bullmqTap",{enumerable:!0,get:e(function(){return tap_bullmq_1.bullmqTap},"get")});var tap_nest_1=require("./lib/tap-nest");Object.defineProperty(exports,"nestTap",{enumerable:!0,get:e(function(){return tap_nest_1.nestTap},"get")}),Object.defineProperty(exports,"installChildAppBridge",{enumerable:!0,get:e(function(){return tap_nest_1.installChildAppBridge},"get")});var install_1=require("./lib/install");Object.defineProperty(exports,"installLensmcpNodeInstrumentation",{enumerable:!0,get:e(function(){return install_1.installLensmcpNodeInstrumentation},"get")});var active_work_1=require("./lib/active-work");Object.defineProperty(exports,"activeWorkSnapshot",{enumerable:!0,get:e(function(){return active_work_1.activeWorkSnapshot},"get")}),Object.defineProperty(exports,"beginActiveWork",{enumerable:!0,get:e(function(){return active_work_1.beginActiveWork},"get")}),Object.defineProperty(exports,"installActiveWorkProbe",{enumerable:!0,get:e(function(){return active_work_1.installActiveWorkProbe},"get")}),Object.defineProperty(exports,"resetActiveWorkForTests",{enumerable:!0,get:e(function(){return active_work_1.resetActiveWorkForTests},"get")});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How much work is this pod still doing that is NOT an open HTTP request?
|
|
3
|
+
*
|
|
4
|
+
* The devserver hot-swaps a pod in place: on every successful webpack rebuild the child
|
|
5
|
+
* re-imports the bundle, builds a fresh app, points the handler at it and closes the
|
|
6
|
+
* previous one. That close used to be fire-and-forget — and it tears down the OLD app's
|
|
7
|
+
* providers, which for a queue consumer means the BullMQ worker and its Redis
|
|
8
|
+
* connection. A job running at that moment loses its lock renewal, so the lock sits
|
|
9
|
+
* until its full TTL lapses and the stalled-checker cannot reclaim it: a `hazard_analyst`
|
|
10
|
+
* step with a 3600 s `lockDuration` stalled for an hour, having already spent ~50k output
|
|
11
|
+
* tokens, and the DB looked byte-identical to a slow model call (foodguard, 2026-08-27).
|
|
12
|
+
*
|
|
13
|
+
* Counting open HTTP requests would not have caught it — the job holds no request. So
|
|
14
|
+
* the taps register their in-process work here, and the devserver waits for it to drain
|
|
15
|
+
* before closing the old app.
|
|
16
|
+
*
|
|
17
|
+
* Published on a global rather than exported for import: the devserver child must read
|
|
18
|
+
* it without depending on this package (instrumentation is optional — a pod runs
|
|
19
|
+
* untapped when it is absent), exactly like `global.createChildApp`.
|
|
20
|
+
*/
|
|
21
|
+
/** The shape the devserver child reads off the global. Keep in sync with `main.devserver.ts`. */
|
|
22
|
+
export interface ActiveWorkSnapshot {
|
|
23
|
+
/** In-process units of work currently running (queue jobs, and whatever else registers). */
|
|
24
|
+
count: number;
|
|
25
|
+
/** When the longest-running one started, for reporting. */
|
|
26
|
+
oldestStartedAt?: number;
|
|
27
|
+
}
|
|
28
|
+
export declare function beginActiveWorkGeneration(): number;
|
|
29
|
+
export declare function activeWorkGeneration(): number;
|
|
30
|
+
/**
|
|
31
|
+
* Register one unit of in-process work. Returns the "done" callback — call it in a
|
|
32
|
+
* `finally` so a throwing job cannot leak a permanent +1 and wedge every future swap.
|
|
33
|
+
*
|
|
34
|
+
* `gen` attributes the work to an app generation. Omitted means UNATTRIBUTED, and
|
|
35
|
+
* unattributed work counts toward every generation — the conservative direction: a drain
|
|
36
|
+
* that waits too long costs bounded memory (the devserver caps concurrent drains), while
|
|
37
|
+
* one that finishes too early kills a running job, which is the incident this exists to
|
|
38
|
+
* prevent.
|
|
39
|
+
*/
|
|
40
|
+
export declare function beginActiveWork(gen?: number): () => void;
|
|
41
|
+
/** Work in flight. With `gen`, only that generation's work plus anything unattributed. */
|
|
42
|
+
export declare function activeWorkSnapshot(gen?: number): ActiveWorkSnapshot;
|
|
43
|
+
/** Publish the reader on the global so the devserver can poll it without importing us. */
|
|
44
|
+
export declare function installActiveWorkProbe(): void;
|
|
45
|
+
/** Tests only. */
|
|
46
|
+
export declare function resetActiveWorkForTests(): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var a=Object.defineProperty;var o=(t,e)=>a(t,"name",{value:e,configurable:!0});var i=Object.defineProperty,n=o((t,e)=>i(t,"name",{value:e,configurable:!0}),"n");Object.defineProperty(exports,"__esModule",{value:!0}),exports.beginActiveWorkGeneration=beginActiveWorkGeneration,exports.activeWorkGeneration=activeWorkGeneration,exports.beginActiveWork=beginActiveWork,exports.activeWorkSnapshot=activeWorkSnapshot,exports.installActiveWorkProbe=installActiveWorkProbe,exports.resetActiveWorkForTests=resetActiveWorkForTests;const GLOBAL_KEY="__lensmcpActiveWork",running=new Set;let currentGeneration=0;function beginActiveWorkGeneration(){return++currentGeneration}o(beginActiveWorkGeneration,"beginActiveWorkGeneration"),n(beginActiveWorkGeneration,"beginActiveWorkGeneration");function activeWorkGeneration(){return currentGeneration}o(activeWorkGeneration,"activeWorkGeneration"),n(activeWorkGeneration,"activeWorkGeneration");function beginActiveWork(t){const e={at:Date.now(),...t===void 0?{}:{gen:t}};running.add(e);let r=!1;return()=>{r||(r=!0,running.delete(e))}}o(beginActiveWork,"beginActiveWork"),n(beginActiveWork,"beginActiveWork");function activeWorkSnapshot(t){let e,r=0;for(const c of running)t!==void 0&&c.gen!==void 0&&c.gen!==t||(r+=1,(e===void 0||c.at<e)&&(e=c.at));return{count:r,...e===void 0?{}:{oldestStartedAt:e}}}o(activeWorkSnapshot,"activeWorkSnapshot"),n(activeWorkSnapshot,"activeWorkSnapshot");function installActiveWorkProbe(){globalThis[GLOBAL_KEY]=activeWorkSnapshot,globalThis.__lensmcpBeginWorkGeneration=beginActiveWorkGeneration}o(installActiveWorkProbe,"installActiveWorkProbe"),n(installActiveWorkProbe,"installActiveWorkProbe");function resetActiveWorkForTests(){running.clear(),currentGeneration=0}o(resetActiveWorkForTests,"resetActiveWorkForTests"),n(resetActiveWorkForTests,"resetActiveWorkForTests");
|
package/lib/emit.d.ts
CHANGED
|
@@ -35,11 +35,15 @@ export interface FlowCtx {
|
|
|
35
35
|
requestId?: string;
|
|
36
36
|
originNodeId?: string;
|
|
37
37
|
}
|
|
38
|
-
export declare function lensEmit(source: string, severity: LensSeverity, title: string, raw: Record<string, unknown>, fingerprint?: string, flowCtx?: FlowCtx
|
|
38
|
+
export declare function lensEmit(source: string, severity: LensSeverity, title: string, raw: Record<string, unknown>, fingerprint?: string, flowCtx?: FlowCtx,
|
|
39
|
+
/** Event category. Defaults to `cluster` — what every tap emitted before this existed. */
|
|
40
|
+
category?: string): void;
|
|
39
41
|
/**
|
|
40
42
|
* Emit a raw service log line — the ACTUAL stdout/Logger output a pod prints — as
|
|
41
43
|
* a `runtime` event so it surfaces in the dashboard Logs view. Same fs-tap-safe
|
|
42
44
|
* write path as {@link lensEmit}; `source: 'nestjs'` + `raw.project` carries the
|
|
43
45
|
* concrete service name (which the dashboard prefers as the log's source).
|
|
44
46
|
*/
|
|
45
|
-
export declare function lensLog(severity: LogSeverity, title: string
|
|
47
|
+
export declare function lensLog(severity: LogSeverity, title: string, detail?: {
|
|
48
|
+
stack?: string;
|
|
49
|
+
}): void;
|
package/lib/emit.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";var u=Object.defineProperty;var E=(e,
|
|
2
|
-
`;maybeRotateEventFile(exports.EVENT_FILE,
|
|
3
|
-
`;maybeRotateEventFile(exports.EVENT_FILE,
|
|
1
|
+
"use strict";var u=Object.defineProperty;var E=(e,s)=>u(e,"name",{value:s,configurable:!0});var a=Object.defineProperty,c=E((e,s)=>a(e,"name",{value:s,configurable:!0}),"c");Object.defineProperty(exports,"__esModule",{value:!0}),exports.EVENT_FILE=exports.PROJECT=exports.EVENT_MAX_FILES=exports.EVENT_MAX_BYTES=void 0,exports.maybeRotateEventFile=maybeRotateEventFile,exports.isLensWriting=isLensWriting,exports.lensEmit=lensEmit,exports.lensLog=lensLog;const tslib_1=require("tslib"),nodeFs=tslib_1.__importStar(require("node:fs")),node_path_1=require("node:path"),flood_guard_1=require("./flood-guard"),flow_context_1=require("./flow-context"),appendFileSync=nodeFs.appendFileSync,mkdirSync=nodeFs.mkdirSync,statSync=nodeFs.statSync,renameSync=nodeFs.renameSync,unlinkSync=nodeFs.unlinkSync;exports.EVENT_MAX_BYTES=(()=>{const e=Number(process.env.LENSMCP_EVENT_MAX_BYTES);return Number.isFinite(e)&&e>0?e:50*1024*1024})(),exports.EVENT_MAX_FILES=(()=>{const e=Number(process.env.LENSMCP_EVENT_MAX_FILES);return Number.isFinite(e)&&e>=1&&e<=20?Math.floor(e):5})();const ROTATE_CHECK_BYTES=1024*1024,bytesSinceCheck=new Map;function maybeRotateEventFile(e,s,o){const n=(bytesSinceCheck.get(e)??0)+s;if(n<ROTATE_CHECK_BYTES&&o===void 0){bytesSinceCheck.set(e,n);return}const i=o?.maxBytes??exports.EVENT_MAX_BYTES,t=o?.maxFiles??exports.EVENT_MAX_FILES;try{const r=statSync(e).size;if(bytesSinceCheck.set(e,0),r<=i)return}catch{bytesSinceCheck.set(e,n);return}try{unlinkSync(`${e}.${t}`)}catch{}for(let r=t-1;r>=1;r--)try{renameSync(`${e}.${r}`,`${e}.${r+1}`)}catch{}try{renameSync(e,`${e}.1`)}catch{}}E(maybeRotateEventFile,"maybeRotateEventFile"),c(maybeRotateEventFile,"maybeRotateEventFile"),exports.PROJECT=process.env.LENSMCP_PROJECT||process.env.SERVICE_NAME||"app",exports.EVENT_FILE=process.env.LENSMCP_EVENT_FILE||`${process.cwd()}/.lensmcp/events.jsonl`;let writing=!1,dirReady=!1;const emitGuard=(0,flood_guard_1.createEventFloodGuard)({burst:30,perSec:5}),logGuard=(0,flood_guard_1.createEventFloodGuard)({burst:120,perSec:20});function isLensWriting(){return writing}E(isLensWriting,"isLensWriting"),c(isLensWriting,"isLensWriting");function lensEmit(e,s,o,n,i,t,r="cluster"){try{writing=!0;const d=i??`${e}:${String(n.name??e)}`,p=emitGuard.admit(d);if(!p.ok)return;dirReady||(mkdirSync((0,node_path_1.dirname)(exports.EVENT_FILE),{recursive:!0}),dirReady=!0);const l=JSON.stringify({id:Date.now().toString(36)+Math.random().toString(36).slice(2,10),sessionId:"pending",timestamp:Date.now(),source:e,category:r,severity:s,context:{sessionId:"pending",projectName:exports.PROJECT,...t?.flowId?{flowId:t.flowId}:{},...t?.requestId?{requestId:t.requestId}:{},...t?.originNodeId?{originNodeId:t.originNodeId}:{}},fingerprint:d,title:o,raw:{project:exports.PROJECT,...n,...p.suppressed>0?{floodSuppressed:p.suppressed}:{}}})+`
|
|
2
|
+
`;maybeRotateEventFile(exports.EVENT_FILE,l.length),appendFileSync(exports.EVENT_FILE,l)}catch{}finally{writing=!1}}E(lensEmit,"lensEmit"),c(lensEmit,"lensEmit");function lensLog(e,s,o){try{writing=!0;const n=e==="error"||e==="fatal"?`log:error:${exports.PROJECT}`:`log:${exports.PROJECT}`,i=logGuard.admit(n);if(!i.ok)return;dirReady||(mkdirSync((0,node_path_1.dirname)(exports.EVENT_FILE),{recursive:!0}),dirReady=!0);const t=(0,flow_context_1.flowContext)(),r=JSON.stringify({id:Date.now().toString(36)+Math.random().toString(36).slice(2,10),sessionId:"pending",timestamp:Date.now(),source:"nestjs",category:"runtime",severity:e,context:{sessionId:"pending",projectName:exports.PROJECT,...t?.flowId?{flowId:t.flowId}:{},...t?.requestId?{requestId:t.requestId}:{}},fingerprint:n,title:s,raw:{project:exports.PROJECT,kind:"log",...o?.stack?{request:{error:{message:s,stack:o.stack}}}:{},...i.suppressed>0?{floodSuppressed:i.suppressed}:{}}})+`
|
|
3
|
+
`;maybeRotateEventFile(exports.EVENT_FILE,r.length),appendFileSync(exports.EVENT_FILE,r)}catch{}finally{writing=!1}}E(lensLog,"lensLog"),c(lensLog,"lensLog");
|
package/lib/install.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var p=Object.defineProperty;var a=(t,r)=>p(t,"name",{value:r,configurable:!0});var s=Object.defineProperty,e=a((t,r)=>s(t,"name",{value:r,configurable:!0}),"e");Object.defineProperty(exports,"__esModule",{value:!0}),exports.installLensmcpNodeInstrumentation=installLensmcpNodeInstrumentation;const require_hook_1=require("./require-hook"),flow_context_1=require("./flow-context"),tap_egress_1=require("./tap-egress"),tap_fs_1=require("./tap-fs"),tap_exec_1=require("./tap-exec"),tap_pg_1=require("./tap-pg"),tap_redis_1=require("./tap-redis"),tap_bullmq_1=require("./tap-bullmq"),tap_nest_1=require("./tap-nest"),tap_stdout_1=require("./tap-stdout");function installLensmcpNodeInstrumentation(){const t=globalThis;if(!t.__lensmcpNodeInstrumented&&(t.__lensmcpNodeInstrumented=!0,process.env.LENSMCP_AUTO!=="0")){try{(0,flow_context_1.primeFlowContext)()}catch{}try{(0,tap_egress_1.tapEgress)()}catch{}try{(0,tap_fs_1.tapFs)()}catch{}try{(0,tap_exec_1.tapExec)()}catch{}try{(0,tap_stdout_1.tapStdout)()}catch{}try{(0,require_hook_1.installRequireHook)({pg:tap_pg_1.pgTap,ioredis:tap_redis_1.redisTap,bullmq:tap_bullmq_1.bullmqTap,"@nestjs/core":tap_nest_1.nestTap})}catch{}try{(0,tap_nest_1.installChildAppBridge)()}catch{}}}a(installLensmcpNodeInstrumentation,"installLensmcpNodeInstrumentation"),e(installLensmcpNodeInstrumentation,"installLensmcpNodeInstrumentation");
|
|
1
|
+
"use strict";var p=Object.defineProperty;var a=(t,r)=>p(t,"name",{value:r,configurable:!0});var s=Object.defineProperty,e=a((t,r)=>s(t,"name",{value:r,configurable:!0}),"e");Object.defineProperty(exports,"__esModule",{value:!0}),exports.installLensmcpNodeInstrumentation=installLensmcpNodeInstrumentation;const require_hook_1=require("./require-hook"),flow_context_1=require("./flow-context"),tap_egress_1=require("./tap-egress"),tap_fs_1=require("./tap-fs"),tap_exec_1=require("./tap-exec"),tap_pg_1=require("./tap-pg"),tap_redis_1=require("./tap-redis"),active_work_1=require("./active-work"),tap_bullmq_1=require("./tap-bullmq"),tap_nest_1=require("./tap-nest"),tap_event_loop_1=require("./tap-event-loop"),tap_stdout_1=require("./tap-stdout");function installLensmcpNodeInstrumentation(){const t=globalThis;if(!t.__lensmcpNodeInstrumented&&(t.__lensmcpNodeInstrumented=!0,process.env.LENSMCP_AUTO!=="0")){try{(0,active_work_1.installActiveWorkProbe)()}catch{}try{(0,flow_context_1.primeFlowContext)()}catch{}try{(0,tap_egress_1.tapEgress)()}catch{}try{(0,tap_fs_1.tapFs)()}catch{}try{(0,tap_exec_1.tapExec)()}catch{}try{(0,tap_stdout_1.tapStdout)()}catch{}try{(0,tap_event_loop_1.tapEventLoop)()}catch{}try{(0,require_hook_1.installRequireHook)({pg:tap_pg_1.pgTap,ioredis:tap_redis_1.redisTap,bullmq:tap_bullmq_1.bullmqTap,"@nestjs/core":tap_nest_1.nestTap})}catch{}try{(0,tap_nest_1.installChildAppBridge)()}catch{}}}a(installLensmcpNodeInstrumentation,"installLensmcpNodeInstrumentation"),e(installLensmcpNodeInstrumentation,"installLensmcpNodeInstrumentation");
|
package/lib/tap-bullmq.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var b=Object.defineProperty;var p=(o,t)=>b(o,"name",{value:t,configurable:!0});var w=Object.defineProperty,l=p((o,t)=>w(o,"name",{value:t,configurable:!0}),"l");Object.defineProperty(exports,"__esModule",{value:!0}),exports.bullmqTap=bullmqTap;const active_work_1=require("./active-work"),workerGeneration=new WeakMap,emit_1=require("./emit"),flow_context_1=require("./flow-context");function jobFlow(o){const t=o?.opts?.__lensmcpFlow;return t&&typeof t=="object"?t:void 0}p(jobFlow,"jobFlow"),l(jobFlow,"jobFlow");const jobLegId=l((o,t)=>`job:${o}#${t?.id??"?"}`,"jobLegId"),publishers=new Map;function bullmqTap(o){const t=o;if(typeof t?.Queue!="function"||typeof t?.Worker!="function")return!1;try{tapQueueAdd(t)}catch{}try{tapWorkerEmit(t)}catch{}try{tapWorkerProcess(t)}catch{}return!0}p(bullmqTap,"bullmqTap"),l(bullmqTap,"bullmqTap");function tapWorkerProcess(o){const t=o.Worker?.prototype,u=t?.callProcessJob;if(!t||typeof u!="function"||u.__lensmcp)return;const i=l(async function(e,...c){let a=workerGeneration.get(this);a===void 0&&(a=(0,active_work_1.activeWorkGeneration)(),workerGeneration.set(this,a));const r=(0,active_work_1.beginActiveWork)(a),s=jobFlow(e);if(!s?.flowId)return u.call(this,e,...c).finally(r);const n=String(this?.name??e?.queueName??"queue"),m=jobLegId(n,e),d=Date.now(),f={flowId:s.flowId,requestId:m};return(0,flow_context_1.runInFlowContext)(f,async()=>{try{const q=await u.call(this,e,...c);return(0,emit_1.lensEmit)("queue","info",`process ${e?.name}#${e?.id} (${Date.now()-d}ms)`,{queue:n,kind:"queue-process",job:e?.name,jobId:e?.id,startedAt:d,durationMs:Date.now()-d,status:"ok"},`queue:${n}`,f),q}catch(q){throw(0,emit_1.lensEmit)("queue","error",`process ${e?.name}#${e?.id} failed (${Date.now()-d}ms)`,{queue:n,kind:"queue-process",job:e?.name,jobId:e?.id,startedAt:d,durationMs:Date.now()-d,status:"error",error:String(q?.message??q)},`queue:${n}`,f),q}finally{r()}})},"wrapped");i.__lensmcp=!0,t.callProcessJob=i}p(tapWorkerProcess,"tapWorkerProcess"),l(tapWorkerProcess,"tapWorkerProcess");function tapQueueAdd(o){const t=o.Queue?.prototype,u=t?.add;if(!t||typeof u!="function"||u.__lensmcp)return;const i=l(async function(e,...c){const a=Date.now(),r=(0,flow_context_1.flowContext)();if(r?.flowId){const n=c[1]??{};c[1]={...n,__lensmcpFlow:{flowId:r.flowId,...r.requestId?{originRequestId:r.requestId}:{}}}}const s=await u.call(this,e,...c);try{const n=String(this?.name??"queue"),m=c[0];let d;try{const f=JSON.stringify(m);d=f&&f!=="undefined"?f.length>300?f.slice(0,299)+"\u2026":f:void 0}catch{}(0,emit_1.lensEmit)("queue","info",`enqueued ${e}#${s?.id} \u2192 ${n}`,{queue:n,kind:"queue-enqueued",job:e,jobId:s?.id,...d?{data:d}:{},startedAt:a,durationMs:Date.now()-a},`queue:${n}`,r),ensureStatePublisher(n,this)}catch{}return s},"wrapped");i.__lensmcp=!0,t.add=i}p(tapQueueAdd,"tapQueueAdd"),l(tapQueueAdd,"tapQueueAdd");function tapWorkerEmit(o){const t=o.Worker?.prototype,u=t?.emit;if(!t||typeof u!="function"||u.__lensmcp)return;const i=l(function(e,...c){try{observeWorkerEvent(this,String(e),c)}catch{}return u.call(this,e,...c)},"wrapped");i.__lensmcp=!0,t.emit=i}p(tapWorkerEmit,"tapWorkerEmit"),l(tapWorkerEmit,"tapWorkerEmit");function observeWorkerEvent(o,t,u){if(t!=="active"&&t!=="completed"&&t!=="failed")return;const i=String(o.name??"queue"),e=u[0],c=jobFlow(e),a=c?.flowId?{flowId:c.flowId,requestId:jobLegId(i,e)}:void 0;if(t==="active")(0,emit_1.lensEmit)("queue","info",`processing ${e?.name}#${e?.id}`,{queue:i,kind:"queue-active",jobId:e?.id},`queue:${i}`,a);else if(t==="completed"){let r;try{const s=e?.returnvalue??u[1],n=JSON.stringify(s);r=n&&n!=="undefined"?n.length>160?n.slice(0,159)+"\u2026":n:void 0}catch{}(0,emit_1.lensEmit)("queue","info",`completed ${e?.name}#${e?.id}`,{queue:i,kind:"queue-completed",jobId:e?.id,...r?{returned:r}:{}},`queue:${i}`,a)}else{const r=u[1];(0,emit_1.lensEmit)("queue","error",`job ${e?.id} failed: ${r?.message}`,{queue:i,kind:"queue-failed",jobId:e?.id,error:String(r?.message??r)},`queue:${i}`,a)}if(!publishers.has(i))try{const r=o.opts,s=require("bullmq").Queue;ensureStatePublisher(i,new s(i,{connection:r?.connection}))}catch{}}p(observeWorkerEvent,"observeWorkerEvent"),l(observeWorkerEvent,"observeWorkerEvent");function ensureStatePublisher(o,t){if(publishers.has(o))return;let u="";const i=setInterval(()=>{(async()=>{try{const e=await t.getJobCounts(),c=[];for(const s of["active","waiting","failed","completed","delayed"])for(const n of await t.getJobs([s],0,7)){const m=n?.data?.to;c.push({id:String(n.id),name:n.name,state:s,timestamp:n.timestamp??0,...typeof m=="string"?{to:m}:{}})}c.sort((s,n)=>Number(n.timestamp)-Number(s.timestamp));const a=c.slice(0,8),r=JSON.stringify([e,a.map(s=>`${s.id}${s.state}`)]);if(r===u)return;u=r,(0,emit_1.lensEmit)("queue","info",`queue state: ${e.active??0} active \xB7 ${e.waiting??0} waiting \xB7 ${e.failed??0} failed`,{queue:o,kind:"queue-state",counts:e,recent:a},`queue:${o}`)}catch{}})()},2e3);i.unref?.(),publishers.set(o,i)}p(ensureStatePublisher,"ensureStatePublisher"),l(ensureStatePublisher,"ensureStatePublisher");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var m=Object.defineProperty;var r=(e,o)=>m(e,"name",{value:o,configurable:!0});var a=Object.defineProperty,n=r((e,o)=>a(e,"name",{value:o,configurable:!0}),"n");Object.defineProperty(exports,"__esModule",{value:!0}),exports.tapEventLoop=tapEventLoop,exports.stopEventLoopTapForTests=stopEventLoopTapForTests;const node_perf_hooks_1=require("node:perf_hooks"),emit_1=require("./emit"),SAMPLE_MS=(()=>{const e=Number(process.env.LENSMCP_EVENT_LOOP_SAMPLE_MS);return Number.isFinite(e)&&e>=1e3?e:3e4})(),REPORT_ABOVE_MS=(()=>{const e=Number(process.env.LENSMCP_EVENT_LOOP_MIN_MS);return Number.isFinite(e)&&e>=0?e:50})(),RESOLUTION_MS=20;let timer,published=!1;function tapEventLoop(){if(process.env.LENSMCP_EVENT_LOOP==="0"||timer)return;const e=(0,node_perf_hooks_1.monitorEventLoopDelay)({resolution:RESOLUTION_MS});e.enable(),timer=setInterval(()=>{const o=RESOLUTION_MS,s=e.mean/1e6;if(!Number.isFinite(s))return;const i=Math.max(0,s-o),t=Math.max(0,e.max/1e6-o),p=Math.max(0,e.percentile(99)/1e6-o);e.reset(),!(published&&t<REPORT_ABOVE_MS)&&(published=!0,(0,emit_1.lensEmit)("perf",t>=1e3?"error":"info",`event loop lag ${i.toFixed(1)}ms mean / ${t.toFixed(1)}ms max`,{kind:"event-loop-lag",lagMs:Number(i.toFixed(2)),maxMs:Number(t.toFixed(2)),p99Ms:Number(p.toFixed(2)),windowMs:SAMPLE_MS},"perf:event-loop-lag",void 0,"performance"))},SAMPLE_MS),timer.unref?.()}r(tapEventLoop,"tapEventLoop"),n(tapEventLoop,"tapEventLoop");function stopEventLoopTapForTests(){timer&&clearInterval(timer),timer=void 0,published=!1}r(stopEventLoopTapForTests,"stopEventLoopTapForTests"),n(stopEventLoopTapForTests,"stopEventLoopTapForTests");
|
package/lib/tap-stdout.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
`)
|
|
1
|
+
"use strict";var a=Object.defineProperty;var c=(e,t)=>a(e,"name",{value:t,configurable:!0});var u=Object.defineProperty,o=c((e,t)=>u(e,"name",{value:t,configurable:!0}),"o");Object.defineProperty(exports,"__esModule",{value:!0}),exports.tapStdout=tapStdout;const emit_1=require("./emit"),ANSI=new RegExp("\x1B\\[[0-9;]*m","g");function severityOf(e,t){return/\bFATAL\b/.test(e)?"fatal":/\bERROR\b/.test(e)?"error":/\bWARN\b/.test(e)?"warning":/\bDEBUG\b/.test(e)||/\bVERBOSE\b/.test(e)?"debug":/\bLOG\b/.test(e)?"info":t}c(severityOf,"severityOf"),o(severityOf,"severityOf");const STACK_FRAME=/^\s+(at\s|\.\.\.\s\d+\smore)/;function emitChunk(e,t){const i=e.split(`
|
|
2
|
+
`).map(r=>r.replace(ANSI,"").replace(/\s+$/,""));let s=0;for(;s<i.length;){const r=i[s];if(s+=1,!r.trim())continue;const n=[];for(;s<i.length&&STACK_FRAME.test(i[s]);)n.push(i[s]),s+=1;const f=n.length>0?"error":severityOf(r,t);(0,emit_1.lensLog)(f,r,n.length>0?{stack:[r,...n].join(`
|
|
3
|
+
`)}:void 0)}}c(emitChunk,"emitChunk"),o(emitChunk,"emitChunk");function tapStdout(){if(process.env.LENSMCP_LOGS==="0"||process.env.APP_RUNNER!=="1")return;const e=[[process.stdout,"info"],[process.stderr,"error"]];for(const[t,i]of e){if(t.write.__lensmcp)continue;const s=t.write.bind(t),r=o(function(n,...f){try{if(!(0,emit_1.isLensWriting)()){const p=typeof n=="string"?n:Buffer.isBuffer(n)?n.toString("utf8"):"";p&&p.indexOf("[lensmcp]")===-1&&emitChunk(p,i)}}catch{}return s(n,...f)},"wrapped");r.__lensmcp=!0,t.write=r}}c(tapStdout,"tapStdout"),o(tapStdout,"tapStdout");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lensmcp/node-instrumentation",
|
|
3
|
-
"version": "1.21.
|
|
3
|
+
"version": "1.21.5",
|
|
4
4
|
"main": "./index.js",
|
|
5
5
|
"types": "./index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@lensmcp/nest-instrumentation": "1.21.
|
|
18
|
+
"@lensmcp/nest-instrumentation": "1.21.5",
|
|
19
19
|
"tslib": "^2.3.0"
|
|
20
20
|
},
|
|
21
21
|
"optionalDependencies": {
|