guardrail-core 1.0.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/__tests__/autopilot.test.d.ts +7 -0
- package/dist/__tests__/autopilot.test.d.ts.map +1 -0
- package/dist/__tests__/autopilot.test.js +156 -0
- package/dist/__tests__/tier-config.test.d.ts +9 -0
- package/dist/__tests__/tier-config.test.d.ts.map +1 -0
- package/dist/__tests__/tier-config.test.js +230 -0
- package/dist/__tests__/utils/hash-inline.test.d.ts +2 -0
- package/dist/__tests__/utils/hash-inline.test.d.ts.map +1 -0
- package/dist/__tests__/utils/hash-inline.test.js +62 -0
- package/dist/__tests__/utils/hash.test.d.ts +3 -0
- package/dist/__tests__/utils/hash.test.d.ts.map +1 -0
- package/dist/__tests__/utils/hash.test.js +95 -0
- package/dist/__tests__/utils/simple.test.d.ts +1 -0
- package/dist/__tests__/utils/simple.test.d.ts.map +1 -0
- package/dist/__tests__/utils/simple.test.js +10 -0
- package/dist/__tests__/utils/utils-simple.test.d.ts +1 -0
- package/dist/__tests__/utils/utils-simple.test.d.ts.map +1 -0
- package/dist/__tests__/utils/utils-simple.test.js +6 -0
- package/dist/__tests__/utils/utils.test.d.ts +15 -0
- package/dist/__tests__/utils/utils.test.d.ts.map +1 -0
- package/dist/__tests__/utils/utils.test.js +172 -0
- package/dist/autopilot/autopilot-runner.d.ts +33 -0
- package/dist/autopilot/autopilot-runner.d.ts.map +1 -0
- package/dist/autopilot/autopilot-runner.js +479 -0
- package/dist/autopilot/index.d.ts +6 -0
- package/dist/autopilot/index.d.ts.map +1 -0
- package/dist/autopilot/index.js +25 -0
- package/dist/autopilot/types.d.ts +102 -0
- package/dist/autopilot/types.d.ts.map +1 -0
- package/dist/autopilot/types.js +18 -0
- package/dist/cache/index.d.ts +7 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +22 -0
- package/dist/cache/redis-cache.d.ts +145 -0
- package/dist/cache/redis-cache.d.ts.map +1 -0
- package/dist/cache/redis-cache.js +459 -0
- package/dist/ci/github-actions.d.ts +77 -0
- package/dist/ci/github-actions.d.ts.map +1 -0
- package/dist/ci/github-actions.js +277 -0
- package/dist/ci/index.d.ts +12 -0
- package/dist/ci/index.d.ts.map +1 -0
- package/dist/ci/index.js +27 -0
- package/dist/ci/pre-commit.d.ts +65 -0
- package/dist/ci/pre-commit.d.ts.map +1 -0
- package/dist/ci/pre-commit.js +286 -0
- package/dist/entitlements.d.ts +149 -0
- package/dist/entitlements.d.ts.map +1 -0
- package/dist/entitlements.js +464 -0
- package/dist/env.d.ts +113 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +204 -0
- package/dist/fix-packs/__tests__/generate-fix-packs.test.d.ts +7 -0
- package/dist/fix-packs/__tests__/generate-fix-packs.test.d.ts.map +1 -0
- package/dist/fix-packs/__tests__/generate-fix-packs.test.js +250 -0
- package/dist/fix-packs/generate-fix-packs.d.ts +15 -0
- package/dist/fix-packs/generate-fix-packs.d.ts.map +1 -0
- package/dist/fix-packs/generate-fix-packs.js +505 -0
- package/dist/fix-packs/index.d.ts +8 -0
- package/dist/fix-packs/index.d.ts.map +1 -0
- package/dist/fix-packs/index.js +23 -0
- package/dist/fix-packs/types.d.ts +113 -0
- package/dist/fix-packs/types.d.ts.map +1 -0
- package/dist/fix-packs/types.js +71 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/metrics/prometheus.d.ts +99 -0
- package/dist/metrics/prometheus.d.ts.map +1 -0
- package/dist/metrics/prometheus.js +306 -0
- package/dist/quota-ledger.d.ts +119 -0
- package/dist/quota-ledger.d.ts.map +1 -0
- package/dist/quota-ledger.js +462 -0
- package/dist/rbac/__tests__/permissions.test.d.ts +8 -0
- package/dist/rbac/__tests__/permissions.test.d.ts.map +1 -0
- package/dist/rbac/__tests__/permissions.test.js +350 -0
- package/dist/rbac/index.d.ts +9 -0
- package/dist/rbac/index.d.ts.map +1 -0
- package/dist/rbac/index.js +32 -0
- package/dist/rbac/permissions.d.ts +71 -0
- package/dist/rbac/permissions.d.ts.map +1 -0
- package/dist/rbac/permissions.js +247 -0
- package/dist/rbac/types.d.ts +69 -0
- package/dist/rbac/types.d.ts.map +1 -0
- package/dist/rbac/types.js +213 -0
- package/dist/tier-config.d.ts +203 -0
- package/dist/tier-config.d.ts.map +1 -0
- package/dist/tier-config.js +675 -0
- package/dist/types.d.ts +365 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/utils.d.ts +36 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +127 -0
- package/dist/verified-autofix/__tests__/format-validator.test.d.ts +11 -0
- package/dist/verified-autofix/__tests__/format-validator.test.d.ts.map +1 -0
- package/dist/verified-autofix/__tests__/format-validator.test.js +285 -0
- package/dist/verified-autofix/__tests__/pipeline.test.d.ts +11 -0
- package/dist/verified-autofix/__tests__/pipeline.test.d.ts.map +1 -0
- package/dist/verified-autofix/__tests__/pipeline.test.js +389 -0
- package/dist/verified-autofix/__tests__/repo-fingerprint.test.d.ts +11 -0
- package/dist/verified-autofix/__tests__/repo-fingerprint.test.d.ts.map +1 -0
- package/dist/verified-autofix/__tests__/repo-fingerprint.test.js +236 -0
- package/dist/verified-autofix/__tests__/workspace.test.d.ts +11 -0
- package/dist/verified-autofix/__tests__/workspace.test.d.ts.map +1 -0
- package/dist/verified-autofix/__tests__/workspace.test.js +314 -0
- package/dist/verified-autofix/format-validator.d.ts +101 -0
- package/dist/verified-autofix/format-validator.d.ts.map +1 -0
- package/dist/verified-autofix/format-validator.js +446 -0
- package/dist/verified-autofix/index.d.ts +14 -0
- package/dist/verified-autofix/index.d.ts.map +1 -0
- package/dist/verified-autofix/index.js +39 -0
- package/dist/verified-autofix/pipeline.d.ts +68 -0
- package/dist/verified-autofix/pipeline.d.ts.map +1 -0
- package/dist/verified-autofix/pipeline.js +330 -0
- package/dist/verified-autofix/repo-fingerprint.d.ts +56 -0
- package/dist/verified-autofix/repo-fingerprint.d.ts.map +1 -0
- package/dist/verified-autofix/repo-fingerprint.js +396 -0
- package/dist/verified-autofix/workspace.d.ts +83 -0
- package/dist/verified-autofix/workspace.d.ts.map +1 -0
- package/dist/verified-autofix/workspace.js +454 -0
- package/dist/verified-autofix.d.ts +182 -0
- package/dist/verified-autofix.d.ts.map +1 -0
- package/dist/verified-autofix.js +1021 -0
- package/dist/visualization/dependency-graph.d.ts +79 -0
- package/dist/visualization/dependency-graph.d.ts.map +1 -0
- package/dist/visualization/dependency-graph.js +399 -0
- package/dist/visualization/index.d.ts +5 -0
- package/dist/visualization/index.d.ts.map +1 -0
- package/dist/visualization/index.js +20 -0
- package/package.json +29 -0
- package/src/__tests__/autopilot.test.ts +196 -0
- package/src/__tests__/tier-config.test.ts +289 -0
- package/src/__tests__/utils/hash-inline.test.ts +76 -0
- package/src/__tests__/utils/hash.test.ts +119 -0
- package/src/__tests__/utils/simple.test.ts +10 -0
- package/src/__tests__/utils/utils-simple.test.ts +5 -0
- package/src/__tests__/utils/utils.test.ts +203 -0
- package/src/autopilot/autopilot-runner.ts +503 -0
- package/src/autopilot/index.ts +6 -0
- package/src/autopilot/types.ts +119 -0
- package/src/cache/index.ts +7 -0
- package/src/cache/redis-cache.d.ts +155 -0
- package/src/cache/redis-cache.d.ts.map +1 -0
- package/src/cache/redis-cache.ts +517 -0
- package/src/ci/github-actions.ts +335 -0
- package/src/ci/index.ts +12 -0
- package/src/ci/pre-commit.ts +338 -0
- package/src/db/usage-schema.prisma +114 -0
- package/src/entitlements.ts +570 -0
- package/src/env.d.ts +68 -0
- package/src/env.d.ts.map +1 -0
- package/src/env.ts +247 -0
- package/src/fix-packs/__tests__/generate-fix-packs.test.ts +317 -0
- package/src/fix-packs/generate-fix-packs.ts +577 -0
- package/src/fix-packs/index.ts +8 -0
- package/src/fix-packs/types.ts +206 -0
- package/src/index.d.ts +7 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.ts +12 -0
- package/src/metrics/prometheus.d.ts +104 -0
- package/src/metrics/prometheus.d.ts.map +1 -0
- package/src/metrics/prometheus.ts +446 -0
- package/src/quota-ledger.ts +548 -0
- package/src/rbac/__tests__/permissions.test.ts +446 -0
- package/src/rbac/index.ts +46 -0
- package/src/rbac/permissions.ts +301 -0
- package/src/rbac/types.ts +298 -0
- package/src/tier-config.json +157 -0
- package/src/tier-config.ts +815 -0
- package/src/types.d.ts +365 -0
- package/src/types.d.ts.map +1 -0
- package/src/types.ts +441 -0
- package/src/utils.d.ts +36 -0
- package/src/utils.d.ts.map +1 -0
- package/src/utils.ts +140 -0
- package/src/verified-autofix/__tests__/format-validator.test.ts +335 -0
- package/src/verified-autofix/__tests__/pipeline.test.ts +419 -0
- package/src/verified-autofix/__tests__/repo-fingerprint.test.ts +241 -0
- package/src/verified-autofix/__tests__/workspace.test.ts +373 -0
- package/src/verified-autofix/format-validator.ts +517 -0
- package/src/verified-autofix/index.ts +63 -0
- package/src/verified-autofix/pipeline.ts +403 -0
- package/src/verified-autofix/repo-fingerprint.ts +459 -0
- package/src/verified-autofix/workspace.ts +531 -0
- package/src/verified-autofix.ts +1187 -0
- package/src/visualization/dependency-graph.d.ts +85 -0
- package/src/visualization/dependency-graph.d.ts.map +1 -0
- package/src/visualization/dependency-graph.ts +495 -0
- package/src/visualization/index.ts +5 -0
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prometheus Metrics
|
|
3
|
+
*
|
|
4
|
+
* Production-ready metrics collection for Guardrail AI
|
|
5
|
+
* Exposes metrics in Prometheus format for monitoring and alerting
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface MetricLabels {
|
|
9
|
+
[key: string]: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface MetricValue {
|
|
13
|
+
value: number;
|
|
14
|
+
labels: MetricLabels;
|
|
15
|
+
timestamp?: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface Metric {
|
|
19
|
+
name: string;
|
|
20
|
+
help: string;
|
|
21
|
+
type: "counter" | "gauge" | "histogram" | "summary";
|
|
22
|
+
values: MetricValue[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
class Counter {
|
|
26
|
+
private values: Map<string, number> = new Map();
|
|
27
|
+
|
|
28
|
+
constructor(
|
|
29
|
+
public readonly name: string,
|
|
30
|
+
public readonly help: string,
|
|
31
|
+
public readonly labelNames: string[] = [],
|
|
32
|
+
) {}
|
|
33
|
+
|
|
34
|
+
inc(labels: MetricLabels = {}, value: number = 1): void {
|
|
35
|
+
const key = this.labelsToKey(labels);
|
|
36
|
+
const current = this.values.get(key) || 0;
|
|
37
|
+
this.values.set(key, current + value);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get(labels: MetricLabels = {}): number {
|
|
41
|
+
const key = this.labelsToKey(labels);
|
|
42
|
+
return this.values.get(key) || 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
reset(): void {
|
|
46
|
+
this.values.clear();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
collect(): MetricValue[] {
|
|
50
|
+
const result: MetricValue[] = [];
|
|
51
|
+
for (const [key, value] of this.values) {
|
|
52
|
+
result.push({
|
|
53
|
+
value,
|
|
54
|
+
labels: this.keyToLabels(key),
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private labelsToKey(labels: MetricLabels): string {
|
|
61
|
+
return this.labelNames.map((name) => labels[name] || "").join("|");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private keyToLabels(key: string): MetricLabels {
|
|
65
|
+
const values = key.split("|");
|
|
66
|
+
const labels: MetricLabels = {};
|
|
67
|
+
this.labelNames.forEach((name, i) => {
|
|
68
|
+
if (values[i]) {
|
|
69
|
+
labels[name] = values[i];
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
return labels;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
class Gauge {
|
|
77
|
+
private values: Map<string, number> = new Map();
|
|
78
|
+
|
|
79
|
+
constructor(
|
|
80
|
+
public readonly name: string,
|
|
81
|
+
public readonly help: string,
|
|
82
|
+
public readonly labelNames: string[] = [],
|
|
83
|
+
) {}
|
|
84
|
+
|
|
85
|
+
set(labels: MetricLabels, value: number): void;
|
|
86
|
+
set(value: number): void;
|
|
87
|
+
set(labelsOrValue: MetricLabels | number, value?: number): void {
|
|
88
|
+
if (typeof labelsOrValue === "number") {
|
|
89
|
+
this.values.set("", labelsOrValue);
|
|
90
|
+
} else {
|
|
91
|
+
const key = this.labelsToKey(labelsOrValue);
|
|
92
|
+
this.values.set(key, value!);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
inc(labels: MetricLabels = {}, value: number = 1): void {
|
|
97
|
+
const key = this.labelsToKey(labels);
|
|
98
|
+
const current = this.values.get(key) || 0;
|
|
99
|
+
this.values.set(key, current + value);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
dec(labels: MetricLabels = {}, value: number = 1): void {
|
|
103
|
+
const key = this.labelsToKey(labels);
|
|
104
|
+
const current = this.values.get(key) || 0;
|
|
105
|
+
this.values.set(key, current - value);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
get(labels: MetricLabels = {}): number {
|
|
109
|
+
const key = this.labelsToKey(labels);
|
|
110
|
+
return this.values.get(key) || 0;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
collect(): MetricValue[] {
|
|
114
|
+
const result: MetricValue[] = [];
|
|
115
|
+
for (const [key, value] of this.values) {
|
|
116
|
+
result.push({
|
|
117
|
+
value,
|
|
118
|
+
labels: this.keyToLabels(key),
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private labelsToKey(labels: MetricLabels): string {
|
|
125
|
+
return this.labelNames.map((name) => labels[name] || "").join("|");
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private keyToLabels(key: string): MetricLabels {
|
|
129
|
+
const values = key.split("|");
|
|
130
|
+
const labels: MetricLabels = {};
|
|
131
|
+
this.labelNames.forEach((name, i) => {
|
|
132
|
+
if (values[i]) {
|
|
133
|
+
labels[name] = values[i];
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
return labels;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
class Histogram {
|
|
141
|
+
private buckets: number[];
|
|
142
|
+
private values: Map<
|
|
143
|
+
string,
|
|
144
|
+
{ sum: number; count: number; buckets: number[] }
|
|
145
|
+
> = new Map();
|
|
146
|
+
|
|
147
|
+
constructor(
|
|
148
|
+
public readonly name: string,
|
|
149
|
+
public readonly help: string,
|
|
150
|
+
public readonly labelNames: string[] = [],
|
|
151
|
+
buckets?: number[],
|
|
152
|
+
) {
|
|
153
|
+
this.buckets = buckets || [
|
|
154
|
+
0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10,
|
|
155
|
+
];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
observe(labels: MetricLabels, value: number): void;
|
|
159
|
+
observe(value: number): void;
|
|
160
|
+
observe(labelsOrValue: MetricLabels | number, value?: number): void {
|
|
161
|
+
let labels: MetricLabels;
|
|
162
|
+
let observedValue: number;
|
|
163
|
+
|
|
164
|
+
if (typeof labelsOrValue === "number") {
|
|
165
|
+
labels = {};
|
|
166
|
+
observedValue = labelsOrValue;
|
|
167
|
+
} else {
|
|
168
|
+
labels = labelsOrValue;
|
|
169
|
+
observedValue = value!;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const key = this.labelsToKey(labels);
|
|
173
|
+
let data = this.values.get(key);
|
|
174
|
+
|
|
175
|
+
if (!data) {
|
|
176
|
+
data = {
|
|
177
|
+
sum: 0,
|
|
178
|
+
count: 0,
|
|
179
|
+
buckets: new Array(this.buckets.length).fill(0),
|
|
180
|
+
};
|
|
181
|
+
this.values.set(key, data);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
data.sum += observedValue;
|
|
185
|
+
data.count++;
|
|
186
|
+
|
|
187
|
+
for (let i = 0; i < this.buckets.length; i++) {
|
|
188
|
+
const bucket = this.buckets[i];
|
|
189
|
+
if (bucket !== undefined && observedValue <= bucket) {
|
|
190
|
+
// @ts-ignore
|
|
191
|
+
data.buckets[i]++;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
startTimer(labels: MetricLabels = {}): () => number {
|
|
197
|
+
const start = process.hrtime.bigint();
|
|
198
|
+
return () => {
|
|
199
|
+
const end = process.hrtime.bigint();
|
|
200
|
+
const durationMs = Number(end - start) / 1e6;
|
|
201
|
+
this.observe(labels, durationMs / 1000); // Convert to seconds
|
|
202
|
+
return durationMs;
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
collect(): MetricValue[] {
|
|
207
|
+
const result: MetricValue[] = [];
|
|
208
|
+
|
|
209
|
+
for (const [key, data] of this.values) {
|
|
210
|
+
const labels = this.keyToLabels(key);
|
|
211
|
+
|
|
212
|
+
// Add bucket values
|
|
213
|
+
for (let i = 0; i < this.buckets.length; i++) {
|
|
214
|
+
const bucketValue = data.buckets[i] ?? 0;
|
|
215
|
+
const bucketLimit = this.buckets[i] ?? 0;
|
|
216
|
+
result.push({
|
|
217
|
+
value: bucketValue,
|
|
218
|
+
labels: { ...labels, le: String(bucketLimit) },
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Add +Inf bucket
|
|
223
|
+
result.push({
|
|
224
|
+
value: data.count,
|
|
225
|
+
labels: { ...labels, le: "+Inf" },
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// Add sum and count
|
|
229
|
+
result.push({
|
|
230
|
+
value: data.sum,
|
|
231
|
+
labels: { ...labels, quantile: "sum" },
|
|
232
|
+
});
|
|
233
|
+
result.push({
|
|
234
|
+
value: data.count,
|
|
235
|
+
labels: { ...labels, quantile: "count" },
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return result;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
private labelsToKey(labels: MetricLabels): string {
|
|
243
|
+
return this.labelNames.map((name) => labels[name] || "").join("|");
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
private keyToLabels(key: string): MetricLabels {
|
|
247
|
+
const values = key.split("|");
|
|
248
|
+
const labels: MetricLabels = {};
|
|
249
|
+
this.labelNames.forEach((name, i) => {
|
|
250
|
+
if (values[i]) {
|
|
251
|
+
labels[name] = values[i];
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
return labels;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Guardrail Metrics Registry
|
|
260
|
+
*/
|
|
261
|
+
class MetricsRegistry {
|
|
262
|
+
// Scan metrics
|
|
263
|
+
readonly scansTotal = new Counter(
|
|
264
|
+
"Guardrail_scans_total",
|
|
265
|
+
"Total number of security scans performed",
|
|
266
|
+
["scan_type", "status"],
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
readonly scanDuration = new Histogram(
|
|
270
|
+
"Guardrail_scan_duration_seconds",
|
|
271
|
+
"Duration of security scans in seconds",
|
|
272
|
+
["scan_type"],
|
|
273
|
+
[0.1, 0.5, 1, 2, 5, 10, 30, 60],
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
// Injection detection metrics
|
|
277
|
+
readonly injectionsDetected = new Counter(
|
|
278
|
+
"Guardrail_injections_detected_total",
|
|
279
|
+
"Total number of prompt injection attempts detected",
|
|
280
|
+
["severity", "type"],
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
readonly injectionScanDuration = new Histogram(
|
|
284
|
+
"Guardrail_injection_scan_duration_seconds",
|
|
285
|
+
"Duration of injection scans in seconds",
|
|
286
|
+
["content_type"],
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
// Vulnerability metrics
|
|
290
|
+
readonly vulnerabilitiesFound = new Counter(
|
|
291
|
+
"Guardrail_vulnerabilities_found_total",
|
|
292
|
+
"Total number of vulnerabilities found",
|
|
293
|
+
["severity", "source"],
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
readonly vulnerablePackages = new Gauge(
|
|
297
|
+
"Guardrail_vulnerable_packages",
|
|
298
|
+
"Current number of vulnerable packages",
|
|
299
|
+
["project_id"],
|
|
300
|
+
);
|
|
301
|
+
|
|
302
|
+
// Secret detection metrics
|
|
303
|
+
readonly secretsDetected = new Counter(
|
|
304
|
+
"Guardrail_secrets_detected_total",
|
|
305
|
+
"Total number of secrets detected",
|
|
306
|
+
["secret_type", "severity"],
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
// Compliance metrics
|
|
310
|
+
readonly complianceScore = new Gauge(
|
|
311
|
+
"Guardrail_compliance_score",
|
|
312
|
+
"Current compliance score (0-100)",
|
|
313
|
+
["framework", "project_id"],
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
readonly complianceViolations = new Counter(
|
|
317
|
+
"Guardrail_compliance_violations_total",
|
|
318
|
+
"Total number of compliance violations",
|
|
319
|
+
["framework", "severity"],
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
// API metrics
|
|
323
|
+
readonly apiRequestsTotal = new Counter(
|
|
324
|
+
"Guardrail_api_requests_total",
|
|
325
|
+
"Total number of API requests",
|
|
326
|
+
["method", "endpoint", "status_code"],
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
readonly apiRequestDuration = new Histogram(
|
|
330
|
+
"Guardrail_api_request_duration_seconds",
|
|
331
|
+
"Duration of API requests in seconds",
|
|
332
|
+
["method", "endpoint"],
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
// Agent metrics
|
|
336
|
+
readonly agentActionsTotal = new Counter(
|
|
337
|
+
"Guardrail_agent_actions_total",
|
|
338
|
+
"Total number of agent actions",
|
|
339
|
+
["agent_id", "action_type", "status"],
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
readonly agentActionsBlocked = new Counter(
|
|
343
|
+
"Guardrail_agent_actions_blocked_total",
|
|
344
|
+
"Total number of agent actions blocked",
|
|
345
|
+
["agent_id", "reason"],
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
// Cache metrics
|
|
349
|
+
readonly cacheHits = new Counter(
|
|
350
|
+
"Guardrail_cache_hits_total",
|
|
351
|
+
"Total number of cache hits",
|
|
352
|
+
["cache_type"],
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
readonly cacheMisses = new Counter(
|
|
356
|
+
"Guardrail_cache_misses_total",
|
|
357
|
+
"Total number of cache misses",
|
|
358
|
+
["cache_type"],
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
// System metrics
|
|
362
|
+
readonly activeConnections = new Gauge(
|
|
363
|
+
"Guardrail_active_connections",
|
|
364
|
+
"Number of active WebSocket connections",
|
|
365
|
+
[],
|
|
366
|
+
);
|
|
367
|
+
|
|
368
|
+
readonly memoryUsageBytes = new Gauge(
|
|
369
|
+
"Guardrail_memory_usage_bytes",
|
|
370
|
+
"Current memory usage in bytes",
|
|
371
|
+
["type"],
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Generate Prometheus-formatted output
|
|
376
|
+
*/
|
|
377
|
+
generatePrometheusOutput(): string {
|
|
378
|
+
const lines: string[] = [];
|
|
379
|
+
|
|
380
|
+
const metrics = [
|
|
381
|
+
{ metric: this.scansTotal, type: "counter" },
|
|
382
|
+
{ metric: this.scanDuration, type: "histogram" },
|
|
383
|
+
{ metric: this.injectionsDetected, type: "counter" },
|
|
384
|
+
{ metric: this.injectionScanDuration, type: "histogram" },
|
|
385
|
+
{ metric: this.vulnerabilitiesFound, type: "counter" },
|
|
386
|
+
{ metric: this.vulnerablePackages, type: "gauge" },
|
|
387
|
+
{ metric: this.secretsDetected, type: "counter" },
|
|
388
|
+
{ metric: this.complianceScore, type: "gauge" },
|
|
389
|
+
{ metric: this.complianceViolations, type: "counter" },
|
|
390
|
+
{ metric: this.apiRequestsTotal, type: "counter" },
|
|
391
|
+
{ metric: this.apiRequestDuration, type: "histogram" },
|
|
392
|
+
{ metric: this.agentActionsTotal, type: "counter" },
|
|
393
|
+
{ metric: this.agentActionsBlocked, type: "counter" },
|
|
394
|
+
{ metric: this.cacheHits, type: "counter" },
|
|
395
|
+
{ metric: this.cacheMisses, type: "counter" },
|
|
396
|
+
{ metric: this.activeConnections, type: "gauge" },
|
|
397
|
+
{ metric: this.memoryUsageBytes, type: "gauge" },
|
|
398
|
+
];
|
|
399
|
+
|
|
400
|
+
for (const { metric, type } of metrics) {
|
|
401
|
+
lines.push(`# HELP ${metric.name} ${metric.help}`);
|
|
402
|
+
lines.push(`# TYPE ${metric.name} ${type}`);
|
|
403
|
+
|
|
404
|
+
const values = metric.collect();
|
|
405
|
+
for (const { value, labels } of values) {
|
|
406
|
+
const labelStr = Object.entries(labels)
|
|
407
|
+
.map(([k, v]) => `${k}="${v}"`)
|
|
408
|
+
.join(",");
|
|
409
|
+
|
|
410
|
+
if (labelStr) {
|
|
411
|
+
lines.push(`${metric.name}{${labelStr}} ${value}`);
|
|
412
|
+
} else {
|
|
413
|
+
lines.push(`${metric.name} ${value}`);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
lines.push("");
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return lines.join("\n");
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Update system metrics
|
|
424
|
+
*/
|
|
425
|
+
updateSystemMetrics(): void {
|
|
426
|
+
const memUsage = process.memoryUsage();
|
|
427
|
+
this.memoryUsageBytes.set({ type: "heap_used" }, memUsage.heapUsed);
|
|
428
|
+
this.memoryUsageBytes.set({ type: "heap_total" }, memUsage.heapTotal);
|
|
429
|
+
this.memoryUsageBytes.set({ type: "rss" }, memUsage.rss);
|
|
430
|
+
this.memoryUsageBytes.set({ type: "external" }, memUsage.external);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* Reset all metrics (for testing)
|
|
435
|
+
*/
|
|
436
|
+
resetAll(): void {
|
|
437
|
+
this.scansTotal.reset();
|
|
438
|
+
// Add reset for other metrics as needed
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// Export singleton registry
|
|
443
|
+
export const metrics = new MetricsRegistry();
|
|
444
|
+
|
|
445
|
+
// Export classes for custom metrics
|
|
446
|
+
export { Counter, Gauge, Histogram };
|