@rasputin-ai/core 0.7.1 → 0.8.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/create-client/create-client-types.d.ts +8 -0
- package/dist/create-client/create-client-types.d.ts.map +1 -1
- package/dist/create-client/create-client.d.ts.map +1 -1
- package/dist/create-ingest-event/create-ingest-event-types.d.ts +2 -0
- package/dist/create-ingest-event/create-ingest-event-types.d.ts.map +1 -1
- package/dist/derivation/rasputin-redacted.d.ts +3 -0
- package/dist/derivation/rasputin-redacted.d.ts.map +1 -0
- package/dist/derivation/redact-env-secret-values.d.ts +10 -0
- package/dist/derivation/redact-env-secret-values.d.ts.map +1 -0
- package/dist/derivation/sensitive-property-name.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +604 -332
- package/dist/sdk-meta.d.ts +1 -1
- package/dist/suppression/compute-burst-key.d.ts +1 -1
- package/dist/suppression/compute-burst-key.d.ts.map +1 -1
- package/dist/suppression/create-suppression.d.ts +3 -4
- package/dist/suppression/create-suppression.d.ts.map +1 -1
- package/dist/suppression/grouping-ref-cache.d.ts +6 -0
- package/dist/suppression/grouping-ref-cache.d.ts.map +1 -0
- package/dist/suppression/parameterize-message.d.ts +2 -4
- package/dist/suppression/parameterize-message.d.ts.map +1 -1
- package/dist/suppression/suppression-types.d.ts +6 -0
- package/dist/suppression/suppression-types.d.ts.map +1 -1
- package/dist/transport/create-transport.d.ts.map +1 -1
- package/dist/transport/default-ingest-request-timeout.d.ts +2 -0
- package/dist/transport/default-ingest-request-timeout.d.ts.map +1 -0
- package/dist/transport/node-http-fetch.d.ts +6 -3
- package/dist/transport/node-http-fetch.d.ts.map +1 -1
- package/dist/transport/send-batch.d.ts +6 -4
- package/dist/transport/send-batch.d.ts.map +1 -1
- package/dist/transport/transport-types.d.ts +13 -3
- package/dist/transport/transport-types.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/suppression/identity-needs-message-template.d.ts +0 -8
- package/dist/suppression/identity-needs-message-template.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
// src/transport/node-http-fetch.ts
|
|
2
|
-
import * as
|
|
3
|
-
import * as
|
|
2
|
+
import * as net from "node:net";
|
|
3
|
+
import * as tls from "node:tls";
|
|
4
|
+
var CONNECT_TIMEOUT_MS = 2e3;
|
|
5
|
+
var abortError = () => Object.assign(new Error("aborted"), { name: "AbortError" });
|
|
6
|
+
var connectTimeoutError = () => Object.assign(new Error("connect timeout"), { name: "ConnectTimeoutError" });
|
|
4
7
|
var headerRecord = (headers) => {
|
|
5
8
|
const view = new Headers(headers);
|
|
6
9
|
const record = {};
|
|
@@ -9,26 +12,84 @@ var headerRecord = (headers) => {
|
|
|
9
12
|
});
|
|
10
13
|
return record;
|
|
11
14
|
};
|
|
12
|
-
var
|
|
13
|
-
if (body == null)
|
|
14
|
-
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
if (typeof body === "string") {
|
|
18
|
-
req.end(body);
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
15
|
+
var toBuffer = (body) => {
|
|
16
|
+
if (body == null) return Buffer.alloc(0);
|
|
17
|
+
if (typeof body === "string") return Buffer.from(body);
|
|
21
18
|
if (ArrayBuffer.isView(body)) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
19
|
+
return Buffer.from(body.buffer, body.byteOffset, body.byteLength);
|
|
20
|
+
}
|
|
21
|
+
if (body instanceof ArrayBuffer) return Buffer.from(body);
|
|
22
|
+
return Buffer.alloc(0);
|
|
23
|
+
};
|
|
24
|
+
var encodeHttpRequest = (url, init) => {
|
|
25
|
+
const method = (init?.method ?? "GET").toUpperCase();
|
|
26
|
+
const path = `${url.pathname}${url.search}` || "/";
|
|
27
|
+
const headers = headerRecord(init?.headers);
|
|
28
|
+
const body = toBuffer(init?.body ?? null);
|
|
29
|
+
if (body.length > 0 && headers["content-length"] === void 0) {
|
|
30
|
+
headers["content-length"] = String(body.length);
|
|
31
|
+
}
|
|
32
|
+
if (headers.host === void 0) headers.host = url.host;
|
|
33
|
+
if (headers.connection === void 0) headers.connection = "close";
|
|
34
|
+
const head = [`${method} ${path} HTTP/1.1`];
|
|
35
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
36
|
+
head.push(`${key}: ${value}`);
|
|
37
|
+
}
|
|
38
|
+
return Buffer.concat([Buffer.from(`${head.join("\r\n")}\r
|
|
39
|
+
\r
|
|
40
|
+
`), body]);
|
|
41
|
+
};
|
|
42
|
+
var tryDecodeChunked = (raw) => {
|
|
43
|
+
const parts = [];
|
|
44
|
+
let offset = 0;
|
|
45
|
+
for (; ; ) {
|
|
46
|
+
const lineEnd = raw.indexOf("\r\n", offset);
|
|
47
|
+
if (lineEnd < 0) return null;
|
|
48
|
+
const size = Number.parseInt(raw.subarray(offset, lineEnd).toString("ascii"), 16);
|
|
49
|
+
if (!Number.isFinite(size) || size < 0) throw new Error("invalid chunk size");
|
|
50
|
+
const dataStart = lineEnd + 2;
|
|
51
|
+
if (size === 0) return raw.length < dataStart + 2 ? null : Buffer.concat(parts);
|
|
52
|
+
const dataEnd = dataStart + size;
|
|
53
|
+
if (raw.length < dataEnd + 2) return null;
|
|
54
|
+
parts.push(raw.subarray(dataStart, dataEnd));
|
|
55
|
+
offset = dataEnd + 2;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
var toResponseBody = (buf) => {
|
|
59
|
+
const copy = new Uint8Array(buf.byteLength);
|
|
60
|
+
copy.set(buf);
|
|
61
|
+
return copy;
|
|
62
|
+
};
|
|
63
|
+
var tryParseHttpResponse = (raw, connectionClosed) => {
|
|
64
|
+
const split = raw.indexOf("\r\n\r\n");
|
|
65
|
+
if (split < 0) return null;
|
|
66
|
+
const lines = raw.subarray(0, split).toString("latin1").split("\r\n");
|
|
67
|
+
const status = /^HTTP\/\d\.\d (\d{3})/.exec(lines[0] ?? "");
|
|
68
|
+
if (!status) throw new Error("invalid HTTP response");
|
|
69
|
+
const headers = new Headers();
|
|
70
|
+
for (const line of lines.slice(1)) {
|
|
71
|
+
const colon = line.indexOf(":");
|
|
72
|
+
if (colon < 0) continue;
|
|
73
|
+
headers.append(line.slice(0, colon).trim(), line.slice(colon + 1).trim());
|
|
74
|
+
}
|
|
75
|
+
const body = raw.subarray(split + 4);
|
|
76
|
+
if (headers.get("transfer-encoding")?.toLowerCase().includes("chunked")) {
|
|
77
|
+
const decoded = tryDecodeChunked(body);
|
|
78
|
+
return decoded === null ? null : new Response(toResponseBody(decoded), { status: Number(status[1]), headers });
|
|
79
|
+
}
|
|
80
|
+
const lengthHeader = headers.get("content-length");
|
|
81
|
+
if (lengthHeader !== null) {
|
|
82
|
+
const length = Number(lengthHeader);
|
|
83
|
+
if (!Number.isInteger(length) || length < 0) throw new Error("invalid content-length");
|
|
84
|
+
if (body.length < length) return null;
|
|
85
|
+
return new Response(toResponseBody(body.subarray(0, length)), {
|
|
86
|
+
status: Number(status[1]),
|
|
87
|
+
headers
|
|
88
|
+
});
|
|
28
89
|
}
|
|
29
|
-
|
|
90
|
+
return connectionClosed ? new Response(toResponseBody(body), { status: Number(status[1]), headers }) : null;
|
|
30
91
|
};
|
|
31
|
-
var
|
|
92
|
+
var defaultIngestFetch = () => (input, init) => new Promise((resolve4, reject) => {
|
|
32
93
|
let parsed;
|
|
33
94
|
try {
|
|
34
95
|
parsed = new URL(String(input));
|
|
@@ -36,62 +97,77 @@ var createNodeHttpFetch = (unrefSockets = false) => (input, init) => new Promise
|
|
|
36
97
|
reject(error);
|
|
37
98
|
return;
|
|
38
99
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (Array.isArray(value)) {
|
|
60
|
-
for (const item of value) headers.append(key, item);
|
|
61
|
-
} else {
|
|
62
|
-
headers.set(key, value);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
resolve4(
|
|
66
|
-
new Response(Buffer.concat(chunks), {
|
|
67
|
-
status: response.statusCode ?? 0,
|
|
68
|
-
headers
|
|
69
|
-
})
|
|
70
|
-
);
|
|
71
|
-
});
|
|
100
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
101
|
+
reject(new Error(`unsupported protocol: ${parsed.protocol}`));
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (init?.signal?.aborted) {
|
|
105
|
+
reject(abortError());
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const port = Number(parsed.port) || (parsed.protocol === "https:" ? 443 : 80);
|
|
109
|
+
const socket = parsed.protocol === "https:" ? tls.connect({ host: parsed.hostname, port, servername: parsed.hostname }) : net.connect({ host: parsed.hostname, port });
|
|
110
|
+
socket.unref();
|
|
111
|
+
let settled = false;
|
|
112
|
+
let sent = false;
|
|
113
|
+
let connectTimer;
|
|
114
|
+
const finish = (error, response) => {
|
|
115
|
+
if (settled) return;
|
|
116
|
+
settled = true;
|
|
117
|
+
if (connectTimer) {
|
|
118
|
+
clearTimeout(connectTimer);
|
|
119
|
+
connectTimer = void 0;
|
|
72
120
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
reject(Object.assign(new Error("aborted"), { name: "AbortError" }));
|
|
121
|
+
socket.destroy();
|
|
122
|
+
if (error) reject(error);
|
|
123
|
+
else if (response) resolve4(response);
|
|
77
124
|
};
|
|
78
|
-
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
|
|
125
|
+
connectTimer = setTimeout(() => {
|
|
126
|
+
if (sent || settled) return;
|
|
127
|
+
finish(connectTimeoutError());
|
|
128
|
+
}, CONNECT_TIMEOUT_MS);
|
|
129
|
+
const onConnected = () => {
|
|
130
|
+
if (settled || sent) return;
|
|
131
|
+
sent = true;
|
|
132
|
+
if (connectTimer) {
|
|
133
|
+
clearTimeout(connectTimer);
|
|
134
|
+
connectTimer = void 0;
|
|
82
135
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
136
|
+
try {
|
|
137
|
+
socket.write(encodeHttpRequest(parsed, init));
|
|
138
|
+
} catch (error) {
|
|
139
|
+
finish(error instanceof Error ? error : new Error(String(error)));
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
if (parsed.protocol === "https:") {
|
|
143
|
+
socket.once("secureConnect", onConnected);
|
|
144
|
+
} else {
|
|
145
|
+
socket.once("connect", onConnected);
|
|
146
|
+
if (socket.remoteAddress) onConnected();
|
|
147
|
+
}
|
|
148
|
+
init?.signal?.addEventListener("abort", () => finish(abortError()), { once: true });
|
|
149
|
+
if (init?.signal?.aborted) finish(abortError());
|
|
150
|
+
let buf = Buffer.alloc(0);
|
|
151
|
+
socket.on("data", (chunk) => {
|
|
152
|
+
buf = Buffer.concat([buf, chunk]);
|
|
153
|
+
try {
|
|
154
|
+
const response = tryParseHttpResponse(buf, false);
|
|
155
|
+
if (response) finish(null, response);
|
|
156
|
+
} catch (error) {
|
|
157
|
+
finish(error instanceof Error ? error : new Error(String(error)));
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
socket.on("end", () => {
|
|
161
|
+
try {
|
|
162
|
+
const response = tryParseHttpResponse(buf, true);
|
|
163
|
+
if (response) finish(null, response);
|
|
164
|
+
else finish(new Error("incomplete HTTP response"));
|
|
165
|
+
} catch (error) {
|
|
166
|
+
finish(error instanceof Error ? error : new Error(String(error)));
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
socket.on("error", (error) => finish(error));
|
|
93
170
|
});
|
|
94
|
-
var defaultIngestFetch = (options) => createNodeHttpFetch(options?.unrefSockets === true);
|
|
95
171
|
|
|
96
172
|
// src/announce-deploy/announce-deploy.ts
|
|
97
173
|
var trimmedString = (value) => typeof value === "string" ? value.trim() : "";
|
|
@@ -361,6 +437,257 @@ var finalizeResolution = (resolution, stackFrames) => {
|
|
|
361
437
|
return "exact";
|
|
362
438
|
};
|
|
363
439
|
|
|
440
|
+
// src/derivation/rasputin-redacted.ts
|
|
441
|
+
var RASPUTIN_REDACTED = "[RASPUTIN_REDACTED]";
|
|
442
|
+
|
|
443
|
+
// src/derivation/sensitive-property-name.ts
|
|
444
|
+
var DEFAULT_SENSITIVE_PROPERTY_NAMES = [
|
|
445
|
+
"password",
|
|
446
|
+
"passwd",
|
|
447
|
+
"pwd",
|
|
448
|
+
"passphrase",
|
|
449
|
+
"cookie",
|
|
450
|
+
"cookies",
|
|
451
|
+
"signedcookies",
|
|
452
|
+
"setcookie",
|
|
453
|
+
"secret",
|
|
454
|
+
"secrets",
|
|
455
|
+
"clientsecret",
|
|
456
|
+
"authorization",
|
|
457
|
+
"proxyauthorization",
|
|
458
|
+
"bearer"
|
|
459
|
+
];
|
|
460
|
+
var DEFAULT_SENSITIVE_PROPERTY_NAME_SET = new Set(DEFAULT_SENSITIVE_PROPERTY_NAMES);
|
|
461
|
+
var SENSITIVE_SUFFIXES = [
|
|
462
|
+
"password",
|
|
463
|
+
"passwd",
|
|
464
|
+
"passphrase",
|
|
465
|
+
"pwd",
|
|
466
|
+
"cookie",
|
|
467
|
+
"cookies"
|
|
468
|
+
];
|
|
469
|
+
var compactKey = (key) => {
|
|
470
|
+
let compacted = "";
|
|
471
|
+
for (let index = 0; index < key.length; index++) {
|
|
472
|
+
const code = key.charCodeAt(index);
|
|
473
|
+
if (code === 45 || code === 46 || code === 95) continue;
|
|
474
|
+
compacted += code >= 65 && code <= 90 ? String.fromCharCode(code + 32) : key[index];
|
|
475
|
+
}
|
|
476
|
+
return compacted;
|
|
477
|
+
};
|
|
478
|
+
var stripTrailingDigits = (value) => {
|
|
479
|
+
let end = value.length;
|
|
480
|
+
while (end > 0) {
|
|
481
|
+
const code = value.charCodeAt(end - 1);
|
|
482
|
+
if (code < 48 || code > 57) break;
|
|
483
|
+
end--;
|
|
484
|
+
}
|
|
485
|
+
return end === 0 ? value : value.slice(0, end);
|
|
486
|
+
};
|
|
487
|
+
var defaultSensitivePropertyNames = () => DEFAULT_SENSITIVE_PROPERTY_NAME_SET;
|
|
488
|
+
var propertyNameIsSensitive = (key) => {
|
|
489
|
+
const compacted = compactKey(key);
|
|
490
|
+
const compactForms = [compacted, stripTrailingDigits(compacted)].filter(
|
|
491
|
+
(value, index, values) => value.length > 0 && values.indexOf(value) === index
|
|
492
|
+
);
|
|
493
|
+
for (const form of compactForms) {
|
|
494
|
+
if (DEFAULT_SENSITIVE_PROPERTY_NAME_SET.has(form)) return true;
|
|
495
|
+
for (const suffix of SENSITIVE_SUFFIXES) {
|
|
496
|
+
if (form.endsWith(suffix)) return true;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
return false;
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
// src/derivation/redact-env-secret-values.ts
|
|
503
|
+
var MIN_ENV_SECRET_LENGTH = 6;
|
|
504
|
+
var MAX_ENV_SECRET_NEEDLE_LENGTH = 512;
|
|
505
|
+
var COMMON_CONFIG_VALUES = /* @__PURE__ */ new Set([
|
|
506
|
+
"enabled",
|
|
507
|
+
"disabled",
|
|
508
|
+
"production",
|
|
509
|
+
"development",
|
|
510
|
+
"staging",
|
|
511
|
+
"testing",
|
|
512
|
+
"localhost",
|
|
513
|
+
"undefined"
|
|
514
|
+
]);
|
|
515
|
+
var identityMatcher = {
|
|
516
|
+
redact: (text) => text,
|
|
517
|
+
needleCount: 0
|
|
518
|
+
};
|
|
519
|
+
var envKeyLooksSensitive = (key) => {
|
|
520
|
+
if (propertyNameIsSensitive(key)) return true;
|
|
521
|
+
const compact = key.replace(/[-._]/g, "").toLowerCase();
|
|
522
|
+
return compact.includes("accesskey") || compact.includes("apikey") || compact.endsWith("secret") || compact.endsWith("token") || compact.includes("privatekey");
|
|
523
|
+
};
|
|
524
|
+
var isCollectableSecretValue = (value) => value.length >= MIN_ENV_SECRET_LENGTH && !COMMON_CONFIG_VALUES.has(value.toLowerCase());
|
|
525
|
+
var looksLikeUrl = (value) => {
|
|
526
|
+
const schemeEnd = value.indexOf("://");
|
|
527
|
+
return schemeEnd > 0 && schemeEnd < 32;
|
|
528
|
+
};
|
|
529
|
+
var urlUserinfo = (value) => {
|
|
530
|
+
const schemeEnd = value.indexOf("://");
|
|
531
|
+
if (schemeEnd <= 0) return void 0;
|
|
532
|
+
const rest = value.slice(schemeEnd + 3);
|
|
533
|
+
let authorityEnd = rest.length;
|
|
534
|
+
for (const marker of ["/", "?", "#"]) {
|
|
535
|
+
const at = rest.indexOf(marker);
|
|
536
|
+
if (at >= 0 && at < authorityEnd) authorityEnd = at;
|
|
537
|
+
}
|
|
538
|
+
const authority = rest.slice(0, authorityEnd);
|
|
539
|
+
const userinfoEnd = authority.lastIndexOf("@");
|
|
540
|
+
if (userinfoEnd < 0) return void 0;
|
|
541
|
+
const userinfo = authority.slice(0, userinfoEnd);
|
|
542
|
+
if (!userinfo) return void 0;
|
|
543
|
+
const colon = userinfo.indexOf(":");
|
|
544
|
+
const encodedPassword = colon < 0 ? "" : userinfo.slice(colon + 1);
|
|
545
|
+
if (!encodedPassword) return void 0;
|
|
546
|
+
let password = encodedPassword;
|
|
547
|
+
try {
|
|
548
|
+
password = decodeURIComponent(encodedPassword.replace(/\+/g, " "));
|
|
549
|
+
} catch {
|
|
550
|
+
password = encodedPassword;
|
|
551
|
+
}
|
|
552
|
+
return { password, encodedPassword, userinfo };
|
|
553
|
+
};
|
|
554
|
+
var querySecretValues = (value) => {
|
|
555
|
+
const queryAt = value.indexOf("?");
|
|
556
|
+
if (queryAt < 0) return [];
|
|
557
|
+
const hashAt = value.indexOf("#", queryAt + 1);
|
|
558
|
+
const query = hashAt < 0 ? value.slice(queryAt + 1) : value.slice(queryAt + 1, hashAt);
|
|
559
|
+
if (!query.includes("=")) return [];
|
|
560
|
+
const found = [];
|
|
561
|
+
const parts = query.split("&");
|
|
562
|
+
for (let index = 0; index < parts.length; index++) {
|
|
563
|
+
const part = parts[index];
|
|
564
|
+
if (!part) continue;
|
|
565
|
+
const equals = part.indexOf("=");
|
|
566
|
+
if (equals <= 0) continue;
|
|
567
|
+
const rawKey = part.slice(0, equals);
|
|
568
|
+
let key = rawKey;
|
|
569
|
+
try {
|
|
570
|
+
key = decodeURIComponent(rawKey.replace(/\+/g, " "));
|
|
571
|
+
} catch {
|
|
572
|
+
key = rawKey;
|
|
573
|
+
}
|
|
574
|
+
if (!propertyNameIsSensitive(key) && !propertyNameIsSensitive(rawKey)) continue;
|
|
575
|
+
const rawValue = part.slice(equals + 1);
|
|
576
|
+
if (!rawValue) continue;
|
|
577
|
+
found.push(rawValue);
|
|
578
|
+
try {
|
|
579
|
+
const decoded = decodeURIComponent(rawValue.replace(/\+/g, " "));
|
|
580
|
+
if (decoded !== rawValue) found.push(decoded);
|
|
581
|
+
} catch {
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
return found;
|
|
585
|
+
};
|
|
586
|
+
var addNeedle = (needles, value) => {
|
|
587
|
+
if (value.length < MIN_ENV_SECRET_LENGTH) return;
|
|
588
|
+
needles.add(
|
|
589
|
+
value.length > MAX_ENV_SECRET_NEEDLE_LENGTH ? value.slice(0, MAX_ENV_SECRET_NEEDLE_LENGTH) : value
|
|
590
|
+
);
|
|
591
|
+
};
|
|
592
|
+
var addWithRepresentations = (needles, value) => {
|
|
593
|
+
addNeedle(needles, value);
|
|
594
|
+
if (value.length > MAX_ENV_SECRET_NEEDLE_LENGTH) return;
|
|
595
|
+
try {
|
|
596
|
+
const encoded = encodeURIComponent(value);
|
|
597
|
+
if (encoded !== value) addNeedle(needles, encoded);
|
|
598
|
+
const plus = encoded.replace(/%20/g, "+");
|
|
599
|
+
if (plus !== encoded) addNeedle(needles, plus);
|
|
600
|
+
} catch {
|
|
601
|
+
}
|
|
602
|
+
try {
|
|
603
|
+
const jsonEscaped = JSON.stringify(value).slice(1, -1);
|
|
604
|
+
if (jsonEscaped !== value) addNeedle(needles, jsonEscaped);
|
|
605
|
+
} catch {
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
var collectEnvSecretValues = (env = process.env) => {
|
|
609
|
+
const needles = /* @__PURE__ */ new Set();
|
|
610
|
+
let keys;
|
|
611
|
+
try {
|
|
612
|
+
keys = Object.keys(env);
|
|
613
|
+
} catch {
|
|
614
|
+
return [];
|
|
615
|
+
}
|
|
616
|
+
for (let index = 0; index < keys.length; index++) {
|
|
617
|
+
const key = keys[index];
|
|
618
|
+
if (!key || key === "PWD") continue;
|
|
619
|
+
let value;
|
|
620
|
+
try {
|
|
621
|
+
value = env[key];
|
|
622
|
+
} catch {
|
|
623
|
+
continue;
|
|
624
|
+
}
|
|
625
|
+
if (typeof value !== "string" || value.length === 0) continue;
|
|
626
|
+
try {
|
|
627
|
+
const userinfo = urlUserinfo(value);
|
|
628
|
+
if (userinfo) {
|
|
629
|
+
addWithRepresentations(needles, userinfo.password);
|
|
630
|
+
if (userinfo.encodedPassword !== userinfo.password) {
|
|
631
|
+
addWithRepresentations(needles, userinfo.encodedPassword);
|
|
632
|
+
}
|
|
633
|
+
if (userinfo.userinfo.length >= MIN_ENV_SECRET_LENGTH) {
|
|
634
|
+
addWithRepresentations(needles, userinfo.userinfo);
|
|
635
|
+
}
|
|
636
|
+
addWithRepresentations(needles, value);
|
|
637
|
+
}
|
|
638
|
+
const queryValues = querySecretValues(value);
|
|
639
|
+
for (let queryIndex = 0; queryIndex < queryValues.length; queryIndex++) {
|
|
640
|
+
const part = queryValues[queryIndex];
|
|
641
|
+
if (part) addWithRepresentations(needles, part);
|
|
642
|
+
}
|
|
643
|
+
if (!envKeyLooksSensitive(key) || !isCollectableSecretValue(value)) continue;
|
|
644
|
+
if (looksLikeUrl(value) && !userinfo && queryValues.length === 0) continue;
|
|
645
|
+
addWithRepresentations(needles, value);
|
|
646
|
+
} catch {
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
return [...needles];
|
|
650
|
+
};
|
|
651
|
+
var createExactSecretMatcher = (secrets) => {
|
|
652
|
+
const unique = [];
|
|
653
|
+
const exact = /* @__PURE__ */ new Set();
|
|
654
|
+
for (let index = 0; index < secrets.length; index++) {
|
|
655
|
+
const secret = secrets[index];
|
|
656
|
+
if (!secret || secret.length < MIN_ENV_SECRET_LENGTH || exact.has(secret)) continue;
|
|
657
|
+
exact.add(secret);
|
|
658
|
+
unique.push(secret);
|
|
659
|
+
}
|
|
660
|
+
if (unique.length === 0) return identityMatcher;
|
|
661
|
+
unique.sort((left, right) => right.length - left.length);
|
|
662
|
+
const minLen = unique[unique.length - 1]?.length ?? MIN_ENV_SECRET_LENGTH;
|
|
663
|
+
return {
|
|
664
|
+
needleCount: unique.length,
|
|
665
|
+
redact(text) {
|
|
666
|
+
try {
|
|
667
|
+
if (text.length < minLen) return text;
|
|
668
|
+
if (exact.has(text)) return RASPUTIN_REDACTED;
|
|
669
|
+
let result = text;
|
|
670
|
+
for (let index = 0; index < unique.length; index++) {
|
|
671
|
+
const needle = unique[index];
|
|
672
|
+
if (!needle || result.length < needle.length) continue;
|
|
673
|
+
if (result.indexOf(needle) === -1) continue;
|
|
674
|
+
result = result.replaceAll(needle, RASPUTIN_REDACTED);
|
|
675
|
+
}
|
|
676
|
+
return result;
|
|
677
|
+
} catch {
|
|
678
|
+
return text;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
};
|
|
682
|
+
};
|
|
683
|
+
var createEnvSecretMatcher = (env = process.env) => {
|
|
684
|
+
try {
|
|
685
|
+
return createExactSecretMatcher(collectEnvSecretValues(env));
|
|
686
|
+
} catch {
|
|
687
|
+
return identityMatcher;
|
|
688
|
+
}
|
|
689
|
+
};
|
|
690
|
+
|
|
364
691
|
// src/normalize-frames/normalize-frames.ts
|
|
365
692
|
import { isAbsolute as isAbsolute2, resolve as resolve2 } from "node:path";
|
|
366
693
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
@@ -808,13 +1135,7 @@ var resolveSourceMaps = async (frames) => {
|
|
|
808
1135
|
|
|
809
1136
|
// src/sdk-meta.ts
|
|
810
1137
|
var SDK_NAME = "@rasputin-ai/core";
|
|
811
|
-
var SDK_VERSION = "0.
|
|
812
|
-
|
|
813
|
-
// src/suppression/identity-needs-message-template.ts
|
|
814
|
-
var identityNeedsMessageTemplate = (type, code) => {
|
|
815
|
-
if (code != null && code !== "") return false;
|
|
816
|
-
return type === "Error";
|
|
817
|
-
};
|
|
1138
|
+
var SDK_VERSION = "0.8.0";
|
|
818
1139
|
|
|
819
1140
|
// src/suppression/parameterize-message.ts
|
|
820
1141
|
var MAX_INPUT_LENGTH = 8192;
|
|
@@ -872,10 +1193,6 @@ var RULES = [
|
|
|
872
1193
|
{
|
|
873
1194
|
token: "duration",
|
|
874
1195
|
pattern: /\b\d+(?:\.\d+)?\s?(?:ns|µs|us|ms|secs?|seconds?|mins?|minutes?|hrs?|hours?|days?)\b/giu
|
|
875
|
-
},
|
|
876
|
-
{
|
|
877
|
-
token: "id",
|
|
878
|
-
pattern: /\b(?=[a-z0-9]*[a-z])(?=[a-z0-9]*\d)[a-z0-9]{8,}\b/giu
|
|
879
1196
|
}
|
|
880
1197
|
];
|
|
881
1198
|
var normalizeForIdentity = (normalized) => {
|
|
@@ -936,19 +1253,22 @@ var frameBurstParts = (frames) => {
|
|
|
936
1253
|
const inApp = collapsed.filter((frame) => frame.in_app);
|
|
937
1254
|
const selected = (inApp.length > 0 ? inApp : collapsed).slice(0, FRAME_COUNT);
|
|
938
1255
|
return selected.map((frame) => {
|
|
939
|
-
const
|
|
1256
|
+
const loc = frame.original ?? frame.generated;
|
|
940
1257
|
const fn = normalizeFunction(frame.function ?? frame.original?.name);
|
|
941
|
-
return `${file}:${fn}`;
|
|
1258
|
+
return `${loc.file}:${fn}:${loc.line ?? ""}:${loc.column ?? ""}`;
|
|
942
1259
|
});
|
|
943
1260
|
};
|
|
944
|
-
var computeBurstKey = (errorType, message, code, frames) => {
|
|
1261
|
+
var computeBurstKey = (errorType, message, code, frames, route, method) => {
|
|
945
1262
|
const parts = frameBurstParts(frames);
|
|
946
1263
|
const codePart = code ?? "";
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
1264
|
+
return [
|
|
1265
|
+
errorType,
|
|
1266
|
+
codePart,
|
|
1267
|
+
method ?? "",
|
|
1268
|
+
route ?? "",
|
|
1269
|
+
parameterizeMessage(message),
|
|
1270
|
+
parts.join("\0")
|
|
1271
|
+
].join("\0");
|
|
952
1272
|
};
|
|
953
1273
|
|
|
954
1274
|
// src/suppression/create-suppression.ts
|
|
@@ -999,9 +1319,12 @@ var createSuppression = (options = {}) => {
|
|
|
999
1319
|
windowStart: bucket.windowStart,
|
|
1000
1320
|
windowEndMs,
|
|
1001
1321
|
lastRelease: bucket.lastRelease,
|
|
1322
|
+
lastRoute: bucket.lastRoute,
|
|
1323
|
+
lastMethod: bucket.lastMethod,
|
|
1002
1324
|
lastEnvironment: bucket.lastEnvironment,
|
|
1003
1325
|
identity: bucket.identity,
|
|
1004
|
-
captureRawFrames: bucket.captureRawFrames
|
|
1326
|
+
captureRawFrames: bucket.captureRawFrames,
|
|
1327
|
+
burstKey: bucket.burstKey
|
|
1005
1328
|
});
|
|
1006
1329
|
const toSummary = (draft, identity) => ({
|
|
1007
1330
|
count: draft.count,
|
|
@@ -1009,7 +1332,8 @@ var createSuppression = (options = {}) => {
|
|
|
1009
1332
|
window_end: new Date(draft.windowEndMs).toISOString(),
|
|
1010
1333
|
release: draft.lastRelease,
|
|
1011
1334
|
environment: draft.lastEnvironment,
|
|
1012
|
-
...identity
|
|
1335
|
+
...identity,
|
|
1336
|
+
...draft.lastRoute || draft.lastMethod ? { request: { route: draft.lastRoute, method: draft.lastMethod } } : {}
|
|
1013
1337
|
});
|
|
1014
1338
|
const flushSuppressed = (bucket, windowEndMs) => {
|
|
1015
1339
|
if (bucket.suppressed <= 0) return;
|
|
@@ -1020,9 +1344,17 @@ var createSuppression = (options = {}) => {
|
|
|
1020
1344
|
const now = input.now ?? Date.now();
|
|
1021
1345
|
const identity = captureIdentity(input);
|
|
1022
1346
|
const captureRawFrames = (input.rawFrames ?? []).slice(0, MAX_STACK_FRAMES);
|
|
1023
|
-
const burstKey = computeBurstKey(
|
|
1347
|
+
const burstKey = computeBurstKey(
|
|
1348
|
+
input.errorType,
|
|
1349
|
+
input.message,
|
|
1350
|
+
input.code,
|
|
1351
|
+
input.frames,
|
|
1352
|
+
input.route,
|
|
1353
|
+
input.method
|
|
1354
|
+
);
|
|
1024
1355
|
const release = input.release;
|
|
1025
1356
|
const route = input.route ?? null;
|
|
1357
|
+
const method = input.method ?? null;
|
|
1026
1358
|
let bucket = burstBuckets.get(burstKey);
|
|
1027
1359
|
if (!bucket) {
|
|
1028
1360
|
bucket = {
|
|
@@ -1031,9 +1363,11 @@ var createSuppression = (options = {}) => {
|
|
|
1031
1363
|
windowStart: now,
|
|
1032
1364
|
lastRelease: release,
|
|
1033
1365
|
lastRoute: route,
|
|
1366
|
+
lastMethod: method,
|
|
1034
1367
|
lastEnvironment: input.environment,
|
|
1035
1368
|
identity,
|
|
1036
|
-
captureRawFrames
|
|
1369
|
+
captureRawFrames,
|
|
1370
|
+
burstKey
|
|
1037
1371
|
};
|
|
1038
1372
|
burstBuckets.set(burstKey, bucket);
|
|
1039
1373
|
evictIfNeeded();
|
|
@@ -1048,6 +1382,7 @@ var createSuppression = (options = {}) => {
|
|
|
1048
1382
|
bucket.windowStart = now;
|
|
1049
1383
|
bucket.lastRelease = release;
|
|
1050
1384
|
bucket.lastRoute = route;
|
|
1385
|
+
bucket.lastMethod = method;
|
|
1051
1386
|
bucket.lastEnvironment = input.environment;
|
|
1052
1387
|
bucket.identity = identity;
|
|
1053
1388
|
bucket.captureRawFrames = captureRawFrames;
|
|
@@ -1057,6 +1392,7 @@ var createSuppression = (options = {}) => {
|
|
|
1057
1392
|
bucket.sentInWindow += 1;
|
|
1058
1393
|
bucket.lastRelease = release;
|
|
1059
1394
|
bucket.lastRoute = route;
|
|
1395
|
+
bucket.lastMethod = method;
|
|
1060
1396
|
bucket.lastEnvironment = input.environment;
|
|
1061
1397
|
return { action: "send", priority: "repeat" };
|
|
1062
1398
|
}
|
|
@@ -1073,7 +1409,8 @@ var createSuppression = (options = {}) => {
|
|
|
1073
1409
|
}
|
|
1074
1410
|
return drafts.map((draft) => ({
|
|
1075
1411
|
summary: toSummary(draft, draft.identity),
|
|
1076
|
-
rawFrames: draft.captureRawFrames
|
|
1412
|
+
rawFrames: draft.captureRawFrames,
|
|
1413
|
+
burstKey: draft.burstKey
|
|
1077
1414
|
}));
|
|
1078
1415
|
};
|
|
1079
1416
|
const takeSummaries = async (now = Date.now(), prepareSummary) => {
|
|
@@ -1103,6 +1440,42 @@ var createSuppression = (options = {}) => {
|
|
|
1103
1440
|
};
|
|
1104
1441
|
};
|
|
1105
1442
|
|
|
1443
|
+
// src/suppression/grouping-ref-cache.ts
|
|
1444
|
+
var GROUPING_REF_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
1445
|
+
var createGroupingRefCache = (maxSize = 2e3) => {
|
|
1446
|
+
const byBurstKey = /* @__PURE__ */ new Map();
|
|
1447
|
+
const get = (burstKey, now = Date.now()) => {
|
|
1448
|
+
const entry = byBurstKey.get(burstKey);
|
|
1449
|
+
if (!entry || entry.expiresAt <= now) {
|
|
1450
|
+
if (entry) byBurstKey.delete(burstKey);
|
|
1451
|
+
return null;
|
|
1452
|
+
}
|
|
1453
|
+
byBurstKey.delete(burstKey);
|
|
1454
|
+
byBurstKey.set(burstKey, entry);
|
|
1455
|
+
return entry.groupingRef;
|
|
1456
|
+
};
|
|
1457
|
+
const set = (burstKey, groupingRef, now = Date.now()) => {
|
|
1458
|
+
byBurstKey.delete(burstKey);
|
|
1459
|
+
byBurstKey.set(burstKey, { groupingRef, expiresAt: now + GROUPING_REF_TTL_MS });
|
|
1460
|
+
while (byBurstKey.size > maxSize) {
|
|
1461
|
+
const oldest = byBurstKey.keys().next().value;
|
|
1462
|
+
if (oldest === void 0) break;
|
|
1463
|
+
byBurstKey.delete(oldest);
|
|
1464
|
+
}
|
|
1465
|
+
};
|
|
1466
|
+
const getOrCreate = (burstKey, now = Date.now()) => {
|
|
1467
|
+
const existing = get(burstKey, now);
|
|
1468
|
+
if (existing) return existing;
|
|
1469
|
+
const groupingRef = crypto.randomUUID();
|
|
1470
|
+
set(burstKey, groupingRef, now);
|
|
1471
|
+
return groupingRef;
|
|
1472
|
+
};
|
|
1473
|
+
return { get, set, getOrCreate };
|
|
1474
|
+
};
|
|
1475
|
+
|
|
1476
|
+
// src/transport/default-ingest-request-timeout.ts
|
|
1477
|
+
var DEFAULT_INGEST_REQUEST_TIMEOUT_MS = 2e4;
|
|
1478
|
+
|
|
1106
1479
|
// src/transport/process-shutdown-hooks.ts
|
|
1107
1480
|
var SIGNAL_EXIT_CODES = { SIGTERM: 143, SIGINT: 130 };
|
|
1108
1481
|
var RASPUTIN_PROCESS_LISTENER = Symbol.for("rasputin.process.listener.v1");
|
|
@@ -1179,33 +1552,32 @@ var encodeJsonRequestBody = (payload, gzipThresholdBytes = GZIP_JSON_THRESHOLD_B
|
|
|
1179
1552
|
|
|
1180
1553
|
// src/transport/send-batch.ts
|
|
1181
1554
|
var sleep = (ms, signal) => new Promise((resolve4) => {
|
|
1182
|
-
if (ms <= 0
|
|
1555
|
+
if (ms <= 0) {
|
|
1183
1556
|
resolve4();
|
|
1184
1557
|
return;
|
|
1185
1558
|
}
|
|
1186
1559
|
const timer = setTimeout(resolve4, ms);
|
|
1187
1560
|
timer.unref?.();
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
()
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
{ once: true }
|
|
1195
|
-
);
|
|
1561
|
+
const onAbort = () => {
|
|
1562
|
+
clearTimeout(timer);
|
|
1563
|
+
resolve4();
|
|
1564
|
+
};
|
|
1565
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
1566
|
+
if (signal.aborted) onAbort();
|
|
1196
1567
|
});
|
|
1197
1568
|
var backoffMs = (attempt) => {
|
|
1198
1569
|
const base = Math.min(3e4, 500 * 2 ** attempt);
|
|
1199
1570
|
return Math.floor(base * (0.5 + Math.random()));
|
|
1200
1571
|
};
|
|
1201
|
-
var
|
|
1572
|
+
var abortError2 = () => Object.assign(new Error("aborted"), { name: "AbortError" });
|
|
1202
1573
|
var fetchUntilAborted = (fetchFn, url, init) => new Promise((resolve4, reject) => {
|
|
1574
|
+
const onAbort = () => reject(abortError2());
|
|
1575
|
+
init.signal.addEventListener("abort", onAbort, { once: true });
|
|
1203
1576
|
if (init.signal.aborted) {
|
|
1204
|
-
|
|
1577
|
+
init.signal.removeEventListener("abort", onAbort);
|
|
1578
|
+
reject(abortError2());
|
|
1205
1579
|
return;
|
|
1206
1580
|
}
|
|
1207
|
-
const onAbort = () => reject(abortError());
|
|
1208
|
-
init.signal.addEventListener("abort", onAbort, { once: true });
|
|
1209
1581
|
void fetchFn(url, init).then(
|
|
1210
1582
|
(value) => {
|
|
1211
1583
|
init.signal.removeEventListener("abort", onAbort);
|
|
@@ -1225,8 +1597,29 @@ var retryAfterMs = (response) => {
|
|
|
1225
1597
|
const date = Date.parse(header);
|
|
1226
1598
|
return Number.isFinite(date) ? Math.max(0, date - Date.now()) : null;
|
|
1227
1599
|
};
|
|
1600
|
+
var asRefList = (value) => {
|
|
1601
|
+
if (!Array.isArray(value)) return [];
|
|
1602
|
+
return value.map((entry) => typeof entry === "string" ? entry : null);
|
|
1603
|
+
};
|
|
1604
|
+
var readGroupingRefs = async (response) => {
|
|
1605
|
+
try {
|
|
1606
|
+
const body = await response.json();
|
|
1607
|
+
const payload = typeof body === "object" && body !== null && "payload" in body && typeof body.payload === "object" && body.payload !== null ? body.payload : body;
|
|
1608
|
+
if (typeof payload !== "object" || payload === null) {
|
|
1609
|
+
return { eventGroupingRefs: [], summaryGroupingRefs: [] };
|
|
1610
|
+
}
|
|
1611
|
+
const record = payload;
|
|
1612
|
+
return {
|
|
1613
|
+
eventGroupingRefs: asRefList(record.event_grouping_refs),
|
|
1614
|
+
summaryGroupingRefs: asRefList(record.summary_grouping_refs)
|
|
1615
|
+
};
|
|
1616
|
+
} catch {
|
|
1617
|
+
return { eventGroupingRefs: [], summaryGroupingRefs: [] };
|
|
1618
|
+
}
|
|
1619
|
+
};
|
|
1228
1620
|
var sendBatch = async (options) => {
|
|
1229
1621
|
const summaries = options.summaries ?? [];
|
|
1622
|
+
const { signal } = options;
|
|
1230
1623
|
let payload;
|
|
1231
1624
|
if (summaries.length > 0) {
|
|
1232
1625
|
payload = { events: options.events, summaries };
|
|
@@ -1235,12 +1628,13 @@ var sendBatch = async (options) => {
|
|
|
1235
1628
|
}
|
|
1236
1629
|
if (options.sdkVersion) payload.sdk_version = options.sdkVersion;
|
|
1237
1630
|
if (options.sdkName) payload.sdk_name = options.sdkName;
|
|
1631
|
+
payload.scrub_pii = options.scrubPii !== false;
|
|
1238
1632
|
if (options.idempotencyKey) payload.idempotency_key = options.idempotencyKey;
|
|
1239
1633
|
let attempts = 0;
|
|
1240
1634
|
let networkErrors = 0;
|
|
1241
1635
|
let rateLimitedResponses = 0;
|
|
1242
1636
|
let serverErrorResponses = 0;
|
|
1243
|
-
const result = (outcome, failureKind = null, statusCode = null) => ({
|
|
1637
|
+
const result = (outcome, failureKind = null, statusCode = null, eventGroupingRefs = [], summaryGroupingRefs = []) => ({
|
|
1244
1638
|
outcome,
|
|
1245
1639
|
attempts,
|
|
1246
1640
|
retries: Math.max(0, attempts - 1),
|
|
@@ -1249,15 +1643,10 @@ var sendBatch = async (options) => {
|
|
|
1249
1643
|
serverErrorResponses,
|
|
1250
1644
|
aborted: failureKind === "aborted",
|
|
1251
1645
|
failureKind,
|
|
1252
|
-
statusCode
|
|
1646
|
+
statusCode,
|
|
1647
|
+
eventGroupingRefs,
|
|
1648
|
+
summaryGroupingRefs
|
|
1253
1649
|
});
|
|
1254
|
-
const abortAfter = (ms) => {
|
|
1255
|
-
const controller = new AbortController();
|
|
1256
|
-
const timer = setTimeout(() => controller.abort(), ms);
|
|
1257
|
-
timer.unref?.();
|
|
1258
|
-
return { signal: controller.signal, cancel: () => clearTimeout(timer) };
|
|
1259
|
-
};
|
|
1260
|
-
const requestTimeoutMs = options.requestTimeoutMs ?? 5e3;
|
|
1261
1650
|
const { body, gzip } = encodeJsonRequestBody(payload, options.gzipThresholdBytes);
|
|
1262
1651
|
const headers = {
|
|
1263
1652
|
Authorization: `Bearer ${options.projectApiKey}`,
|
|
@@ -1266,10 +1655,8 @@ var sendBatch = async (options) => {
|
|
|
1266
1655
|
};
|
|
1267
1656
|
if (gzip) headers["Content-Encoding"] = "gzip";
|
|
1268
1657
|
for (let attempt = 0; attempt <= options.maxRetries; attempt++) {
|
|
1269
|
-
if (
|
|
1658
|
+
if (signal.aborted) return result("failed", "aborted");
|
|
1270
1659
|
attempts++;
|
|
1271
|
-
const timeout = abortAfter(requestTimeoutMs);
|
|
1272
|
-
const signal = options.signal ? AbortSignal.any([options.signal, timeout.signal]) : timeout.signal;
|
|
1273
1660
|
try {
|
|
1274
1661
|
const response = await fetchUntilAborted(options.fetch, options.ingestUrl, {
|
|
1275
1662
|
method: "POST",
|
|
@@ -1277,13 +1664,22 @@ var sendBatch = async (options) => {
|
|
|
1277
1664
|
body,
|
|
1278
1665
|
signal
|
|
1279
1666
|
});
|
|
1280
|
-
if (response.ok)
|
|
1667
|
+
if (response.ok) {
|
|
1668
|
+
const refs = await readGroupingRefs(response);
|
|
1669
|
+
return result(
|
|
1670
|
+
"ok",
|
|
1671
|
+
null,
|
|
1672
|
+
response.status,
|
|
1673
|
+
refs.eventGroupingRefs,
|
|
1674
|
+
refs.summaryGroupingRefs
|
|
1675
|
+
);
|
|
1676
|
+
}
|
|
1281
1677
|
if (response.status === 429) {
|
|
1282
1678
|
rateLimitedResponses++;
|
|
1283
1679
|
if (attempt === options.maxRetries)
|
|
1284
1680
|
return result("failed", "rate_limited", response.status);
|
|
1285
1681
|
const wait = retryAfterMs(response) ?? backoffMs(attempt);
|
|
1286
|
-
await sleep(wait,
|
|
1682
|
+
await sleep(wait, signal);
|
|
1287
1683
|
continue;
|
|
1288
1684
|
}
|
|
1289
1685
|
if (response.status >= 400 && response.status < 500) {
|
|
@@ -1291,19 +1687,17 @@ var sendBatch = async (options) => {
|
|
|
1291
1687
|
}
|
|
1292
1688
|
serverErrorResponses++;
|
|
1293
1689
|
if (attempt === options.maxRetries) return result("failed", "server_error", response.status);
|
|
1294
|
-
await sleep(backoffMs(attempt),
|
|
1690
|
+
await sleep(backoffMs(attempt), signal);
|
|
1295
1691
|
} catch (error) {
|
|
1296
1692
|
if (signal.aborted || error instanceof Error && error.name === "AbortError") {
|
|
1297
1693
|
return result("failed", "aborted");
|
|
1298
1694
|
}
|
|
1299
1695
|
networkErrors++;
|
|
1300
1696
|
if (attempt === options.maxRetries) return result("failed", "network_error");
|
|
1301
|
-
await sleep(backoffMs(attempt),
|
|
1302
|
-
} finally {
|
|
1303
|
-
timeout.cancel();
|
|
1697
|
+
await sleep(backoffMs(attempt), signal);
|
|
1304
1698
|
}
|
|
1305
1699
|
}
|
|
1306
|
-
return result("failed",
|
|
1700
|
+
return result("failed", signal.aborted ? "aborted" : "network_error");
|
|
1307
1701
|
};
|
|
1308
1702
|
|
|
1309
1703
|
// src/transport/transport-queue.ts
|
|
@@ -1430,9 +1824,8 @@ var createTransport = (options) => {
|
|
|
1430
1824
|
const flushIntervalMs = options.flushIntervalMs ?? DEFAULTS2.flushIntervalMs;
|
|
1431
1825
|
const gzipThresholdBytes = options.gzipThresholdBytes ?? DEFAULTS2.gzipThresholdBytes;
|
|
1432
1826
|
const maxRetries = options.maxRetries ?? DEFAULTS2.maxRetries;
|
|
1433
|
-
const requestTimeoutMs = options.requestTimeoutMs ??
|
|
1827
|
+
const requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_INGEST_REQUEST_TIMEOUT_MS;
|
|
1434
1828
|
const fetchFn = options.fetch ?? defaultIngestFetch();
|
|
1435
|
-
const backgroundFetch = options.fetch ?? defaultIngestFetch({ unrefSockets: true });
|
|
1436
1829
|
const queue = createQueue(
|
|
1437
1830
|
options.maxQueueSize ?? DEFAULTS2.maxQueueSize,
|
|
1438
1831
|
options.maxQueueBytes ?? DEFAULTS2.maxQueueBytes
|
|
@@ -1460,6 +1853,7 @@ var createTransport = (options) => {
|
|
|
1460
1853
|
let flushAbort;
|
|
1461
1854
|
let flushAbortTimer;
|
|
1462
1855
|
let flushDeadlineMs = 0;
|
|
1856
|
+
let flushHoldsProcess = false;
|
|
1463
1857
|
let inFlightBytes = 0;
|
|
1464
1858
|
let retryBytes = 0;
|
|
1465
1859
|
const estimateItemsBytes = (items) => {
|
|
@@ -1474,23 +1868,30 @@ var createTransport = (options) => {
|
|
|
1474
1868
|
};
|
|
1475
1869
|
const setFlushDeadline = (timeoutMs, holdProcess = false) => {
|
|
1476
1870
|
const nextDeadline = timeoutMs > 0 ? Date.now() + timeoutMs : Number.POSITIVE_INFINITY;
|
|
1477
|
-
if (
|
|
1478
|
-
|
|
1479
|
-
if (!
|
|
1871
|
+
if (holdProcess) flushHoldsProcess = true;
|
|
1872
|
+
const shouldReplace = !flushAbort || nextDeadline < flushDeadlineMs;
|
|
1873
|
+
if (!shouldReplace && !holdProcess) return;
|
|
1874
|
+
if (shouldReplace) {
|
|
1875
|
+
flushDeadlineMs = nextDeadline;
|
|
1876
|
+
if (!flushAbort) flushAbort = new AbortController();
|
|
1877
|
+
}
|
|
1480
1878
|
if (flushAbortTimer) clearTimeout(flushAbortTimer);
|
|
1481
|
-
if (Number.isFinite(
|
|
1482
|
-
flushAbortTimer =
|
|
1483
|
-
|
|
1484
|
-
Math.max(0, nextDeadline - Date.now())
|
|
1485
|
-
);
|
|
1486
|
-
if (!holdProcess) flushAbortTimer.unref?.();
|
|
1879
|
+
if (!Number.isFinite(flushDeadlineMs)) {
|
|
1880
|
+
flushAbortTimer = void 0;
|
|
1881
|
+
return;
|
|
1487
1882
|
}
|
|
1883
|
+
flushAbortTimer = setTimeout(
|
|
1884
|
+
() => flushAbort?.abort(),
|
|
1885
|
+
Math.max(0, flushDeadlineMs - Date.now())
|
|
1886
|
+
);
|
|
1887
|
+
if (!flushHoldsProcess) flushAbortTimer.unref?.();
|
|
1488
1888
|
};
|
|
1489
1889
|
const clearFlushDeadline = () => {
|
|
1490
1890
|
if (flushAbortTimer) clearTimeout(flushAbortTimer);
|
|
1491
1891
|
flushAbortTimer = void 0;
|
|
1492
1892
|
flushAbort = void 0;
|
|
1493
1893
|
flushDeadlineMs = 0;
|
|
1894
|
+
flushHoldsProcess = false;
|
|
1494
1895
|
};
|
|
1495
1896
|
const schedule = () => {
|
|
1496
1897
|
if (timer || startTimer || !enabled || closed || shuttingDown2) return;
|
|
@@ -1529,11 +1930,8 @@ var createTransport = (options) => {
|
|
|
1529
1930
|
};
|
|
1530
1931
|
const whenAborted = (signal) => new Promise((_, reject) => {
|
|
1531
1932
|
const abort = () => reject(signal.reason ?? new Error("aborted"));
|
|
1532
|
-
if (signal.aborted) {
|
|
1533
|
-
abort();
|
|
1534
|
-
return;
|
|
1535
|
-
}
|
|
1536
1933
|
signal.addEventListener("abort", abort, { once: true });
|
|
1934
|
+
if (signal.aborted) abort();
|
|
1537
1935
|
});
|
|
1538
1936
|
const performFlush = async () => {
|
|
1539
1937
|
options.beforeFlush?.();
|
|
@@ -1587,15 +1985,15 @@ var createTransport = (options) => {
|
|
|
1587
1985
|
}
|
|
1588
1986
|
}
|
|
1589
1987
|
const retainOrDrop = (nextReplays, createdAt) => {
|
|
1988
|
+
inFlightBytes = 0;
|
|
1590
1989
|
if (nextReplays >= DEFAULTS2.maxBatchReplays || Date.now() - createdAt >= DEFAULTS2.maxRetryBatchAgeMs) {
|
|
1591
1990
|
batchesDropped++;
|
|
1592
1991
|
retryBatch = null;
|
|
1593
1992
|
retryBytes = 0;
|
|
1594
1993
|
} else {
|
|
1595
1994
|
retryBatch = { items: batch, idempotencyKey, createdAt, replays: nextReplays };
|
|
1596
|
-
retryBytes =
|
|
1995
|
+
retryBytes = estimateItemsBytes(batch);
|
|
1597
1996
|
}
|
|
1598
|
-
inFlightBytes = 0;
|
|
1599
1997
|
syncReservedBytes();
|
|
1600
1998
|
};
|
|
1601
1999
|
if (controller.signal.aborted) {
|
|
@@ -1610,10 +2008,10 @@ var createTransport = (options) => {
|
|
|
1610
2008
|
idempotencyKey,
|
|
1611
2009
|
sdkVersion: options.sdkVersion,
|
|
1612
2010
|
sdkName: options.sdkName,
|
|
2011
|
+
scrubPii: options.scrubPii,
|
|
1613
2012
|
gzipThresholdBytes,
|
|
1614
2013
|
maxRetries: shuttingDown2 ? 0 : maxRetries,
|
|
1615
|
-
|
|
1616
|
-
fetch: shuttingDown2 ? fetchFn : backgroundFetch,
|
|
2014
|
+
fetch: fetchFn,
|
|
1617
2015
|
signal: controller.signal
|
|
1618
2016
|
});
|
|
1619
2017
|
sendAttempts += result.attempts;
|
|
@@ -1622,8 +2020,21 @@ var createTransport = (options) => {
|
|
|
1622
2020
|
rateLimitedResponses += result.rateLimitedResponses;
|
|
1623
2021
|
serverErrorResponses += result.serverErrorResponses;
|
|
1624
2022
|
if (result.aborted) flushTimeouts++;
|
|
1625
|
-
if (result.outcome === "ok")
|
|
1626
|
-
|
|
2023
|
+
if (result.outcome === "ok") {
|
|
2024
|
+
batchesSucceeded++;
|
|
2025
|
+
const eventBurstKeys = [];
|
|
2026
|
+
const summaryBurstKeys = [];
|
|
2027
|
+
for (const item of batch) {
|
|
2028
|
+
if (item.kind === "event") eventBurstKeys.push(item.burstKey);
|
|
2029
|
+
else summaryBurstKeys.push(item.burstKey);
|
|
2030
|
+
}
|
|
2031
|
+
options.onGroupingRefs?.({
|
|
2032
|
+
eventBurstKeys,
|
|
2033
|
+
summaryBurstKeys,
|
|
2034
|
+
eventGroupingRefs: result.eventGroupingRefs,
|
|
2035
|
+
summaryGroupingRefs: result.summaryGroupingRefs
|
|
2036
|
+
});
|
|
2037
|
+
} else {
|
|
1627
2038
|
lastFailureKind = result.failureKind;
|
|
1628
2039
|
lastFailureStatusCode = result.statusCode;
|
|
1629
2040
|
if (result.outcome === "dropped") batchesDropped++;
|
|
@@ -1679,15 +2090,15 @@ var createTransport = (options) => {
|
|
|
1679
2090
|
}
|
|
1680
2091
|
await startFlushWorker();
|
|
1681
2092
|
};
|
|
1682
|
-
const enqueue = (event, priority = "first", rawFrames = [], encodedBytes) => {
|
|
2093
|
+
const enqueue = (event, priority = "first", rawFrames = [], encodedBytes, burstKey) => {
|
|
1683
2094
|
if (!enabled || closed) return;
|
|
1684
|
-
queue.enqueue({ kind: "event", event, priority, rawFrames, encodedBytes });
|
|
2095
|
+
queue.enqueue({ kind: "event", event, priority, rawFrames, encodedBytes, burstKey });
|
|
1685
2096
|
schedule();
|
|
1686
2097
|
if (queue.size() >= batchSize) kickBackgroundFlush();
|
|
1687
2098
|
};
|
|
1688
|
-
const enqueueSummary = (summary, rawFrames = []) => {
|
|
2099
|
+
const enqueueSummary = (summary, rawFrames = [], burstKey) => {
|
|
1689
2100
|
if (!enabled || closed) return;
|
|
1690
|
-
queue.enqueue({ kind: "summary", summary, priority: "summary", rawFrames });
|
|
2101
|
+
queue.enqueue({ kind: "summary", summary, priority: "summary", rawFrames, burstKey });
|
|
1691
2102
|
schedule();
|
|
1692
2103
|
if (queue.size() >= batchSize) kickBackgroundFlush();
|
|
1693
2104
|
};
|
|
@@ -1730,21 +2141,10 @@ var createTransport = (options) => {
|
|
|
1730
2141
|
stopTimer();
|
|
1731
2142
|
unregisterSignals();
|
|
1732
2143
|
shuttingDown2 = true;
|
|
1733
|
-
await
|
|
1734
|
-
const timer2 = setTimeout(resolve4, DEFAULTS2.shutdownFlushMs + 250);
|
|
1735
|
-
void flush(DEFAULTS2.shutdownFlushMs).then(
|
|
1736
|
-
() => {
|
|
1737
|
-
clearTimeout(timer2);
|
|
1738
|
-
resolve4();
|
|
1739
|
-
},
|
|
1740
|
-
(error) => {
|
|
1741
|
-
clearTimeout(timer2);
|
|
1742
|
-
reject(error);
|
|
1743
|
-
}
|
|
1744
|
-
);
|
|
2144
|
+
await flush(DEFAULTS2.shutdownFlushMs).catch(() => {
|
|
1745
2145
|
});
|
|
1746
|
-
dropRemainingOnExit();
|
|
1747
2146
|
closed = true;
|
|
2147
|
+
dropRemainingOnExit();
|
|
1748
2148
|
queue.clear();
|
|
1749
2149
|
retryBatch = null;
|
|
1750
2150
|
};
|
|
@@ -1937,6 +2337,7 @@ var createClient = (options, hooks = {}) => {
|
|
|
1937
2337
|
const activation = resolveClientActivation(options);
|
|
1938
2338
|
if (!activation.enabled) return noopClient();
|
|
1939
2339
|
const { ingestToken, projectApiKey, apiUrl, release } = activation;
|
|
2340
|
+
const redactEnvSecrets = createEnvSecretMatcher().redact;
|
|
1940
2341
|
const environment = options.environment;
|
|
1941
2342
|
const { ingestUrl, deployUrl } = resolveEndpointUrls(apiUrl);
|
|
1942
2343
|
const repoRoot = resolveRepoRoot(options);
|
|
@@ -1965,6 +2366,7 @@ var createClient = (options, hooks = {}) => {
|
|
|
1965
2366
|
return pending;
|
|
1966
2367
|
};
|
|
1967
2368
|
const suppression = createSuppression();
|
|
2369
|
+
const groupingRefs = createGroupingRefCache();
|
|
1968
2370
|
let enqueuePendingSummaries = () => {
|
|
1969
2371
|
};
|
|
1970
2372
|
const transport = createTransport({
|
|
@@ -1975,7 +2377,23 @@ var createClient = (options, hooks = {}) => {
|
|
|
1975
2377
|
installSignalHandlers: hooks.installTransportSignalHandlers,
|
|
1976
2378
|
sdkVersion: hooks.sdkVersion ?? SDK_VERSION,
|
|
1977
2379
|
sdkName: hooks.sdkName ?? SDK_NAME,
|
|
2380
|
+
scrubPii: options.scrubPII !== false,
|
|
1978
2381
|
beforeFlush: () => enqueuePendingSummaries(),
|
|
2382
|
+
onGroupingRefs: ({
|
|
2383
|
+
eventBurstKeys,
|
|
2384
|
+
summaryBurstKeys,
|
|
2385
|
+
eventGroupingRefs,
|
|
2386
|
+
summaryGroupingRefs
|
|
2387
|
+
}) => {
|
|
2388
|
+
for (const [index, burstKey] of eventBurstKeys.entries()) {
|
|
2389
|
+
const groupingRef = eventGroupingRefs[index];
|
|
2390
|
+
if (burstKey && groupingRef) groupingRefs.set(burstKey, groupingRef);
|
|
2391
|
+
}
|
|
2392
|
+
for (const [index, burstKey] of summaryBurstKeys.entries()) {
|
|
2393
|
+
const groupingRef = summaryGroupingRefs[index];
|
|
2394
|
+
if (burstKey && groupingRef) groupingRefs.set(burstKey, groupingRef);
|
|
2395
|
+
}
|
|
2396
|
+
},
|
|
1979
2397
|
prepareEvent: async ({ event, rawFrames }) => {
|
|
1980
2398
|
const prepared = await resolveStack(rawFrames);
|
|
1981
2399
|
return withResolvedFrames(event, prepared.frames, prepared.resolution);
|
|
@@ -2008,6 +2426,17 @@ var createClient = (options, hooks = {}) => {
|
|
|
2008
2426
|
resolution: "none",
|
|
2009
2427
|
request: context?.request
|
|
2010
2428
|
});
|
|
2429
|
+
event.message = redactEnvSecrets(event.message);
|
|
2430
|
+
const burstKey = computeBurstKey(
|
|
2431
|
+
event.type,
|
|
2432
|
+
event.message,
|
|
2433
|
+
event.code,
|
|
2434
|
+
frames,
|
|
2435
|
+
context?.request?.route,
|
|
2436
|
+
context?.request?.method
|
|
2437
|
+
);
|
|
2438
|
+
const groupingRef = groupingRefs.getOrCreate(burstKey);
|
|
2439
|
+
event.grouping_ref = groupingRef;
|
|
2011
2440
|
const decision = suppression.decide({
|
|
2012
2441
|
errorType: event.type,
|
|
2013
2442
|
message: event.message,
|
|
@@ -2017,7 +2446,8 @@ var createClient = (options, hooks = {}) => {
|
|
|
2017
2446
|
code: event.code,
|
|
2018
2447
|
environment,
|
|
2019
2448
|
release,
|
|
2020
|
-
route: context?.request?.route
|
|
2449
|
+
route: context?.request?.route,
|
|
2450
|
+
method: context?.request?.method
|
|
2021
2451
|
});
|
|
2022
2452
|
if (decision.action !== "send") return;
|
|
2023
2453
|
const runtimeState = resolveRuntimeEvidence(context, hooks);
|
|
@@ -2028,13 +2458,15 @@ var createClient = (options, hooks = {}) => {
|
|
|
2028
2458
|
} catch {
|
|
2029
2459
|
encodedBytes = void 0;
|
|
2030
2460
|
}
|
|
2031
|
-
transport.enqueue(event, decision.priority, rawFrames, encodedBytes);
|
|
2461
|
+
transport.enqueue(event, decision.priority, rawFrames, encodedBytes, burstKey);
|
|
2032
2462
|
} catch {
|
|
2033
2463
|
}
|
|
2034
2464
|
};
|
|
2035
2465
|
enqueuePendingSummaries = () => {
|
|
2036
|
-
for (const { summary, rawFrames } of suppression.drainSummaries()) {
|
|
2037
|
-
|
|
2466
|
+
for (const { summary, rawFrames, burstKey } of suppression.drainSummaries()) {
|
|
2467
|
+
const groupingRef = groupingRefs.getOrCreate(burstKey);
|
|
2468
|
+
summary.grouping_ref = groupingRef;
|
|
2469
|
+
transport.enqueueSummary(summary, rawFrames, burstKey);
|
|
2038
2470
|
}
|
|
2039
2471
|
};
|
|
2040
2472
|
const flush = async (timeoutMs) => {
|
|
@@ -2139,169 +2571,6 @@ var isRasputinTaggedValue = (value) => {
|
|
|
2139
2571
|
};
|
|
2140
2572
|
var rasputinTagKind = (value) => isRasputinTaggedValue(value) ? value[1] : void 0;
|
|
2141
2573
|
|
|
2142
|
-
// src/derivation/sensitive-property-name.ts
|
|
2143
|
-
var DEFAULT_SENSITIVE_PROPERTY_NAMES = [
|
|
2144
|
-
"password",
|
|
2145
|
-
"passwd",
|
|
2146
|
-
"pwd",
|
|
2147
|
-
"passphrase",
|
|
2148
|
-
"token",
|
|
2149
|
-
"accesstoken",
|
|
2150
|
-
"refreshtoken",
|
|
2151
|
-
"sessiontoken",
|
|
2152
|
-
"authorization",
|
|
2153
|
-
"auth",
|
|
2154
|
-
"bearer",
|
|
2155
|
-
"cookie",
|
|
2156
|
-
"cookies",
|
|
2157
|
-
"signedcookies",
|
|
2158
|
-
"setcookie",
|
|
2159
|
-
"secret",
|
|
2160
|
-
"secrets",
|
|
2161
|
-
"clientsecret",
|
|
2162
|
-
"apikey",
|
|
2163
|
-
"xapikey",
|
|
2164
|
-
"credential",
|
|
2165
|
-
"credentials",
|
|
2166
|
-
"privatekey",
|
|
2167
|
-
"privkey",
|
|
2168
|
-
"pem",
|
|
2169
|
-
"jwt",
|
|
2170
|
-
"otp",
|
|
2171
|
-
"totp",
|
|
2172
|
-
"pin",
|
|
2173
|
-
"mfacode",
|
|
2174
|
-
"sessionid",
|
|
2175
|
-
"sid",
|
|
2176
|
-
"databaseurl",
|
|
2177
|
-
"connectionstring",
|
|
2178
|
-
"dsn",
|
|
2179
|
-
"mongouri",
|
|
2180
|
-
"redisurl",
|
|
2181
|
-
"signingkey",
|
|
2182
|
-
"encryptionkey",
|
|
2183
|
-
"cvv",
|
|
2184
|
-
"cvc",
|
|
2185
|
-
"cardnumber",
|
|
2186
|
-
"ssn",
|
|
2187
|
-
"creditcard",
|
|
2188
|
-
"securitycode",
|
|
2189
|
-
"twofactorcode",
|
|
2190
|
-
"masterkey",
|
|
2191
|
-
"servicerolekey",
|
|
2192
|
-
"stripekey",
|
|
2193
|
-
"rawheaders"
|
|
2194
|
-
];
|
|
2195
|
-
var DEFAULT_SENSITIVE_PROPERTY_NAME_SET = new Set(DEFAULT_SENSITIVE_PROPERTY_NAMES);
|
|
2196
|
-
var SENSITIVE_SEGMENTS = /* @__PURE__ */ new Set([
|
|
2197
|
-
"password",
|
|
2198
|
-
"passwd",
|
|
2199
|
-
"pwd",
|
|
2200
|
-
"passphrase",
|
|
2201
|
-
"token",
|
|
2202
|
-
"secret",
|
|
2203
|
-
"cookie",
|
|
2204
|
-
"cookies",
|
|
2205
|
-
"authorization",
|
|
2206
|
-
"auth",
|
|
2207
|
-
"bearer",
|
|
2208
|
-
"credential",
|
|
2209
|
-
"credentials",
|
|
2210
|
-
"jwt",
|
|
2211
|
-
"otp",
|
|
2212
|
-
"totp",
|
|
2213
|
-
"pin",
|
|
2214
|
-
"sid",
|
|
2215
|
-
"dsn",
|
|
2216
|
-
"pem",
|
|
2217
|
-
"privkey",
|
|
2218
|
-
"cvv",
|
|
2219
|
-
"cvc",
|
|
2220
|
-
"ssn",
|
|
2221
|
-
"secrets"
|
|
2222
|
-
]);
|
|
2223
|
-
var SENSITIVE_SUFFIXES = [
|
|
2224
|
-
"password",
|
|
2225
|
-
"passwd",
|
|
2226
|
-
"token",
|
|
2227
|
-
"secret",
|
|
2228
|
-
"apikey",
|
|
2229
|
-
"privatekey",
|
|
2230
|
-
"credential",
|
|
2231
|
-
"credentials",
|
|
2232
|
-
"cookie"
|
|
2233
|
-
];
|
|
2234
|
-
var compactKey = (key) => {
|
|
2235
|
-
let compacted = "";
|
|
2236
|
-
for (let index = 0; index < key.length; index++) {
|
|
2237
|
-
const code = key.charCodeAt(index);
|
|
2238
|
-
if (code === 45 || code === 46 || code === 95) continue;
|
|
2239
|
-
compacted += code >= 65 && code <= 90 ? String.fromCharCode(code + 32) : key[index];
|
|
2240
|
-
}
|
|
2241
|
-
return compacted;
|
|
2242
|
-
};
|
|
2243
|
-
var stripTrailingDigits = (value) => {
|
|
2244
|
-
let end = value.length;
|
|
2245
|
-
while (end > 0) {
|
|
2246
|
-
const code = value.charCodeAt(end - 1);
|
|
2247
|
-
if (code < 48 || code > 57) break;
|
|
2248
|
-
end--;
|
|
2249
|
-
}
|
|
2250
|
-
return end === 0 ? value : value.slice(0, end);
|
|
2251
|
-
};
|
|
2252
|
-
var segmentsOf = (key) => {
|
|
2253
|
-
const segments = [];
|
|
2254
|
-
let current = "";
|
|
2255
|
-
for (let index = 0; index < key.length; index++) {
|
|
2256
|
-
const char = key[index] ?? "";
|
|
2257
|
-
const code = key.charCodeAt(index);
|
|
2258
|
-
if (code === 45 || code === 46 || code === 95) {
|
|
2259
|
-
if (current) segments.push(current.toLowerCase());
|
|
2260
|
-
current = "";
|
|
2261
|
-
continue;
|
|
2262
|
-
}
|
|
2263
|
-
if (current && code >= 65 && code <= 90) {
|
|
2264
|
-
const prev = current.charCodeAt(current.length - 1);
|
|
2265
|
-
const prevIsLower = prev >= 97 && prev <= 122;
|
|
2266
|
-
const next = key.charCodeAt(index + 1);
|
|
2267
|
-
const nextIsLower = next >= 97 && next <= 122;
|
|
2268
|
-
if (prevIsLower || nextIsLower) {
|
|
2269
|
-
segments.push(current.toLowerCase());
|
|
2270
|
-
current = char;
|
|
2271
|
-
continue;
|
|
2272
|
-
}
|
|
2273
|
-
}
|
|
2274
|
-
current += char;
|
|
2275
|
-
}
|
|
2276
|
-
if (current) segments.push(current.toLowerCase());
|
|
2277
|
-
return segments;
|
|
2278
|
-
};
|
|
2279
|
-
var adjacentPairsSensitive = (left, right) => left === "api" && right === "key" || left === "private" && right === "key" || left === "client" && right === "secret" || left === "set" && right === "cookie" || left === "database" && right === "url" || left === "connection" && right === "string" || left === "mongo" && (right === "uri" || right === "url") || left === "mongodb" && (right === "uri" || right === "url") || left === "redis" && (right === "uri" || right === "url") || left === "postgres" && (right === "uri" || right === "url") || left === "database" && right === "uri" || left === "signing" && right === "key" || left === "master" && right === "key" || left === "stripe" && right === "key" || left === "service" && right === "role" || left === "security" && right === "code" || left === "two" && right === "factor" || left === "encryption" && right === "key" || left === "session" && (right === "id" || right === "key" || right === "token") || left === "card" && right === "number" || left === "mfa" && right === "code";
|
|
2280
|
-
var defaultSensitivePropertyNames = () => DEFAULT_SENSITIVE_PROPERTY_NAME_SET;
|
|
2281
|
-
var propertyNameIsSensitive = (key) => {
|
|
2282
|
-
const compacted = compactKey(key);
|
|
2283
|
-
const compactForms = [compacted, stripTrailingDigits(compacted)].filter(
|
|
2284
|
-
(value, index, values) => value.length > 0 && values.indexOf(value) === index
|
|
2285
|
-
);
|
|
2286
|
-
for (const form of compactForms) {
|
|
2287
|
-
if (DEFAULT_SENSITIVE_PROPERTY_NAME_SET.has(form)) return true;
|
|
2288
|
-
for (const suffix of SENSITIVE_SUFFIXES) {
|
|
2289
|
-
if (form.endsWith(suffix)) return true;
|
|
2290
|
-
}
|
|
2291
|
-
if (form.includes("apikey") || form.includes("xapikey")) return true;
|
|
2292
|
-
}
|
|
2293
|
-
const segments = segmentsOf(key).map((segment) => stripTrailingDigits(segment) || segment);
|
|
2294
|
-
for (const segment of segments) {
|
|
2295
|
-
if (SENSITIVE_SEGMENTS.has(segment)) return true;
|
|
2296
|
-
}
|
|
2297
|
-
for (let index = 0; index < segments.length - 1; index++) {
|
|
2298
|
-
const left = segments[index];
|
|
2299
|
-
const right = segments[index + 1];
|
|
2300
|
-
if (left && right && adjacentPairsSensitive(left, right)) return true;
|
|
2301
|
-
}
|
|
2302
|
-
return false;
|
|
2303
|
-
};
|
|
2304
|
-
|
|
2305
2574
|
// src/instrumentation-manifest/instrumentation-manifest-types.ts
|
|
2306
2575
|
var INSTRUMENTATION_MANIFEST_SCHEMA_VERSION = 3;
|
|
2307
2576
|
|
|
@@ -2333,9 +2602,12 @@ var uploadInstrumentationManifest = async (options) => {
|
|
|
2333
2602
|
};
|
|
2334
2603
|
export {
|
|
2335
2604
|
INSTRUMENTATION_MANIFEST_SCHEMA_VERSION,
|
|
2605
|
+
MAX_ENV_SECRET_NEEDLE_LENGTH,
|
|
2606
|
+
RASPUTIN_REDACTED,
|
|
2336
2607
|
RASPUTIN_WIRE_TAG,
|
|
2337
2608
|
announceDeploy,
|
|
2338
2609
|
createClient,
|
|
2610
|
+
createEnvSecretMatcher,
|
|
2339
2611
|
createIngestEvent,
|
|
2340
2612
|
createSuppression,
|
|
2341
2613
|
createTransport,
|