Repository navigation
Expand file tree
/
Copy pathobservability.ts
More file actions
57 lines (53 loc) · 2.06 KB
/
Copy pathobservability.ts
File metadata and controls
57 lines (53 loc) · 2.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import { redactCheckInSecrets } from "./checkin-secrets.js";
import { randomUUID } from "node:crypto";
import type { FastifyInstance } from "fastify";
import { safeSanitizeSentryEvent, sanitizeSentryBreadcrumb } from "./sentry-privacy.js";
import { sentryPrivacyOptions } from "./sentry-policy.js";
let sentryInitialized = false;
/**
* Optional Sentry (`SENTRY_DSN`). Skipped in tests and when DSN is unset.
* Call from `index.ts` before dynamically importing `./app.js` so OpenTelemetry
* instrumentation can patch http, database clients, etc. Do not rely on calling this from `createApp()`.
*/
export async function initSentryIfConfigured(): Promise<void> {
if (process.env.NODE_ENV === "test") return;
const dsn = process.env.SENTRY_DSN?.trim();
if (!dsn || sentryInitialized) return;
const Sentry = await import("@sentry/node");
Sentry.init({
dsn,
environment: process.env.NODE_ENV ?? "development",
...sentryPrivacyOptions,
beforeBreadcrumb: sanitizeSentryBreadcrumb,
beforeSend(event) {
return safeSanitizeSentryEvent(event);
},
integrations(integrations) {
return integrations.filter((integration) => !integration.name.startsWith("Replay")).map((integration) =>
integration.name === "Http"
? Sentry.httpIntegration({ maxIncomingRequestBodySize: "none" })
: integration
);
},
});
sentryInitialized = true;
}
/** Request id + error logging + optional Sentry capture on `onError`. */
export function registerObservabilityHooks(app: FastifyInstance): void {
app.addHook("onError", async (request, _reply, error) => {
request.log.error(
{ err: error, reqId: request.id, url: redactCheckInSecrets(request.url), method: request.method },
redactCheckInSecrets(error.message)
);
if (process.env.NODE_ENV === "test" || !process.env.SENTRY_DSN?.trim()) return;
try {
const Sentry = await import("@sentry/node");
Sentry.captureException(error);
} catch {
/* optional dep failed to load */
}
});
}
export function genReqId(): string {
return randomUUID();
}