@lensmcp/memory-tracker 1.23.13 → 1.24.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/README.md +7 -7
- package/index.d.ts +1 -1
- package/lib/context.d.ts +1 -0
- package/lib/detectors.d.ts +6 -0
- package/lib/emit.d.ts +5 -0
- package/lib/types.d.ts +5 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Track memory growth in long-lived JavaScript containers, attribute it to the flow that caused it, and surface suspected leaks as LensMCP events.
|
|
4
4
|
|
|
5
|
-
`@lensmcp/memory-tracker` instruments the mutating methods of `Map`, `Set`, and `Array` instances in place. Every mutation updates a per-container "owner" record (item count plus a rough byte estimate) and is attributed to the active request/flow. When a flow grows a container past a threshold and the items do not shrink back, the tracker emits a `memory-retention` ("memory leak suspected") event.
|
|
5
|
+
`@lensmcp/memory-tracker` instruments the mutating methods of `Map`, `Set`, and `Array` instances in place. Every mutation updates a per-container "owner" record (item count plus a rough byte estimate) and is attributed to the active request/flow. When a flow grows a container past a threshold and the items do not shrink back, the tracker emits a `memory-retention` ("memory leak suspected") event. The result is a deterministic, attributable memory signal in the LensMCP lens — instead of a flat heap graph, you see *which owner grew, by how much, and under which flow*.
|
|
6
6
|
|
|
7
7
|
It is designed to run in "light mode" inside the LensMCP node/NestJS instrumentation: zero sampling timers in the hot path, bounded per-mutation work, and a pluggable event sink so the host process forwards events to the LensMCP bus.
|
|
8
8
|
|
|
@@ -33,7 +33,6 @@ configureMemoryTracker({
|
|
|
33
33
|
sessionId: 'session-123',
|
|
34
34
|
sink: (event) => bus.publish(event),
|
|
35
35
|
leakItemThreshold: 50, // items of growth that flips a suspected leak (default 50)
|
|
36
|
-
staleGenerationBytesThreshold: 1024 * 1024, // bytes a disposed singleton may retain (default 1 MB)
|
|
37
36
|
settleMs: 1000, // grace period after a flow ends (default 1000)
|
|
38
37
|
contextGetter: () => currentLensmcpContext(), // optional: returns { sessionId, flowId?, requestId?, originNodeId? }
|
|
39
38
|
});
|
|
@@ -64,13 +63,12 @@ const flaggedOwnerIds = onFlowSettled('req-42'); // string[] of suspected-leak o
|
|
|
64
63
|
|
|
65
64
|
## API
|
|
66
65
|
|
|
67
|
-
- **`configureMemoryTracker(opts)`** — Set the active session id, the event `sink`, the optional `contextGetter`, and detector thresholds (`leakItemThreshold`, `
|
|
66
|
+
- **`configureMemoryTracker(opts)`** — Set the active session id, the event `sink`, the optional `contextGetter`, and detector thresholds (`leakItemThreshold`, `settleMs`). Returns the resolved options. Must be called before events are emitted. (`staleGenerationBytesThreshold` is still accepted and ignored.)
|
|
68
67
|
- **`trackContainer({ ownerInstanceId, fieldName, container })`** — Instrument a `Map`/`Set`/`Array` in place so each mutation updates its owner record and emits a `memory-mutation` event. Idempotent and non-destructive.
|
|
69
68
|
- **`onFlowStart(flowId)`** — Snapshot every owner's item count at the start of a flow.
|
|
70
69
|
- **`onFlowSettled(flowId)`** — Compare each owner's attributed growth against `leakItemThreshold`; emit `memory-retention` for owners that grew and stayed resident. Returns the flagged owner ids.
|
|
71
|
-
- **`checkStaleGeneration({ logicalId, instanceId, generation, retainedBytes })`** — On singleton disposal, emit `singleton-stale-generation` when retained bytes exceed `staleGenerationBytesThreshold`. Returns whether it flagged.
|
|
72
70
|
- **`allOwners()` / `getOwner(ownerId)` / `ownerKey(ownerInstanceId, fieldName)`** — Inspect the owner registry: list owner snapshots, fetch one record, or compute an owner key (`<ownerInstanceId>::<fieldName>`).
|
|
73
|
-
- **`emitMutation` / `emitRetention
|
|
71
|
+
- **`emitMutation` / `emitRetention`** — Low-level emit helpers that build each memory `BaseEvent` and push it to the sink (used internally; exported for advanced hosts).
|
|
74
72
|
- **`activeMemoryOptions()` / `currentMemoryContext()` / `resetMemoryTracker()`** — Read the resolved options, read the current flow context, or reset tracker state (test hook).
|
|
75
73
|
- **`markFlowStart` / `recordFlowDelta` / `flowGrowth` / `ensureOwner` / `resetOwners`** — Lower-level owner/flow primitives behind the detectors.
|
|
76
74
|
- **Types** — `MemoryEventSink`, `MemoryContext`, `ResolvedMemoryOptions`, `MemoryOwnerSnapshot`, `MemoryContainerKind`, `MemoryMutationOperation`, and the `TrackContainerArgs` input.
|
|
@@ -79,11 +77,13 @@ const flaggedOwnerIds = onFlowSettled('req-42'); // string[] of suspected-leak o
|
|
|
79
77
|
|
|
80
78
|
`@lensmcp/memory-tracker` is enabled by `@lensmcp/nest-instrumentation` via its `memory` option (the node instrumentation does the same). The host supplies the `sessionId`, the event `sink`, and a `contextGetter` bound to its own request context, and brackets each request with `onFlowStart` / `onFlowSettled`.
|
|
81
79
|
|
|
82
|
-
Every event is a `@lensmcp/protocol-types` `BaseEvent` with `source` and `category` of `memory`, carrying one of
|
|
80
|
+
Every event is a `@lensmcp/protocol-types` `BaseEvent` with `source` and `category` of `memory`, carrying one of two payload kinds:
|
|
83
81
|
|
|
84
82
|
- `memory-mutation` — `debug` severity; per-mutation before/after counts and an estimated byte delta.
|
|
85
83
|
- `memory-retention` — `warning` severity; the "memory leak suspected" signal (owner id, flow, growth) surfaced in the lens.
|
|
86
|
-
|
|
84
|
+
|
|
85
|
+
A hot-swapped app generation that stays in memory after its close is not this package's signal: the dev cluster's
|
|
86
|
+
pod proves it from the heap itself and publishes `pod-memory-retained` (see `lensmcp mem`).
|
|
87
87
|
|
|
88
88
|
These events flow through the host's sink to the LensMCP bus, where the lens renders them in the **"memory leak suspected"** channel.
|
|
89
89
|
|
package/index.d.ts
CHANGED
|
@@ -2,5 +2,5 @@ export { configureMemoryTracker, activeMemoryOptions, currentMemoryContext, rese
|
|
|
2
2
|
export { trackContainer, type TrackContainerArgs } from './lib/track-container.js';
|
|
3
3
|
export { ensureOwner, allOwners, getOwner, ownerKey, resetOwners, markFlowStart, recordFlowDelta, flowGrowth, } from './lib/owners.js';
|
|
4
4
|
export { emitMutation, emitRetention, emitStaleGeneration } from './lib/emit.js';
|
|
5
|
-
export { onFlowStart, onFlowSettled, checkStaleGeneration
|
|
5
|
+
export { onFlowStart, onFlowSettled, checkStaleGeneration } from './lib/detectors.js';
|
|
6
6
|
export type { MemoryEventSink, MemoryContext, ResolvedMemoryOptions, MemoryOwnerSnapshot, MemoryContainerKind, MemoryMutationOperation, } from './lib/types.js';
|
package/lib/context.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export declare function configureMemoryTracker(opts: {
|
|
|
11
11
|
sessionId: string;
|
|
12
12
|
sink: MemoryEventSink;
|
|
13
13
|
leakItemThreshold?: number;
|
|
14
|
+
/** @deprecated Ignored — see `ResolvedMemoryOptions.staleGenerationBytesThreshold`. */
|
|
14
15
|
staleGenerationBytesThreshold?: number;
|
|
15
16
|
settleMs?: number;
|
|
16
17
|
contextGetter?: ContextGetter;
|
package/lib/detectors.d.ts
CHANGED
|
@@ -5,6 +5,12 @@ export declare function onFlowStart(flowId: string): void;
|
|
|
5
5
|
* the list of flagged owner ids (also useful for tests).
|
|
6
6
|
*/
|
|
7
7
|
export declare function onFlowSettled(flowKey: string, flowId?: string): string[];
|
|
8
|
+
/**
|
|
9
|
+
* @deprecated Kept for API compatibility only — nothing in LensMCP calls it, because no host can
|
|
10
|
+
* measure a disposed singleton's retained bytes cheaply. A hot-swapped generation that outlives its
|
|
11
|
+
* close is proven by `@lensmcp/cluster` itself (`pod-memory-retained`, issues/closed/pod-memory-02).
|
|
12
|
+
* Will be removed in the next major version.
|
|
13
|
+
*/
|
|
8
14
|
export declare function checkStaleGeneration(args: {
|
|
9
15
|
logicalId: string;
|
|
10
16
|
instanceId: string;
|
package/lib/emit.d.ts
CHANGED
|
@@ -22,6 +22,11 @@ export declare function emitRetention(args: {
|
|
|
22
22
|
context?: MemoryContext;
|
|
23
23
|
timestamp?: number;
|
|
24
24
|
}): void;
|
|
25
|
+
/**
|
|
26
|
+
* @deprecated Kept for API compatibility only (see `checkStaleGeneration`). Hot-swap generations that
|
|
27
|
+
* outlive their close are reported by `@lensmcp/cluster` as `pod-memory-retained`. Will be removed in the
|
|
28
|
+
* next major version.
|
|
29
|
+
*/
|
|
25
30
|
export declare function emitStaleGeneration(args: {
|
|
26
31
|
options: ResolvedMemoryOptions;
|
|
27
32
|
logicalId: string;
|
package/lib/types.d.ts
CHANGED
|
@@ -19,7 +19,11 @@ export interface ResolvedMemoryOptions {
|
|
|
19
19
|
sink: MemoryEventSink;
|
|
20
20
|
/** Owner growth (in items) within a flow that flips a suspected leak. Default 50. */
|
|
21
21
|
leakItemThreshold: number;
|
|
22
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* @deprecated Read by nothing since `checkStaleGeneration` was removed (it had no caller); kept so existing
|
|
24
|
+
* `configureMemoryTracker` calls still compile. Stale hot-swap generations are reported by the cluster pod
|
|
25
|
+
* (`pod-memory-retained`).
|
|
26
|
+
*/
|
|
23
27
|
staleGenerationBytesThreshold: number;
|
|
24
28
|
/** ms to wait after flow end before checking owner shrinkage. Default 1000. */
|
|
25
29
|
settleMs: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lensmcp/memory-tracker",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.24.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@lensmcp/protocol-types": "1.
|
|
17
|
+
"@lensmcp/protocol-types": "1.24.0",
|
|
18
18
|
"tslib": "^2.3.0"
|
|
19
19
|
},
|
|
20
20
|
"license": "Apache-2.0",
|