diff --git a/apps/web/.env.production b/apps/web/.env.production
index 6c50e0284..41b5ebb3d 100644
--- a/apps/web/.env.production
+++ b/apps/web/.env.production
@@ -44,4 +44,8 @@ NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
NEXT_PUBLIC_ENABLE_ACCOUNT_DELETION=true
NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_BILLING=true
NEXT_PUBLIC_ENABLE_ORGANIZATION_DELETION=true
-NEXT_PUBLIC_ENABLE_ORGANIZATION_BILLING=true
\ No newline at end of file
+NEXT_PUBLIC_ENABLE_ORGANIZATION_BILLING=true
+
+# MONITORING
+MONITORING_PROVIDER=
+MONITORING_INSTRUMENTATION_ENABLED=false
diff --git a/apps/web/app/(dashboard)/home/[account]/billing/error.tsx b/apps/web/app/(dashboard)/home/[account]/billing/error.tsx
index 509bbdb22..5eb160524 100644
--- a/apps/web/app/(dashboard)/home/[account]/billing/error.tsx
+++ b/apps/web/app/(dashboard)/home/[account]/billing/error.tsx
@@ -1,16 +1,21 @@
'use client';
-import { useRouter } from 'next/navigation';
-
import { ExclamationTriangleIcon } from '@radix-ui/react-icons';
+import { useCaptureException } from '@kit/monitoring/hooks';
import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert';
import { Button } from '@kit/ui/button';
import { PageBody, PageHeader } from '@kit/ui/page';
import { Trans } from '@kit/ui/trans';
-export default function BillingErrorPage() {
- const router = useRouter();
+export default function BillingErrorPage({
+ error,
+ reset,
+}: {
+ error: Error & { digest?: string };
+ reset: () => void;
+}) {
+ useCaptureException(error);
return (
<>
@@ -34,7 +39,7 @@ export default function BillingErrorPage() {
-
diff --git a/apps/web/app/error.tsx b/apps/web/app/error.tsx
index a3e84ac15..57ea2a3d5 100644
--- a/apps/web/app/error.tsx
+++ b/apps/web/app/error.tsx
@@ -4,13 +4,22 @@ import Link from 'next/link';
import { ArrowLeft } from 'lucide-react';
+import { useCaptureException } from '@kit/monitoring/hooks';
import { Button } from '@kit/ui/button';
import { Heading } from '@kit/ui/heading';
import { Trans } from '@kit/ui/trans';
import { SiteHeader } from '~/(marketing)/_components/site-header';
-const ErrorPage = () => {
+const ErrorPage = ({
+ error,
+ reset,
+}: {
+ error: Error & { digest?: string };
+ reset: () => void;
+}) => {
+ useCaptureException(error);
+
return (
@@ -39,13 +48,11 @@ const ErrorPage = () => {
diff --git a/apps/web/instrumentation.ts b/apps/web/instrumentation.ts
index cc4b7aeec..9c4237a0e 100644
--- a/apps/web/instrumentation.ts
+++ b/apps/web/instrumentation.ts
@@ -2,11 +2,17 @@
* This file is used to register monitoring instrumentation
* for your Next.js application.
*/
+
+const RUNTIME = process.env.NEXT_RUNTIME;
+
+const ENABLE_INSTRUMENTATION =
+ process.env.MONITORING_INSTRUMENTATION_ENABLED === 'true';
+
export async function register() {
// only run in nodejs runtime
- if (process.env.NEXT_RUNTIME === 'nodejs') {
+ if (RUNTIME === 'nodejs' && ENABLE_INSTRUMENTATION) {
const { registerMonitoringInstrumentation } = await import(
- '@kit/monitoring'
+ '@kit/monitoring/instrumentation'
);
// Register monitoring instrumentation based on the
diff --git a/apps/web/public/locales/en/common.json b/apps/web/public/locales/en/common.json
index d0c75538f..bcf564bb9 100644
--- a/apps/web/public/locales/en/common.json
+++ b/apps/web/public/locales/en/common.json
@@ -21,6 +21,7 @@
"clear": "Clear",
"notFound": "Not Found",
"backToHomePage": "Back to Home Page",
+ "goBack": "Go Back",
"genericServerError": "Sorry, something went wrong.",
"genericServerErrorHeading": "Sorry, something went wrong while processing your request. Please contact us if the issue persists.",
"pageNotFound": "Sorry, this page does not exist.",
diff --git a/packages/features/accounts/package.json b/packages/features/accounts/package.json
index 298b5e8be..f79eb62fa 100644
--- a/packages/features/accounts/package.json
+++ b/packages/features/accounts/package.json
@@ -23,6 +23,7 @@
"@kit/email-templates": "workspace:^",
"@kit/eslint-config": "workspace:*",
"@kit/mailers": "workspace:^",
+ "@kit/monitoring": "workspace:^",
"@kit/prettier-config": "workspace:*",
"@kit/shared": "workspace:^",
"@kit/supabase": "workspace:^",
diff --git a/packages/features/accounts/src/components/personal-account-settings/account-danger-zone.tsx b/packages/features/accounts/src/components/personal-account-settings/account-danger-zone.tsx
index f8a0192d8..3c5177a4e 100644
--- a/packages/features/accounts/src/components/personal-account-settings/account-danger-zone.tsx
+++ b/packages/features/accounts/src/components/personal-account-settings/account-danger-zone.tsx
@@ -6,6 +6,7 @@ import { zodResolver } from '@hookform/resolvers/zod';
import { ExclamationTriangleIcon } from '@radix-ui/react-icons';
import { useForm } from 'react-hook-form';
+import { ErrorBoundary } from '@kit/monitoring/components';
import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert';
import {
AlertDialog,
@@ -17,7 +18,6 @@ import {
AlertDialogTrigger,
} from '@kit/ui/alert-dialog';
import { Button } from '@kit/ui/button';
-import { ErrorBoundary } from '@kit/ui/error-boundary';
import { Form, FormControl, FormItem, FormLabel } from '@kit/ui/form';
import { Input } from '@kit/ui/input';
import { Trans } from '@kit/ui/trans';
diff --git a/packages/features/team-accounts/package.json b/packages/features/team-accounts/package.json
index 53b7ea95f..c8118b0ca 100644
--- a/packages/features/team-accounts/package.json
+++ b/packages/features/team-accounts/package.json
@@ -22,6 +22,7 @@
"@kit/email-templates": "workspace:^",
"@kit/eslint-config": "workspace:*",
"@kit/mailers": "workspace:^",
+ "@kit/monitoring": "workspace:*",
"@kit/prettier-config": "workspace:*",
"@kit/shared": "workspace:^",
"@kit/supabase": "workspace:^",
diff --git a/packages/features/team-accounts/src/components/settings/team-account-danger-zone.tsx b/packages/features/team-accounts/src/components/settings/team-account-danger-zone.tsx
index d036c9f33..f4c8fcee4 100644
--- a/packages/features/team-accounts/src/components/settings/team-account-danger-zone.tsx
+++ b/packages/features/team-accounts/src/components/settings/team-account-danger-zone.tsx
@@ -6,6 +6,7 @@ import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
+import { ErrorBoundary } from '@kit/monitoring/components';
import { useUser } from '@kit/supabase/hooks/use-user';
import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert';
import {
@@ -19,7 +20,6 @@ import {
AlertDialogTrigger,
} from '@kit/ui/alert-dialog';
import { Button } from '@kit/ui/button';
-import { ErrorBoundary } from '@kit/ui/error-boundary';
import {
Form,
FormControl,
diff --git a/packages/monitoring/baselime/package.json b/packages/monitoring/baselime/package.json
index c581fa704..06ce9abc3 100644
--- a/packages/monitoring/baselime/package.json
+++ b/packages/monitoring/baselime/package.json
@@ -10,10 +10,13 @@
},
"prettier": "@kit/prettier-config",
"exports": {
- ".": "./src/index.ts"
+ ".": "./src/index.ts",
+ "./instrumentation": "./src/instrumentation.ts",
+ "./provider": "./src/components/provider.tsx"
},
"dependencies": {
- "@baselime/node-opentelemetry": "^0.5.8"
+ "@baselime/node-opentelemetry": "^0.5.8",
+ "@baselime/react-rum": "^0.2.9"
},
"devDependencies": {
"@kit/eslint-config": "workspace:*",
diff --git a/packages/monitoring/baselime/src/capture-exception.ts b/packages/monitoring/baselime/src/capture-exception.ts
new file mode 100644
index 000000000..c9e1114dc
--- /dev/null
+++ b/packages/monitoring/baselime/src/capture-exception.ts
@@ -0,0 +1,4 @@
+export function captureException(error: Error) {
+ console.info(`No yet defined...`);
+ return console.error(`Caught exception: ${JSON.stringify(error)}`);
+}
diff --git a/packages/monitoring/baselime/src/components/provider.tsx b/packages/monitoring/baselime/src/components/provider.tsx
new file mode 100644
index 000000000..a78ff5d39
--- /dev/null
+++ b/packages/monitoring/baselime/src/components/provider.tsx
@@ -0,0 +1,22 @@
+import { BaselimeRum } from '@baselime/react-rum';
+
+export function BaselineProvider({
+ children,
+ apiKey,
+ enableWebVitals,
+ ErrorPage,
+}: React.PropsWithChildren<{
+ apiKey: string;
+ enableWebVitals?: boolean;
+ ErrorPage?: React.ReactElement;
+}>) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/packages/monitoring/baselime/src/hooks/use-capture-exception.ts b/packages/monitoring/baselime/src/hooks/use-capture-exception.ts
new file mode 100644
index 000000000..29bacd09d
--- /dev/null
+++ b/packages/monitoring/baselime/src/hooks/use-capture-exception.ts
@@ -0,0 +1,12 @@
+import { useCallback } from 'react';
+
+import { useBaselimeRum } from '@baselime/react-rum';
+
+export function useCaptureException() {
+ const { captureException } = useBaselimeRum();
+
+ return useCallback(
+ (error: Error) => captureException(error),
+ [captureException],
+ );
+}
diff --git a/packages/monitoring/baselime/src/index.ts b/packages/monitoring/baselime/src/index.ts
index 590437486..c258b27a8 100644
--- a/packages/monitoring/baselime/src/index.ts
+++ b/packages/monitoring/baselime/src/index.ts
@@ -1,31 +1 @@
-const INSTRUMENTATION_SERVICE_NAME = process.env.INSTRUMENTATION_SERVICE_NAME;
-
-if (!INSTRUMENTATION_SERVICE_NAME) {
- throw new Error(`
- You have set the Baselime instrumentation provider, but have not set the INSTRUMENTATION_SERVICE_NAME environment variable. Please set the INSTRUMENTATION_SERVICE_NAME environment variable.
- `);
-}
-
-/**
- * @name registerBaselimeInstrumentation
- * @description This file is used to register Baselime instrumentation for your Next.js application.
- *
- * Please set the MONITORING_INSTRUMENTATION_PROVIDER environment variable to 'baselime' to register Baselime instrumentation.
- */
-export async function registerBaselimeInstrumentation() {
- const { BaselimeSDK, BetterHttpInstrumentation, VercelPlugin } = await import(
- '@baselime/node-opentelemetry'
- );
-
- const sdk = new BaselimeSDK({
- serverless: true,
- service: INSTRUMENTATION_SERVICE_NAME,
- instrumentations: [
- new BetterHttpInstrumentation({
- plugins: [new VercelPlugin()],
- }),
- ],
- });
-
- sdk.start();
-}
+export * from './capture-exception';
diff --git a/packages/monitoring/baselime/src/instrumentation.ts b/packages/monitoring/baselime/src/instrumentation.ts
new file mode 100644
index 000000000..590437486
--- /dev/null
+++ b/packages/monitoring/baselime/src/instrumentation.ts
@@ -0,0 +1,31 @@
+const INSTRUMENTATION_SERVICE_NAME = process.env.INSTRUMENTATION_SERVICE_NAME;
+
+if (!INSTRUMENTATION_SERVICE_NAME) {
+ throw new Error(`
+ You have set the Baselime instrumentation provider, but have not set the INSTRUMENTATION_SERVICE_NAME environment variable. Please set the INSTRUMENTATION_SERVICE_NAME environment variable.
+ `);
+}
+
+/**
+ * @name registerBaselimeInstrumentation
+ * @description This file is used to register Baselime instrumentation for your Next.js application.
+ *
+ * Please set the MONITORING_INSTRUMENTATION_PROVIDER environment variable to 'baselime' to register Baselime instrumentation.
+ */
+export async function registerBaselimeInstrumentation() {
+ const { BaselimeSDK, BetterHttpInstrumentation, VercelPlugin } = await import(
+ '@baselime/node-opentelemetry'
+ );
+
+ const sdk = new BaselimeSDK({
+ serverless: true,
+ service: INSTRUMENTATION_SERVICE_NAME,
+ instrumentations: [
+ new BetterHttpInstrumentation({
+ plugins: [new VercelPlugin()],
+ }),
+ ],
+ });
+
+ sdk.start();
+}
diff --git a/packages/monitoring/package.json b/packages/monitoring/package.json
index f94331b89..987655f66 100644
--- a/packages/monitoring/package.json
+++ b/packages/monitoring/package.json
@@ -11,7 +11,10 @@
},
"prettier": "@kit/prettier-config",
"exports": {
- ".": "./src/index.ts"
+ ".": "./src/index.ts",
+ "./instrumentation": "./src/instrumentation.ts",
+ "./hooks": "./src/hooks/index.ts",
+ "./components": "./src/components/index.ts"
},
"devDependencies": {
"@kit/baselime": "workspace:*",
@@ -19,7 +22,12 @@
"@kit/prettier-config": "workspace:*",
"@kit/sentry": "workspace:*",
"@kit/tailwind-config": "workspace:*",
- "@kit/tsconfig": "workspace:*"
+ "@kit/tsconfig": "workspace:*",
+ "@types/react": "^18.2.77",
+ "react": "18.2.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
},
"eslintConfig": {
"root": true,
diff --git a/packages/monitoring/sentry/package.json b/packages/monitoring/sentry/package.json
index cb61b722b..04ee4ac9e 100644
--- a/packages/monitoring/sentry/package.json
+++ b/packages/monitoring/sentry/package.json
@@ -11,6 +11,7 @@
"prettier": "@kit/prettier-config",
"exports": {
".": "./src/index.ts",
+ "./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.server.edge.ts"
diff --git a/packages/monitoring/sentry/src/capture-exception.ts b/packages/monitoring/sentry/src/capture-exception.ts
new file mode 100644
index 000000000..5342fa459
--- /dev/null
+++ b/packages/monitoring/sentry/src/capture-exception.ts
@@ -0,0 +1,5 @@
+import * as Sentry from '@sentry/nextjs';
+
+export function captureException(error: Error & { digest?: string }) {
+ return Sentry.captureException(error);
+}
diff --git a/packages/monitoring/sentry/src/index.ts b/packages/monitoring/sentry/src/index.ts
index d2b87772c..7000d7f04 100644
--- a/packages/monitoring/sentry/src/index.ts
+++ b/packages/monitoring/sentry/src/index.ts
@@ -1,36 +1 @@
-const INSTRUMENTATION_SERVICE_NAME = process.env.INSTRUMENTATION_SERVICE_NAME;
-
-if (!INSTRUMENTATION_SERVICE_NAME) {
- 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.
- `);
-}
-
-/**
- * @name registerSentryInstrumentation
- * @description This file is used to register Sentry instrumentation for your Next.js application.
- *
- * Please set the MONITORING_INSTRUMENTATION_PROVIDER environment variable to 'sentry' to register Sentry instrumentation.
- */
-export async function registerSentryInstrumentation() {
- const { Resource } = await import('@opentelemetry/resources');
- const { NodeSDK } = await import('@opentelemetry/sdk-node');
-
- const { SEMRESATTRS_SERVICE_NAME } = await import(
- '@opentelemetry/semantic-conventions'
- );
-
- const { SentrySpanProcessor, SentryPropagator } = await import(
- '@sentry/opentelemetry-node'
- );
-
- const sdk = new NodeSDK({
- resource: new Resource({
- [SEMRESATTRS_SERVICE_NAME]: INSTRUMENTATION_SERVICE_NAME,
- }),
- spanProcessor: new SentrySpanProcessor(),
- textMapPropagator: new SentryPropagator(),
- });
-
- sdk.start();
-}
+export { captureException } from './capture-exception';
diff --git a/packages/monitoring/sentry/src/instrumentation.ts b/packages/monitoring/sentry/src/instrumentation.ts
new file mode 100644
index 000000000..d2b87772c
--- /dev/null
+++ b/packages/monitoring/sentry/src/instrumentation.ts
@@ -0,0 +1,36 @@
+const INSTRUMENTATION_SERVICE_NAME = process.env.INSTRUMENTATION_SERVICE_NAME;
+
+if (!INSTRUMENTATION_SERVICE_NAME) {
+ 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.
+ `);
+}
+
+/**
+ * @name registerSentryInstrumentation
+ * @description This file is used to register Sentry instrumentation for your Next.js application.
+ *
+ * Please set the MONITORING_INSTRUMENTATION_PROVIDER environment variable to 'sentry' to register Sentry instrumentation.
+ */
+export async function registerSentryInstrumentation() {
+ const { Resource } = await import('@opentelemetry/resources');
+ const { NodeSDK } = await import('@opentelemetry/sdk-node');
+
+ const { SEMRESATTRS_SERVICE_NAME } = await import(
+ '@opentelemetry/semantic-conventions'
+ );
+
+ const { SentrySpanProcessor, SentryPropagator } = await import(
+ '@sentry/opentelemetry-node'
+ );
+
+ const sdk = new NodeSDK({
+ resource: new Resource({
+ [SEMRESATTRS_SERVICE_NAME]: INSTRUMENTATION_SERVICE_NAME,
+ }),
+ spanProcessor: new SentrySpanProcessor(),
+ textMapPropagator: new SentryPropagator(),
+ });
+
+ sdk.start();
+}
diff --git a/packages/monitoring/src/capture-exception.ts b/packages/monitoring/src/capture-exception.ts
new file mode 100644
index 000000000..f99873bfa
--- /dev/null
+++ b/packages/monitoring/src/capture-exception.ts
@@ -0,0 +1,44 @@
+import { InstrumentationProvider } from './monitoring-providers.enum';
+
+/**
+ * @name MONITORING_PROVIDER
+ * @description Register monitoring instrumentation based on the MONITORING_PROVIDER environment variable.
+ */
+const MONITORING_PROVIDER = process.env.MONITORING_PROVIDER as
+ | InstrumentationProvider
+ | undefined;
+
+/**
+ * @name captureException
+ * @description Capture an exception and send it to the monitoring provider defined.
+ * @param error
+ */
+export async function captureException(error: Error) {
+ if (!MONITORING_PROVIDER) {
+ console.info(
+ `No instrumentation provider specified. Logging to console...`,
+ );
+
+ return console.error(`Caught exception: ${JSON.stringify(error)}`);
+ }
+
+ switch (MONITORING_PROVIDER) {
+ case InstrumentationProvider.Baselime: {
+ const { captureException } = await import('@kit/baselime');
+
+ return captureException(error);
+ }
+
+ case InstrumentationProvider.Sentry: {
+ const { captureException } = await import('@kit/sentry');
+
+ return captureException(error);
+ }
+
+ default: {
+ throw new Error(
+ `Please set the MONITORING_PROVIDER environment variable to register the monitoring instrumentation provider.`,
+ );
+ }
+ }
+}
diff --git a/packages/monitoring/src/components/error-boundary.tsx b/packages/monitoring/src/components/error-boundary.tsx
new file mode 100644
index 000000000..6a5b4f265
--- /dev/null
+++ b/packages/monitoring/src/components/error-boundary.tsx
@@ -0,0 +1,39 @@
+import type { ErrorInfo, ReactNode } from 'react';
+import { Component } from 'react';
+
+import { captureException } from '../capture-exception';
+
+interface Props {
+ onError?: (error: Error, info: ErrorInfo) => void;
+ fallback: ReactNode;
+ children: ReactNode;
+}
+
+export class ErrorBoundary extends Component {
+ readonly state = { hasError: false, error: null };
+
+ constructor(props: Props) {
+ super(props);
+ }
+
+ static getDerivedStateFromError(error: unknown) {
+ return {
+ hasError: true,
+ error,
+ };
+ }
+
+ async componentDidCatch(error: Error, info: ErrorInfo) {
+ this.props.onError?.(error, info);
+
+ await captureException(error);
+ }
+
+ render() {
+ if (this.state.hasError) {
+ return this.props.fallback;
+ }
+
+ return this.props.children;
+ }
+}
diff --git a/packages/monitoring/src/components/index.ts b/packages/monitoring/src/components/index.ts
new file mode 100644
index 000000000..39d945d40
--- /dev/null
+++ b/packages/monitoring/src/components/index.ts
@@ -0,0 +1 @@
+export * from './error-boundary';
diff --git a/packages/monitoring/src/hooks/index.ts b/packages/monitoring/src/hooks/index.ts
new file mode 100644
index 000000000..bb2203ca8
--- /dev/null
+++ b/packages/monitoring/src/hooks/index.ts
@@ -0,0 +1 @@
+export * from './use-capture-exception';
diff --git a/packages/monitoring/src/hooks/use-capture-exception.ts b/packages/monitoring/src/hooks/use-capture-exception.ts
new file mode 100644
index 000000000..68e780c7b
--- /dev/null
+++ b/packages/monitoring/src/hooks/use-capture-exception.ts
@@ -0,0 +1,11 @@
+import { useEffect } from 'react';
+
+import { captureException } from '../capture-exception';
+
+export function useCaptureException(error: Error) {
+ useEffect(() => {
+ void captureException(error);
+ }, [error]);
+
+ return null;
+}
diff --git a/packages/monitoring/src/index.ts b/packages/monitoring/src/index.ts
index c75c68adc..c258b27a8 100644
--- a/packages/monitoring/src/index.ts
+++ b/packages/monitoring/src/index.ts
@@ -1 +1 @@
-export * from './instrumentation';
+export * from './capture-exception';
diff --git a/packages/monitoring/src/instrumentation.ts b/packages/monitoring/src/instrumentation.ts
index c8a722d9e..de4c9b5e4 100644
--- a/packages/monitoring/src/instrumentation.ts
+++ b/packages/monitoring/src/instrumentation.ts
@@ -1,44 +1,46 @@
-enum InstrumentationProvider {
- Baselime = 'baselime',
- Sentry = 'sentry',
-}
+import { InstrumentationProvider } from './monitoring-providers.enum';
/**
- * @name DEFAULT_INSTRUMENTATION_PROVIDER
- * @description Register monitoring instrumentation based on the MONITORING_INSTRUMENTATION_PROVIDER environment variable.
+ * @name MONITORING_PROVIDER
+ * @description Register monitoring instrumentation based on the MONITORING_PROVIDER environment variable.
*/
-const DEFAULT_INSTRUMENTATION_PROVIDER = process.env
- .MONITORING_INSTRUMENTATION_PROVIDER as InstrumentationProvider | undefined;
+const MONITORING_PROVIDER = process.env.MONITORING_PROVIDER as
+ | InstrumentationProvider
+ | undefined;
/**
* @name registerMonitoringInstrumentation
- * @description Register monitoring instrumentation based on the MONITORING_INSTRUMENTATION_PROVIDER environment variable.
+ * @description Register monitoring instrumentation based on the MONITORING_PROVIDER environment variable.
*
- * Please set the MONITORING_INSTRUMENTATION_PROVIDER environment variable to register the monitoring instrumentation provider.
+ * Please set the MONITORING_PROVIDER environment variable to register the monitoring instrumentation provider.
*/
export async function registerMonitoringInstrumentation() {
- if (!DEFAULT_INSTRUMENTATION_PROVIDER) {
+ if (!MONITORING_PROVIDER) {
console.info(`No instrumentation provider specified. Skipping...`);
return;
}
- switch (DEFAULT_INSTRUMENTATION_PROVIDER) {
+ switch (MONITORING_PROVIDER) {
case InstrumentationProvider.Baselime: {
- const { registerBaselimeInstrumentation } = await import('@kit/baselime');
+ const { registerBaselimeInstrumentation } = await import(
+ '@kit/baselime/instrumentation'
+ );
return registerBaselimeInstrumentation();
}
case InstrumentationProvider.Sentry: {
- const { registerSentryInstrumentation } = await import('@kit/sentry');
+ const { registerSentryInstrumentation } = await import(
+ '@kit/sentry/instrumentation'
+ );
return registerSentryInstrumentation();
}
default:
throw new Error(
- `Unknown instrumentation provider: ${DEFAULT_INSTRUMENTATION_PROVIDER as string}`,
+ `Unknown instrumentation provider: ${MONITORING_PROVIDER as string}`,
);
}
}
diff --git a/packages/monitoring/src/monitoring-providers.enum.ts b/packages/monitoring/src/monitoring-providers.enum.ts
new file mode 100644
index 000000000..030610031
--- /dev/null
+++ b/packages/monitoring/src/monitoring-providers.enum.ts
@@ -0,0 +1,4 @@
+export enum InstrumentationProvider {
+ Baselime = 'baselime',
+ Sentry = 'sentry',
+}
diff --git a/packages/ui/package.json b/packages/ui/package.json
index e21558de9..482dc4a27 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -119,7 +119,6 @@
"./page": "./src/makerkit/page.tsx",
"./image-uploader": "./src/makerkit/image-uploader.tsx",
"./global-loader": "./src/makerkit/global-loader.tsx",
- "./error-boundary": "./src/makerkit/error-boundary.tsx",
"./auth-change-listener": "./src/makerkit/auth-change-listener.tsx",
"./loading-overlay": "./src/makerkit/loading-overlay.tsx",
"./profile-avatar": "./src/makerkit/profile-avatar.tsx",
diff --git a/packages/ui/src/makerkit/error-boundary.tsx b/packages/ui/src/makerkit/error-boundary.tsx
deleted file mode 100644
index 04aeaa64e..000000000
--- a/packages/ui/src/makerkit/error-boundary.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-'use client';
-
-import type { ReactNode } from 'react';
-import { Component } from 'react';
-
-export class ErrorBoundary extends Component<{
- fallback: ReactNode;
- children: ReactNode;
-}> {
- readonly state = { hasError: false, error: null };
-
- static getDerivedStateFromError(error: unknown) {
- return {
- hasError: true,
- error,
- };
- }
-
- render() {
- if (this.state.hasError) {
- return this.props.fallback;
- }
-
- return this.props.children;
- }
-}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4c6483b16..503390801 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -554,6 +554,9 @@ importers:
'@kit/mailers':
specifier: workspace:^
version: link:../../mailers
+ '@kit/monitoring':
+ specifier: workspace:^
+ version: link:../../monitoring
'@kit/prettier-config':
specifier: workspace:*
version: link:../../../tooling/prettier
@@ -759,6 +762,9 @@ importers:
'@kit/mailers':
specifier: workspace:^
version: link:../../mailers
+ '@kit/monitoring':
+ specifier: workspace:*
+ version: link:../../monitoring
'@kit/prettier-config':
specifier: workspace:*
version: link:../../../tooling/prettier
@@ -901,12 +907,21 @@ importers:
'@kit/tsconfig':
specifier: workspace:*
version: link:../../tooling/typescript
+ '@types/react':
+ specifier: ^18.2.77
+ version: 18.2.78
+ react:
+ specifier: 18.2.0
+ version: 18.2.0
packages/monitoring/baselime:
dependencies:
'@baselime/node-opentelemetry':
specifier: ^0.5.8
version: 0.5.8(@trpc/server@10.45.2)
+ '@baselime/react-rum':
+ specifier: ^0.2.9
+ version: 0.2.9(react@18.2.0)
devDependencies:
'@kit/eslint-config':
specifier: workspace:*
@@ -1584,6 +1599,17 @@ packages:
- supports-color
dev: false
+ /@baselime/react-rum@0.2.9(react@18.2.0):
+ resolution: {integrity: sha512-x5+eYsNCsasHD6jbfH02HmwA7i8A+3Ac3PS2tKwgFgoqi1EmIgktjAvdYFosTZe73VIQMal19peRXAu2/lGxAA==}
+ peerDependencies:
+ react: ^18.2.0
+ dependencies:
+ js-cookie: 3.0.5
+ react: 18.2.0
+ react-error-boundary: 4.0.13(react@18.2.0)
+ web-vitals: 3.5.2
+ dev: false
+
/@braintree/sanitize-url@6.0.4:
resolution: {integrity: sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==}
dev: false
@@ -11690,6 +11716,15 @@ packages:
- webpack-cli
dev: false
+ /react-error-boundary@4.0.13(react@18.2.0):
+ resolution: {integrity: sha512-b6PwbdSv8XeOSYvjt8LpgpKrZ0yGdtZokYwkwV2wlcZbxgopHX/hgPl5VgpnoVOWd868n1hktM8Qm4b+02MiLQ==}
+ peerDependencies:
+ react: '>=16.13.1'
+ dependencies:
+ '@babel/runtime': 7.24.4
+ react: 18.2.0
+ dev: false
+
/react-hook-form@7.51.3(react@18.2.0):
resolution: {integrity: sha512-cvJ/wbHdhYx8aviSWh28w9ImjmVsb5Y05n1+FW786vEZQJV5STNM0pW6ujS+oiBecb0ARBxJFyAnXj9+GHXACQ==}
engines: {node: '>=12.22.0'}
@@ -13296,6 +13331,10 @@ packages:
engines: {node: '>= 8'}
dev: true
+ /web-vitals@3.5.2:
+ resolution: {integrity: sha512-c0rhqNcHXRkY/ogGDJQxZ9Im9D19hDihbzSQJrsioex+KnFgmMzBiy57Z1EjkhX/+OjyBpclDCzz2ITtjokFmg==}
+ dev: false
+
/webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}