apcore-js 0.10.0 → 0.11.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 +59 -3
- package/dist/client.d.ts +37 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +85 -4
- package/dist/client.js.map +1 -1
- package/dist/errors.d.ts +11 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +18 -2
- package/dist/errors.js.map +1 -1
- package/dist/events/emitter.d.ts +30 -0
- package/dist/events/emitter.d.ts.map +1 -0
- package/dist/events/emitter.js +67 -0
- package/dist/events/emitter.js.map +1 -0
- package/dist/events/index.d.ts +4 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +3 -0
- package/dist/events/index.js.map +1 -0
- package/dist/events/subscribers.d.ts +32 -0
- package/dist/events/subscribers.d.ts.map +1 -0
- package/dist/events/subscribers.js +128 -0
- package/dist/events/subscribers.js.map +1 -0
- package/dist/executor.d.ts +3 -3
- package/dist/executor.d.ts.map +1 -1
- package/dist/executor.js +4 -4
- package/dist/executor.js.map +1 -1
- package/dist/index.d.ts +12 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -3
- package/dist/index.js.map +1 -1
- package/dist/middleware/error-history.d.ts +16 -0
- package/dist/middleware/error-history.d.ts.map +1 -0
- package/dist/middleware/error-history.js +23 -0
- package/dist/middleware/error-history.js.map +1 -0
- package/dist/middleware/index.d.ts +2 -0
- package/dist/middleware/index.d.ts.map +1 -1
- package/dist/middleware/index.js +2 -0
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/platform-notify.d.ts +30 -0
- package/dist/middleware/platform-notify.d.ts.map +1 -0
- package/dist/middleware/platform-notify.js +84 -0
- package/dist/middleware/platform-notify.js.map +1 -0
- package/dist/observability/error-history.d.ts +33 -0
- package/dist/observability/error-history.d.ts.map +1 -0
- package/dist/observability/error-history.js +96 -0
- package/dist/observability/error-history.js.map +1 -0
- package/dist/observability/index.d.ts +4 -0
- package/dist/observability/index.d.ts.map +1 -1
- package/dist/observability/index.js +2 -0
- package/dist/observability/index.js.map +1 -1
- package/dist/observability/metrics-utils.d.ts +30 -0
- package/dist/observability/metrics-utils.d.ts.map +1 -0
- package/dist/observability/metrics-utils.js +71 -0
- package/dist/observability/metrics-utils.js.map +1 -0
- package/dist/observability/usage.d.ts +66 -0
- package/dist/observability/usage.d.ts.map +1 -0
- package/dist/observability/usage.js +216 -0
- package/dist/observability/usage.js.map +1 -0
- package/dist/registry/registry.d.ts +5 -0
- package/dist/registry/registry.d.ts.map +1 -1
- package/dist/registry/registry.js +32 -0
- package/dist/registry/registry.js.map +1 -1
- package/dist/sys-modules/control.d.ts +39 -0
- package/dist/sys-modules/control.d.ts.map +1 -0
- package/dist/sys-modules/control.js +105 -0
- package/dist/sys-modules/control.js.map +1 -0
- package/dist/sys-modules/health.d.ts +45 -0
- package/dist/sys-modules/health.d.ts.map +1 -0
- package/dist/sys-modules/health.js +115 -0
- package/dist/sys-modules/health.js.map +1 -0
- package/dist/sys-modules/index.d.ts +8 -0
- package/dist/sys-modules/index.d.ts.map +1 -0
- package/dist/sys-modules/index.js +7 -0
- package/dist/sys-modules/index.js.map +1 -0
- package/dist/sys-modules/manifest.d.ts +38 -0
- package/dist/sys-modules/manifest.d.ts.map +1 -0
- package/dist/sys-modules/manifest.js +91 -0
- package/dist/sys-modules/manifest.js.map +1 -0
- package/dist/sys-modules/registration.d.ts +35 -0
- package/dist/sys-modules/registration.d.ts.map +1 -0
- package/dist/sys-modules/registration.js +132 -0
- package/dist/sys-modules/registration.js.map +1 -0
- package/dist/sys-modules/toggle.d.ts +44 -0
- package/dist/sys-modules/toggle.d.ts.map +1 -0
- package/dist/sys-modules/toggle.js +82 -0
- package/dist/sys-modules/toggle.js.map +1 -0
- package/dist/sys-modules/usage.d.ts +35 -0
- package/dist/sys-modules/usage.d.ts.map +1 -0
- package/dist/sys-modules/usage.js +105 -0
- package/dist/sys-modules/usage.js.map +1 -0
- package/package.json +1 -1
package/dist/middleware/index.js
CHANGED
|
@@ -3,4 +3,6 @@ export { MiddlewareManager, MiddlewareChainError } from './manager.js';
|
|
|
3
3
|
export { BeforeMiddleware, AfterMiddleware } from './adapters.js';
|
|
4
4
|
export { LoggingMiddleware } from './logging.js';
|
|
5
5
|
export { RetryMiddleware, CTX_RETRY_COUNT_PREFIX, CTX_RETRY_DELAY_PREFIX } from './retry.js';
|
|
6
|
+
export { ErrorHistoryMiddleware } from './error-history.js';
|
|
7
|
+
export { PlatformNotifyMiddleware } from './platform-notify.js';
|
|
6
8
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAElE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAElE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAE7F,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PlatformNotifyMiddleware -- threshold sensor with hysteresis.
|
|
3
|
+
*
|
|
4
|
+
* Monitors error rates and latency, emits threshold events with hysteresis.
|
|
5
|
+
* Emits error_threshold_exceeded when a module's error rate crosses the
|
|
6
|
+
* configured threshold, latency_threshold_exceeded when p99 latency
|
|
7
|
+
* exceeds the limit, and module_health_changed when a previously alerted
|
|
8
|
+
* module recovers below threshold * 0.5.
|
|
9
|
+
*/
|
|
10
|
+
import type { Context } from '../context.js';
|
|
11
|
+
import type { EventEmitter } from '../events/emitter.js';
|
|
12
|
+
import type { MetricsCollector } from '../observability/metrics.js';
|
|
13
|
+
import { Middleware } from './base.js';
|
|
14
|
+
export declare class PlatformNotifyMiddleware extends Middleware {
|
|
15
|
+
private readonly _emitter;
|
|
16
|
+
private readonly _metricsCollector;
|
|
17
|
+
private readonly _errorRateThreshold;
|
|
18
|
+
private readonly _latencyP99ThresholdMs;
|
|
19
|
+
private readonly _alerted;
|
|
20
|
+
constructor(eventEmitter: EventEmitter, metricsCollector?: MetricsCollector | null, errorRateThreshold?: number, latencyP99ThresholdMs?: number);
|
|
21
|
+
after(moduleId: string, _inputs: Record<string, unknown>, _output: Record<string, unknown>, _context: Context): Record<string, unknown> | null;
|
|
22
|
+
onError(moduleId: string, _inputs: Record<string, unknown>, _error: Error, _context: Context): Record<string, unknown> | null;
|
|
23
|
+
private _getAlerted;
|
|
24
|
+
private _computeErrorRate;
|
|
25
|
+
private _checkErrorRateThreshold;
|
|
26
|
+
private _checkLatencyThreshold;
|
|
27
|
+
private _estimateP99Ms;
|
|
28
|
+
private _checkErrorRecovery;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=platform-notify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform-notify.d.ts","sourceRoot":"","sources":["../../src/middleware/platform-notify.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAe,MAAM,sBAAsB,CAAC;AAEtE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,qBAAa,wBAAyB,SAAQ,UAAU;IACtD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA0B;IAC5D,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAS;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;gBAG9D,YAAY,EAAE,YAAY,EAC1B,gBAAgB,GAAE,gBAAgB,GAAG,IAAW,EAChD,kBAAkB,GAAE,MAAY,EAChC,qBAAqB,GAAE,MAAa;IAS7B,KAAK,CACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,QAAQ,EAAE,OAAO,GAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAMxB,OAAO,CACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,MAAM,EAAE,KAAK,EACb,QAAQ,EAAE,OAAO,GAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAKjC,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,wBAAwB;IAchC,OAAO,CAAC,sBAAsB;IAiB9B,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,mBAAmB;CAe5B"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PlatformNotifyMiddleware -- threshold sensor with hysteresis.
|
|
3
|
+
*
|
|
4
|
+
* Monitors error rates and latency, emits threshold events with hysteresis.
|
|
5
|
+
* Emits error_threshold_exceeded when a module's error rate crosses the
|
|
6
|
+
* configured threshold, latency_threshold_exceeded when p99 latency
|
|
7
|
+
* exceeds the limit, and module_health_changed when a previously alerted
|
|
8
|
+
* module recovers below threshold * 0.5.
|
|
9
|
+
*/
|
|
10
|
+
import { createEvent } from '../events/emitter.js';
|
|
11
|
+
import { computeModuleErrorRate, estimateP99FromHistogram } from '../observability/metrics-utils.js';
|
|
12
|
+
import { Middleware } from './base.js';
|
|
13
|
+
export class PlatformNotifyMiddleware extends Middleware {
|
|
14
|
+
_emitter;
|
|
15
|
+
_metricsCollector;
|
|
16
|
+
_errorRateThreshold;
|
|
17
|
+
_latencyP99ThresholdMs;
|
|
18
|
+
_alerted = new Map();
|
|
19
|
+
constructor(eventEmitter, metricsCollector = null, errorRateThreshold = 0.1, latencyP99ThresholdMs = 5000) {
|
|
20
|
+
super();
|
|
21
|
+
this._emitter = eventEmitter;
|
|
22
|
+
this._metricsCollector = metricsCollector;
|
|
23
|
+
this._errorRateThreshold = errorRateThreshold;
|
|
24
|
+
this._latencyP99ThresholdMs = latencyP99ThresholdMs;
|
|
25
|
+
}
|
|
26
|
+
after(moduleId, _inputs, _output, _context) {
|
|
27
|
+
this._checkLatencyThreshold(moduleId);
|
|
28
|
+
this._checkErrorRecovery(moduleId);
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
onError(moduleId, _inputs, _error, _context) {
|
|
32
|
+
this._checkErrorRateThreshold(moduleId);
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
_getAlerted(moduleId) {
|
|
36
|
+
let set = this._alerted.get(moduleId);
|
|
37
|
+
if (!set) {
|
|
38
|
+
set = new Set();
|
|
39
|
+
this._alerted.set(moduleId, set);
|
|
40
|
+
}
|
|
41
|
+
return set;
|
|
42
|
+
}
|
|
43
|
+
_computeErrorRate(moduleId) {
|
|
44
|
+
if (!this._metricsCollector)
|
|
45
|
+
return 0;
|
|
46
|
+
return computeModuleErrorRate(this._metricsCollector, moduleId).errorRate;
|
|
47
|
+
}
|
|
48
|
+
_checkErrorRateThreshold(moduleId) {
|
|
49
|
+
const errorRate = this._computeErrorRate(moduleId);
|
|
50
|
+
const alerted = this._getAlerted(moduleId);
|
|
51
|
+
if (errorRate >= this._errorRateThreshold && !alerted.has('error_rate')) {
|
|
52
|
+
this._emitter.emit(createEvent('error_threshold_exceeded', moduleId, 'warning', { error_rate: errorRate, threshold: this._errorRateThreshold }));
|
|
53
|
+
alerted.add('error_rate');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
_checkLatencyThreshold(moduleId) {
|
|
57
|
+
if (!this._metricsCollector)
|
|
58
|
+
return;
|
|
59
|
+
const alerted = this._getAlerted(moduleId);
|
|
60
|
+
if (alerted.has('latency'))
|
|
61
|
+
return;
|
|
62
|
+
const p99Ms = this._estimateP99Ms(moduleId);
|
|
63
|
+
if (p99Ms >= this._latencyP99ThresholdMs) {
|
|
64
|
+
this._emitter.emit(createEvent('latency_threshold_exceeded', moduleId, 'warning', { p99_latency_ms: p99Ms, threshold_ms: this._latencyP99ThresholdMs }));
|
|
65
|
+
alerted.add('latency');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
_estimateP99Ms(moduleId) {
|
|
69
|
+
if (!this._metricsCollector)
|
|
70
|
+
return 0;
|
|
71
|
+
return estimateP99FromHistogram(this._metricsCollector, moduleId).p99LatencyMs;
|
|
72
|
+
}
|
|
73
|
+
_checkErrorRecovery(moduleId) {
|
|
74
|
+
const alerted = this._alerted.get(moduleId);
|
|
75
|
+
if (!alerted || !alerted.has('error_rate'))
|
|
76
|
+
return;
|
|
77
|
+
const errorRate = this._computeErrorRate(moduleId);
|
|
78
|
+
if (errorRate < this._errorRateThreshold * 0.5) {
|
|
79
|
+
this._emitter.emit(createEvent('module_health_changed', moduleId, 'info', { status: 'recovered', error_rate: errorRate }));
|
|
80
|
+
alerted.delete('error_rate');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=platform-notify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform-notify.js","sourceRoot":"","sources":["../../src/middleware/platform-notify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error history with ring-buffer eviction and deduplication.
|
|
3
|
+
*/
|
|
4
|
+
import { ModuleError } from '../errors.js';
|
|
5
|
+
export interface ErrorEntry {
|
|
6
|
+
readonly moduleId: string;
|
|
7
|
+
readonly code: string;
|
|
8
|
+
readonly message: string;
|
|
9
|
+
readonly aiGuidance: string | null;
|
|
10
|
+
readonly timestamp: string;
|
|
11
|
+
count: number;
|
|
12
|
+
firstOccurred: string;
|
|
13
|
+
lastOccurred: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Ring buffer storing recent error details per module.
|
|
17
|
+
* Supports deduplication by (code, message) within each module,
|
|
18
|
+
* per-module eviction, and global total eviction.
|
|
19
|
+
*/
|
|
20
|
+
export declare class ErrorHistory {
|
|
21
|
+
private readonly _maxEntriesPerModule;
|
|
22
|
+
private readonly _maxTotalEntries;
|
|
23
|
+
private readonly _entries;
|
|
24
|
+
constructor(maxEntriesPerModule?: number, maxTotalEntries?: number);
|
|
25
|
+
record(moduleId: string, error: ModuleError): void;
|
|
26
|
+
get(moduleId: string, limit?: number): ErrorEntry[];
|
|
27
|
+
clear(): void;
|
|
28
|
+
clearModule(moduleId: string): void;
|
|
29
|
+
getAll(limit?: number): ErrorEntry[];
|
|
30
|
+
private _evictModule;
|
|
31
|
+
private _evictTotal;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=error-history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-history.d.ts","sourceRoot":"","sources":["../../src/observability/error-history.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAC9C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwC;gBAErD,mBAAmB,GAAE,MAAW,EAAE,eAAe,GAAE,MAAa;IAK5E,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI;IAgClD,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE;IAMnD,KAAK,IAAI,IAAI;IAIb,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAInC,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE;IASpC,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,WAAW;CA0BpB"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error history with ring-buffer eviction and deduplication.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Ring buffer storing recent error details per module.
|
|
6
|
+
* Supports deduplication by (code, message) within each module,
|
|
7
|
+
* per-module eviction, and global total eviction.
|
|
8
|
+
*/
|
|
9
|
+
export class ErrorHistory {
|
|
10
|
+
_maxEntriesPerModule;
|
|
11
|
+
_maxTotalEntries;
|
|
12
|
+
_entries = new Map();
|
|
13
|
+
constructor(maxEntriesPerModule = 50, maxTotalEntries = 1000) {
|
|
14
|
+
this._maxEntriesPerModule = maxEntriesPerModule;
|
|
15
|
+
this._maxTotalEntries = maxTotalEntries;
|
|
16
|
+
}
|
|
17
|
+
record(moduleId, error) {
|
|
18
|
+
const now = new Date().toISOString();
|
|
19
|
+
let moduleEntries = this._entries.get(moduleId);
|
|
20
|
+
if (!moduleEntries) {
|
|
21
|
+
moduleEntries = [];
|
|
22
|
+
this._entries.set(moduleId, moduleEntries);
|
|
23
|
+
}
|
|
24
|
+
const existing = moduleEntries.find((e) => e.code === error.code && e.message === error.message);
|
|
25
|
+
if (existing) {
|
|
26
|
+
existing.count++;
|
|
27
|
+
existing.lastOccurred = now;
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const entry = {
|
|
31
|
+
moduleId,
|
|
32
|
+
code: error.code,
|
|
33
|
+
message: error.message,
|
|
34
|
+
aiGuidance: error.aiGuidance,
|
|
35
|
+
timestamp: now,
|
|
36
|
+
count: 1,
|
|
37
|
+
firstOccurred: now,
|
|
38
|
+
lastOccurred: now,
|
|
39
|
+
};
|
|
40
|
+
moduleEntries.push(entry);
|
|
41
|
+
this._evictModule(moduleEntries);
|
|
42
|
+
this._evictTotal();
|
|
43
|
+
}
|
|
44
|
+
get(moduleId, limit) {
|
|
45
|
+
const moduleEntries = this._entries.get(moduleId) ?? [];
|
|
46
|
+
const result = [...moduleEntries].reverse();
|
|
47
|
+
return limit !== undefined ? result.slice(0, limit) : result;
|
|
48
|
+
}
|
|
49
|
+
clear() {
|
|
50
|
+
this._entries.clear();
|
|
51
|
+
}
|
|
52
|
+
clearModule(moduleId) {
|
|
53
|
+
this._entries.delete(moduleId);
|
|
54
|
+
}
|
|
55
|
+
getAll(limit) {
|
|
56
|
+
const all = [];
|
|
57
|
+
for (const entries of this._entries.values()) {
|
|
58
|
+
all.push(...entries);
|
|
59
|
+
}
|
|
60
|
+
all.sort((a, b) => (a.lastOccurred > b.lastOccurred ? -1 : 1));
|
|
61
|
+
return limit !== undefined ? all.slice(0, limit) : all;
|
|
62
|
+
}
|
|
63
|
+
_evictModule(moduleEntries) {
|
|
64
|
+
while (moduleEntries.length > this._maxEntriesPerModule) {
|
|
65
|
+
moduleEntries.shift();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
_evictTotal() {
|
|
69
|
+
let total = 0;
|
|
70
|
+
for (const entries of this._entries.values()) {
|
|
71
|
+
total += entries.length;
|
|
72
|
+
}
|
|
73
|
+
while (total > this._maxTotalEntries) {
|
|
74
|
+
let oldestEntry = null;
|
|
75
|
+
let oldestModuleId = null;
|
|
76
|
+
for (const [mid, entries] of this._entries) {
|
|
77
|
+
if (entries.length > 0) {
|
|
78
|
+
const candidate = entries[0];
|
|
79
|
+
if (oldestEntry === null || candidate.lastOccurred < oldestEntry.lastOccurred) {
|
|
80
|
+
oldestEntry = candidate;
|
|
81
|
+
oldestModuleId = mid;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (oldestModuleId === null)
|
|
86
|
+
break;
|
|
87
|
+
const entries = this._entries.get(oldestModuleId);
|
|
88
|
+
entries.shift();
|
|
89
|
+
if (entries.length === 0) {
|
|
90
|
+
this._entries.delete(oldestModuleId);
|
|
91
|
+
}
|
|
92
|
+
total--;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=error-history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-history.js","sourceRoot":"","sources":["../../src/observability/error-history.ts"],"names":[],"mappings":"AAAA;;GAEG;AAeH;;;;GAIG;AACH,MAAM,OAAO,YAAY;IACN,oBAAoB,CAAS;IAC7B,gBAAgB,CAAS;IACzB,QAAQ,GAA8B,IAAI,GAAG,EAAE,CAAC;IAEjE,YAAY,sBAA8B,EAAE,EAAE,kBAA0B,IAAI;QAC1E,IAAI,CAAC,oBAAoB,GAAG,mBAAmB,CAAC;QAChD,IAAI,CAAC,gBAAgB,GAAG,eAAe,CAAC;IAC1C,CAAC;IAED,MAAM,CAAC,QAAgB,EAAE,KAAkB;QACzC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,IAAI,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAChD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,aAAa,GAAG,EAAE,CAAC;YACnB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CACjC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,CAC5D,CAAC;QACF,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,KAAK,EAAE,CAAC;YACjB,QAAQ,CAAC,YAAY,GAAG,GAAG,CAAC;YAC5B,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAe;YACxB,QAAQ;YACR,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,SAAS,EAAE,GAAG;YACd,KAAK,EAAE,CAAC;YACR,aAAa,EAAE,GAAG;YAClB,YAAY,EAAE,GAAG;SAClB,CAAC;QACF,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QACjC,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED,GAAG,CAAC,QAAgB,EAAE,KAAc;QAClC,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACxD,MAAM,MAAM,GAAG,CAAC,GAAG,aAAa,CAAC,CAAC,OAAO,EAAE,CAAC;QAC5C,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAC/D,CAAC;IAED,KAAK;QACH,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;IAED,WAAW,CAAC,QAAgB;QAC1B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;IAED,MAAM,CAAC,KAAc;QACnB,MAAM,GAAG,GAAiB,EAAE,CAAC;QAC7B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC7C,GAAG,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;QACvB,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/D,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACzD,CAAC;IAEO,YAAY,CAAC,aAA2B;QAC9C,OAAO,aAAa,CAAC,MAAM,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;YACxD,aAAa,CAAC,KAAK,EAAE,CAAC;QACxB,CAAC;IACH,CAAC;IAEO,WAAW;QACjB,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC7C,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;QAC1B,CAAC;QACD,OAAO,KAAK,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACrC,IAAI,WAAW,GAAsB,IAAI,CAAC;YAC1C,IAAI,cAAc,GAAkB,IAAI,CAAC;YACzC,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAC3C,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACvB,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;oBAC7B,IAAI,WAAW,KAAK,IAAI,IAAI,SAAS,CAAC,YAAY,GAAG,WAAW,CAAC,YAAY,EAAE,CAAC;wBAC9E,WAAW,GAAG,SAAS,CAAC;wBACxB,cAAc,GAAG,GAAG,CAAC;oBACvB,CAAC;gBACH,CAAC;YACH,CAAC;YACD,IAAI,cAAc,KAAK,IAAI;gBAAE,MAAM;YACnC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAE,CAAC;YACnD,OAAO,CAAC,KAAK,EAAE,CAAC;YAChB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;YACvC,CAAC;YACD,KAAK,EAAE,CAAC;QACV,CAAC;IACH,CAAC;CACF"}
|
|
@@ -2,4 +2,8 @@ export { TracingMiddleware, StdoutExporter, InMemoryExporter, createSpan } from
|
|
|
2
2
|
export type { Span, SpanExporter } from './tracing.js';
|
|
3
3
|
export { MetricsCollector, MetricsMiddleware } from './metrics.js';
|
|
4
4
|
export { ContextLogger, ObsLoggingMiddleware } from './context-logger.js';
|
|
5
|
+
export { ErrorHistory } from './error-history.js';
|
|
6
|
+
export type { ErrorEntry } from './error-history.js';
|
|
7
|
+
export { UsageCollector, UsageMiddleware, bucketKey } from './usage.js';
|
|
8
|
+
export type { UsageRecord, CallerUsageSummary, HourlyBucket, ModuleUsageSummary, ModuleUsageDetail } from './usage.js';
|
|
5
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/observability/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/F,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/observability/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/F,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACxE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { TracingMiddleware, StdoutExporter, InMemoryExporter, createSpan } from './tracing.js';
|
|
2
2
|
export { MetricsCollector, MetricsMiddleware } from './metrics.js';
|
|
3
3
|
export { ContextLogger, ObsLoggingMiddleware } from './context-logger.js';
|
|
4
|
+
export { ErrorHistory } from './error-history.js';
|
|
5
|
+
export { UsageCollector, UsageMiddleware, bucketKey } from './usage.js';
|
|
4
6
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/observability/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/F,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/observability/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/F,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for extracting module-level metrics from MetricsCollector snapshots.
|
|
3
|
+
*/
|
|
4
|
+
import type { MetricsCollector } from './metrics.js';
|
|
5
|
+
export declare const METRIC_CALLS_TOTAL = "apcore_module_calls_total";
|
|
6
|
+
export declare const METRIC_DURATION_SECONDS = "apcore_module_duration_seconds";
|
|
7
|
+
/**
|
|
8
|
+
* Check if a metric key's labels contain an exact module_id match.
|
|
9
|
+
* Keys have the format: "metric_name|module_id=foo,status=bar"
|
|
10
|
+
* This prevents false-matching when one module ID is a suffix of another.
|
|
11
|
+
*/
|
|
12
|
+
export declare function matchesModuleId(key: string, moduleId: string): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Compute error rate for a module from a MetricsCollector snapshot.
|
|
15
|
+
*/
|
|
16
|
+
export declare function computeModuleErrorRate(metricsCollector: MetricsCollector, moduleId: string): {
|
|
17
|
+
totalCalls: number;
|
|
18
|
+
errorCount: number;
|
|
19
|
+
errorRate: number;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Estimate p99 latency in milliseconds from histogram buckets.
|
|
23
|
+
* Returns the upper bound of the first bucket that contains ≥99% of observations.
|
|
24
|
+
* If all observations exceed the largest bucket, returns the last bucket upper bound.
|
|
25
|
+
*/
|
|
26
|
+
export declare function estimateP99FromHistogram(metricsCollector: MetricsCollector, moduleId: string): {
|
|
27
|
+
avgLatencyMs: number;
|
|
28
|
+
p99LatencyMs: number;
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=metrics-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics-utils.d.ts","sourceRoot":"","sources":["../../src/observability/metrics-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,eAAO,MAAM,kBAAkB,8BAA8B,CAAC;AAC9D,eAAO,MAAM,uBAAuB,mCAAmC,CAAC;AAMxE;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGtE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,gBAAgB,EAAE,gBAAgB,EAClC,QAAQ,EAAE,MAAM,GACf;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAiB/D;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,gBAAgB,EAAE,gBAAgB,EAClC,QAAQ,EAAE,MAAM,GACf;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CA8BhD"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for extracting module-level metrics from MetricsCollector snapshots.
|
|
3
|
+
*/
|
|
4
|
+
export const METRIC_CALLS_TOTAL = 'apcore_module_calls_total';
|
|
5
|
+
export const METRIC_DURATION_SECONDS = 'apcore_module_duration_seconds';
|
|
6
|
+
const DEFAULT_HISTOGRAM_BUCKETS = [
|
|
7
|
+
0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0, 30.0, 60.0,
|
|
8
|
+
];
|
|
9
|
+
/**
|
|
10
|
+
* Check if a metric key's labels contain an exact module_id match.
|
|
11
|
+
* Keys have the format: "metric_name|module_id=foo,status=bar"
|
|
12
|
+
* This prevents false-matching when one module ID is a suffix of another.
|
|
13
|
+
*/
|
|
14
|
+
export function matchesModuleId(key, moduleId) {
|
|
15
|
+
const labelMatch = `|module_id=${moduleId}`;
|
|
16
|
+
return key.includes(`${labelMatch},`) || key.endsWith(labelMatch);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Compute error rate for a module from a MetricsCollector snapshot.
|
|
20
|
+
*/
|
|
21
|
+
export function computeModuleErrorRate(metricsCollector, moduleId) {
|
|
22
|
+
const snap = metricsCollector.snapshot();
|
|
23
|
+
const counters = snap['counters'];
|
|
24
|
+
if (!counters)
|
|
25
|
+
return { totalCalls: 0, errorCount: 0, errorRate: 0 };
|
|
26
|
+
let total = 0;
|
|
27
|
+
let errors = 0;
|
|
28
|
+
const prefix = `${METRIC_CALLS_TOTAL}|`;
|
|
29
|
+
for (const [key, value] of Object.entries(counters)) {
|
|
30
|
+
if (!key.startsWith(prefix))
|
|
31
|
+
continue;
|
|
32
|
+
if (!matchesModuleId(key, moduleId))
|
|
33
|
+
continue;
|
|
34
|
+
total += value;
|
|
35
|
+
if (key.includes('status=error')) {
|
|
36
|
+
errors += value;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return { totalCalls: total, errorCount: errors, errorRate: total === 0 ? 0 : errors / total };
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Estimate p99 latency in milliseconds from histogram buckets.
|
|
43
|
+
* Returns the upper bound of the first bucket that contains ≥99% of observations.
|
|
44
|
+
* If all observations exceed the largest bucket, returns the last bucket upper bound.
|
|
45
|
+
*/
|
|
46
|
+
export function estimateP99FromHistogram(metricsCollector, moduleId) {
|
|
47
|
+
const snap = metricsCollector.snapshot();
|
|
48
|
+
const histograms = snap['histograms'];
|
|
49
|
+
if (!histograms)
|
|
50
|
+
return { avgLatencyMs: 0, p99LatencyMs: 0 };
|
|
51
|
+
const durationKey = `${METRIC_DURATION_SECONDS}|module_id=${moduleId}`;
|
|
52
|
+
const sumVal = histograms.sums?.[durationKey] ?? 0;
|
|
53
|
+
const countVal = histograms.counts?.[durationKey] ?? 0;
|
|
54
|
+
const avgLatencyMs = countVal > 0 ? (sumVal / countVal) * 1000 : 0;
|
|
55
|
+
let p99LatencyMs = 0;
|
|
56
|
+
if (countVal > 0 && histograms.buckets) {
|
|
57
|
+
const target = countVal * 0.99;
|
|
58
|
+
for (const b of DEFAULT_HISTOGRAM_BUCKETS) {
|
|
59
|
+
const bkey = `${durationKey}|${b}`;
|
|
60
|
+
const cumCount = histograms.buckets[bkey] ?? 0;
|
|
61
|
+
if (cumCount >= target) {
|
|
62
|
+
p99LatencyMs = b * 1000;
|
|
63
|
+
return { avgLatencyMs, p99LatencyMs };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// All observations exceed the largest bucket
|
|
67
|
+
p99LatencyMs = DEFAULT_HISTOGRAM_BUCKETS[DEFAULT_HISTOGRAM_BUCKETS.length - 1] * 1000;
|
|
68
|
+
}
|
|
69
|
+
return { avgLatencyMs, p99LatencyMs };
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=metrics-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics-utils.js","sourceRoot":"","sources":["../../src/observability/metrics-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Time-windowed usage tracking with per-module and per-caller analytics.
|
|
3
|
+
*/
|
|
4
|
+
import { Middleware } from '../middleware/base.js';
|
|
5
|
+
import type { Context } from '../context.js';
|
|
6
|
+
export interface UsageRecord {
|
|
7
|
+
readonly timestamp: string;
|
|
8
|
+
readonly callerId: string;
|
|
9
|
+
readonly latencyMs: number;
|
|
10
|
+
readonly success: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface CallerUsageSummary {
|
|
13
|
+
readonly callerId: string;
|
|
14
|
+
readonly callCount: number;
|
|
15
|
+
readonly errorCount: number;
|
|
16
|
+
readonly avgLatencyMs: number;
|
|
17
|
+
}
|
|
18
|
+
export interface HourlyBucket {
|
|
19
|
+
readonly hour: string;
|
|
20
|
+
readonly callCount: number;
|
|
21
|
+
readonly errorCount: number;
|
|
22
|
+
}
|
|
23
|
+
export interface ModuleUsageSummary {
|
|
24
|
+
readonly moduleId: string;
|
|
25
|
+
readonly callCount: number;
|
|
26
|
+
readonly errorCount: number;
|
|
27
|
+
readonly avgLatencyMs: number;
|
|
28
|
+
readonly uniqueCallers: number;
|
|
29
|
+
readonly trend: string;
|
|
30
|
+
}
|
|
31
|
+
export interface ModuleUsageDetail extends ModuleUsageSummary {
|
|
32
|
+
readonly callers: CallerUsageSummary[];
|
|
33
|
+
readonly hourlyDistribution: HourlyBucket[];
|
|
34
|
+
}
|
|
35
|
+
export declare function bucketKey(date: Date): string;
|
|
36
|
+
/**
|
|
37
|
+
* In-memory usage tracker with hourly buckets and configurable retention.
|
|
38
|
+
*/
|
|
39
|
+
export declare class UsageCollector {
|
|
40
|
+
readonly retentionHours: number;
|
|
41
|
+
private readonly _maxRecordsPerBucket;
|
|
42
|
+
private readonly _data;
|
|
43
|
+
constructor(retentionHours?: number, maxRecordsPerBucket?: number);
|
|
44
|
+
record(moduleId: string, callerId: string, latencyMs: number, success: boolean, timestamp?: string): void;
|
|
45
|
+
getSummary(period?: string): ModuleUsageSummary[];
|
|
46
|
+
getModule(moduleId: string, period?: string): ModuleUsageDetail;
|
|
47
|
+
getLatencies(moduleId: string, period?: string): number[];
|
|
48
|
+
private _collectRecords;
|
|
49
|
+
private _buildSummary;
|
|
50
|
+
private _buildDetail;
|
|
51
|
+
private _perCallerBreakdown;
|
|
52
|
+
private _hourlyDistribution;
|
|
53
|
+
private _cleanupExpired;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Middleware that records module call usage via UsageCollector.
|
|
57
|
+
*/
|
|
58
|
+
export declare class UsageMiddleware extends Middleware {
|
|
59
|
+
private readonly _collector;
|
|
60
|
+
constructor(collector: UsageCollector);
|
|
61
|
+
before(_moduleId: string, _inputs: Record<string, unknown>, context: Context): Record<string, unknown> | null;
|
|
62
|
+
after(moduleId: string, _inputs: Record<string, unknown>, _output: Record<string, unknown>, context: Context): Record<string, unknown> | null;
|
|
63
|
+
onError(moduleId: string, _inputs: Record<string, unknown>, _error: Error, context: Context): Record<string, unknown> | null;
|
|
64
|
+
private _popElapsedMs;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../src/observability/usage.ts"],"names":[],"mappings":"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"}
|