diff --git a/apps/web/.env.production b/apps/web/.env.production
index e7f400b5c..13f173141 100644
--- a/apps/web/.env.production
+++ b/apps/web/.env.production
@@ -13,4 +13,4 @@ NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
# MONITORING
NEXT_PUBLIC_MONITORING_PROVIDER=
-MONITORING_INSTRUMENTATION_ENABLED=false
+ENABLE_MONITORING_INSTRUMENTATION=false
diff --git a/apps/web/instrumentation.ts b/apps/web/instrumentation.ts
index 9f751880c..a7cd2ce42 100644
--- a/apps/web/instrumentation.ts
+++ b/apps/web/instrumentation.ts
@@ -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();
}
diff --git a/packages/monitoring/api/README.md b/packages/monitoring/api/README.md
index c69428686..8481b7c32 100644
--- a/packages/monitoring/api/README.md
+++ b/packages/monitoring/api/README.md
@@ -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
```
\ No newline at end of file
diff --git a/packages/monitoring/api/src/services/get-server-monitoring-service.ts b/packages/monitoring/api/src/services/get-server-monitoring-service.ts
index bfc67ae4d..236e6d77c 100644
--- a/packages/monitoring/api/src/services/get-server-monitoring-service.ts
+++ b/packages/monitoring/api/src/services/get-server-monitoring-service.ts
@@ -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: {
diff --git a/packages/monitoring/baselime/src/instrumentation.ts b/packages/monitoring/baselime/src/instrumentation.ts
index b570cc28a..8f9654276 100644
--- a/packages/monitoring/baselime/src/instrumentation.ts
+++ b/packages/monitoring/baselime/src/instrumentation.ts
@@ -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();
+ }
}
diff --git a/packages/monitoring/sentry/package.json b/packages/monitoring/sentry/package.json
index 25e531f50..c273ae9e1 100644
--- a/packages/monitoring/sentry/package.json
+++ b/packages/monitoring/sentry/package.json
@@ -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",
diff --git a/packages/monitoring/sentry/src/components/provider.tsx b/packages/monitoring/sentry/src/components/provider.tsx
index 1a71e3765..f5bb2c948 100644
--- a/packages/monitoring/sentry/src/components/provider.tsx
+++ b/packages/monitoring/sentry/src/components/provider.tsx
@@ -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 {children};
}
function MonitoringProvider(props: React.PropsWithChildren) {
- const service = useRef(new SentryServerMonitoringService());
+ const service = useRef(new SentryMonitoringService());
return (
diff --git a/packages/monitoring/sentry/src/config/sentry.client.config.ts b/packages/monitoring/sentry/src/config/sentry.client.config.ts
deleted file mode 100644
index c6ab3ca5f..000000000
--- a/packages/monitoring/sentry/src/config/sentry.client.config.ts
+++ /dev/null
@@ -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
-});
diff --git a/packages/monitoring/sentry/src/config/sentry.edge.config.ts b/packages/monitoring/sentry/src/config/sentry.edge.config.ts
deleted file mode 100644
index 8b74c1b56..000000000
--- a/packages/monitoring/sentry/src/config/sentry.edge.config.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import * as Sentry from '@sentry/nextjs';
-
-Sentry.init({
- dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
- tracesSampleRate: 1.0,
-});
diff --git a/packages/monitoring/sentry/src/config/sentry.server.config.ts b/packages/monitoring/sentry/src/config/sentry.server.config.ts
deleted file mode 100644
index 8b74c1b56..000000000
--- a/packages/monitoring/sentry/src/config/sentry.server.config.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import * as Sentry from '@sentry/nextjs';
-
-Sentry.init({
- dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
- tracesSampleRate: 1.0,
-});
diff --git a/packages/monitoring/sentry/src/index.ts b/packages/monitoring/sentry/src/index.ts
new file mode 100644
index 000000000..d4d9ce20c
--- /dev/null
+++ b/packages/monitoring/sentry/src/index.ts
@@ -0,0 +1 @@
+export * from './services/sentry-monitoring.service';
diff --git a/packages/monitoring/sentry/src/instrumentation.ts b/packages/monitoring/sentry/src/instrumentation.ts
index 3a15c301c..244668b9f 100644
--- a/packages/monitoring/sentry/src/instrumentation.ts
+++ b/packages/monitoring/sentry/src/instrumentation.ts
@@ -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();
+ }
}
diff --git a/packages/monitoring/sentry/src/sentry.client.config.ts b/packages/monitoring/sentry/src/sentry.client.config.ts
new file mode 100644
index 000000000..195e3f100
--- /dev/null
+++ b/packages/monitoring/sentry/src/sentry.client.config.ts
@@ -0,0 +1,39 @@
+import * as Sentry from '@sentry/nextjs';
+
+type Parameters unknown> = T extends (
+ ...args: infer P
+) => unknown
+ ? P
+ : never;
+
+/**
+ * @name initializeSentryBrowserClient
+ * @description Initialize the Sentry client
+ * @param props
+ */
+export function initializeSentryBrowserClient(
+ props: Parameters[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,
+ });
+}
diff --git a/packages/monitoring/sentry/src/sentry.server.config.ts b/packages/monitoring/sentry/src/sentry.server.config.ts
new file mode 100644
index 000000000..7fb9f6aef
--- /dev/null
+++ b/packages/monitoring/sentry/src/sentry.server.config.ts
@@ -0,0 +1,27 @@
+import * as Sentry from '@sentry/nextjs';
+
+type Parameters 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[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,
+ });
+}
diff --git a/packages/monitoring/sentry/src/server.ts b/packages/monitoring/sentry/src/server.ts
deleted file mode 100644
index 400c7c280..000000000
--- a/packages/monitoring/sentry/src/server.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './services/sentry-server-monitoring.service';
diff --git a/packages/monitoring/sentry/src/services/sentry-server-monitoring.service.ts b/packages/monitoring/sentry/src/services/sentry-monitoring.service.ts
similarity index 58%
rename from packages/monitoring/sentry/src/services/sentry-server-monitoring.service.ts
rename to packages/monitoring/sentry/src/services/sentry-monitoring.service.ts
index bf09a69f3..cdb2f49f7 100644
--- a/packages/monitoring/sentry/src/services/sentry-server-monitoring.service.ts
+++ b/packages/monitoring/sentry/src/services/sentry-monitoring.service.ts
@@ -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();
+ }
+ }
}