Next.js+Vercel 및 Sentry 결합
개요
Next.다음은 js+Vercel에서 사용되는 응용 프로그램을 Sentry와 결합시키는 절차입니다.
이번에는 자신이 실제 개발·운용한 서비스친구/친구에 이러한 설정을 추가해 실제 설정 내용에 따라 설명한다.
LGTMeow
독자 대상
Next.js의 응용 프로그램을 Vercel로 설계한 사람을 대상 독자로 삼다.
사전 준비
Sentry에 서명
다음 페이지에서 서명을 시작합니다.
GiitHub 계정을 이용해서 만들었어요.
Sentryorganization의 제작
다음 페이지에서 작성합니다.
GiitHub Organization과 같은 이름으로 만들었어요.
Sentry 프로젝트 제작
프로젝트를 작성합니다.
I'll create my own alerts later
응용 프로그램에서 Sentry 설정
왼쪽'프로젝트'에서 제작된 프로젝트를 확인할 수 있을 것 같습니다.
설치 방법을 누르면 응용 프로그램 설정 화면이 나타나므로 Next.js 를 선택합니다.
Next.js를 선택하면 다음과 같은 설치 방법을 보여 줍니다.
여기에 기재된 내용에 따라 패키지 설치와 설정 파일 수정 등을 진행한다.
@sentry/nextjs 설치 및 설정
다음을 수행합니다.
npm install --save @sentry/nextjs
Sentrywizard의 실행
다음을 수행합니다.
npx @sentry/wizard -i nextjs
브라우저에서 다음 페이지가 열립니다.Sentry의 인증 엔드포인트로 마이그레이션하고 토큰을 가져오는 중일 수 있습니다.(확인되지 않음)
터미널에서 사용할 항목을 선택하는 화면입니다. 선택하십시오.
항목을 선택하면 Sentrywizard가 완료됩니다.
다양한 파일을 생성, 수정합니다.
Sentrywizard에서 추가된 파일
sentry.client.config.js
// This file configures the initialization of Sentry on the browser.
// The config you add here will be used whenever a page is visited.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
import * as Sentry from '@sentry/nextjs';
const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
Sentry.init({
dsn: SENTRY_DSN || 'https://[email protected]/0000000',
// Adjust this value in production, or use tracesSampler for greater control
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
});
sentry.server.config.js// 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';
const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
Sentry.init({
dsn: SENTRY_DSN || 'https://[email protected]/0000000',
// Adjust this value in production, or use tracesSampler for greater control
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
});
sentry.propertiesdefaults.url=https://sentry.io/
defaults.org=あなたのSentry organization名
defaults.project=あなたのSentryプロジェクト名
cli.executable=../../.npm/_npx/xxxxxxxxxxxxxxxx/node_modules/@sentry/cli/bin/sentry-cli
next.config.js// This file sets a custom webpack configuration to use your Next.js app
// with Sentry.
// https://nextjs.org/docs/api-reference/next.config.js/introduction
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
const { withSentryConfig } = require('@sentry/nextjs');
const moduleExports = {
// Your existing module.exports
};
const sentryWebpackPluginOptions = {
// Additional config options for the Sentry Webpack plugin. Keep in mind that
// the following options are set automatically, and overriding them is not
// recommended:
// release, url, org, project, authToken, configFile, stripPrefix,
// urlPrefix, include, ignore
silent: true, // Suppresses all logs
// For all available options, see:
// https://github.com/getsentry/sentry-webpack-plugin#options.
};
// Make sure adding Sentry options is the last code to run before exporting, to
// ensure that your source maps include changes from all other Webpack plugins
module.exports = withSentryConfig(moduleExports, sentryWebpackPluginOptions);
src/pages/_error.jsimport NextErrorComponent from 'next/error';
import * as Sentry from '@sentry/nextjs';
const MyError = ({ statusCode, hasGetInitialPropsRun, err }) => {
if (!hasGetInitialPropsRun && err) {
// getInitialProps is not called in case of
// https://github.com/vercel/next.js/issues/8592. As a workaround, we pass
// err via _app.js so it can be captured
Sentry.captureException(err);
// Flushing is not required in this case as it only happens on the client
}
return <NextErrorComponent statusCode={statusCode} />;
};
MyError.getInitialProps = async (context) => {
const errorInitialProps = await NextErrorComponent.getInitialProps(context);
const { res, err, asPath } = context;
// Workaround for https://github.com/vercel/next.js/issues/8592, mark when
// getInitialProps has run
errorInitialProps.hasGetInitialPropsRun = true;
// Returning early because we don't want to log 404 errors to Sentry.
if (res?.statusCode === 404) {
return errorInitialProps;
}
// Running on the server, the response object (`res`) is available.
//
// Next.js will pass an err on the server if a page's data fetching methods
// threw or returned a Promise that rejected
//
// Running on the client (browser), Next.js will provide an err if:
//
// - a page's `getInitialProps` threw or returned a Promise that rejected
// - an exception was thrown somewhere in the React lifecycle (render,
// componentDidMount, etc) that was caught by Next.js's React Error
// Boundary. Read more about what types of exceptions are caught by Error
// Boundaries: https://reactjs.org/docs/error-boundaries.html
if (err) {
Sentry.captureException(err);
// Flushing before returning is necessary if deploying to Vercel, see
// https://vercel.com/docs/platform/limits#streaming-responses
await Sentry.flush(2000);
return errorInitialProps;
}
// If this point is reached, getInitialProps was called without any
// information about what the error might be. This is unexpected and may
// indicate a bug introduced in Next.js, so record it in Sentry
Sentry.captureException(
new Error(`_error.js getInitialProps missing data at path: ${asPath}`),
);
await Sentry.flush(2000);
return errorInitialProps;
};
export default MyError;
.sentryclirc[auth]
token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
next.config.정보
프로젝트 경로가
next.config.js
이미 존재하면 next.config.wizardcopy.js
의 이름으로 생성됩니다.대다수 항목
next.config.js
이 이미 존재하기 때문에 대다수 상황에서 생성된다next.config.wizardcopy.js
.이 경우 기존
next.config.js
과 합병해야 한다.필자의 환경
next.config.js
은 다음과 같다.next.config.js
const { withSentryConfig } = require('@sentry/nextjs');
/**
* @type {import('next').NextConfig}
*/
const moduleExports = {
images: {
domains: ['lgtm-images.lgtmeow.com', 'stg-lgtm-images.lgtmeow.com'],
},
swcMinify: true,
};
const sentryWebpackPluginOptions = {
silent: true,
};
module.exports = withSentryConfig(moduleExports, sentryWebpackPluginOptions);
필자가 확인하지 않았을 때withSentryConfig
이외에 여러 플러그인을 사용할 때 가 비교적 좋다.미리 참고 가치가 있는 보도를 붙이다.
(참고 자료)next-compose-plugins
src/pages/_error.정보
필자의 환경에서 만들었다
src/pages/_error.tsx
.따라서 생성된
src/pages/_error.js
내용을 병합하면서 TypeScript의 대응을 할 필요가 있다.AS를 사용하여 강제로 해결하는 형식이 있는 부분도 있지만, 잠시 이 동작을 사용했습니다.
src/pages/_error.tsx
import * as Sentry from '@sentry/nextjs';
import { NextPage, NextPageContext } from 'next';
import NextErrorComponent from 'next/error';
import { httpStatusCode, HttpStatusCode } from '../constants/httpStatusCode';
type Props = {
statusCode: HttpStatusCode;
err?: Error;
hasGetInitialPropsRun?: boolean;
};
const CustomErrorPage: NextPage<Props> = ({
statusCode,
hasGetInitialPropsRun,
err,
}) => {
if (!hasGetInitialPropsRun && err) {
Sentry.captureException(err);
}
return <NextErrorComponent statusCode={statusCode} />;
};
const defaultTimeout = 2000;
CustomErrorPage.getInitialProps = async (
context: NextPageContext,
): Promise<Props> => {
const errorInitialProps = (await NextErrorComponent.getInitialProps(
context,
)) as Props;
const { res, err, asPath } = context;
errorInitialProps.hasGetInitialPropsRun = true;
if (res?.statusCode === httpStatusCode.notFound) {
return errorInitialProps;
}
if (err) {
Sentry.captureException(err);
await Sentry.flush(defaultTimeout);
return errorInitialProps;
}
Sentry.captureException(
new Error(`_error.tsx getInitialProps missing data at path: ${asPath}`),
);
await Sentry.flush(defaultTimeout);
return errorInitialProps;
};
export default CustomErrorPage;
뒷말import { httpStatusCode, HttpStatusCode } from '../constants/httpStatusCode';
부분은 HTTP 상태 코드를 나타내는 내용이다.src/constants/httpStatusCode.ts
// https://developer.mozilla.org/ja/docs/Web/HTTP/Status から必要なものを抜粋して定義
export const httpStatusCode = {
ok: 200,
created: 201,
accepted: 202,
noContent: 204,
movedPermanently: 301,
badRequest: 400,
unauthorized: 401,
forbidden: 403,
notFound: 404,
requestTimeout: 408,
unprocessableEntity: 422,
internalServerError: 500,
serviceUnavailable: 503,
} as const;
export type HttpStatusCode = typeof httpStatusCode[keyof typeof httpStatusCode];
Sentrywizard에서 업데이트된 파일
.gitignore
에는 다음과 같은 내용이 추가된다..sentryclirc
에 기밀정보 영패가 기재돼 있어 제출할 수 없음을 고려했다..gitignore
# Sentry
.sentryclirc
Next.js API Route 정보
Next.js의 API Route를 사용하는 경우 매개변수
withSentry
에 함수를 전달하도록 수정됩니다.이렇게 하면 API Route 내에서 발생한 Error도 Sentry에 의해 공지됩니다.
import type { NextApiRequest, NextApiResponse } from "next"
import { withSentry } from "@sentry/nextjs";
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
res.status(200).json({ name: "John Doe" });
};
export default withSentry(handler);
Sentry에 오류가 발생했는지 로컬에서 확인
적당한 단추를 눌렀을 때 예외가 발생하도록 프로그램 서버를 시작합니다.
왼쪽 메뉴의 과제를 확인하면 오류 발송을 확인할 수 있다.
자세한 내용을 확인하면 오류 발생 시 브라우저 정보와 IP 주소 등을 확인할 수 있습니다.
Vercel 및 Sentry 제휴
Sentry Integration을 사용하는 것이 가장 간단하므로 먼저 단계를 구현합니다.
Next.Vercel의 합작을 가볍게 하는 일
추가할 Vercel의 Teams를 선택합니다.
여기서 필요한 Vercel 항목만 선택합니다.
Install Vercel 키를 누릅니다.
Vercel 항목과 Sentry 항목을 연합하여 "Compulete on Vercel"을 누릅니다.
이렇게 하면 완성된다.Vercel에서 환경 변수를 확인한 후 Sentry에서 추가한 환경 변수를 확인할 수 있습니다.
필요한 환경 변수는 문제없습니다.
handler
에서 읽을 수 있는 설정입니다.필요에 따라 설정을 변경하여
Production
,Preview
도 읽을 수 있도록 한다.Vercel에서 작업 확인
Sentry Integration은 Sentry 작업에 필요한 환경 변수를 추가하기 때문에 각 설정 파일도 환경 변수에서 필요한 값을 로드하는 것으로 변경됩니다.
Development의 수정 사항
next.config.js
,authToken
,org
는 환경 변수에서 불러오는 것으로 변경되었다.next.config.js
const { withSentryConfig } = require('@sentry/nextjs');
/**
* @type {import('next').NextConfig}
*/
const moduleExports = {
// 任意の設定
};
const sentryWebpackPluginOptions = {
silent: true,
authToken: process.env.SENTRY_AUTH_TOKEN,
org: process.env.SENTRY_ORG,
project: process.env.SENTRY_PROJECT,
};
module.exports = withSentryConfig(moduleExports, sentryWebpackPluginOptions);
project , sentry.client.config.js
내용이 모두 같다.
Vercel에 등록된
sentry.server.config.js
를 참조합니다.그런 다음 설정
dsn
합니다.이걸 설정하면 어느 환경에서 일어났는지 Sentry에서 쉽게 알 수 있으니 추천해드려요.
필자는 환경 변수
NEXT_PUBLIC_SENTRY_DSN
를 다음과 같이 정의했다.environment
를 지정하여 로컬 환경에서 발생하는 ErrorNEXT_PUBLIC_APP_ENV
Vercel의 개발 환경에서 발생한 Errorlocal
, Vercel의 공식 환경에서 발생한 Error↓ 이렇게 필터링이 가능하고 공지할 때 공식 환경에서 일어나는 것만 공지하는 등 대응이 가능해져 편리하다.
sentry.client.config.js
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
environment: process.env.NEXT_PUBLIC_APP_ENV,
tracesSampleRate: 1.0,
});
sentry.server.config.jsimport * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
environment: process.env.NEXT_PUBLIC_APP_ENV,
tracesSampleRate: 1.0,
});
개발자 삭제
production
,sentry.properties
,authToken
는 환경 변수에서 불러왔기 때문에 이 파일은 삭제되었고 문제가 없습니다.Vercel에서 디버깅 후 동작 확인
다음과 같이 Vercel에서 발생한 Error에게도 공지가 있는지 확인할 수 있습니다.
끝말
다음은
org
를 사용하는 Sentry 설정에 대한 설명입니다.환경 변수의 추가를 잊고 움직이지 않거나 푹 빠진 부분도 있기 때문에 정리해봤습니다.
이 기사는 입문을 위한 것이지만 좀 더 실천적인 내용https://vercel.com/integrations/sentry/add을 설명해 준 사람이 있기 때문에 참고 링크로 게재됐다.
이 기사에서 Sentry를 가져온 후 읽는 것을 추천합니다.
Next.js에서 Sentry를 가져올 때의 과제와 해결 방법
이상입니다.끝까지 읽어주셔서 감사합니다.
Reference
이 문제에 관하여(Next.js+Vercel 및 Sentry 결합), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/keitakn/articles/add-sentry-to-nextjs-vercel텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)