paygate-mcp 10.17.0 → 10.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api-metrics.d.ts +95 -0
- package/dist/api-metrics.d.ts.map +1 -0
- package/dist/api-metrics.js +187 -0
- package/dist/api-metrics.js.map +1 -0
- package/dist/error-classifier.d.ts +109 -0
- package/dist/error-classifier.d.ts.map +1 -0
- package/dist/error-classifier.js +181 -0
- package/dist/error-classifier.js.map +1 -0
- package/dist/grace-period.d.ts +113 -0
- package/dist/grace-period.d.ts.map +1 -0
- package/dist/grace-period.js +250 -0
- package/dist/grace-period.js.map +1 -0
- package/dist/incident-manager.d.ts +108 -0
- package/dist/incident-manager.d.ts.map +1 -0
- package/dist/incident-manager.js +178 -0
- package/dist/incident-manager.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -1
- package/dist/index.js.map +1 -1
- package/dist/key-migration.d.ts +88 -0
- package/dist/key-migration.d.ts.map +1 -0
- package/dist/key-migration.js +168 -0
- package/dist/key-migration.js.map +1 -0
- package/dist/sliding-window.d.ts +78 -0
- package/dist/sliding-window.d.ts.map +1 -0
- package/dist/sliding-window.js +194 -0
- package/dist/sliding-window.js.map +1 -0
- package/dist/webhook-batch.d.ts +93 -0
- package/dist/webhook-batch.d.ts.map +1 -0
- package/dist/webhook-batch.js +191 -0
- package/dist/webhook-batch.js.map +1 -0
- package/dist/webhook-retry.d.ts +94 -0
- package/dist/webhook-retry.d.ts.map +1 -0
- package/dist/webhook-retry.js +186 -0
- package/dist/webhook-retry.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* APIMetricsAggregator — Time-bucketed API metrics with percentile calculations.
|
|
3
|
+
*
|
|
4
|
+
* Record API call metrics, aggregate into time buckets,
|
|
5
|
+
* and compute percentile latencies for monitoring.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* const agg = new APIMetricsAggregator();
|
|
10
|
+
*
|
|
11
|
+
* agg.record({ method: 'tools/call', tool: 'search', latencyMs: 45, statusCode: 200 });
|
|
12
|
+
* agg.record({ method: 'tools/call', tool: 'search', latencyMs: 120, statusCode: 200 });
|
|
13
|
+
*
|
|
14
|
+
* const summary = agg.getSummary('1m');
|
|
15
|
+
* // { totalRequests, avgLatencyMs, p50, p95, p99, errorRate, ... }
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export type MetricGranularity = '1m' | '5m' | '1h' | '1d';
|
|
19
|
+
export interface MetricRecord {
|
|
20
|
+
method?: string;
|
|
21
|
+
tool?: string;
|
|
22
|
+
key?: string;
|
|
23
|
+
latencyMs: number;
|
|
24
|
+
statusCode: number;
|
|
25
|
+
credits?: number;
|
|
26
|
+
timestamp?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface MetricBucket {
|
|
29
|
+
start: number;
|
|
30
|
+
end: number;
|
|
31
|
+
count: number;
|
|
32
|
+
errors: number;
|
|
33
|
+
latencies: number[];
|
|
34
|
+
totalCredits: number;
|
|
35
|
+
}
|
|
36
|
+
export interface MetricSummary {
|
|
37
|
+
granularity: MetricGranularity;
|
|
38
|
+
bucketCount: number;
|
|
39
|
+
totalRequests: number;
|
|
40
|
+
totalErrors: number;
|
|
41
|
+
errorRate: number;
|
|
42
|
+
avgLatencyMs: number;
|
|
43
|
+
p50LatencyMs: number;
|
|
44
|
+
p95LatencyMs: number;
|
|
45
|
+
p99LatencyMs: number;
|
|
46
|
+
minLatencyMs: number;
|
|
47
|
+
maxLatencyMs: number;
|
|
48
|
+
totalCredits: number;
|
|
49
|
+
requestsPerSecond: number;
|
|
50
|
+
}
|
|
51
|
+
export interface ToolMetricSummary {
|
|
52
|
+
tool: string;
|
|
53
|
+
count: number;
|
|
54
|
+
errors: number;
|
|
55
|
+
avgLatencyMs: number;
|
|
56
|
+
totalCredits: number;
|
|
57
|
+
}
|
|
58
|
+
export interface APIMetricsConfig {
|
|
59
|
+
/** Max raw records to keep. Default 100000. */
|
|
60
|
+
maxRecords?: number;
|
|
61
|
+
/** Max age for records in ms. Default 86400000 (24h). */
|
|
62
|
+
maxAgeMs?: number;
|
|
63
|
+
}
|
|
64
|
+
export interface APIMetricsStats {
|
|
65
|
+
totalRecords: number;
|
|
66
|
+
totalRequests: number;
|
|
67
|
+
totalErrors: number;
|
|
68
|
+
oldestRecord: number | null;
|
|
69
|
+
newestRecord: number | null;
|
|
70
|
+
}
|
|
71
|
+
export declare class APIMetricsAggregator {
|
|
72
|
+
private records;
|
|
73
|
+
private maxRecords;
|
|
74
|
+
private maxAgeMs;
|
|
75
|
+
constructor(config?: APIMetricsConfig);
|
|
76
|
+
/** Record a metric data point. */
|
|
77
|
+
record(metric: MetricRecord): void;
|
|
78
|
+
/** Get aggregated summary for a granularity. */
|
|
79
|
+
getSummary(granularity?: MetricGranularity, options?: {
|
|
80
|
+
tool?: string;
|
|
81
|
+
key?: string;
|
|
82
|
+
}): MetricSummary;
|
|
83
|
+
/** Get per-tool breakdown. */
|
|
84
|
+
getToolBreakdown(): ToolMetricSummary[];
|
|
85
|
+
/** Get time-series buckets. */
|
|
86
|
+
getBuckets(granularity: MetricGranularity): MetricBucket[];
|
|
87
|
+
/** Remove records older than maxAge. */
|
|
88
|
+
cleanup(): number;
|
|
89
|
+
getStats(): APIMetricsStats;
|
|
90
|
+
/** Clear all data. */
|
|
91
|
+
destroy(): void;
|
|
92
|
+
private getRelevantRecords;
|
|
93
|
+
private percentile;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=api-metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-metrics.d.ts","sourceRoot":"","sources":["../src/api-metrics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE1D,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,iBAAiB,CAAC;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAqBD,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAS;gBAEb,MAAM,GAAE,gBAAqB;IAOzC,kCAAkC;IAClC,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAqBlC,gDAAgD;IAChD,UAAU,CAAC,WAAW,GAAE,iBAAwB,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,aAAa;IAmD3G,8BAA8B;IAC9B,gBAAgB,IAAI,iBAAiB,EAAE;IAyBvC,+BAA+B;IAC/B,UAAU,CAAC,WAAW,EAAE,iBAAiB,GAAG,YAAY,EAAE;IA+B1D,wCAAwC;IACxC,OAAO,IAAI,MAAM;IASjB,QAAQ,IAAI,eAAe;IAU3B,sBAAsB;IACtB,OAAO,IAAI,IAAI;IAMf,OAAO,CAAC,kBAAkB;IAK1B,OAAO,CAAC,UAAU;CAKnB"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* APIMetricsAggregator — Time-bucketed API metrics with percentile calculations.
|
|
4
|
+
*
|
|
5
|
+
* Record API call metrics, aggregate into time buckets,
|
|
6
|
+
* and compute percentile latencies for monitoring.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const agg = new APIMetricsAggregator();
|
|
11
|
+
*
|
|
12
|
+
* agg.record({ method: 'tools/call', tool: 'search', latencyMs: 45, statusCode: 200 });
|
|
13
|
+
* agg.record({ method: 'tools/call', tool: 'search', latencyMs: 120, statusCode: 200 });
|
|
14
|
+
*
|
|
15
|
+
* const summary = agg.getSummary('1m');
|
|
16
|
+
* // { totalRequests, avgLatencyMs, p50, p95, p99, errorRate, ... }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.APIMetricsAggregator = void 0;
|
|
21
|
+
const GRANULARITY_MS = {
|
|
22
|
+
'1m': 60_000,
|
|
23
|
+
'5m': 300_000,
|
|
24
|
+
'1h': 3_600_000,
|
|
25
|
+
'1d': 86_400_000,
|
|
26
|
+
};
|
|
27
|
+
class APIMetricsAggregator {
|
|
28
|
+
records = [];
|
|
29
|
+
maxRecords;
|
|
30
|
+
maxAgeMs;
|
|
31
|
+
constructor(config = {}) {
|
|
32
|
+
this.maxRecords = config.maxRecords ?? 100_000;
|
|
33
|
+
this.maxAgeMs = config.maxAgeMs ?? 86_400_000;
|
|
34
|
+
}
|
|
35
|
+
// ── Recording ─────────────────────────────────────────────────
|
|
36
|
+
/** Record a metric data point. */
|
|
37
|
+
record(metric) {
|
|
38
|
+
const stored = {
|
|
39
|
+
method: metric.method ?? '',
|
|
40
|
+
tool: metric.tool ?? '',
|
|
41
|
+
key: metric.key ?? '',
|
|
42
|
+
latencyMs: metric.latencyMs,
|
|
43
|
+
statusCode: metric.statusCode,
|
|
44
|
+
credits: metric.credits ?? 0,
|
|
45
|
+
timestamp: metric.timestamp ?? Date.now(),
|
|
46
|
+
};
|
|
47
|
+
this.records.push(stored);
|
|
48
|
+
// Evict oldest if over limit
|
|
49
|
+
if (this.records.length > this.maxRecords) {
|
|
50
|
+
this.records.splice(0, this.records.length - this.maxRecords);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// ── Aggregation ───────────────────────────────────────────────
|
|
54
|
+
/** Get aggregated summary for a granularity. */
|
|
55
|
+
getSummary(granularity = '1m', options) {
|
|
56
|
+
let filtered = this.getRelevantRecords();
|
|
57
|
+
if (options?.tool)
|
|
58
|
+
filtered = filtered.filter(r => r.tool === options.tool);
|
|
59
|
+
if (options?.key)
|
|
60
|
+
filtered = filtered.filter(r => r.key === options.key);
|
|
61
|
+
if (filtered.length === 0) {
|
|
62
|
+
return {
|
|
63
|
+
granularity,
|
|
64
|
+
bucketCount: 0,
|
|
65
|
+
totalRequests: 0,
|
|
66
|
+
totalErrors: 0,
|
|
67
|
+
errorRate: 0,
|
|
68
|
+
avgLatencyMs: 0,
|
|
69
|
+
p50LatencyMs: 0,
|
|
70
|
+
p95LatencyMs: 0,
|
|
71
|
+
p99LatencyMs: 0,
|
|
72
|
+
minLatencyMs: 0,
|
|
73
|
+
maxLatencyMs: 0,
|
|
74
|
+
totalCredits: 0,
|
|
75
|
+
requestsPerSecond: 0,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const latencies = filtered.map(r => r.latencyMs).sort((a, b) => a - b);
|
|
79
|
+
const errors = filtered.filter(r => r.statusCode >= 400).length;
|
|
80
|
+
const totalCredits = filtered.reduce((s, r) => s + r.credits, 0);
|
|
81
|
+
const oldest = filtered[0].timestamp;
|
|
82
|
+
const newest = filtered[filtered.length - 1].timestamp;
|
|
83
|
+
const durationSec = Math.max(1, (newest - oldest) / 1000);
|
|
84
|
+
const bucketMs = GRANULARITY_MS[granularity];
|
|
85
|
+
const bucketCount = Math.ceil((newest - oldest + 1) / bucketMs);
|
|
86
|
+
return {
|
|
87
|
+
granularity,
|
|
88
|
+
bucketCount,
|
|
89
|
+
totalRequests: filtered.length,
|
|
90
|
+
totalErrors: errors,
|
|
91
|
+
errorRate: Math.round((errors / filtered.length) * 10000) / 100,
|
|
92
|
+
avgLatencyMs: Math.round(latencies.reduce((s, l) => s + l, 0) / latencies.length * 100) / 100,
|
|
93
|
+
p50LatencyMs: this.percentile(latencies, 50),
|
|
94
|
+
p95LatencyMs: this.percentile(latencies, 95),
|
|
95
|
+
p99LatencyMs: this.percentile(latencies, 99),
|
|
96
|
+
minLatencyMs: latencies[0],
|
|
97
|
+
maxLatencyMs: latencies[latencies.length - 1],
|
|
98
|
+
totalCredits,
|
|
99
|
+
requestsPerSecond: Math.round((filtered.length / durationSec) * 100) / 100,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/** Get per-tool breakdown. */
|
|
103
|
+
getToolBreakdown() {
|
|
104
|
+
const records = this.getRelevantRecords();
|
|
105
|
+
const toolMap = new Map();
|
|
106
|
+
for (const r of records) {
|
|
107
|
+
if (!r.tool)
|
|
108
|
+
continue;
|
|
109
|
+
const existing = toolMap.get(r.tool) ?? { count: 0, errors: 0, latencySum: 0, credits: 0 };
|
|
110
|
+
existing.count++;
|
|
111
|
+
if (r.statusCode >= 400)
|
|
112
|
+
existing.errors++;
|
|
113
|
+
existing.latencySum += r.latencyMs;
|
|
114
|
+
existing.credits += r.credits;
|
|
115
|
+
toolMap.set(r.tool, existing);
|
|
116
|
+
}
|
|
117
|
+
return [...toolMap.entries()]
|
|
118
|
+
.map(([tool, data]) => ({
|
|
119
|
+
tool,
|
|
120
|
+
count: data.count,
|
|
121
|
+
errors: data.errors,
|
|
122
|
+
avgLatencyMs: Math.round((data.latencySum / data.count) * 100) / 100,
|
|
123
|
+
totalCredits: data.credits,
|
|
124
|
+
}))
|
|
125
|
+
.sort((a, b) => b.count - a.count);
|
|
126
|
+
}
|
|
127
|
+
/** Get time-series buckets. */
|
|
128
|
+
getBuckets(granularity) {
|
|
129
|
+
const records = this.getRelevantRecords();
|
|
130
|
+
if (records.length === 0)
|
|
131
|
+
return [];
|
|
132
|
+
const bucketMs = GRANULARITY_MS[granularity];
|
|
133
|
+
const oldest = records[0].timestamp;
|
|
134
|
+
const newest = records[records.length - 1].timestamp;
|
|
135
|
+
const buckets = [];
|
|
136
|
+
let start = Math.floor(oldest / bucketMs) * bucketMs;
|
|
137
|
+
while (start <= newest) {
|
|
138
|
+
const end = start + bucketMs;
|
|
139
|
+
const inBucket = records.filter(r => r.timestamp >= start && r.timestamp < end);
|
|
140
|
+
buckets.push({
|
|
141
|
+
start,
|
|
142
|
+
end,
|
|
143
|
+
count: inBucket.length,
|
|
144
|
+
errors: inBucket.filter(r => r.statusCode >= 400).length,
|
|
145
|
+
latencies: inBucket.map(r => r.latencyMs),
|
|
146
|
+
totalCredits: inBucket.reduce((s, r) => s + r.credits, 0),
|
|
147
|
+
});
|
|
148
|
+
start = end;
|
|
149
|
+
}
|
|
150
|
+
return buckets;
|
|
151
|
+
}
|
|
152
|
+
// ── Cleanup ───────────────────────────────────────────────────
|
|
153
|
+
/** Remove records older than maxAge. */
|
|
154
|
+
cleanup() {
|
|
155
|
+
const cutoff = Date.now() - this.maxAgeMs;
|
|
156
|
+
const before = this.records.length;
|
|
157
|
+
this.records = this.records.filter(r => r.timestamp >= cutoff);
|
|
158
|
+
return before - this.records.length;
|
|
159
|
+
}
|
|
160
|
+
// ── Stats ──────────────────────────────────────────────────────
|
|
161
|
+
getStats() {
|
|
162
|
+
return {
|
|
163
|
+
totalRecords: this.records.length,
|
|
164
|
+
totalRequests: this.records.length,
|
|
165
|
+
totalErrors: this.records.filter(r => r.statusCode >= 400).length,
|
|
166
|
+
oldestRecord: this.records.length > 0 ? this.records[0].timestamp : null,
|
|
167
|
+
newestRecord: this.records.length > 0 ? this.records[this.records.length - 1].timestamp : null,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/** Clear all data. */
|
|
171
|
+
destroy() {
|
|
172
|
+
this.records = [];
|
|
173
|
+
}
|
|
174
|
+
// ── Private ───────────────────────────────────────────────────
|
|
175
|
+
getRelevantRecords() {
|
|
176
|
+
const cutoff = Date.now() - this.maxAgeMs;
|
|
177
|
+
return this.records.filter(r => r.timestamp >= cutoff).sort((a, b) => a.timestamp - b.timestamp);
|
|
178
|
+
}
|
|
179
|
+
percentile(sorted, p) {
|
|
180
|
+
if (sorted.length === 0)
|
|
181
|
+
return 0;
|
|
182
|
+
const idx = Math.ceil((p / 100) * sorted.length) - 1;
|
|
183
|
+
return sorted[Math.max(0, idx)];
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
exports.APIMetricsAggregator = APIMetricsAggregator;
|
|
187
|
+
//# sourceMappingURL=api-metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-metrics.js","sourceRoot":"","sources":["../src/api-metrics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ErrorClassifier — Classify and categorize errors for analytics and routing.
|
|
3
|
+
*
|
|
4
|
+
* Register error patterns, classify incoming errors by matching,
|
|
5
|
+
* and track error frequency for prioritization.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* const classifier = new ErrorClassifier();
|
|
10
|
+
*
|
|
11
|
+
* classifier.registerPattern({
|
|
12
|
+
* category: 'rate_limit',
|
|
13
|
+
* pattern: /rate limit|too many requests|429/i,
|
|
14
|
+
* severity: 'warning',
|
|
15
|
+
* retryable: true,
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* const result = classifier.classify(new Error('Rate limit exceeded'));
|
|
19
|
+
* // { category: 'rate_limit', severity: 'warning', retryable: true, ... }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export type ErrorSeverity = 'info' | 'warning' | 'error' | 'critical';
|
|
23
|
+
export interface ErrorPattern {
|
|
24
|
+
id: string;
|
|
25
|
+
category: string;
|
|
26
|
+
pattern: RegExp;
|
|
27
|
+
severity: ErrorSeverity;
|
|
28
|
+
retryable: boolean;
|
|
29
|
+
description: string;
|
|
30
|
+
}
|
|
31
|
+
export interface PatternRegistration {
|
|
32
|
+
category: string;
|
|
33
|
+
pattern: RegExp;
|
|
34
|
+
severity?: ErrorSeverity;
|
|
35
|
+
retryable?: boolean;
|
|
36
|
+
description?: string;
|
|
37
|
+
}
|
|
38
|
+
export interface ClassifyResult {
|
|
39
|
+
classified: boolean;
|
|
40
|
+
category: string;
|
|
41
|
+
severity: ErrorSeverity;
|
|
42
|
+
retryable: boolean;
|
|
43
|
+
patternId: string | null;
|
|
44
|
+
description: string;
|
|
45
|
+
message: string;
|
|
46
|
+
timestamp: number;
|
|
47
|
+
}
|
|
48
|
+
export interface ErrorFrequency {
|
|
49
|
+
category: string;
|
|
50
|
+
count: number;
|
|
51
|
+
lastSeen: number;
|
|
52
|
+
firstSeen: number;
|
|
53
|
+
}
|
|
54
|
+
export interface ErrorClassifierConfig {
|
|
55
|
+
/** Max classification history. Default 10000. */
|
|
56
|
+
maxHistory?: number;
|
|
57
|
+
/** Max registered patterns. Default 500. */
|
|
58
|
+
maxPatterns?: number;
|
|
59
|
+
/** Default severity for unclassified errors. Default 'error'. */
|
|
60
|
+
defaultSeverity?: ErrorSeverity;
|
|
61
|
+
}
|
|
62
|
+
export interface ErrorClassifierStats {
|
|
63
|
+
totalPatterns: number;
|
|
64
|
+
totalClassified: number;
|
|
65
|
+
totalUnclassified: number;
|
|
66
|
+
categories: number;
|
|
67
|
+
topCategories: ErrorFrequency[];
|
|
68
|
+
}
|
|
69
|
+
export declare class ErrorClassifier {
|
|
70
|
+
private patterns;
|
|
71
|
+
private history;
|
|
72
|
+
private frequency;
|
|
73
|
+
private nextId;
|
|
74
|
+
private maxHistory;
|
|
75
|
+
private maxPatterns;
|
|
76
|
+
private defaultSeverity;
|
|
77
|
+
private totalClassified;
|
|
78
|
+
private totalUnclassified;
|
|
79
|
+
constructor(config?: ErrorClassifierConfig);
|
|
80
|
+
/** Register an error pattern. */
|
|
81
|
+
registerPattern(reg: PatternRegistration): ErrorPattern;
|
|
82
|
+
/** Remove a pattern by ID. */
|
|
83
|
+
removePattern(id: string): boolean;
|
|
84
|
+
/** Get a pattern by ID. */
|
|
85
|
+
getPattern(id: string): ErrorPattern | null;
|
|
86
|
+
/** List all patterns. */
|
|
87
|
+
listPatterns(): ErrorPattern[];
|
|
88
|
+
/** Classify an error. */
|
|
89
|
+
classify(error: Error | string): ClassifyResult;
|
|
90
|
+
/** Classify and return just the category name. */
|
|
91
|
+
categorize(error: Error | string): string;
|
|
92
|
+
/** Check if an error is retryable. */
|
|
93
|
+
isRetryable(error: Error | string): boolean;
|
|
94
|
+
/** Get classification history. */
|
|
95
|
+
getHistory(options?: {
|
|
96
|
+
category?: string;
|
|
97
|
+
severity?: ErrorSeverity;
|
|
98
|
+
limit?: number;
|
|
99
|
+
}): ClassifyResult[];
|
|
100
|
+
/** Get error frequency by category. */
|
|
101
|
+
getFrequency(): ErrorFrequency[];
|
|
102
|
+
/** Get frequency for a specific category. */
|
|
103
|
+
getCategoryFrequency(category: string): ErrorFrequency | null;
|
|
104
|
+
getStats(): ErrorClassifierStats;
|
|
105
|
+
/** Clear all data. */
|
|
106
|
+
destroy(): void;
|
|
107
|
+
private recordResult;
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=error-classifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-classifier.d.ts","sourceRoot":"","sources":["../src/error-classifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ErrorClassifier — Classify and categorize errors for analytics and routing.
|
|
4
|
+
*
|
|
5
|
+
* Register error patterns, classify incoming errors by matching,
|
|
6
|
+
* and track error frequency for prioritization.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const classifier = new ErrorClassifier();
|
|
11
|
+
*
|
|
12
|
+
* classifier.registerPattern({
|
|
13
|
+
* category: 'rate_limit',
|
|
14
|
+
* pattern: /rate limit|too many requests|429/i,
|
|
15
|
+
* severity: 'warning',
|
|
16
|
+
* retryable: true,
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* const result = classifier.classify(new Error('Rate limit exceeded'));
|
|
20
|
+
* // { category: 'rate_limit', severity: 'warning', retryable: true, ... }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.ErrorClassifier = void 0;
|
|
25
|
+
// ── Implementation ───────────────────────────────────────────────────
|
|
26
|
+
class ErrorClassifier {
|
|
27
|
+
patterns = new Map();
|
|
28
|
+
history = [];
|
|
29
|
+
frequency = new Map();
|
|
30
|
+
nextId = 1;
|
|
31
|
+
maxHistory;
|
|
32
|
+
maxPatterns;
|
|
33
|
+
defaultSeverity;
|
|
34
|
+
// Stats
|
|
35
|
+
totalClassified = 0;
|
|
36
|
+
totalUnclassified = 0;
|
|
37
|
+
constructor(config = {}) {
|
|
38
|
+
this.maxHistory = config.maxHistory ?? 10_000;
|
|
39
|
+
this.maxPatterns = config.maxPatterns ?? 500;
|
|
40
|
+
this.defaultSeverity = config.defaultSeverity ?? 'error';
|
|
41
|
+
}
|
|
42
|
+
// ── Pattern Management ────────────────────────────────────────
|
|
43
|
+
/** Register an error pattern. */
|
|
44
|
+
registerPattern(reg) {
|
|
45
|
+
if (!reg.category)
|
|
46
|
+
throw new Error('Category is required');
|
|
47
|
+
if (!reg.pattern)
|
|
48
|
+
throw new Error('Pattern is required');
|
|
49
|
+
if (this.patterns.size >= this.maxPatterns) {
|
|
50
|
+
throw new Error(`Maximum ${this.maxPatterns} patterns reached`);
|
|
51
|
+
}
|
|
52
|
+
const pattern = {
|
|
53
|
+
id: `ep_${this.nextId++}`,
|
|
54
|
+
category: reg.category,
|
|
55
|
+
pattern: reg.pattern,
|
|
56
|
+
severity: reg.severity ?? this.defaultSeverity,
|
|
57
|
+
retryable: reg.retryable ?? false,
|
|
58
|
+
description: reg.description ?? '',
|
|
59
|
+
};
|
|
60
|
+
this.patterns.set(pattern.id, pattern);
|
|
61
|
+
return pattern;
|
|
62
|
+
}
|
|
63
|
+
/** Remove a pattern by ID. */
|
|
64
|
+
removePattern(id) {
|
|
65
|
+
return this.patterns.delete(id);
|
|
66
|
+
}
|
|
67
|
+
/** Get a pattern by ID. */
|
|
68
|
+
getPattern(id) {
|
|
69
|
+
return this.patterns.get(id) ?? null;
|
|
70
|
+
}
|
|
71
|
+
/** List all patterns. */
|
|
72
|
+
listPatterns() {
|
|
73
|
+
return [...this.patterns.values()];
|
|
74
|
+
}
|
|
75
|
+
// ── Classification ─────────────────────────────────────────────
|
|
76
|
+
/** Classify an error. */
|
|
77
|
+
classify(error) {
|
|
78
|
+
const message = typeof error === 'string' ? error : error.message;
|
|
79
|
+
const now = Date.now();
|
|
80
|
+
// Try to match against registered patterns
|
|
81
|
+
for (const pattern of this.patterns.values()) {
|
|
82
|
+
if (pattern.pattern.test(message)) {
|
|
83
|
+
const result = {
|
|
84
|
+
classified: true,
|
|
85
|
+
category: pattern.category,
|
|
86
|
+
severity: pattern.severity,
|
|
87
|
+
retryable: pattern.retryable,
|
|
88
|
+
patternId: pattern.id,
|
|
89
|
+
description: pattern.description,
|
|
90
|
+
message,
|
|
91
|
+
timestamp: now,
|
|
92
|
+
};
|
|
93
|
+
this.recordResult(result);
|
|
94
|
+
this.totalClassified++;
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Unclassified
|
|
99
|
+
const result = {
|
|
100
|
+
classified: false,
|
|
101
|
+
category: 'unknown',
|
|
102
|
+
severity: this.defaultSeverity,
|
|
103
|
+
retryable: false,
|
|
104
|
+
patternId: null,
|
|
105
|
+
description: 'No matching pattern found',
|
|
106
|
+
message,
|
|
107
|
+
timestamp: now,
|
|
108
|
+
};
|
|
109
|
+
this.recordResult(result);
|
|
110
|
+
this.totalUnclassified++;
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
/** Classify and return just the category name. */
|
|
114
|
+
categorize(error) {
|
|
115
|
+
return this.classify(error).category;
|
|
116
|
+
}
|
|
117
|
+
/** Check if an error is retryable. */
|
|
118
|
+
isRetryable(error) {
|
|
119
|
+
return this.classify(error).retryable;
|
|
120
|
+
}
|
|
121
|
+
// ── Query ──────────────────────────────────────────────────────
|
|
122
|
+
/** Get classification history. */
|
|
123
|
+
getHistory(options) {
|
|
124
|
+
let results = [...this.history];
|
|
125
|
+
if (options?.category)
|
|
126
|
+
results = results.filter(r => r.category === options.category);
|
|
127
|
+
if (options?.severity)
|
|
128
|
+
results = results.filter(r => r.severity === options.severity);
|
|
129
|
+
const limit = options?.limit ?? 50;
|
|
130
|
+
return results.slice(-limit);
|
|
131
|
+
}
|
|
132
|
+
/** Get error frequency by category. */
|
|
133
|
+
getFrequency() {
|
|
134
|
+
return [...this.frequency.values()].sort((a, b) => b.count - a.count);
|
|
135
|
+
}
|
|
136
|
+
/** Get frequency for a specific category. */
|
|
137
|
+
getCategoryFrequency(category) {
|
|
138
|
+
return this.frequency.get(category) ?? null;
|
|
139
|
+
}
|
|
140
|
+
// ── Stats ──────────────────────────────────────────────────────
|
|
141
|
+
getStats() {
|
|
142
|
+
const topCategories = this.getFrequency().slice(0, 5);
|
|
143
|
+
return {
|
|
144
|
+
totalPatterns: this.patterns.size,
|
|
145
|
+
totalClassified: this.totalClassified,
|
|
146
|
+
totalUnclassified: this.totalUnclassified,
|
|
147
|
+
categories: this.frequency.size,
|
|
148
|
+
topCategories,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/** Clear all data. */
|
|
152
|
+
destroy() {
|
|
153
|
+
this.patterns.clear();
|
|
154
|
+
this.history = [];
|
|
155
|
+
this.frequency.clear();
|
|
156
|
+
this.totalClassified = 0;
|
|
157
|
+
this.totalUnclassified = 0;
|
|
158
|
+
}
|
|
159
|
+
// ── Private ───────────────────────────────────────────────────
|
|
160
|
+
recordResult(result) {
|
|
161
|
+
this.history.push(result);
|
|
162
|
+
if (this.history.length > this.maxHistory) {
|
|
163
|
+
this.history.splice(0, this.history.length - this.maxHistory);
|
|
164
|
+
}
|
|
165
|
+
const existing = this.frequency.get(result.category);
|
|
166
|
+
if (existing) {
|
|
167
|
+
existing.count++;
|
|
168
|
+
existing.lastSeen = result.timestamp;
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
this.frequency.set(result.category, {
|
|
172
|
+
category: result.category,
|
|
173
|
+
count: 1,
|
|
174
|
+
lastSeen: result.timestamp,
|
|
175
|
+
firstSeen: result.timestamp,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
exports.ErrorClassifier = ErrorClassifier;
|
|
181
|
+
//# sourceMappingURL=error-classifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-classifier.js","sourceRoot":"","sources":["../src/error-classifier.ts"],"names":[],"mappings":"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"}
|