Merge branch 'main' of github.com:makerkit/next-supabase-saas-kit-turbo
This commit is contained in:
@@ -13,4 +13,4 @@ NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
|
||||
|
||||
# MONITORING
|
||||
NEXT_PUBLIC_MONITORING_PROVIDER=
|
||||
MONITORING_INSTRUMENTATION_ENABLED=false
|
||||
ENABLE_MONITORING_INSTRUMENTATION=false
|
||||
|
||||
@@ -2,18 +2,12 @@
|
||||
* This file is used to register monitoring instrumentation
|
||||
* for your Next.js application.
|
||||
*/
|
||||
|
||||
export async function register() {
|
||||
// only run in nodejs runtime
|
||||
if (
|
||||
process.env.NEXT_RUNTIME === 'nodejs' &&
|
||||
process.env.MONITORING_INSTRUMENTATION_ENABLED === 'true'
|
||||
) {
|
||||
const { registerMonitoringInstrumentation } = await import(
|
||||
'@kit/monitoring/instrumentation'
|
||||
);
|
||||
const { registerMonitoringInstrumentation } = await import(
|
||||
'@kit/monitoring/instrumentation'
|
||||
);
|
||||
|
||||
// Register monitoring instrumentation based on the MONITORING_PROVIDER environment variable.
|
||||
return registerMonitoringInstrumentation();
|
||||
}
|
||||
// Register monitoring instrumentation
|
||||
// based on the MONITORING_PROVIDER environment variable.
|
||||
await registerMonitoringInstrumentation();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ Please set the following environment variable to your preferred monitoring provi
|
||||
|
||||
```
|
||||
NEXT_PUBLIC_MONITORING_PROVIDER=
|
||||
MONITORING_INSTRUMENTATION_ENABLED=true
|
||||
ENABLE_MONITORING_INSTRUMENTATION=true
|
||||
```
|
||||
|
||||
## Available Providers
|
||||
@@ -32,8 +32,8 @@ NEXT_PUBLIC_MONITORING_PROVIDER=sentry
|
||||
|
||||
## Instrumentation
|
||||
|
||||
To enable instrumentation, set the `MONITORING_INSTRUMENTATION_ENABLED` environment variable to `true`.
|
||||
To enable instrumentation, set the `ENABLE_MONITORING_INSTRUMENTATION` environment variable to `true`.
|
||||
|
||||
```
|
||||
MONITORING_INSTRUMENTATION_ENABLED=true
|
||||
ENABLE_MONITORING_INSTRUMENTATION=true
|
||||
```
|
||||
@@ -28,11 +28,9 @@ export async function getServerMonitoringService() {
|
||||
}
|
||||
|
||||
case InstrumentationProvider.Sentry: {
|
||||
const { SentryServerMonitoringService } = await import(
|
||||
'@kit/sentry/server'
|
||||
);
|
||||
const { SentryMonitoringService } = await import('@kit/sentry');
|
||||
|
||||
return new SentryServerMonitoringService();
|
||||
return new SentryMonitoringService();
|
||||
}
|
||||
|
||||
default: {
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
* Please set the MONITORING_PROVIDER environment variable to 'baselime' to register Baselime instrumentation.
|
||||
*/
|
||||
export async function registerInstrumentation() {
|
||||
if (!process.env.ENABLE_MONITORING_INSTRUMENTATION) {
|
||||
return;
|
||||
}
|
||||
|
||||
const serviceName = process.env.INSTRUMENTATION_SERVICE_NAME;
|
||||
|
||||
if (!serviceName) {
|
||||
@@ -14,19 +18,20 @@ export async function registerInstrumentation() {
|
||||
`);
|
||||
}
|
||||
|
||||
const { BaselimeSDK, BetterHttpInstrumentation, VercelPlugin } = await import(
|
||||
'@baselime/node-opentelemetry'
|
||||
);
|
||||
if (process.env.NEXT_RUNTIME === 'nodejs') {
|
||||
const { BaselimeSDK, BetterHttpInstrumentation, VercelPlugin } =
|
||||
await import('@baselime/node-opentelemetry');
|
||||
|
||||
const sdk = new BaselimeSDK({
|
||||
serverless: true,
|
||||
service: serviceName,
|
||||
instrumentations: [
|
||||
new BetterHttpInstrumentation({
|
||||
plugins: [new VercelPlugin()],
|
||||
}),
|
||||
],
|
||||
});
|
||||
const sdk = new BaselimeSDK({
|
||||
serverless: true,
|
||||
service: serviceName,
|
||||
instrumentations: [
|
||||
new BetterHttpInstrumentation({
|
||||
plugins: [new VercelPlugin()],
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
sdk.start();
|
||||
sdk.start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,10 @@
|
||||
"prettier": "@kit/prettier-config",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./server": "./src/server.ts",
|
||||
"./provider": "./src/components/provider.tsx",
|
||||
"./instrumentation": "./src/instrumentation.ts",
|
||||
"./config/client": "./src/config/sentry.client.config.ts",
|
||||
"./config/server": "./src/config/sentry.server.config.ts",
|
||||
"./config/edge": "./src/config/sentry.edge.config.ts"
|
||||
"./config/client": "./src/sentry.client.config.ts",
|
||||
"./config/server": "./src/sentry.client.server.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@opentelemetry/exporter-jaeger": "1.24.1",
|
||||
|
||||
@@ -2,14 +2,14 @@ import { useRef } from 'react';
|
||||
|
||||
import { MonitoringContext } from '@kit/monitoring-core';
|
||||
|
||||
import { SentryServerMonitoringService } from '../services/sentry-server-monitoring.service';
|
||||
import { SentryMonitoringService } from '../services/sentry-monitoring.service';
|
||||
|
||||
export function SentryProvider({ children }: React.PropsWithChildren) {
|
||||
return <MonitoringProvider>{children}</MonitoringProvider>;
|
||||
}
|
||||
|
||||
function MonitoringProvider(props: React.PropsWithChildren) {
|
||||
const service = useRef(new SentryServerMonitoringService());
|
||||
const service = useRef(new SentryMonitoringService());
|
||||
|
||||
return (
|
||||
<MonitoringContext.Provider value={service.current}>
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
|
||||
Sentry.init({
|
||||
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
||||
// Replay may only be enabled for the client-side
|
||||
integrations: [Sentry.replayIntegration()],
|
||||
|
||||
// Set tracesSampleRate to 1.0 to capture 100%
|
||||
// of transactions for performance monitoring.
|
||||
// We recommend adjusting this value in production
|
||||
tracesSampleRate: 1.0,
|
||||
|
||||
// Capture Replay for 10% of all sessions,
|
||||
// plus for 100% of sessions with an error
|
||||
replaysSessionSampleRate: 0.1,
|
||||
replaysOnErrorSampleRate: 1.0,
|
||||
|
||||
// ...
|
||||
|
||||
// Note: if you want to override the automatic release value, do not set a
|
||||
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
|
||||
// that it will also get attached to your source maps
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
|
||||
Sentry.init({
|
||||
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
||||
tracesSampleRate: 1.0,
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
|
||||
Sentry.init({
|
||||
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
||||
tracesSampleRate: 1.0,
|
||||
});
|
||||
1
packages/monitoring/sentry/src/index.ts
Normal file
1
packages/monitoring/sentry/src/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './services/sentry-monitoring.service';
|
||||
@@ -5,32 +5,46 @@
|
||||
* Please set the MONITORING_PROVIDER environment variable to 'sentry' to register Sentry instrumentation.
|
||||
*/
|
||||
export async function registerInstrumentation() {
|
||||
const serviceName = process.env.INSTRUMENTATION_SERVICE_NAME;
|
||||
const { initializeSentryServerClient } = await import(
|
||||
'./sentry.server.config'
|
||||
);
|
||||
|
||||
if (!serviceName) {
|
||||
throw new Error(
|
||||
`You have set the Sentry instrumentation provider, but have not set the INSTRUMENTATION_SERVICE_NAME environment variable. Please set the INSTRUMENTATION_SERVICE_NAME environment variable.`,
|
||||
);
|
||||
// initialize the Sentry client in the server
|
||||
void initializeSentryServerClient();
|
||||
|
||||
if (!process.env.ENABLE_MONITORING_INSTRUMENTATION) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { Resource } = await import('@opentelemetry/resources');
|
||||
const { NodeSDK } = await import('@opentelemetry/sdk-node');
|
||||
// make sure the instrumentation is only run in a Node.js environment
|
||||
if (process.env.NEXT_RUNTIME === 'nodejs') {
|
||||
const serviceName = process.env.INSTRUMENTATION_SERVICE_NAME;
|
||||
|
||||
const { SEMRESATTRS_SERVICE_NAME } = await import(
|
||||
'@opentelemetry/semantic-conventions'
|
||||
);
|
||||
if (!serviceName) {
|
||||
throw new Error(
|
||||
`You have set the Sentry instrumentation provider, but have not set the INSTRUMENTATION_SERVICE_NAME environment variable. Please set the INSTRUMENTATION_SERVICE_NAME environment variable.`,
|
||||
);
|
||||
}
|
||||
|
||||
const { SentrySpanProcessor, SentryPropagator } = await import(
|
||||
'@sentry/opentelemetry-node'
|
||||
);
|
||||
const { Resource } = await import('@opentelemetry/resources');
|
||||
const { NodeSDK } = await import('@opentelemetry/sdk-node');
|
||||
|
||||
const sdk = new NodeSDK({
|
||||
resource: new Resource({
|
||||
[SEMRESATTRS_SERVICE_NAME]: serviceName,
|
||||
}),
|
||||
spanProcessors: [new SentrySpanProcessor()],
|
||||
textMapPropagator: new SentryPropagator(),
|
||||
});
|
||||
const { SEMRESATTRS_SERVICE_NAME } = await import(
|
||||
'@opentelemetry/semantic-conventions'
|
||||
);
|
||||
|
||||
sdk.start();
|
||||
const { SentrySpanProcessor, SentryPropagator } = await import(
|
||||
'@sentry/opentelemetry-node'
|
||||
);
|
||||
|
||||
const sdk = new NodeSDK({
|
||||
resource: new Resource({
|
||||
[SEMRESATTRS_SERVICE_NAME]: serviceName,
|
||||
}),
|
||||
spanProcessors: [new SentrySpanProcessor()],
|
||||
textMapPropagator: new SentryPropagator(),
|
||||
});
|
||||
|
||||
sdk.start();
|
||||
}
|
||||
}
|
||||
|
||||
39
packages/monitoring/sentry/src/sentry.client.config.ts
Normal file
39
packages/monitoring/sentry/src/sentry.client.config.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
|
||||
type Parameters<T extends (args: never) => unknown> = T extends (
|
||||
...args: infer P
|
||||
) => unknown
|
||||
? P
|
||||
: never;
|
||||
|
||||
/**
|
||||
* @name initializeSentryBrowserClient
|
||||
* @description Initialize the Sentry client
|
||||
* @param props
|
||||
*/
|
||||
export function initializeSentryBrowserClient(
|
||||
props: Parameters<typeof Sentry.init>[0] = {},
|
||||
) {
|
||||
return Sentry.init({
|
||||
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
||||
// Replay may only be enabled for the client-side
|
||||
integrations: [Sentry.replayIntegration()],
|
||||
|
||||
// Set tracesSampleRate to 1.0 to capture 100%
|
||||
// of transactions for performance monitoring.
|
||||
// We recommend adjusting this value in production
|
||||
tracesSampleRate: props?.tracesSampleRate ?? 1.0,
|
||||
|
||||
// Capture Replay for 10% of all sessions,
|
||||
// plus for 100% of sessions with an error
|
||||
replaysSessionSampleRate: 0.1,
|
||||
replaysOnErrorSampleRate: 1.0,
|
||||
|
||||
// ...
|
||||
|
||||
// Note: if you want to override the automatic release value, do not set a
|
||||
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
|
||||
// that it will also get attached to your source maps,
|
||||
...props,
|
||||
});
|
||||
}
|
||||
27
packages/monitoring/sentry/src/sentry.server.config.ts
Normal file
27
packages/monitoring/sentry/src/sentry.server.config.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
|
||||
type Parameters<T extends (args: never) => unknown> = T extends (
|
||||
...args: infer P
|
||||
) => unknown
|
||||
? P
|
||||
: never;
|
||||
|
||||
/**
|
||||
* @name initializeSentryServerClient
|
||||
* @description Initialize the Sentry client in the server
|
||||
* @param props
|
||||
*/
|
||||
export function initializeSentryServerClient(
|
||||
props: Parameters<typeof Sentry.init>[0] = {},
|
||||
) {
|
||||
return Sentry.init({
|
||||
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
||||
|
||||
// ...
|
||||
|
||||
// Note: if you want to override the automatic release value, do not set a
|
||||
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
|
||||
// that it will also get attached to your source maps,
|
||||
...props,
|
||||
});
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export * from './services/sentry-server-monitoring.service';
|
||||
@@ -7,7 +7,11 @@ import { MonitoringService } from '@kit/monitoring-core';
|
||||
* @implements {MonitoringService}
|
||||
* ServerSentryMonitoringService is responsible for capturing exceptions and identifying users using the Sentry monitoring service.
|
||||
*/
|
||||
export class SentryServerMonitoringService implements MonitoringService {
|
||||
export class SentryMonitoringService implements MonitoringService {
|
||||
constructor() {
|
||||
void this.initialize();
|
||||
}
|
||||
|
||||
captureException(error: Error | null) {
|
||||
return Sentry.captureException(error);
|
||||
}
|
||||
@@ -22,4 +26,18 @@ export class SentryServerMonitoringService implements MonitoringService {
|
||||
identifyUser(user: Sentry.User) {
|
||||
Sentry.setUser(user);
|
||||
}
|
||||
|
||||
private initialize() {
|
||||
return this.initializeIfBrowser();
|
||||
}
|
||||
|
||||
private async initializeIfBrowser() {
|
||||
if (typeof document !== 'undefined') {
|
||||
const { initializeSentryBrowserClient } = await import(
|
||||
'../sentry.client.config'
|
||||
);
|
||||
|
||||
initializeSentryBrowserClient();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user