Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | 1x | import { config, define, t, type ConfigFromDefs } from '@devmoods/config';
import { type LoggerAdapter } from '@devmoods/observability';
import * as Sentry from '@sentry/node';
import { type ErrorRequestHandler } from 'express';
declare module '@devmoods/config' {
interface Config extends ConfigFromDefs<typeof sentryConfig> {}
}
export const sentryConfig = define({
SENTRY_DSN: t.string(),
SENTRY_TRACES_SAMPLE_RATE: t.number(0.3),
SENTRY_PROFILES_SAMPLE_RATE: t.number(0.3),
SENTRY_EVENT_LOOP_THRESHOLD: t.number(750),
});
export type { Sentry };
export interface SentryOptions extends Sentry.NodeOptions {}
/* c8 ignore start */
export async function initSentry(options: SentryOptions = {}) {
Sentry.init(await sentryOptions(options));
}
export async function closeSentry() {
await Sentry.close(5000);
}
/* c8 ignore end */
/**
* Safely imports native Sentry integrations if available.
* Returns null if native modules are not available (e.g., on unsupported Node.js versions).
*/
async function getNativeIntegrations() {
const integrations = [];
/* v8 ignore next -- @preserve */
try {
const { nodeProfilingIntegration } = await import('@sentry/profiling-node');
integrations.push(nodeProfilingIntegration());
} catch {
// Native profiling integration not available
}
/* v8 ignore next -- @preserve */
try {
const { eventLoopBlockIntegration } = await import('@sentry/node-native');
integrations.push(
eventLoopBlockIntegration({
threshold: config.SENTRY_EVENT_LOOP_THRESHOLD,
}),
);
} catch {
// Native event loop integration not available
}
return integrations;
}
export async function sentryOptions(
options: SentryOptions = {},
): Promise<SentryOptions> {
const nativeIntegrations = await getNativeIntegrations();
return {
dsn: config.SENTRY_DSN,
tracesSampleRate: config.SENTRY_TRACES_SAMPLE_RATE,
profileSessionSampleRate: config.SENTRY_PROFILES_SAMPLE_RATE,
integrations: nativeIntegrations,
enableLogs: true,
...options,
};
}
export function sentryErrorHandler(
options: Sentry.NodeOptions = {},
): ErrorRequestHandler {
return Sentry.expressErrorHandler({
shouldHandleError() {
return process.env.NODE_ENV === 'production';
},
...options,
}) as unknown as ErrorRequestHandler;
}
export class SentryLoggerAdapter implements LoggerAdapter {
constructor() {}
captureError(error: Error | null, attributes?: Record<string, any>) {
/* v8 ignore next -- @preserve */
if (error == null) {
return;
}
/* v8 ignore next -- @preserve */
if (Sentry.isInitialized()) {
Sentry.captureException(error, {
tags: attributes,
});
}
}
write(log: Record<string, any>) {
const { message, ...attributes } = log;
/* v8 ignore next -- @preserve */
if (Sentry.isInitialized()) {
const fn = log.level as
| 'trace'
| 'debug'
| 'info'
| 'warn'
| 'error'
| 'fatal';
Sentry.logger[fn](message, attributes);
}
return true;
}
}
|