Adding Sentry is basically done now. We have a nice lil component to help us get started to!
This commit is contained in:
@ -11,7 +11,6 @@
|
|||||||
#SKIP_ENV_VALIDATION= # false
|
#SKIP_ENV_VALIDATION= # false
|
||||||
#NEXT_RUNTIME= # nodejs
|
#NEXT_RUNTIME= # nodejs
|
||||||
# Sentry Variables # Default Values:
|
# Sentry Variables # Default Values:
|
||||||
#SENTRY_URL= # https://sentry.gbrown.org
|
|
||||||
SENTRY_AUTH_TOKEN=
|
SENTRY_AUTH_TOKEN=
|
||||||
#CI= # true
|
#CI= # true
|
||||||
|
|
||||||
@ -23,6 +22,7 @@ NEXT_PUBLIC_SUPABASE_URL=
|
|||||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=
|
NEXT_PUBLIC_SUPABASE_ANON_KEY=
|
||||||
# Sentry Variables
|
# Sentry Variables
|
||||||
NEXT_PUBLIC_SENTRY_DSN=
|
NEXT_PUBLIC_SENTRY_DSN=
|
||||||
|
NEXT_PUBLIC_SENTRY_URL= # https://sentry.gbrown.org
|
||||||
|
|
||||||
### Script Variables ### These variables are only needed for our scripts, so do not add these to env.js! ###
|
### Script Variables ### These variables are only needed for our scripts, so do not add these to env.js! ###
|
||||||
# generateTypes # Default Values:
|
# generateTypes # Default Values:
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -44,3 +44,5 @@ yarn-error.log*
|
|||||||
|
|
||||||
# idea files
|
# idea files
|
||||||
.idea
|
.idea
|
||||||
|
# Sentry Config File
|
||||||
|
.env.sentry-build-plugin
|
||||||
|
@ -7,14 +7,6 @@ import { withSentryConfig } from '@sentry/nextjs';
|
|||||||
|
|
||||||
/** @type {import("next").NextConfig} */
|
/** @type {import("next").NextConfig} */
|
||||||
const config = {
|
const config = {
|
||||||
turbopack: {
|
|
||||||
rules: {
|
|
||||||
'*.svg': {
|
|
||||||
loaders: ['@svgr/webpack'],
|
|
||||||
as: '*.js',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
output: 'standalone',
|
output: 'standalone',
|
||||||
images: {
|
images: {
|
||||||
remotePatterns: [
|
remotePatterns: [
|
||||||
@ -24,11 +16,20 @@ const config = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
serverExternalPackages: ['require-in-the-middle'],
|
||||||
experimental: {
|
experimental: {
|
||||||
serverActions: {
|
serverActions: {
|
||||||
bodySizeLimit: '10mb',
|
bodySizeLimit: '10mb',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
//turbopack: {
|
||||||
|
//rules: {
|
||||||
|
//'*.svg': {
|
||||||
|
//loaders: ['@svgr/webpack'],
|
||||||
|
//as: '*.js',
|
||||||
|
//},
|
||||||
|
//},
|
||||||
|
//},
|
||||||
};
|
};
|
||||||
|
|
||||||
const sentryConfig = {
|
const sentryConfig = {
|
||||||
@ -36,7 +37,7 @@ const sentryConfig = {
|
|||||||
// https://www.npmjs.com/package/@sentry/webpack-plugin#options
|
// https://www.npmjs.com/package/@sentry/webpack-plugin#options
|
||||||
org: 'gib',
|
org: 'gib',
|
||||||
project: 't3-supabase-template',
|
project: 't3-supabase-template',
|
||||||
sentryUrl: process.env.SENTRY_URL,
|
sentryUrl: process.env.NEXT_PUBLIC_SENTRY_URL,
|
||||||
authToken: process.env.SENTRY_AUTH_TOKEN,
|
authToken: process.env.SENTRY_AUTH_TOKEN,
|
||||||
// Only print logs for uploading source maps in CI
|
// Only print logs for uploading source maps in CI
|
||||||
silent: !process.env.CI,
|
silent: !process.env.CI,
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"check": "next lint && tsc --noEmit",
|
"check": "next lint && tsc --noEmit",
|
||||||
"dev": "next dev --turbo",
|
"dev": "next dev",
|
||||||
|
"dev:turbo": "next dev --turbo",
|
||||||
"format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,mdx}\" --cache",
|
"format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,mdx}\" --cache",
|
||||||
"format:write": "prettier --write \"**/*.{ts,tsx,js,jsx,mdx}\" --cache",
|
"format:write": "prettier --write \"**/*.{ts,tsx,js,jsx,mdx}\" --cache",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
@ -16,7 +17,7 @@
|
|||||||
"typecheck": "tsc --noEmit"
|
"typecheck": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hookform/resolvers": "^5.0.1",
|
"@hookform/resolvers": "^5.1.0",
|
||||||
"@radix-ui/react-avatar": "^1.1.10",
|
"@radix-ui/react-avatar": "^1.1.10",
|
||||||
"@radix-ui/react-checkbox": "^1.3.2",
|
"@radix-ui/react-checkbox": "^1.3.2",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.15",
|
"@radix-ui/react-dropdown-menu": "^2.1.15",
|
||||||
@ -42,8 +43,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.3.1",
|
"@eslint/eslintrc": "^3.3.1",
|
||||||
"@tailwindcss/postcss": "^4.1.8",
|
"@tailwindcss/postcss": "^4.1.8",
|
||||||
"@types/cors": "^2.8.18",
|
"@types/cors": "^2.8.19",
|
||||||
"@types/express": "^5.0.2",
|
"@types/express": "^5.0.3",
|
||||||
"@types/node": "^20.19.0",
|
"@types/node": "^20.19.0",
|
||||||
"@types/react": "^19.1.6",
|
"@types/react": "^19.1.6",
|
||||||
"@types/react-dom": "^19.1.6",
|
"@types/react-dom": "^19.1.6",
|
||||||
|
3533
pnpm-lock.yaml
generated
3533
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,7 @@
|
|||||||
* for Docker builds.
|
* for Docker builds.
|
||||||
*/
|
*/
|
||||||
import './src/env.js';
|
import './src/env.js';
|
||||||
|
import { withSentryConfig } from '@sentry/nextjs';
|
||||||
|
|
||||||
/** @type {import("next").NextConfig} */
|
/** @type {import("next").NextConfig} */
|
||||||
const config = {
|
const config = {
|
||||||
@ -15,6 +16,7 @@ const config = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
serverExternalPackages: ['require-in-the-middle'],
|
||||||
experimental: {
|
experimental: {
|
||||||
serverActions: {
|
serverActions: {
|
||||||
bodySizeLimit: '10mb',
|
bodySizeLimit: '10mb',
|
||||||
@ -26,6 +28,40 @@ const config = {
|
|||||||
eslint: {
|
eslint: {
|
||||||
ignoreDuringBuilds: true,
|
ignoreDuringBuilds: true,
|
||||||
},
|
},
|
||||||
|
//turbopack: {
|
||||||
|
//rules: {
|
||||||
|
//'*.svg': {
|
||||||
|
//loaders: ['@svgr/webpack'],
|
||||||
|
//as: '*.js',
|
||||||
|
//},
|
||||||
|
//},
|
||||||
|
//},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
const sentryConfig = {
|
||||||
|
// For all available options, see:
|
||||||
|
// https://www.npmjs.com/package/@sentry/webpack-plugin#options
|
||||||
|
org: 'gib',
|
||||||
|
project: 't3-supabase-template',
|
||||||
|
sentryUrl: process.env.SENTRY_URL,
|
||||||
|
authToken: process.env.SENTRY_AUTH_TOKEN,
|
||||||
|
// Only print logs for uploading source maps in CI
|
||||||
|
silent: !process.env.CI,
|
||||||
|
// For all available options, see:
|
||||||
|
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
|
||||||
|
// Upload a larger set of source maps for prettier stack traces (increases build time)
|
||||||
|
widenClientFileUpload: true,
|
||||||
|
// Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
|
||||||
|
// This can increase your server load as well as your hosting bill.
|
||||||
|
// Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-
|
||||||
|
// side errors will fail.
|
||||||
|
tunnelRoute: '/monitoring',
|
||||||
|
// Automatically tree-shake Sentry logger statements to reduce bundle size
|
||||||
|
disableLogger: true,
|
||||||
|
// Capture React Component Names
|
||||||
|
reactComponentAnnotation: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default withSentryConfig(config, sentryConfig);
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
* for Docker builds.
|
* for Docker builds.
|
||||||
*/
|
*/
|
||||||
import './src/env.js';
|
import './src/env.js';
|
||||||
|
import { withSentryConfig } from '@sentry/nextjs';
|
||||||
|
|
||||||
/** @type {import("next").NextConfig} */
|
/** @type {import("next").NextConfig} */
|
||||||
const config = {
|
const config = {
|
||||||
@ -15,11 +16,46 @@ const config = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
serverExternalPackages: ['require-in-the-middle'],
|
||||||
experimental: {
|
experimental: {
|
||||||
serverActions: {
|
serverActions: {
|
||||||
bodySizeLimit: '10mb',
|
bodySizeLimit: '10mb',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
//turbopack: {
|
||||||
|
//rules: {
|
||||||
|
//'*.svg': {
|
||||||
|
//loaders: ['@svgr/webpack'],
|
||||||
|
//as: '*.js',
|
||||||
|
//},
|
||||||
|
//},
|
||||||
|
//},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
const sentryConfig = {
|
||||||
|
// For all available options, see:
|
||||||
|
// https://www.npmjs.com/package/@sentry/webpack-plugin#options
|
||||||
|
org: 'gib',
|
||||||
|
project: 't3-supabase-template',
|
||||||
|
sentryUrl: process.env.SENTRY_URL,
|
||||||
|
authToken: process.env.SENTRY_AUTH_TOKEN,
|
||||||
|
// Only print logs for uploading source maps in CI
|
||||||
|
silent: !process.env.CI,
|
||||||
|
// For all available options, see:
|
||||||
|
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
|
||||||
|
// Upload a larger set of source maps for prettier stack traces (increases build time)
|
||||||
|
widenClientFileUpload: true,
|
||||||
|
// Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
|
||||||
|
// This can increase your server load as well as your hosting bill.
|
||||||
|
// Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-
|
||||||
|
// side errors will fail.
|
||||||
|
tunnelRoute: '/monitoring',
|
||||||
|
// Automatically tree-shake Sentry logger statements to reduce bundle size
|
||||||
|
disableLogger: true,
|
||||||
|
// Capture React Component Names
|
||||||
|
reactComponentAnnotation: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default withSentryConfig(config, sentryConfig);
|
||||||
|
@ -1,23 +1,16 @@
|
|||||||
|
// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on).
|
||||||
|
// The config you add here will be used whenever one of the edge features is loaded.
|
||||||
|
// Note that this config is unrelated to the Vercel Edge Runtime and is also required when running locally.
|
||||||
|
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
|
||||||
|
|
||||||
import * as Sentry from "@sentry/nextjs";
|
import * as Sentry from '@sentry/nextjs';
|
||||||
|
|
||||||
Sentry.init({
|
Sentry.init({
|
||||||
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN!,
|
dsn: 'https://0468176d5291bc2b914261147bfef117@sentry.gbrown.org/6',
|
||||||
|
|
||||||
// Adds request headers and IP for users, for more info visit:
|
// Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.
|
||||||
// https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/options/#sendDefaultPii
|
tracesSampleRate: 1,
|
||||||
sendDefaultPii: true,
|
|
||||||
|
|
||||||
// Set tracesSampleRate to 1.0 to capture 100%
|
// Setting this option to true will print useful information to the console while you're setting up Sentry.
|
||||||
// of transactions for tracing.
|
debug: false,
|
||||||
// We recommend adjusting this value in production
|
|
||||||
// Learn more at
|
|
||||||
// https://docs.sentry.io/platforms/javascript/configuration/options/#traces-sample-rate
|
|
||||||
tracesSampleRate: 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,23 +1,15 @@
|
|||||||
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
|
// This file configures the initialization of Sentry on the server.
|
||||||
|
// The config you add here will be used whenever the server handles a request.
|
||||||
|
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
|
||||||
|
|
||||||
import * as Sentry from '@sentry/nextjs';
|
import * as Sentry from '@sentry/nextjs';
|
||||||
|
|
||||||
Sentry.init({
|
Sentry.init({
|
||||||
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN!,
|
dsn: 'https://0468176d5291bc2b914261147bfef117@sentry.gbrown.org/6',
|
||||||
|
|
||||||
// Adds request headers and IP for users, for more info visit:
|
// Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.
|
||||||
// https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/options/#sendDefaultPii
|
tracesSampleRate: 1,
|
||||||
sendDefaultPii: true,
|
|
||||||
|
|
||||||
// Set tracesSampleRate to 1.0 to capture 100%
|
// Setting this option to true will print useful information to the console while you're setting up Sentry.
|
||||||
// of transactions for tracing.
|
debug: false,
|
||||||
// We recommend adjusting this value in production
|
|
||||||
// Learn more at
|
|
||||||
// https://docs.sentry.io/platforms/javascript/configuration/options/#traces-sample-rate
|
|
||||||
tracesSampleRate: 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
|
|
||||||
});
|
});
|
||||||
|
16
src/app/(sentry)/api/sentry/example/route.ts
Normal file
16
src/app/(sentry)/api/sentry/example/route.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
|
||||||
|
export const dynamic = 'force-dynamic';
|
||||||
|
class SentryExampleAPIError extends Error {
|
||||||
|
constructor(message: string | undefined) {
|
||||||
|
super(message);
|
||||||
|
this.name = 'SentryExampleAPIError';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// A faulty API route to test Sentry's error monitoring
|
||||||
|
export function GET() {
|
||||||
|
throw new SentryExampleAPIError(
|
||||||
|
'This error is raised on the backend called by the example page.',
|
||||||
|
);
|
||||||
|
return NextResponse.json({ data: 'Testing Sentry Error...' });
|
||||||
|
}
|
@ -4,14 +4,51 @@ import { FetchDataSteps } from '@/components/default/tutorial';
|
|||||||
import { InfoIcon } from 'lucide-react';
|
import { InfoIcon } from 'lucide-react';
|
||||||
import { getUser } from '@/lib/actions';
|
import { getUser } from '@/lib/actions';
|
||||||
import type { User } from '@/utils/supabase';
|
import type { User } from '@/utils/supabase';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { TestSentryCard } from '@/components/default/sentry';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
Separator,
|
||||||
|
} from '@/components/ui';
|
||||||
|
|
||||||
const HomePage = async () => {
|
const HomePage = async () => {
|
||||||
const response = await getUser();
|
const response = await getUser();
|
||||||
if (!response.success || !response.data) {
|
if (!response.success || !response.data) {
|
||||||
return (
|
return (
|
||||||
<main className='w-full items-center justify-center'>
|
<main className='w-full items-center justify-center'>
|
||||||
<div className='flex p-5 items-center justify-center'>
|
<div className='flex flex-col p-5 items-center justify-center space-y-6'>
|
||||||
<h1>Make sure you can sign in!</h1>
|
<Card className='md:min-w-2xl'>
|
||||||
|
<CardHeader className='flex flex-col items-center'>
|
||||||
|
<CardTitle className='text-3xl'>
|
||||||
|
Welcome to the T3 Supabase Template!
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription className='text-[1.0rem] mb-2'>
|
||||||
|
A great place to start is by creating a new user account &
|
||||||
|
ensuring you can sign in!
|
||||||
|
</CardDescription>
|
||||||
|
<Button
|
||||||
|
asChild
|
||||||
|
size='sm'
|
||||||
|
variant={'default'}
|
||||||
|
className='w-1/3 items-center'
|
||||||
|
>
|
||||||
|
<Link href='/sign-up'>Sign up</Link>
|
||||||
|
</Button>
|
||||||
|
</CardHeader>
|
||||||
|
<Separator className='bg-accent' />
|
||||||
|
<CardContent className='flex flex-col px-5 py-2 items-center justify-center'>
|
||||||
|
<CardTitle className='text-lg mb-6 w-2/3 text-center'>
|
||||||
|
You can also test out your connection to Sentry if you want to
|
||||||
|
start there!
|
||||||
|
</CardTitle>
|
||||||
|
<TestSentryCard />
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
@ -30,14 +67,15 @@ const HomePage = async () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex flex-col gap-2 items-start'>
|
<div className='flex flex-col gap-2 items-start'>
|
||||||
<h2 className='font-bold text-2xl mb-4'>Your user details</h2>
|
<h2 className='font-bold text-3xl mb-4'>Your user details</h2>
|
||||||
<pre
|
<pre
|
||||||
className='text-xs font-mono p-3 rounded
|
className='text-sm font-mono p-3 rounded
|
||||||
border max-h-32 overflow-auto'
|
border max-h-50 overflow-auto'
|
||||||
>
|
>
|
||||||
{JSON.stringify(user, null, 2)}
|
{JSON.stringify(user, null, 2)}
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
<TestSentryCard />
|
||||||
<div>
|
<div>
|
||||||
<h2 className='font-bold text-2xl mb-4'>Next steps</h2>
|
<h2 className='font-bold text-2xl mb-4'>Next steps</h2>
|
||||||
<FetchDataSteps />
|
<FetchDataSteps />
|
||||||
|
125
src/components/default/sentry/TestSentry.tsx
Normal file
125
src/components/default/sentry/TestSentry.tsx
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import * as Sentry from '@sentry/nextjs';
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
Separator,
|
||||||
|
} from '@/components/ui';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { CheckCircle, MessageCircleWarning } from 'lucide-react';
|
||||||
|
|
||||||
|
class SentryExampleFrontendError extends Error {
|
||||||
|
constructor(message: string | undefined) {
|
||||||
|
super(message);
|
||||||
|
this.name = 'SentryExampleFrontendError';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TestSentryCard = () => {
|
||||||
|
const [hasSentError, setHasSentError] = useState(false);
|
||||||
|
const [isConnected, setIsConnected] = useState(true);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const checkConnectivity = async () => {
|
||||||
|
const result = await Sentry.diagnoseSdkConnectivity();
|
||||||
|
setIsConnected(result !== 'sentry-unreachable');
|
||||||
|
};
|
||||||
|
checkConnectivity().catch((error) => {
|
||||||
|
console.error('Error trying to connect to Sentry: ', error);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const createError = async () => {
|
||||||
|
await Sentry.startSpan(
|
||||||
|
{
|
||||||
|
name: 'Example Frontend Span',
|
||||||
|
op: 'test',
|
||||||
|
},
|
||||||
|
async () => {
|
||||||
|
const res = await fetch('/api/sentry/example');
|
||||||
|
if (!res.ok) {
|
||||||
|
setHasSentError(true);
|
||||||
|
throw new SentryExampleFrontendError(
|
||||||
|
'This error is raised in our TestSentry component on the main page.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<div className='flex flex-row my-auto space-x-4'>
|
||||||
|
<svg
|
||||||
|
height='40'
|
||||||
|
width='40'
|
||||||
|
fill='none'
|
||||||
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d='M21.85 2.995a3.698 3.698 0 0 1 1.353 1.354l16.303 28.278a3.703 3.703 0 0 1-1.354 5.053 3.694 3.694 0 0 1-1.848.496h-3.828a31.149 31.149 0 0 0 0-3.09h3.815a.61.61 0 0 0 .537-.917L20.523 5.893a.61.61 0 0 0-1.057 0l-3.739 6.494a28.948 28.948 0 0 1 9.63 10.453 28.988 28.988 0 0 1 3.499 13.78v1.542h-9.852v-1.544a19.106 19.106 0 0 0-2.182-8.85 19.08 19.08 0 0 0-6.032-6.829l-1.85 3.208a15.377 15.377 0 0 1 6.382 12.484v1.542H3.696A3.694 3.694 0 0 1 0 34.473c0-.648.17-1.286.494-1.849l2.33-4.074a8.562 8.562 0 0 1 2.689 1.536L3.158 34.17a.611.611 0 0 0 .538.917h8.448a12.481 12.481 0 0 0-6.037-9.09l-1.344-.772 4.908-8.545 1.344.77a22.16 22.16 0 0 1 7.705 7.444 22.193 22.193 0 0 1 3.316 10.193h3.699a25.892 25.892 0 0 0-3.811-12.033 25.856 25.856 0 0 0-9.046-8.796l-1.344-.772 5.269-9.136a3.698 3.698 0 0 1 3.2-1.849c.648 0 1.285.17 1.847.495Z'
|
||||||
|
fill='currentcolor'
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<CardTitle className='text-3xl my-auto'>Test Sentry</CardTitle>
|
||||||
|
</div>
|
||||||
|
<CardDescription className='text-[1.0rem]'>
|
||||||
|
Click the button below & view the sample error on{' '}
|
||||||
|
<Link
|
||||||
|
href={`${process.env.NEXT_PUBLIC_SENTRY_URL}`}
|
||||||
|
className='text-accent-foreground underline hover:text-primary'
|
||||||
|
>
|
||||||
|
the Sentry website
|
||||||
|
</Link>
|
||||||
|
. Navigate to the {"'"}Issues{"'"} page & you should see the sample
|
||||||
|
error!
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className='flex flex-row gap-4 my-auto'>
|
||||||
|
<Button
|
||||||
|
type='button'
|
||||||
|
onClick={createError}
|
||||||
|
className='cursor-pointer text-md my-auto py-6'
|
||||||
|
>
|
||||||
|
<span>Throw Sample Error</span>
|
||||||
|
</Button>
|
||||||
|
{hasSentError ? (
|
||||||
|
<div className='rounded-md bg-green-500/80 dark:bg-green-500/50 py-2 px-4 flex flex-row gap-2 my-auto'>
|
||||||
|
<CheckCircle size={30} className='my-auto' />
|
||||||
|
<p className='text-lg'>Sample error was sent to Sentry!</p>
|
||||||
|
</div>
|
||||||
|
) : !isConnected ? (
|
||||||
|
<div className='rounded-md bg-red-600/50 dark:bg-red-500/50 py-2 px-4 flex flex-row gap-2 my-auto'>
|
||||||
|
<MessageCircleWarning size={40} className='my-auto' />
|
||||||
|
<p>
|
||||||
|
Wait! The Sentry SDK is not able to reach Sentry right now -
|
||||||
|
this may be due to an adblocker. For more information, see{' '}
|
||||||
|
<Link
|
||||||
|
href='https://docs.sentry.io/platforms/javascript/guides/nextjs/troubleshooting/#the-sdk-is-not-sending-any-data'
|
||||||
|
className='text-accent-foreground underline hover:text-primary'
|
||||||
|
>
|
||||||
|
the troubleshooting guide.
|
||||||
|
</Link>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className='success_placeholder' />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<Separator className='my-4 bg-accent' />
|
||||||
|
<p className='description'>
|
||||||
|
Warning! Sometimes Adblockers will prevent errors from being sent to
|
||||||
|
Sentry.
|
||||||
|
</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
1
src/components/default/sentry/index.tsx
Normal file
1
src/components/default/sentry/index.tsx
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { TestSentryCard } from './TestSentry';
|
13
src/env.js
13
src/env.js
@ -7,11 +7,12 @@ export const env = createEnv({
|
|||||||
* This way you can ensure the app isn't built with invalid env vars.
|
* This way you can ensure the app isn't built with invalid env vars.
|
||||||
*/
|
*/
|
||||||
server: {
|
server: {
|
||||||
NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),
|
NODE_ENV: z
|
||||||
|
.enum(['development', 'test', 'production'])
|
||||||
|
.default('development'),
|
||||||
NEXT_RUNTIME: z.enum(['nodejs', 'edge']).default('nodejs'),
|
NEXT_RUNTIME: z.enum(['nodejs', 'edge']).default('nodejs'),
|
||||||
SENTRY_URL: z.string().url().default('https://sentry.gbrown.org'),
|
|
||||||
SENTRY_AUTH_TOKEN: z.string().min(1),
|
SENTRY_AUTH_TOKEN: z.string().min(1),
|
||||||
CI: z.enum(['true', 'false']).default('true'),
|
CI: z.enum(['true', 'false']).default('false'),
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,6 +25,10 @@ export const env = createEnv({
|
|||||||
NEXT_PUBLIC_SUPABASE_ANON_KEY: z.string().min(1),
|
NEXT_PUBLIC_SUPABASE_ANON_KEY: z.string().min(1),
|
||||||
NEXT_PUBLIC_SITE_URL: z.string().url().default('http://localhost:3000'),
|
NEXT_PUBLIC_SITE_URL: z.string().url().default('http://localhost:3000'),
|
||||||
NEXT_PUBLIC_SENTRY_DSN: z.string().min(1),
|
NEXT_PUBLIC_SENTRY_DSN: z.string().min(1),
|
||||||
|
NEXT_PUBLIC_SENTRY_URL: z
|
||||||
|
.string()
|
||||||
|
.url()
|
||||||
|
.default('https://sentry.gbrown.org'),
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,7 +38,6 @@ export const env = createEnv({
|
|||||||
runtimeEnv: {
|
runtimeEnv: {
|
||||||
NODE_ENV: process.env.NODE_ENV,
|
NODE_ENV: process.env.NODE_ENV,
|
||||||
NEXT_RUNTIME: process.env.NEXT_RUNTIME,
|
NEXT_RUNTIME: process.env.NEXT_RUNTIME,
|
||||||
SENTRY_URL: process.env.SENTRY_URL,
|
|
||||||
SENTRY_AUTH_TOKEN: process.env.SENTRY_AUTH_TOKEN,
|
SENTRY_AUTH_TOKEN: process.env.SENTRY_AUTH_TOKEN,
|
||||||
CI: process.env.CI,
|
CI: process.env.CI,
|
||||||
|
|
||||||
@ -41,6 +45,7 @@ export const env = createEnv({
|
|||||||
NEXT_PUBLIC_SUPABASE_ANON_KEY: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
|
NEXT_PUBLIC_SUPABASE_ANON_KEY: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
|
||||||
NEXT_PUBLIC_SITE_URL: process.env.NEXT_PUBLIC_SITE_URL,
|
NEXT_PUBLIC_SITE_URL: process.env.NEXT_PUBLIC_SITE_URL,
|
||||||
NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
||||||
|
NEXT_PUBLIC_SENTRY_URL: process.env.NEXT_PUBLIC_SENTRY_URL,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially
|
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
|
// This file configures the initialization of Sentry on the client.
|
||||||
|
// The added config here will be used whenever a users loads a page in their browser.
|
||||||
|
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
|
||||||
import * as Sentry from '@sentry/nextjs';
|
import * as Sentry from '@sentry/nextjs';
|
||||||
import './src/env.js';
|
|
||||||
|
|
||||||
Sentry.init({
|
Sentry.init({
|
||||||
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN!,
|
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN!,
|
@ -1,7 +1,6 @@
|
|||||||
import * as Sentry from '@sentry/nextjs';
|
import * as Sentry from '@sentry/nextjs';
|
||||||
import type { Instrumentation } from 'next';
|
import type { Instrumentation } from 'next';
|
||||||
|
|
||||||
|
|
||||||
export const register = async () => {
|
export const register = async () => {
|
||||||
if (process.env.NEXT_RUNTIME === 'edge') {
|
if (process.env.NEXT_RUNTIME === 'edge') {
|
||||||
await import('../sentry.edge.config');
|
await import('../sentry.edge.config');
|
||||||
|
Reference in New Issue
Block a user