apcore-js 0.19.0 → 0.20.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 +110 -9
- package/dist/acl.d.ts +18 -0
- package/dist/acl.d.ts.map +1 -1
- package/dist/acl.js +54 -17
- package/dist/acl.js.map +1 -1
- package/dist/async-task.d.ts +70 -16
- package/dist/async-task.d.ts.map +1 -1
- package/dist/async-task.js +212 -72
- package/dist/async-task.js.map +1 -1
- package/dist/builtin-steps.d.ts +16 -5
- package/dist/builtin-steps.d.ts.map +1 -1
- package/dist/builtin-steps.js +45 -28
- package/dist/builtin-steps.js.map +1 -1
- package/dist/config.d.ts +38 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +163 -33
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +12 -1
- package/dist/context.js.map +1 -1
- package/dist/errors.d.ts +32 -10
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +55 -16
- package/dist/errors.js.map +1 -1
- package/dist/events/circuit-breaker.d.ts +45 -0
- package/dist/events/circuit-breaker.d.ts.map +1 -0
- package/dist/events/circuit-breaker.js +115 -0
- package/dist/events/circuit-breaker.js.map +1 -0
- package/dist/events/emitter.d.ts +22 -1
- package/dist/events/emitter.d.ts.map +1 -1
- package/dist/events/emitter.js +66 -2
- package/dist/events/emitter.js.map +1 -1
- package/dist/events/index.d.ts +4 -2
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +3 -2
- package/dist/events/index.js.map +1 -1
- package/dist/events/subscribers.d.ts +33 -1
- package/dist/events/subscribers.d.ts.map +1 -1
- package/dist/events/subscribers.js +124 -1
- package/dist/events/subscribers.js.map +1 -1
- package/dist/executor.d.ts +10 -2
- package/dist/executor.d.ts.map +1 -1
- package/dist/executor.js +134 -51
- package/dist/executor.js.map +1 -1
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/index.d.ts +35 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -17
- package/dist/index.js.map +1 -1
- package/dist/middleware/base.d.ts +25 -3
- package/dist/middleware/base.d.ts.map +1 -1
- package/dist/middleware/base.js +24 -0
- package/dist/middleware/base.js.map +1 -1
- package/dist/middleware/circuit-breaker.d.ts +54 -0
- package/dist/middleware/circuit-breaker.d.ts.map +1 -0
- package/dist/middleware/circuit-breaker.js +168 -0
- package/dist/middleware/circuit-breaker.js.map +1 -0
- package/dist/middleware/context-namespace.d.ts +30 -0
- package/dist/middleware/context-namespace.d.ts.map +1 -0
- package/dist/middleware/context-namespace.js +38 -0
- package/dist/middleware/context-namespace.js.map +1 -0
- package/dist/middleware/index.d.ts +7 -1
- package/dist/middleware/index.d.ts.map +1 -1
- package/dist/middleware/index.js +4 -1
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/manager.d.ts +11 -4
- package/dist/middleware/manager.d.ts.map +1 -1
- package/dist/middleware/manager.js +25 -9
- package/dist/middleware/manager.js.map +1 -1
- package/dist/middleware/platform-notify.d.ts +8 -4
- package/dist/middleware/platform-notify.d.ts.map +1 -1
- package/dist/middleware/platform-notify.js +11 -7
- package/dist/middleware/platform-notify.js.map +1 -1
- package/dist/middleware/tracing.d.ts +50 -0
- package/dist/middleware/tracing.d.ts.map +1 -0
- package/dist/middleware/tracing.js +89 -0
- package/dist/middleware/tracing.js.map +1 -0
- package/dist/observability/batch-span-processor.d.ts +48 -0
- package/dist/observability/batch-span-processor.d.ts.map +1 -0
- package/dist/observability/batch-span-processor.js +89 -0
- package/dist/observability/batch-span-processor.js.map +1 -0
- package/dist/observability/context-logger.d.ts +54 -1
- package/dist/observability/context-logger.d.ts.map +1 -1
- package/dist/observability/context-logger.js +270 -6
- package/dist/observability/context-logger.js.map +1 -1
- package/dist/observability/error-history.d.ts +36 -7
- package/dist/observability/error-history.d.ts.map +1 -1
- package/dist/observability/error-history.js +169 -50
- package/dist/observability/error-history.js.map +1 -1
- package/dist/observability/index.d.ts +16 -5
- package/dist/observability/index.d.ts.map +1 -1
- package/dist/observability/index.js +8 -3
- package/dist/observability/index.js.map +1 -1
- package/dist/observability/metrics.d.ts +14 -1
- package/dist/observability/metrics.d.ts.map +1 -1
- package/dist/observability/metrics.js +23 -2
- package/dist/observability/metrics.js.map +1 -1
- package/dist/observability/prometheus-exporter.d.ts +37 -0
- package/dist/observability/prometheus-exporter.d.ts.map +1 -0
- package/dist/observability/prometheus-exporter.js +135 -0
- package/dist/observability/prometheus-exporter.js.map +1 -0
- package/dist/observability/storage.d.ts +43 -0
- package/dist/observability/storage.d.ts.map +1 -0
- package/dist/observability/storage.js +58 -0
- package/dist/observability/storage.js.map +1 -0
- package/dist/observability/store.d.ts +29 -0
- package/dist/observability/store.d.ts.map +1 -0
- package/dist/observability/store.js +36 -0
- package/dist/observability/store.js.map +1 -0
- package/dist/observability/usage-exporter.d.ts +58 -0
- package/dist/observability/usage-exporter.d.ts.map +1 -0
- package/dist/observability/usage-exporter.js +86 -0
- package/dist/observability/usage-exporter.js.map +1 -0
- package/dist/observability/usage.d.ts +18 -1
- package/dist/observability/usage.d.ts.map +1 -1
- package/dist/observability/usage.js +25 -3
- package/dist/observability/usage.js.map +1 -1
- package/dist/pipeline-config.d.ts +11 -0
- package/dist/pipeline-config.d.ts.map +1 -1
- package/dist/pipeline-config.js +36 -10
- package/dist/pipeline-config.js.map +1 -1
- package/dist/pipeline.d.ts +123 -2
- package/dist/pipeline.d.ts.map +1 -1
- package/dist/pipeline.js +249 -50
- package/dist/pipeline.js.map +1 -1
- package/dist/registry/index.d.ts +2 -0
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/index.js +1 -0
- package/dist/registry/index.js.map +1 -1
- package/dist/registry/multi-class.d.ts +57 -0
- package/dist/registry/multi-class.d.ts.map +1 -0
- package/dist/registry/multi-class.js +120 -0
- package/dist/registry/multi-class.js.map +1 -0
- package/dist/registry/registry.d.ts +91 -3
- package/dist/registry/registry.d.ts.map +1 -1
- package/dist/registry/registry.js +181 -11
- package/dist/registry/registry.js.map +1 -1
- package/dist/schema/constants.d.ts +9 -0
- package/dist/schema/constants.d.ts.map +1 -0
- package/dist/schema/constants.js +9 -0
- package/dist/schema/constants.js.map +1 -0
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +1 -1
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/loader.d.ts +27 -3
- package/dist/schema/loader.d.ts.map +1 -1
- package/dist/schema/loader.js +137 -32
- package/dist/schema/loader.js.map +1 -1
- package/dist/schema/types.d.ts +4 -0
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js.map +1 -1
- package/dist/schema/validator.d.ts +9 -0
- package/dist/schema/validator.d.ts.map +1 -1
- package/dist/schema/validator.js +153 -4
- package/dist/schema/validator.js.map +1 -1
- package/dist/sys-modules/audit.d.ts +50 -0
- package/dist/sys-modules/audit.d.ts.map +1 -0
- package/dist/sys-modules/audit.js +89 -0
- package/dist/sys-modules/audit.js.map +1 -0
- package/dist/sys-modules/control.d.ts +32 -4
- package/dist/sys-modules/control.d.ts.map +1 -1
- package/dist/sys-modules/control.js +196 -25
- package/dist/sys-modules/control.js.map +1 -1
- package/dist/sys-modules/index.d.ts +7 -2
- package/dist/sys-modules/index.d.ts.map +1 -1
- package/dist/sys-modules/index.js +3 -1
- package/dist/sys-modules/index.js.map +1 -1
- package/dist/sys-modules/overrides.d.ts +58 -0
- package/dist/sys-modules/overrides.d.ts.map +1 -0
- package/dist/sys-modules/overrides.js +106 -0
- package/dist/sys-modules/overrides.js.map +1 -0
- package/dist/sys-modules/registration.d.ts +17 -12
- package/dist/sys-modules/registration.d.ts.map +1 -1
- package/dist/sys-modules/registration.js +115 -23
- package/dist/sys-modules/registration.js.map +1 -1
- package/dist/sys-modules/toggle.d.ts +7 -2
- package/dist/sys-modules/toggle.d.ts.map +1 -1
- package/dist/sys-modules/toggle.js +61 -5
- package/dist/sys-modules/toggle.js.map +1 -1
- package/dist/trace-context.d.ts +47 -9
- package/dist/trace-context.d.ts.map +1 -1
- package/dist/trace-context.js +139 -16
- package/dist/trace-context.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prometheus text-format exporter with /metrics, /healthz, and /readyz HTTP endpoints.
|
|
3
|
+
*/
|
|
4
|
+
import { createServer } from 'node:http';
|
|
5
|
+
function computePercentiles(values, ps) {
|
|
6
|
+
if (values.length === 0)
|
|
7
|
+
return ps.map(() => 0);
|
|
8
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
9
|
+
return ps.map((p) => {
|
|
10
|
+
const idx = Math.ceil((p / 100) * sorted.length) - 1;
|
|
11
|
+
return sorted[Math.max(0, idx)];
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Serves Prometheus text metrics and K8s health endpoints over HTTP.
|
|
16
|
+
*
|
|
17
|
+
* Serves:
|
|
18
|
+
* GET {path} (default /metrics) — Prometheus text exposition format
|
|
19
|
+
* GET /healthz — liveness probe, always 200 OK
|
|
20
|
+
* GET /readyz — readiness probe, 200 OK after markReady() is called
|
|
21
|
+
*/
|
|
22
|
+
export class PrometheusExporter {
|
|
23
|
+
_collector;
|
|
24
|
+
_usageCollector;
|
|
25
|
+
_server = null;
|
|
26
|
+
_ready = false;
|
|
27
|
+
constructor(options) {
|
|
28
|
+
this._collector = options.collector;
|
|
29
|
+
this._usageCollector = options.usageCollector ?? null;
|
|
30
|
+
}
|
|
31
|
+
/** Return current metrics in Prometheus text exposition format. */
|
|
32
|
+
export() {
|
|
33
|
+
let output = this._collector.exportPrometheus();
|
|
34
|
+
if (this._usageCollector !== null) {
|
|
35
|
+
output += this._exportUsageMetrics();
|
|
36
|
+
}
|
|
37
|
+
return output;
|
|
38
|
+
}
|
|
39
|
+
_exportUsageMetrics() {
|
|
40
|
+
const summaries = this._usageCollector.getSummary();
|
|
41
|
+
if (summaries.length === 0)
|
|
42
|
+
return '';
|
|
43
|
+
// Build per-metric-family lines so HELP/TYPE immediately precede each family's data.
|
|
44
|
+
const callsLines = [
|
|
45
|
+
'# HELP apcore_usage_calls_total Total usage calls by module and status',
|
|
46
|
+
'# TYPE apcore_usage_calls_total counter',
|
|
47
|
+
];
|
|
48
|
+
const errorRateLines = [
|
|
49
|
+
'# HELP apcore_usage_error_rate Module error rate (0.0-1.0)',
|
|
50
|
+
'# TYPE apcore_usage_error_rate gauge',
|
|
51
|
+
];
|
|
52
|
+
const p50Lines = [
|
|
53
|
+
'# HELP apcore_usage_p50_latency_ms Module p50 latency in milliseconds',
|
|
54
|
+
'# TYPE apcore_usage_p50_latency_ms gauge',
|
|
55
|
+
];
|
|
56
|
+
const p95Lines = [
|
|
57
|
+
'# HELP apcore_usage_p95_latency_ms Module p95 latency in milliseconds',
|
|
58
|
+
'# TYPE apcore_usage_p95_latency_ms gauge',
|
|
59
|
+
];
|
|
60
|
+
const p99Lines = [
|
|
61
|
+
'# HELP apcore_usage_p99_latency_ms Module p99 latency in milliseconds',
|
|
62
|
+
'# TYPE apcore_usage_p99_latency_ms gauge',
|
|
63
|
+
];
|
|
64
|
+
for (const summary of summaries) {
|
|
65
|
+
const { moduleId, callCount, errorCount } = summary;
|
|
66
|
+
const successCount = callCount - errorCount;
|
|
67
|
+
const errorRate = callCount > 0 ? errorCount / callCount : 0;
|
|
68
|
+
callsLines.push(`apcore_usage_calls_total{module_id="${moduleId}",status="success"} ${successCount}`);
|
|
69
|
+
callsLines.push(`apcore_usage_calls_total{module_id="${moduleId}",status="error"} ${errorCount}`);
|
|
70
|
+
errorRateLines.push(`apcore_usage_error_rate{module_id="${moduleId}"} ${errorRate}`);
|
|
71
|
+
const latencies = this._usageCollector.getLatencies(moduleId);
|
|
72
|
+
const [p50, p95, p99] = computePercentiles(latencies, [50, 95, 99]);
|
|
73
|
+
p50Lines.push(`apcore_usage_p50_latency_ms{module_id="${moduleId}"} ${p50}`);
|
|
74
|
+
p95Lines.push(`apcore_usage_p95_latency_ms{module_id="${moduleId}"} ${p95}`);
|
|
75
|
+
p99Lines.push(`apcore_usage_p99_latency_ms{module_id="${moduleId}"} ${p99}`);
|
|
76
|
+
}
|
|
77
|
+
return [...callsLines, ...errorRateLines, ...p50Lines, ...p95Lines, ...p99Lines].join('\n') + '\n';
|
|
78
|
+
}
|
|
79
|
+
/** Signal that the application is ready to serve traffic (/readyz → 200). */
|
|
80
|
+
markReady() {
|
|
81
|
+
this._ready = true;
|
|
82
|
+
}
|
|
83
|
+
/** Start the HTTP server in a background listener. */
|
|
84
|
+
start(options) {
|
|
85
|
+
const port = options?.port ?? 9090;
|
|
86
|
+
const metricsPath = options?.path ?? '/metrics';
|
|
87
|
+
if (this._server !== null) {
|
|
88
|
+
throw new Error('PrometheusExporter is already running. Call stop() first.');
|
|
89
|
+
}
|
|
90
|
+
const exporter = this;
|
|
91
|
+
this._server = createServer((req, res) => {
|
|
92
|
+
const url = req.url ?? '/';
|
|
93
|
+
if (url === metricsPath) {
|
|
94
|
+
const body = Buffer.from(exporter.export(), 'utf-8');
|
|
95
|
+
res.writeHead(200, {
|
|
96
|
+
'Content-Type': 'text/plain; version=0.0.4; charset=utf-8',
|
|
97
|
+
'Content-Length': String(body.length),
|
|
98
|
+
});
|
|
99
|
+
res.end(body);
|
|
100
|
+
}
|
|
101
|
+
else if (url === '/healthz') {
|
|
102
|
+
res.writeHead(200);
|
|
103
|
+
res.end('OK');
|
|
104
|
+
}
|
|
105
|
+
else if (url === '/readyz') {
|
|
106
|
+
if (exporter._ready) {
|
|
107
|
+
res.writeHead(200);
|
|
108
|
+
res.end('OK');
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
res.writeHead(503);
|
|
112
|
+
res.end('Not ready');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
res.writeHead(404);
|
|
117
|
+
res.end();
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
this._server.listen(port);
|
|
121
|
+
}
|
|
122
|
+
/** Shut down the HTTP server. */
|
|
123
|
+
stop() {
|
|
124
|
+
return new Promise((resolve) => {
|
|
125
|
+
if (this._server !== null) {
|
|
126
|
+
this._server.close(() => resolve());
|
|
127
|
+
this._server = null;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
resolve();
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=prometheus-exporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prometheus-exporter.js","sourceRoot":"","sources":["../../src/observability/prometheus-exporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pluggable observability storage backend (Issue #43 §1).
|
|
3
|
+
*
|
|
4
|
+
* Provides a language-agnostic key/value abstraction so SDK consumers can
|
|
5
|
+
* persist error history, usage records, and metric snapshots to redis,
|
|
6
|
+
* postgres, etc. without ErrorHistory / UsageCollector / MetricsCollector
|
|
7
|
+
* needing to know the underlying technology.
|
|
8
|
+
*
|
|
9
|
+
* The default `InMemoryStorageBackend` keeps everything in a Map and is the
|
|
10
|
+
* implicit fallback when no backend is supplied.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Pluggable key/value storage backend.
|
|
14
|
+
*
|
|
15
|
+
* All operations may return synchronously or asynchronously — implementations
|
|
16
|
+
* targeting redis/postgres typically return Promises, while in-memory
|
|
17
|
+
* implementations return values directly. Callers should `await` the result.
|
|
18
|
+
*
|
|
19
|
+
* Namespaces partition the key space (e.g. "errors", "usage", "metrics") so
|
|
20
|
+
* a single backend instance can be shared by multiple collectors safely.
|
|
21
|
+
*/
|
|
22
|
+
export interface StorageBackend {
|
|
23
|
+
save(namespace: string, key: string, value: Record<string, unknown>): Promise<void> | void;
|
|
24
|
+
get(namespace: string, key: string): Promise<Record<string, unknown> | null> | Record<string, unknown> | null;
|
|
25
|
+
list(namespace: string, prefix?: string): Promise<Array<[string, Record<string, unknown>]>> | Array<[string, Record<string, unknown>]>;
|
|
26
|
+
delete(namespace: string, key: string): Promise<void> | void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* In-memory default backend.
|
|
30
|
+
*
|
|
31
|
+
* Each namespace is its own `Map<string, Record<string, unknown>>`. Values are
|
|
32
|
+
* stored by reference — callers that need snapshot semantics should clone
|
|
33
|
+
* before save. This is the implicit default when no backend is supplied to
|
|
34
|
+
* `ErrorHistory`, `UsageCollector`, or `MetricsCollector`.
|
|
35
|
+
*/
|
|
36
|
+
export declare class InMemoryStorageBackend implements StorageBackend {
|
|
37
|
+
private readonly _namespaces;
|
|
38
|
+
save(namespace: string, key: string, value: Record<string, unknown>): void;
|
|
39
|
+
get(namespace: string, key: string): Record<string, unknown> | null;
|
|
40
|
+
list(namespace: string, prefix?: string): Array<[string, Record<string, unknown>]>;
|
|
41
|
+
delete(namespace: string, key: string): void;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/observability/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;;;;;;;;GASG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,CACF,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAExB,GAAG,CACD,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAE5E,IAAI,CACF,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GAEb,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,GACjD,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAE7C,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC9D;AAED;;;;;;;GAOG;AACH,qBAAa,sBAAuB,YAAW,cAAc;IAC3D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAgE;IAE5F,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAS1E,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAMnE,IAAI,CACF,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAY3C,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;CAQ7C"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pluggable observability storage backend (Issue #43 §1).
|
|
3
|
+
*
|
|
4
|
+
* Provides a language-agnostic key/value abstraction so SDK consumers can
|
|
5
|
+
* persist error history, usage records, and metric snapshots to redis,
|
|
6
|
+
* postgres, etc. without ErrorHistory / UsageCollector / MetricsCollector
|
|
7
|
+
* needing to know the underlying technology.
|
|
8
|
+
*
|
|
9
|
+
* The default `InMemoryStorageBackend` keeps everything in a Map and is the
|
|
10
|
+
* implicit fallback when no backend is supplied.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* In-memory default backend.
|
|
14
|
+
*
|
|
15
|
+
* Each namespace is its own `Map<string, Record<string, unknown>>`. Values are
|
|
16
|
+
* stored by reference — callers that need snapshot semantics should clone
|
|
17
|
+
* before save. This is the implicit default when no backend is supplied to
|
|
18
|
+
* `ErrorHistory`, `UsageCollector`, or `MetricsCollector`.
|
|
19
|
+
*/
|
|
20
|
+
export class InMemoryStorageBackend {
|
|
21
|
+
_namespaces = new Map();
|
|
22
|
+
save(namespace, key, value) {
|
|
23
|
+
let ns = this._namespaces.get(namespace);
|
|
24
|
+
if (ns === undefined) {
|
|
25
|
+
ns = new Map();
|
|
26
|
+
this._namespaces.set(namespace, ns);
|
|
27
|
+
}
|
|
28
|
+
ns.set(key, value);
|
|
29
|
+
}
|
|
30
|
+
get(namespace, key) {
|
|
31
|
+
const ns = this._namespaces.get(namespace);
|
|
32
|
+
if (ns === undefined)
|
|
33
|
+
return null;
|
|
34
|
+
return ns.get(key) ?? null;
|
|
35
|
+
}
|
|
36
|
+
list(namespace, prefix) {
|
|
37
|
+
const ns = this._namespaces.get(namespace);
|
|
38
|
+
if (ns === undefined)
|
|
39
|
+
return [];
|
|
40
|
+
const entries = [];
|
|
41
|
+
for (const [k, v] of ns.entries()) {
|
|
42
|
+
if (prefix === undefined || k.startsWith(prefix)) {
|
|
43
|
+
entries.push([k, v]);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return entries;
|
|
47
|
+
}
|
|
48
|
+
delete(namespace, key) {
|
|
49
|
+
const ns = this._namespaces.get(namespace);
|
|
50
|
+
if (ns === undefined)
|
|
51
|
+
return;
|
|
52
|
+
ns.delete(key);
|
|
53
|
+
if (ns.size === 0) {
|
|
54
|
+
this._namespaces.delete(namespace);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/observability/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAkCH;;;;;;;GAOG;AACH,MAAM,OAAO,sBAAsB;IAChB,WAAW,GAAsD,IAAI,GAAG,EAAE,CAAC;IAE5F,IAAI,CAAC,SAAiB,EAAE,GAAW,EAAE,KAA8B;QACjE,IAAI,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACzC,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YACrB,EAAE,GAAG,IAAI,GAAG,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QACtC,CAAC;QACD,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACrB,CAAC;IAED,GAAG,CAAC,SAAiB,EAAE,GAAW;QAChC,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,EAAE,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QAClC,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;IAC7B,CAAC;IAED,IAAI,CACF,SAAiB,EACjB,MAAe;QAEf,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,EAAE,KAAK,SAAS;YAAE,OAAO,EAAE,CAAC;QAChC,MAAM,OAAO,GAA6C,EAAE,CAAC;QAC7D,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC;YAClC,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,CAAC,SAAiB,EAAE,GAAW;QACnC,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,EAAE,KAAK,SAAS;YAAE,OAAO;QAC7B,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACf,IAAI,EAAE,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAClB,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pluggable observability storage backend interface and in-memory default.
|
|
3
|
+
*/
|
|
4
|
+
export interface MetricPoint {
|
|
5
|
+
readonly name: string;
|
|
6
|
+
readonly value: number;
|
|
7
|
+
readonly moduleId: string | null;
|
|
8
|
+
readonly labels: Record<string, string>;
|
|
9
|
+
readonly timestamp: string;
|
|
10
|
+
}
|
|
11
|
+
export interface ObservabilityStore {
|
|
12
|
+
recordError(entry: unknown): void;
|
|
13
|
+
getErrors(moduleId?: string | null, limit?: number | null): unknown[];
|
|
14
|
+
recordMetric(metric: MetricPoint): void;
|
|
15
|
+
getMetrics(moduleId?: string | null, metricName?: string | null): MetricPoint[];
|
|
16
|
+
flush(): void;
|
|
17
|
+
clear(): void;
|
|
18
|
+
}
|
|
19
|
+
export declare class InMemoryObservabilityStore implements ObservabilityStore {
|
|
20
|
+
private _errors;
|
|
21
|
+
private _metrics;
|
|
22
|
+
recordError(entry: unknown): void;
|
|
23
|
+
getErrors(moduleId?: string | null, limit?: number | null): unknown[];
|
|
24
|
+
recordMetric(metric: MetricPoint): void;
|
|
25
|
+
getMetrics(moduleId?: string | null, metricName?: string | null): MetricPoint[];
|
|
26
|
+
flush(): void;
|
|
27
|
+
clear(): void;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/observability/store.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAClC,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,EAAE,CAAC;IACtE,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IACxC,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,WAAW,EAAE,CAAC;IAChF,KAAK,IAAI,IAAI,CAAC;IACd,KAAK,IAAI,IAAI,CAAC;CACf;AAED,qBAAa,0BAA2B,YAAW,kBAAkB;IACnE,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,QAAQ,CAAqB;IAErC,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAIjC,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,EAAE;IAQrE,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAIvC,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,WAAW,EAAE;IAW/E,KAAK,IAAI,IAAI;IAEb,KAAK,IAAI,IAAI;CAId"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pluggable observability storage backend interface and in-memory default.
|
|
3
|
+
*/
|
|
4
|
+
export class InMemoryObservabilityStore {
|
|
5
|
+
_errors = [];
|
|
6
|
+
_metrics = [];
|
|
7
|
+
recordError(entry) {
|
|
8
|
+
this._errors.push(entry);
|
|
9
|
+
}
|
|
10
|
+
getErrors(moduleId, limit) {
|
|
11
|
+
let entries = [...this._errors];
|
|
12
|
+
if (moduleId != null) {
|
|
13
|
+
entries = entries.filter((e) => e['moduleId'] === moduleId);
|
|
14
|
+
}
|
|
15
|
+
return limit != null ? entries.slice(0, limit) : entries;
|
|
16
|
+
}
|
|
17
|
+
recordMetric(metric) {
|
|
18
|
+
this._metrics.push(metric);
|
|
19
|
+
}
|
|
20
|
+
getMetrics(moduleId, metricName) {
|
|
21
|
+
let metrics = [...this._metrics];
|
|
22
|
+
if (moduleId != null) {
|
|
23
|
+
metrics = metrics.filter((m) => m.moduleId === moduleId);
|
|
24
|
+
}
|
|
25
|
+
if (metricName != null) {
|
|
26
|
+
metrics = metrics.filter((m) => m.name === metricName);
|
|
27
|
+
}
|
|
28
|
+
return metrics;
|
|
29
|
+
}
|
|
30
|
+
flush() { }
|
|
31
|
+
clear() {
|
|
32
|
+
this._errors = [];
|
|
33
|
+
this._metrics = [];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/observability/store.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmBH,MAAM,OAAO,0BAA0B;IAC7B,OAAO,GAAc,EAAE,CAAC;IACxB,QAAQ,GAAkB,EAAE,CAAC;IAErC,WAAW,CAAC,KAAc;QACxB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED,SAAS,CAAC,QAAwB,EAAE,KAAqB;QACvD,IAAI,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;YACrB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAE,CAA6B,CAAC,UAAU,CAAC,KAAK,QAAQ,CAAC,CAAC;QAC3F,CAAC;QACD,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAC3D,CAAC;IAED,YAAY,CAAC,MAAmB;QAC9B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;IAED,UAAU,CAAC,QAAwB,EAAE,UAA0B;QAC7D,IAAI,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;YACrB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;YACvB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;QACzD,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,KAAU,CAAC;IAEhB,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;IACrB,CAAC;CACF"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UsageExporter — push interface for delivering UsageCollector summaries
|
|
3
|
+
* to external sinks on a schedule (Issue #45 §3).
|
|
4
|
+
*
|
|
5
|
+
* The collector pulls; the exporter pushes. Keep them decoupled so an
|
|
6
|
+
* application can swap in (for example) a Prometheus, OTLP, or HTTP
|
|
7
|
+
* exporter without changing how the collector is wired into the pipeline.
|
|
8
|
+
*
|
|
9
|
+
* Cross-language alignment: mirrors apcore-python's
|
|
10
|
+
* `apcore.observability.usage.UsageExporter` / `PeriodicUsageExporter` and
|
|
11
|
+
* the Rust trait in `apcore::observability::usage::UsageExporter`.
|
|
12
|
+
*/
|
|
13
|
+
import type { UsageCollector } from './usage.js';
|
|
14
|
+
/**
|
|
15
|
+
* Contract for a usage-summary sink.
|
|
16
|
+
*
|
|
17
|
+
* `export` is invoked by {@link PeriodicUsageExporter} (or any caller) with
|
|
18
|
+
* the latest summary snapshot. Implementations may be sync or async; the
|
|
19
|
+
* scheduler awaits whichever is returned.
|
|
20
|
+
*
|
|
21
|
+
* `shutdown` is invoked once during graceful teardown so an exporter can
|
|
22
|
+
* flush buffers, close sockets, etc.
|
|
23
|
+
*/
|
|
24
|
+
export interface UsageExporter {
|
|
25
|
+
export(summary: Record<string, unknown>): Promise<void> | void;
|
|
26
|
+
shutdown(): Promise<void> | void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* No-op exporter — the safe default. Useful as a placeholder when an
|
|
30
|
+
* application has registered a {@link PeriodicUsageExporter} but does not
|
|
31
|
+
* yet have a real backend wired up.
|
|
32
|
+
*/
|
|
33
|
+
export declare class NoopUsageExporter implements UsageExporter {
|
|
34
|
+
export(_summary: Record<string, unknown>): void;
|
|
35
|
+
shutdown(): void;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Periodically pushes a {@link UsageCollector} summary into a
|
|
39
|
+
* {@link UsageExporter}.
|
|
40
|
+
*
|
|
41
|
+
* Default interval is 1 hour (3 600 000 ms) which matches apcore-python's
|
|
42
|
+
* `PeriodicUsageExporter` default. The first push happens one interval
|
|
43
|
+
* after `start()`; nothing is exported synchronously on start.
|
|
44
|
+
*/
|
|
45
|
+
export declare class PeriodicUsageExporter {
|
|
46
|
+
private readonly collector;
|
|
47
|
+
private readonly exporter;
|
|
48
|
+
private readonly intervalMs;
|
|
49
|
+
private _timer;
|
|
50
|
+
private _running;
|
|
51
|
+
constructor(collector: UsageCollector, exporter: UsageExporter, intervalMs?: number);
|
|
52
|
+
/** Begin periodic export. Idempotent — calling twice is a no-op. */
|
|
53
|
+
start(): void;
|
|
54
|
+
/** Stop the timer and await `exporter.shutdown()`. Idempotent. */
|
|
55
|
+
stop(): Promise<void>;
|
|
56
|
+
private _tick;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=usage-exporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-exporter.d.ts","sourceRoot":"","sources":["../../src/observability/usage-exporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC/D,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAClC;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,aAAa;IAErD,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI/C,QAAQ,IAAI,IAAI;CAGjB;AAED;;;;;;;GAOG;AACH,qBAAa,qBAAqB;IAK9B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAN7B,OAAO,CAAC,MAAM,CAA+C;IAC7D,OAAO,CAAC,QAAQ,CAAS;gBAGN,SAAS,EAAE,cAAc,EACzB,QAAQ,EAAE,aAAa,EACvB,UAAU,GAAE,MAAkB;IAGjD,oEAAoE;IACpE,KAAK,IAAI,IAAI;IAQb,kEAAkE;IAC5D,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAS3B,OAAO,CAAC,KAAK;CAmBd"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UsageExporter — push interface for delivering UsageCollector summaries
|
|
3
|
+
* to external sinks on a schedule (Issue #45 §3).
|
|
4
|
+
*
|
|
5
|
+
* The collector pulls; the exporter pushes. Keep them decoupled so an
|
|
6
|
+
* application can swap in (for example) a Prometheus, OTLP, or HTTP
|
|
7
|
+
* exporter without changing how the collector is wired into the pipeline.
|
|
8
|
+
*
|
|
9
|
+
* Cross-language alignment: mirrors apcore-python's
|
|
10
|
+
* `apcore.observability.usage.UsageExporter` / `PeriodicUsageExporter` and
|
|
11
|
+
* the Rust trait in `apcore::observability::usage::UsageExporter`.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* No-op exporter — the safe default. Useful as a placeholder when an
|
|
15
|
+
* application has registered a {@link PeriodicUsageExporter} but does not
|
|
16
|
+
* yet have a real backend wired up.
|
|
17
|
+
*/
|
|
18
|
+
export class NoopUsageExporter {
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
20
|
+
export(_summary) {
|
|
21
|
+
// no-op
|
|
22
|
+
}
|
|
23
|
+
shutdown() {
|
|
24
|
+
// no-op
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Periodically pushes a {@link UsageCollector} summary into a
|
|
29
|
+
* {@link UsageExporter}.
|
|
30
|
+
*
|
|
31
|
+
* Default interval is 1 hour (3 600 000 ms) which matches apcore-python's
|
|
32
|
+
* `PeriodicUsageExporter` default. The first push happens one interval
|
|
33
|
+
* after `start()`; nothing is exported synchronously on start.
|
|
34
|
+
*/
|
|
35
|
+
export class PeriodicUsageExporter {
|
|
36
|
+
collector;
|
|
37
|
+
exporter;
|
|
38
|
+
intervalMs;
|
|
39
|
+
_timer = null;
|
|
40
|
+
_running = false;
|
|
41
|
+
constructor(collector, exporter, intervalMs = 3_600_000) {
|
|
42
|
+
this.collector = collector;
|
|
43
|
+
this.exporter = exporter;
|
|
44
|
+
this.intervalMs = intervalMs;
|
|
45
|
+
}
|
|
46
|
+
/** Begin periodic export. Idempotent — calling twice is a no-op. */
|
|
47
|
+
start() {
|
|
48
|
+
if (this._running)
|
|
49
|
+
return;
|
|
50
|
+
this._running = true;
|
|
51
|
+
this._timer = setInterval(() => {
|
|
52
|
+
this._tick();
|
|
53
|
+
}, this.intervalMs);
|
|
54
|
+
}
|
|
55
|
+
/** Stop the timer and await `exporter.shutdown()`. Idempotent. */
|
|
56
|
+
async stop() {
|
|
57
|
+
if (this._timer !== null) {
|
|
58
|
+
clearInterval(this._timer);
|
|
59
|
+
this._timer = null;
|
|
60
|
+
}
|
|
61
|
+
this._running = false;
|
|
62
|
+
await this.exporter.shutdown();
|
|
63
|
+
}
|
|
64
|
+
_tick() {
|
|
65
|
+
let summary;
|
|
66
|
+
try {
|
|
67
|
+
summary = { modules: this.collector.getSummary() };
|
|
68
|
+
}
|
|
69
|
+
catch (e) {
|
|
70
|
+
console.warn('[apcore:usage-exporter] Failed to build summary:', e);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
const result = this.exporter.export(summary);
|
|
75
|
+
if (result instanceof Promise) {
|
|
76
|
+
result.catch((e) => {
|
|
77
|
+
console.warn('[apcore:usage-exporter] export() rejected:', e);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch (e) {
|
|
82
|
+
console.warn('[apcore:usage-exporter] export() threw:', e);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=usage-exporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-exporter.js","sourceRoot":"","sources":["../../src/observability/usage-exporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAmBH;;;;GAIG;AACH,MAAM,OAAO,iBAAiB;IAC5B,6DAA6D;IAC7D,MAAM,CAAC,QAAiC;QACtC,QAAQ;IACV,CAAC;IAED,QAAQ;QACN,QAAQ;IACV,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,qBAAqB;IAKb;IACA;IACA;IANX,MAAM,GAA0C,IAAI,CAAC;IACrD,QAAQ,GAAG,KAAK,CAAC;IAEzB,YACmB,SAAyB,EACzB,QAAuB,EACvB,aAAqB,SAAS;QAF9B,cAAS,GAAT,SAAS,CAAgB;QACzB,aAAQ,GAAR,QAAQ,CAAe;QACvB,eAAU,GAAV,UAAU,CAAoB;IAC9C,CAAC;IAEJ,oEAAoE;IACpE,KAAK;QACH,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE;YAC7B,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACtB,CAAC;IAED,kEAAkE;IAClE,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YACzB,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC3B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACrB,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;IACjC,CAAC;IAEO,KAAK;QACX,IAAI,OAAgC,CAAC;QACrC,IAAI,CAAC;YACH,OAAO,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC;QACrD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,kDAAkD,EAAE,CAAC,CAAC,CAAC;YACpE,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC7C,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;gBAC9B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE;oBAC1B,OAAO,CAAC,IAAI,CAAC,4CAA4C,EAAE,CAAC,CAAC,CAAC;gBAChE,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,yCAAyC,EAAE,CAAC,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;CACF"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { Middleware } from '../middleware/base.js';
|
|
5
5
|
import type { Context } from '../context.js';
|
|
6
|
+
import { type StorageBackend } from './storage.js';
|
|
6
7
|
export interface UsageRecord {
|
|
7
8
|
readonly timestamp: string;
|
|
8
9
|
readonly callerId: string;
|
|
@@ -33,14 +34,30 @@ export interface ModuleUsageDetail extends ModuleUsageSummary {
|
|
|
33
34
|
readonly hourlyDistribution: HourlyBucket[];
|
|
34
35
|
}
|
|
35
36
|
export declare function bucketKey(date: Date): string;
|
|
37
|
+
export interface UsageCollectorOptions {
|
|
38
|
+
retentionHours?: number;
|
|
39
|
+
maxRecordsPerBucket?: number;
|
|
40
|
+
/** Pluggable key/value storage backend (Issue #43 §1). Optional. */
|
|
41
|
+
storage?: StorageBackend;
|
|
42
|
+
}
|
|
36
43
|
/**
|
|
37
44
|
* In-memory usage tracker with hourly buckets and configurable retention.
|
|
38
45
|
*/
|
|
39
46
|
export declare class UsageCollector {
|
|
40
47
|
readonly retentionHours: number;
|
|
41
48
|
private readonly _maxRecordsPerBucket;
|
|
49
|
+
private readonly _storage;
|
|
42
50
|
private readonly _data;
|
|
43
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Construct a `UsageCollector`.
|
|
53
|
+
*
|
|
54
|
+
* Two construction shapes are supported for backwards compatibility:
|
|
55
|
+
* - Positional: `new UsageCollector(retentionHours, maxRecordsPerBucket)`.
|
|
56
|
+
* - Options: `new UsageCollector({ retentionHours, maxRecordsPerBucket, storage })`.
|
|
57
|
+
*/
|
|
58
|
+
constructor(optionsOrRetentionHours?: UsageCollectorOptions | number, maxRecordsPerBucket?: number);
|
|
59
|
+
/** The pluggable storage backend (Issue #43 §1). */
|
|
60
|
+
get storage(): StorageBackend;
|
|
44
61
|
record(moduleId: string, callerId: string, latencyMs: number, success: boolean, timestamp?: string): void;
|
|
45
62
|
getSummary(period?: string): ModuleUsageSummary[];
|
|
46
63
|
getModule(moduleId: string, period?: string): ModuleUsageDetail;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../src/observability/usage.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../src/observability/usage.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAA0B,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAE3E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,QAAQ,CAAC,OAAO,EAAE,kBAAkB,EAAE,CAAC;IACvC,QAAQ,CAAC,kBAAkB,EAAE,YAAY,EAAE,CAAC;CAC7C;AAUD,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAM5C;AAYD,MAAM,WAAW,qBAAqB;IACpC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oEAAoE;IACpE,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B;AAED;;GAEG;AACH,qBAAa,cAAc;IACzB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAC9C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;IAE1C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAsD;IAE5E;;;;;;OAMG;gBAED,uBAAuB,CAAC,EAAE,qBAAqB,GAAG,MAAM,EACxD,mBAAmB,GAAE,MAAc;IAcrC,oDAAoD;IACpD,IAAI,OAAO,IAAI,cAAc,CAE5B;IAED,MAAM,CACJ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,EAChB,SAAS,CAAC,EAAE,MAAM,GACjB,IAAI;IAwBP,UAAU,CAAC,MAAM,GAAE,MAAc,GAAG,kBAAkB,EAAE;IAYxD,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAE,MAAc,GAAG,iBAAiB;IAQtE,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAE,MAAc,GAAG,MAAM,EAAE;IAQhE,OAAO,CAAC,eAAe;IAsBvB,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,mBAAmB;IAoB3B,OAAO,CAAC,mBAAmB;IAuB3B,OAAO,CAAC,eAAe;CAWxB;AAID;;GAEG;AACH,qBAAa,eAAgB,SAAQ,UAAU;IAC7C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAiB;gBAEhC,SAAS,EAAE,cAAc;IAK5B,MAAM,CACb,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,OAAO,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAOxB,KAAK,CACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,OAAO,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAOxB,OAAO,CACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,MAAM,EAAE,KAAK,EACb,OAAO,EAAE,OAAO,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAOjC,OAAO,CAAC,aAAa;CAMtB"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Time-windowed usage tracking with per-module and per-caller analytics.
|
|
3
3
|
*/
|
|
4
4
|
import { Middleware } from '../middleware/base.js';
|
|
5
|
+
import { InMemoryStorageBackend } from './storage.js';
|
|
5
6
|
function parsePeriod(period) {
|
|
6
7
|
const match = period.match(/^(\d+)([hd])$/);
|
|
7
8
|
if (!match)
|
|
@@ -38,11 +39,32 @@ function computeTrend(currentCount, previousCount) {
|
|
|
38
39
|
export class UsageCollector {
|
|
39
40
|
retentionHours;
|
|
40
41
|
_maxRecordsPerBucket;
|
|
42
|
+
_storage;
|
|
41
43
|
// moduleId -> bucketKey -> UsageRecord[]
|
|
42
44
|
_data = new Map();
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Construct a `UsageCollector`.
|
|
47
|
+
*
|
|
48
|
+
* Two construction shapes are supported for backwards compatibility:
|
|
49
|
+
* - Positional: `new UsageCollector(retentionHours, maxRecordsPerBucket)`.
|
|
50
|
+
* - Options: `new UsageCollector({ retentionHours, maxRecordsPerBucket, storage })`.
|
|
51
|
+
*/
|
|
52
|
+
constructor(optionsOrRetentionHours, maxRecordsPerBucket = 10000) {
|
|
53
|
+
if (typeof optionsOrRetentionHours === 'object' && optionsOrRetentionHours !== null) {
|
|
54
|
+
const options = optionsOrRetentionHours;
|
|
55
|
+
this.retentionHours = options.retentionHours ?? 168;
|
|
56
|
+
this._maxRecordsPerBucket = options.maxRecordsPerBucket ?? 10000;
|
|
57
|
+
this._storage = options.storage ?? new InMemoryStorageBackend();
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
this.retentionHours = optionsOrRetentionHours ?? 168;
|
|
61
|
+
this._maxRecordsPerBucket = maxRecordsPerBucket;
|
|
62
|
+
this._storage = new InMemoryStorageBackend();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** The pluggable storage backend (Issue #43 §1). */
|
|
66
|
+
get storage() {
|
|
67
|
+
return this._storage;
|
|
46
68
|
}
|
|
47
69
|
record(moduleId, callerId, latencyMs, success, timestamp) {
|
|
48
70
|
const now = timestamp ? new Date(timestamp) : new Date();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../../src/observability/usage.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../../src/observability/usage.ts"],"names":[],"mappings":"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"}
|