Next.js: サヌバヌ偎でログを報告するための゚ラヌをキャッチしお凊理する方法

䜜成日 2017幎05月02日  Â·  74コメント  Â·  ゜ヌス: vercel/next.js

こんにちは、
サヌバヌ偎ずクラむアント偎の䞡方で、Sentryツヌルに゚ラヌを送信したい状況にありたす。

このアプリは、Expressをカスタムサヌバヌずしお䜿甚したす。 基本的に、Expressアプリを䜜成し、いく぀かのミドルりェアを適甚したすが、実際のすべおのゞョブをnext.jsハンドルに委任したす。

  const app = nextJs({ dev: process.env.NODE_ENV !== 'production' });
  const handler = routes.getRequestHandler(app);
  const expressApp = express();

  ...
  ...

  expressApp.use(morgan('combined', { stream: logger.stream }));
  expressApp.use(statsdMiddleware);

  // Add security
  expressApp.use(helmet());

  // Sentry handler
  expressApp.use(sentry.requestHandler());

  // Load locale and translation messages
  expressApp.use(i18n);

  // Next.js handler
  expressApp.use(handler);

  // Sentry error handler.
  // MUST be placed before any other express error handler !!!
  expressApp.use(sentry.errorHandler());

このアプロヌチでは、next.jsがレンダリングプロセスを制埡し、゚ラヌはnext.jsによっおキャッチされたす。これを凊理する唯䞀の方法は、 _error.jsペヌゞファむルをオヌバヌラむドするこずです。

その_error.jsファむル内で、Sentryに゚ラヌを報告するための普遍的な方法が必芁です。 珟圚、2぀のラむブラリがありたすノヌド甚のravenずjavascript甚のraven-js 。 問題は、 ravenがSSRで機胜するが、webpackがバンドルをビルドするずきに倱敗し、XMLHTTPRequestの䟝存関係のためにraven-js倱敗するため、䞡方をむンポヌトできないこずです。

サヌバヌ偎でnext.js゚ラヌを通知する方法はありたすか

story feature request

最も参考になるコメント

_unortodox_゜リュヌションが倧奜きです

function installErrorHandler(app) {
  const _renderErrorToHTML = app.renderErrorToHTML.bind(app)
  const errorHandler = rollbar.errorHandler()

  app.renderErrorToHTML = (err, req, res, pathname, query) => {
    if (err) {
      errorHandler(err, req, res, () => {})
    }

    return _renderErrorToHTML(err, req, res, pathname, query)
  }

  return app
}
// ¯\_(ツ)_/¯

党おのコメント74件

クラむアント偎で゚ラヌをログに蚘録するために、次のこずを行っおいたす。
https://gist.github.com/jgautheron/044b88307d934d486f59ae87c5a5a5a0

基本的にサヌバヌに゚ラヌを送信したす。゚ラヌは最終的にstdoutに出力され、 Dockerロギングドラむバヌによっおキャッチされたす。
react-guardでSSR゚ラヌを正垞に怜出し、コアNextファむルをオヌバヌラむドする必芁はありたせん。

私もこの問題を抱えおいたす。 私は疑問に思いたす次のhandleRequestから拒吊された玄束を返すだけで十分でしょうか ぀たり、ここのコヌドを次のように倉曎したす。

handleRequest (req, res, parsedUrl) {
  // .....snip....

   return this.run(req, res, parsedUrl)
     .catch((err) => {
       if (!this.quiet) console.error(err)
       res.statusCode = 500
       res.end(STATUS_CODES[500])

       // rethrow error to create new, rejected promise 
       throw err;
     })
}

次に、ナヌザヌコヌドで

const app = nextJs({ dev: process.env.NODE_ENV !== 'production' });
const nextJsHandler = app.getRequestHandler();
const expressApp = express();

app.prepare().then(() => {
   // invoke express middlewares
   // ...

   // time to run next
   expressApp.use(function(req, res, next) {
     nextJsHandler(req, res).catch(e => {
       // use rejected promise to forward error to next express middleware
       next(e)
     })
   });

   // Use standard express error middlewares to handle the error from next
   // this makes it easy to log to sentry etc.
})

@arunoda @rauchg私がすぐ䞊で提案した倉曎は

゚ラヌを再スロヌしお、それを詊しおみるこずに同意したす。
たた、 renderToHTMLでも再スロヌする必芁がありたす...

たた、サヌバヌ偎ずクラむアント偎の䞡方で、Sentryず同様のサヌビスに゚ラヌを送信したいずいう状況にありたす。

このようなサヌビス/ツヌルの最も䟡倀のある機胜は、最も予期しない問題を報告するこずであるず私は信じおいたす。これは、私の経隓では、実際の぀たり、クラむアント偎のキャッチされない゚ラヌです。 残念ながら、関連する問題2334で以前に匷調したように、Next.jsのクラむアント偎ハンドラヌはこれらの゚ラヌを自分自身に保持し、そのような他のツヌルのSentryにそれらを枡す方法はありたせん。

私たちを特に苊しめたのは、これです。クラむアント偎でReactレンダリングを行う前にキャッチされない䟋倖が発生した堎合、適切にサヌバヌ偎でレンダリングされたペヌゞが゚ラヌペヌゞずしお再レンダリングされたす。 これは優れた機胜であるず同時に、クラむアントの驚くべき郚分で既にレンダリングされたドキュメントを提䟛する利点を本質的に損なうため、むラむラする開発者゚クスペリ゚ンスず芋なすこずができたす。

問題を説明するサンプルペヌゞを次に瀺したす。

import React from 'react';

// Works well in Node 8, but crashes in Chrome<56, Firefox<48, Edge<15, Safari<10, any IE

const whoops = 'Phew, I made it to the client-side
'.padEnd(80);

export default () => <pre>{whoops}</pre>;

䞊蚘のコヌドは、サヌバヌ偎で完党にレンダリングしおクラむアントに配信できたすが、ほずんどのブラりザでペヌゞ党䜓がクラむアント偎で恐ろしい「予期しない゚ラヌが発生したした」ずいうメッセヌゞに眮き換えられる前に、䞍芁なコンテンツのフラッシュになりたす。 、 Sentry たたは他のサヌビス/ツヌルにたせん。

この「゚ラヌの飲み蟌み」は、ほずんどのクラむアント偎の゚ラヌ報告ツヌルがフックする暙準のonerrorハンドラヌたたは、クラむアント偎の非同期性を考えるずより適切な、より珟代的ではあるが普及しおいないonunhandledrejection の掻甚も防ぎたす。コヌド。

考えられるクラむアント偎の解決策

私の知る限り、このタむプのpre-Reactクラむアント偎゚ラヌは、Next.jsのclient / index.jsのtry / catchブロックに飲み蟌たれたす。 Componentレンダリングされる皋床の倀に再割り圓おされErrorComponent 珟圚の線67-72 。

Next.jsの䜜成者およびメンテナの皆様、レンダリング内容を制埡するために、次のアむデアの䞭で䜕が蚱容可胜/可胜であるず思いたすか。

  • この皮の゚ラヌを凊理するために、client / index.jsのcatchブロックにフックを導入したすか
  • ゚ラヌが怜出された堎合は、onerror / onunhandledrejectionハンドラヌに゚ラヌを送信したすか
  • ゚ラヌを再スロヌするオプションを提䟛したすか
  • ゚ラヌコンポヌネントを衚瀺しないオプションを提䟛したすか
  • カスタム゚ラヌコンポヌネントを衚瀺するオプションを提䟛したすか

この皮の゚ラヌを凊理するために、client / index.jsのそのcatchブロックにフックを導入したすか
゚ラヌが怜出された堎合は、onerror / onunhandledrejectionハンドラヌに゚ラヌを送信したすか

これは私たちが瀟内で話し合ったこずです。 そしお、私たちはすぐに察凊したす。

私はSentry.ioを䜿甚しお゚ラヌを報告しおいたすが、適甚する解決策は次のずおりです。

1-サヌバヌ偎でravenノヌドを構成したす
2-クラむアント偎でravenjsを構成したす _document 。

この2぀の手順で、クラむアントずサヌバヌの䞡方で未凊理の䟋倖をキャッチしたす。

3- _errorペヌゞを䜜成したす。 nextjsがリク゚ストを凊理するずクラむアント偎かサヌバヌ偎かに関係なく、そのペヌゞがレンダリングされるず゚ラヌが発生したす。 _errorペヌゞのgetInitialPropsメ゜ッドで、歩哚に゚ラヌを報告したす。

クラむアントconst Raven = require('raven-js');たたはサヌバヌ偎const Raven = require('raven');どちらにいるかに応じお、動的にむンポヌトしおraven-nodeたたはravenjsが解決されるかどうかをロヌドする方法を決定する方法。
ravenモゞュヌルサヌバヌ偎のモゞュヌルをバンドルしないようにwebpackを構成したこずに泚意しおください。これにより、 next.config.jsが次のように曎新されたす。

const webpack = require('webpack');

module.exports = {
  // Do not show the X-Powered-By header in the responses
  poweredByHeader: false,
  webpack: (config) => {
    config.plugins.push(new webpack.IgnorePlugin(/^raven$/));
    return config;
  },
};

@acanimal

2-クラむアント偎でravenjsを構成したすこれは_documentで行いたした。

_document.js raven-jsをどのように蚭定したか教えおいただけたすか ゚ラヌが発生しおも歩哚は䜕も起こらないので、うたくいきたせん。

_error.jsペヌゞですべおの゚ラヌを手動で歩哚に送信する必芁がありたすか

// _document constructor
constructor(props) {
    super(props);
    Raven
      .config('...')
      .install();
}

Next.jsは、 quietに蚭定しない限り、サヌバヌ䞊のconsole.errorに゚ラヌを出力したす。

Sentryを䜿甚するず、 autoBreadcrumbsを有効にしおこの出力をキャプチャしおから、独自のメッセヌゞを手動でキャプチャできたす。 タむトルはわかりにくくなりたすが、スタックトレヌス党䜓が含たれたす。

実装䟋

const express = require('express');
const nextjs = require('next');
const Raven = require('raven');

const dev = process.env.NODE_ENV !== 'production';

// Must configure Raven before doing anything else with it
if (!dev) {
  Raven.config('__DSN__', {
    autoBreadcrumbs: true,
    captureUnhandledRejections: true,
  }).install();
}

const app = nextjs({ dev });
const handle = app.getRequestHandler();

const captureMessage = (req, res) => () => {
  if (res.statusCode > 200) {
    Raven.captureMessage(`Next.js Server Side Error: ${res.statusCode}`, {
      req,
      res,
    });
  }
};

app
  .prepare()
  .then(() => {
    const server = express();

    if (!dev) {
      server.use((req, res, next) => {
        res.on('close', captureMessage(req, res));
        res.on('finish', captureMessage(req, res));
        next();
      });
    }

    [...]

    server.get('/', (req, res) => {
      return app.render(req, res, '/home', req.query)
    })

    server.get('*', (req, res) => {
      return handle(req, res)
    })

    server.listen('3000', (err) => {
      if (err) throw err
      console.log(`> Ready on http://localhost:${port}`)
    })
  })
  .catch(ex => {
    console.error(ex.stack);
    process.exit(1);
  });

これは、実際のコヌドを応甚した非垞に工倫された䟋です。 私はこの圢匏でそれをテストしおいたせん。 壊れたら教えおください。

もちろん、Next.jsがこれらの゚ラヌをExpressに枡すこずができれば、それでも最善です。そうすれば、Sentry / Express統合をすぐに䜿甚できたす。

@tusgavomelo返信が遅くなっおすみたせん。

曎新がありたす。 私たちのアプリには、クラむアント偎たたはサヌバヌ偎にいる堎合にRavenむンスタンスを考慮に入れるためのメ゜ッドを含むヘルパヌファむルがありたす。

let clientInstance;
let serverInstance;

const getRavenInstance = (key, config) => {
  const clientSide = typeof window !== 'undefined';

  if (clientSide) {
    if (!clientInstance) {
      const Raven = require('raven-js');  // eslint-disable-line global-require
      Raven.config(key, config).install();
      clientInstance = Raven;
    }

    return clientInstance;
  }

  if (!serverInstance) {
    // NOTE: raven (for node) is not bundled by webpack (see rules in next.config.js).
    const RavenNode = require('raven'); // eslint-disable-line global-require
    RavenNode.config(key, config).install();
    serverInstance = RavenNode;
  }
  return serverInstance;
};

このコヌドは、サヌバヌ偎リク゚ストが到着したずきずクラむアント偎の䞡方で実行されたす。 ravenパッケヌゞのバンドルを回避するために、webpack next.config.jsファむルを構成したした。

@acanimalあなたは倚分実甚的な䟋を提䟛できたすか フルスタックトレヌスを取埗しおいないようですか たたは倚分あなたはあなたの_error.jsを投皿できたすか

_error.jsでRavenInstance.captureException(err)ようなこずをしおいたすが、発生した゚ラヌの皮類ず堎所がわかりたせん。

export default class Error extends React.Component {
  static getInitialProps({ res, err }) {
    const RavenInstance = getRavenInstance('__SENTRY__')
    if (!(err instanceof Error)) {
      err = new Error(err && err.message)
    }
    RavenInstance.captureException(err)
    // const statusCode = res ? res.statusCode : err ? err.statusCode : null;

    return { }
  }

  render() {
    return (
      <div>
        <p>An error occurred on server</p>
      </div>
    )
  }
}

モゞュヌルの再構築時に次の画面がクリアされお゚ラヌが衚瀺されないようにするには、 quietをfalseに蚭定する必芁があるため、これはカスタムロガヌのサポヌトを求める堎所のようですが、ここで実行可胜な唯䞀のハックにはquietをfalseに蚭定したす。

゚ラヌの詳现は、stderrストリヌムでも入手できたす。
process.stderr.write = error => yourErrorLog(error);

_unortodox_゜リュヌションが倧奜きです

function installErrorHandler(app) {
  const _renderErrorToHTML = app.renderErrorToHTML.bind(app)
  const errorHandler = rollbar.errorHandler()

  app.renderErrorToHTML = (err, req, res, pathname, query) => {
    if (err) {
      errorHandler(err, req, res, () => {})
    }

    return _renderErrorToHTML(err, req, res, pathname, query)
  }

  return app
}
// ¯\_(ツ)_/¯

カスタムWebpack構成なしでノヌドずブラりザヌの正しいRavenを取埗する方法のコンパクトバヌゞョン。 @acanimalコメントに觊発された

// package.json
"browser": {
    "raven": "raven-js"
}

// getRaven.js
const Raven = require('raven')

if (process.env.NODE_ENV === 'production') {
  Raven.config('YOUR_SENTRY_DSN').install()
}

module.exports = Raven

芁旚

この問題を調査しおいる人のための簡単な芁玄。

// pages/_error.js
import Raven from 'raven';
...
static async getInitialProps({ store, err, isServer }) {
   if (isServer && err) {
      // https://github.com/zeit/next.js/issues/1852
      // eslint-disable-next-line global-require
      const Raven = require('raven');

      Raven.captureException(err);
    }
    ...
// next.config.js
config.plugins.push(new webpack.IgnorePlugin(/^raven$/));

@acanimalのコメントに感謝したす。

raven 前のコメントで提案されおいるようにwebpackでは無芖しおくださいずraven-js䞡方をむンストヌルしおから、同圢のRavenをむンスタンス化するヘルパヌを䜜成したす䟋 lib/raven.js

import Raven from 'raven-js';

// https://gist.github.com/impressiver/5092952
const clientIgnores = {
  ignoreErrors: [
    'top.GLOBALS',
    'originalCreateNotification',
    'canvas.contentDocument',
    'MyApp_RemoveAllHighlights',
    'http://tt.epicplay.com',
    "Can't find variable: ZiteReader",
    'jigsaw is not defined',
    'ComboSearch is not defined',
    'http://loading.retry.widdit.com/',
    'atomicFindClose',
    'fb_xd_fragment',
    'bmi_SafeAddOnload',
    'EBCallBackMessageReceived',
    'conduitPage',
    'Script error.',
  ],
  ignoreUrls: [
    // Facebook flakiness
    /graph\.facebook\.com/i,
    // Facebook blocked
    /connect\.facebook\.net\/en_US\/all\.js/i,
    // Woopra flakiness
    /eatdifferent\.com\.woopra-ns\.com/i,
    /static\.woopra\.com\/js\/woopra\.js/i,
    // Chrome extensions
    /extensions\//i,
    /^chrome:\/\//i,
    // Other plugins
    /127\.0\.0\.1:4001\/isrunning/i, // Cacaoweb
    /webappstoolbarba\.texthelp\.com\//i,
    /metrics\.itunes\.apple\.com\.edgesuite\.net\//i,
  ],
};

const options = {
  autoBreadcrumbs: true,
  captureUnhandledRejections: true,
};

let IsomorphicRaven = null;

if (process.browser === true) {
  IsomorphicRaven = Raven;
  IsomorphicRaven.config(SENTRY_PUBLIC_DSN, {
    ...clientIgnores,
    ...options,
  }).install();
} else {
  // https://arunoda.me/blog/ssr-and-server-only-modules
  IsomorphicRaven = eval("require('raven')");
  IsomorphicRaven.config(
    SENTRY_DSN,
    options,
  ).install();
}

export default IsomorphicRaven;

その埌、 pages/_error.jsで䜿甚でき、サヌバヌ偎ずクラむアント偎の䞡方で機胜したす。

import NextError from 'next/error';
import IsomorphicRaven from 'lib/raven';

class MyError extends NextError {
  static getInitialProps = async (context) => {
    if (context.err) {
      IsomorphicRaven.captureException(context.err);
    }
    const errorInitialProps = await NextError.getInitialProps(context);
    return errorInitialProps;
  };
}

export default MyError;

これが、Next.jsをサポヌトするRollbar sourcemapwepbackプラグむンhttps://github.com/thredup/rollbar-sourcemap-webpack-plugin/pull/56のPRです:)

@tusgavomelo 、ストリヌムに存圚する゚ラヌを利甚する方法に぀いお詳しく説明しおいただけたすか
"process.stderr.write = error => yourErrorLogerror;"

゚ラヌをノヌドコン゜ヌルに蚘録するために、このコヌド行をどこに曞く必芁がありたすか

それはクラむアント偎だけです。
Rollbar.error('some error')

https://docs.rollbar.com/docs/javascript

@ teekey99 @sentry/browserに぀いお同様の解決策はありたすか たぶん-sentryの䟋で曎新したすか

@sheerunこれたでravenずraven-js䜿甚しおきたした。 すべおの新機胜が@sentry/nodeず@sentry/browser远加されたため、これらはおそらく非掚奚になるこずを認識しおいたす。 プロゞェクトでこれらの新しいラむブラリをただ䜿甚しおいたせんが、調べおみたす。 実甚的な䟋があれば、それを取り戻したす。

with-sentryの䟋は最近曎新されたした。

@timneutkensわかりたしたが、サヌバヌ゚ラヌをキャッチするには遅すぎるアプリ内でSentryが初期化されるため、サヌバヌ偎゚ラヌはサポヌトされおいたせん。 適切な解決策はおそらくどこかで@sentry/node䜿甚するでしょう

@sheerun同じ問題が発生しおいたす。 @sentry/nodeを䜿甚するのは簡単ではありたせん。 このSentryの䟋のreadmeは、私が䜜業しおいるアプリケヌションにすでにあるカスタムサヌバヌの䜿甚を提案しおいたす。 カスタムExpress.jsサヌバヌで䟋倖をキャプチャするには、ミドルりェアを凊理する最初の゚ラヌずしおSentry゚ラヌハンドラミドルりェア゚ラヌを挿入する必芁がありたす。 次のハンドラヌの盎埌にSentryの゚ラヌハンドラヌを挿入するず、゚ラヌはその時点ですでに飲み蟌たれおおり、Sentryはそれを認識したせん。

@sentry/browserのgetInitialPropsで_error.jsを䜿甚しおいたすが、クラむアント偎ずサヌバヌ偎の䞡方で機胜しおいるようです。 @sentry/browserがサヌバヌ偎でサポヌトされるこずになっおいるのかどうかはわかりたせんが、Sentryにむベントを受信しお​​いたす。

カスタムExpressサヌバヌの゚ントリファむルで@sentry/node Sentry.init()を介しお

これが私が䜿甚しおいるセットアップの芁点です https 

面癜い

ここでは確かにある皮のグロヌバルな状態が起こっおいたすこれは少し怖く、おそらくもろくお望たしくありたせん。 _error.js倉曎を適甚する

  • __なし__カスタムサヌバヌでSentryを構成する

    • 開発モヌドたたは本番環境で実行しおいる堎合぀たり、アプリをビルドしおいる堎合、サヌバヌ偎の゚ラヌが発生しおもSentryに䜕も報告されたせんが、サヌバヌログにReferenceError: XMLHttpRequest is not defined゚ラヌが発生したす

  • __構成埌__カスタムサヌバヌでSentry

    • サヌバヌ偎の䟋倖が報告されたすが、Sentryに奇劙なError: Sentry syntheticException蚘録されたす

公匏の解決策が䜕であるかを理解するのは良いこずです。 Nextのドキュメントでは、カスタムの<App>コンポヌネントの䜿甚を掚奚しおいるようです。これは、「with Sentry」の䟋で行われおいるこずですが、これはクラむアント偎でのみ機胜したす。

確かに゚ラヌ報告は、アプリが最初にレンダリングされるたで発生したせん。 次は、たずえばペヌゞをレンダリングする前に倱敗する可胜性がありたす。 たたたた、アプリがサヌバヌ偎で最初にレンダリングされた埌に機胜する堎合もありたすが、完党な゜リュヌションではないこずは確かです。

with-sentryの䟋は、@ timneutkensでも機胜したせん。 プロゞェクトを実行し、実際のDSNでテストするず、400の応答が返され、歩哚には䜕も届きたせんAPIのバヌゞョン7。

{"error":"Bad data reconstructing object (JSONDecodeError, Expecting value: line 1 column 1 (char 0))"}

@mcdougalは私のために機胜したせんでした。 どういうわけかクラむアントにバブルアップするグロヌバルなサヌバヌ偎のセットアップがあるこずは、すでにそれほど玠晎らしいこずではありたせんでしたが、そのハックがあっおも、私は歩哚301の応答を受け取りたした。

倚くのオプションがなく、耇数のプロゞェクトで実行されおいるため、歩哚のセルフホストセットアップで構成が誀っおいる可胜性があるかどうかはわかりたせん。

with-sentryの䟋で掚奚されおいるのず同じ方法で@sentry/browserを䜿甚しおいたすが、サヌバヌずクラむアントの䞡方から歩哚に゚ラヌを送信しおいるようです。 特別な蚭定はありたせん。䟋ず同じコヌドだけです。

@Jaunyサヌバヌから送信しおもよろしいですか どのようにそれをテストしたしたか 䟋のreadmeは、サヌバヌでは機胜しないこずを瀺唆しおいるようです。

@timrogersはい、確かに私の悪いです。テストされた゚ラヌはサヌバヌから来おいるず思いたしたが、実際にはクラむアントからトリガヌされたした:(

珟圚の䟋with-sentryは、getInitialPropsでスロヌされた゚ラヌをキャッチせず、アプリケヌションのレンダリングツリヌにある゚ラヌをキャッチしおいるようです。私の堎合、゚ラヌのほずんどはgetInitialPropsからのものです。

@sheerun䞊蚘のmcdougal回避策を詊すこずができたすか 完璧ではありたせんが奇劙な合成歩哚゚ラヌ、すべおの゚ラヌが発生するずいう印象を受けおおり、それが正しくないかどうかを知りたいず思いたす。 trueの堎合、with-sentryの䟋は、Next.jsがそれを改善する方法をアドバむスできるようになるたで、おそらくそれで曎新する必芁がありたす理想的には、server.jsの歩哚゚ラヌハンドラヌがスキップされないようにしたすか。

それは2぀の䞻芁な問題でちょっずうたくいくようです

  1. おそらく、非同期サヌバヌ偎コヌドが䞍必芁にリゞェネレヌタヌコヌドにコンパむルされるため、本番環境のサヌバヌ偎スタックトレヌスはinternal / process / next_tick.jsで切り捚おられるこずが倚く、゚ラヌの原因はたったくわかりたせん。
  2. 次のリク゚ストハンドラが呌び出される前に゚ラヌがスロヌされた堎合、゚ラヌ凊理は機胜したせんカスタムサヌバヌコヌドなど

実際には、カスタム゚ラヌのgetInitialPropsをさらにテストした埌、たずえばカスタム_appのgetInitialProps内で゚ラヌが発生した堎合、䜕らかの理由で本番環境で発生するこずさえありたせん。

ええ、私は数日間私の詊みで走った埌、確かにいく぀かの奇劙な行動をずっおいたす。 私たちが盎面しおいる䞻な問題は次のようです。

  1. CSRの堎合は@sentry/browserをむンポヌトし、SSRの堎合は@sentry/nodeをむンポヌトしたす
  2. CSRずSSRの䞡方で垞にトリガヌされる゚ラヌ凊理を配眮する堎所を芋぀ける

私は怠惰なむンポヌトずグロヌバル状態を䜿甚しお#1を解決しようず考えおいたした。

const sentryInitialized = false;

# Inside some trigger point
const Sentry = ssr ? eval(`require('@sentry/node')`) : eval(`require('@sentry/browser')`);
if (!sentryInitialized) {
  Sentry.init({dsn: SENTRY_DSN});
}
Sentry.captureException(err);

Nextの動的むンポヌトを䜿甚できるかもしれたせんが、私はただそれらに粟通しおいたせん。 たた、゚ラヌ凊理コヌドがトリガヌされるたびにrequireを呌び出すこずの圱響もわかりたせん。 これを詊しおみたら曎新したす。

問題#2限り、可胜性は次のように思われたす。

  1. _app.componentDidCatch 、これはSSRでは起動したせん
  2. _error.getInitialProps 、これには倚くの問題がありたす
  3. ...他に䜕かありたすか Nextサヌバヌハンドラヌ関数でSSRに察しおできるこずはありたすか

私の盎感では、Nextの前にSentryの゚ラヌハンドラヌを挿入するこずでサヌバヌ䞊でこれを行う方法があるず思いたすが、ただ詊しおみたせん。

珟時点では、Nextはそれを行うのに圹立぀フックを提䟛しおいたせん。 これが機胜するこずがわかった堎合は、それらを远加できたす👌

ただし、Nextのキャッチが早すぎるため、これが機胜しないリスクがありたす。

@mcdougal Ah回避策が、

私の完党な無知を蚱しおください。しかし、

@Enalmada次の゚ラヌハンドラヌを無効にしたくないず思いたす。これは、適切な゚ラヌペヌゞをレンダリングするものになるためです。 その前に他のミドルりェアを挿入したいだけです。 それでうたくいくず思いたすが、詊しおみる必芁がありたす。

それを修正しおも、クラむアント偎の゚ラヌ凊理がうたく機胜しおいるずは思えたせん:(

この問題党䜓は残念であり、Nextを本番環境で安党に実行するための障害になりたす。

参考たでに、私はどこにでも@sentry/nodeをむンポヌトし、next.config.jsに次のように配眮したす。

        if (!isServer) {
          config.resolve.alias['@sentry/node$'] = '@sentry/browser'
        }

これは@mcdougalのevalよりも優れおいる可胜性がありたす

カスタム_appコンポヌネントず゚ラヌ凊理に関する远加の泚意事項は次のずおりです。

  1. _app.jsは、 _error.jsたたは404のようなペヌゞを含むすべおのペヌゞに䜿甚されるため、 ctx.errが枡されたずきに゚ラヌがスロヌされないようにする必芁がありたす。
  2. _error.js getInitialPropsが呌び出されないようにするため、アプリのgetInitialPropsでComponent.getInitialPropsを呌び出すこずを忘れないでください ctx.errが存圚する堎合でも呌び出す
class MyApp extends App {
  static async getInitialProps (appContext) {
    const { Component, ctx } = appContext
    if (ctx.err) {
      if (Component.getInitialProps) {
        pageProps = await Component.getInitialProps(ctx)
      }
      return { error: true, pageProps }
    }
    // here code that can throw an error, and then:
    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx)
    }
    return { pageProps }
  }
  render() {
    if (this.props.error) return super.render()
    // rest of code that can throw an error
  }
}

これたでのずころ、next.jsで゚ラヌレポヌトを適切に蚭定するこずは非垞に壊れやすい手順です:(

正しい方向ぞの良い停止のように芋える@sheerunに感謝したす。 次の゚ラヌ凊理は珟時点では最適ではないこずに同意したす。゚ラヌ凊理などを远加できるように、拡匵可胜なモゞュヌル/ミドルりェアが远加されおいるのを芋るのは玠晎らしいこずです。

歩哚などの同圢ラむブラリがないため、事態は耇雑になっおいたす。぀たり、コンポヌネントにどちらのラむブラリも単玔にむンポヌトできないため、実行時に動的にむンポヌトしお、サヌバヌ偎たたはブラりザ偎で゚ラヌが発生したかどうかを垞に確認する必芁がありたす。

この問題の曎新はありたすか これたでに詊したこずは次のずおりです。すべおのトラッキングコヌドを_app.jsに移動したした

constructor(args: any) {
        super(args)
        Sentry.init({
            dsn: 'blah',
            environment: 'local',
        })
        Sentry.configureScope(scope => {
            scope.setTag('errorOrigin', isServer ? 'SSR' : 'Client')
        })
    }
    static async getInitialProps({ Component, router, ctx }: any) {
        let pageProps = {}

        try {
            if (Component.getInitialProps) {
                pageProps = await Component.getInitialProps(ctx)
            }
        } catch (error) {
            // console.log('we caught an error')
            console.log(error)
            Sentry.captureException(error)
            throw error
        }

        return { pageProps }
    }

@sheerunからのnext.config.jsの远加ず、server.jsでの歩哚の初期化ず組み合わせおif (!isServer) { config.resolve.alias['@sentry/node$'] = '@sentry/browser' }
これは、クラむアント偎のすべおの゚ラヌを远跡しおいるように芋えたすが、サヌバヌ偎では、サヌバヌの再起動埌に発生した最初の゚ラヌのみを远跡しおいるようです。 ただし、サヌバヌ䞊のそれ以降の゚ラヌは远跡されたせん。 このアプロヌチでは、ログにSyntheticErrorsはありたせんが、実際の゚ラヌのみがありたす。

それでも、これは私にはかなりハッキヌだず感じたす。サヌバヌ偎の远跡は初めお機胜するだけなので、ただ䜿甚できたせん。

with-Sentryの䟋からこの郚分も远加したした

    componentDidCatch(error: any, errorInfo: any) {
        // if (process.env.FIAAS_NAMESPACE !== undefined) {
        Sentry.configureScope(scope => {
            Object.keys(errorInfo).forEach(key => {
                scope.setExtra(key, errorInfo[key])
            })
        })
        Sentry.captureException(error)
        console.log('componentDidCatch')

        // This is needed to render errors correctly in development / production
        super.componentDidCatch(error, errorInfo)
        // }
    }

しかし、これが必芁かどうかは完党にはわかりたせん

私の堎合、問題なく動䜜したす。 たた、あなたは歩哚を初期化しないでください
_app.jsコンストラクタヌですが、完党にこのクラスの倖にありたす

2時53分PMで氎曜日、2018幎11月21日にはabraxxas [email protected]曞きたした

この問題の曎新はありたすか 私がこれたでに詊したこずは次のずおりです。
すべおの远跡コヌドを_app.jsに移動したした

`
コンストラクタヌ匕数任意{
superargs
Sentry.init{
dsn '䜕ずか'、
環境 'ロヌカル'、
}
Sentry.configureScopescope => {
scope.setTag 'errorOrigin'、isServer 'SSR' 'クラむアント'
}
}

static async getInitialProps{Component、router、ctx}any{
pageProps = {}

try {
    if (Component.getInitialProps) {
        pageProps = await Component.getInitialProps(ctx)
    }
} catch (error) {
    // console.log('we caught an error')
    console.log(error)
    Sentry.captureException(error)
    throw error
}

return { pageProps }

}

`

@sheerunからのnext.config.jsの远加ず組み合わせお
https://github.com/sheerunおよびserver.jsでの歩哚の初期化も
isServer{config.resolve.alias ['@セントリヌ/ノヌド$'] = '@ sentry / browser'}
これはクラむアント偎ではすべおの゚ラヌを远跡しおいるようですが、サヌバヌ偎では
再起動埌に発生する最初の゚ラヌのみを远跡しおいるようです。
サヌバ。 ただし、サヌバヌ䞊のそれ以降の゚ラヌは远跡されたせん。 これずずもに
アプロヌチログにSyntheticErrorsはありたせんが、実際の゚ラヌのみがありたす。

それでも、これは私にはかなりハッキヌだず感じたす。サヌバヌ偎の远跡は
初めお動䜜する堎合のみ、ただ䜿甚できたせん。

—
あなたが蚀及されたので、あなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/zeit/next.js/issues/1852#issuecomment-440668980 、たたはミュヌト
スレッド
https://github.com/notifications/unsubscribe-auth/AAR2DeIhoOj6PdWRA2VqiEZyrO5Jui8vks5uxVrHgaJpZM4NOQlp
。

私はすでにそれを移動しようずしたしたが、それでも同じ動䜜です。 @sheerunセットアップの最小限の芁点を投皿できたすか 提䟛されたスニペットを䜿甚しお蚭定しようずしたしたが、機胜したせん。 党䜓が非垞に耇雑に芋えるので、私はかなり単玔なタスクであるず期埅しおいたした:(サヌバヌで歩哚を初期化しおいたすか、それずもクラス倖の_app.jsでのみ初期化しおいたすか

公匏の歩哚の䟋を曎新したすが、「耇雑すぎる」ずしお拒吊されるのではないかず思いたすが、時間があれば投皿を詊みるこずができたす。

@sheerun公匏の䟋に曎新しようずしおも、非垞に䟡倀がありたす。 SyntheticErrorsなしでsentryssrを動䜜させるため、たたは発生した最初のサヌバヌ゚ラヌのみを蚘録するために必芁な最小限の耇雑さであれば、マヌゞされるず思いたす。 次に、そこから、それを改善する方法、たたはnextjsコアの改善たたは歩哚同型サポヌトを掚進する方法を芋぀けるこずができたす。

ここに行きたす..https//github.com/zeit/next.js/pull/5727

必然的に耇雑な実䟋ができたので、状況を改善するための次のステップは䜕ですか。

next.jsで必芁なのは、next.config.jsにカスタムミドルりェアを远加する機胜ず、ナニバヌサル同圢プラグむン構成甚のnext.browser.jsなどですnext.config.jsは、特にWebpack構成に䜿甚されたす。぀たり、このファむルで定矩されおいる他のものは、埪環䟝存を匕き起こすため、アプリケヌションコヌドでは䜿甚できたせん。

next.browser.jsの堎合、next.jsは、アプリたたはドキュメントコンポヌネントのデコレヌタのような構成を定矩できたす。 このようにしお、歩哚統合を完党にプラグむンずしお実装できたした。

線集これのチケットがあるかどうかはわかりたせんが、 @ timneutkensはすでに次のサヌバヌを別のパッケヌゞに抜出しおいるず思いたす。 最高のプラグむンむンタヌフェヌスは次のようなものになるず思いたす。

module.exports = {
  server: server => {
    server.use(Sentry.Handlers.errorHandler())
  }
}

そのようなAPIの提案を6922で実装したした

コントラクトが.listen()自動的に呌び出さないものに倉曎されるため、カスタムサヌバヌコヌドにデコレヌタを远加できるため、next.jsでむンスタンス化する前にさらにデコレヌタを䜜成できたす。

with-sentry䟋を䜿甚するのに倚くの問題があったので、もっず簡単な䟋のPRを開きたした。 それはすべおの鐘ず笛を持っおいるわけではありたせんが、それは私のために働いおいたす。

https://github.com/zeit/next.js/pull/7119

カスタム_document.jsこれを詊しおください

import React from "react";
import Document, {
  Html,
  Head,
  Main,
  NextScript,
} from "next/document";
import { NodeClient } from "@sentry/node";

const { default: getConfig } = require("next/config");
const { publicRuntimeConfig: { sentryDSN } } = getConfig();

let sentry = null;
if (sentryDSN) {
  sentry = new NodeClient({ dsn: sentryDSN });
}

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx);
    if (ctx.err && sentry) sentry.captureException(ctx.err);
    return { ...initialProps };
  }

  render() {
    return (
      <Html>
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

そしおこれはカスタム_app.js 

import * as Sentry from "@sentry/browser";

const { default: getConfig } = require("next/config");
const { publicRuntimeConfig: { sentryDSN } } = getConfig();

if (sentryDSN) {
  Sentry.init({ dsn: sentryDSN });
}

それはわたしを助ける。

Tbh私はnext.jsの゚ラヌをキャッチする正しい堎所が今䜕であるかに぀いお非垞に混乱しおいたす。 _app.tsx、_error.tsx、および_document.tsxがあり、いく぀かのものを_error.tsxに取り蟌む必芁があるずいうコメントがありたすhttps://github.com/zeit/next.js/pull/5727/filesなど。 r235981700ただし、珟圚の䟋では_app.tsxたたは_appず_documentのいずれかを䜿甚しおいたす。

私は今䞡方の方法を詊したしたが、ssr䞭に発生するいく぀かの゚ラヌが私に捕らえられおいないようです。 ゚ラヌをチェックするのに正しい堎所はどこですか 私にずっお最も論理的なものは、_appのcomponentDidCatchず_errorのgetInitialPropsをチェックむンするようです。これは、゚ラヌの堎合に提䟛されるためです。 _documentのprocess.on郚分党䜓に぀いお少し混乱しおいたす

より深い知識を持っおいる人がこの質問を解決しおくれたせんか

@abraxxas process.onで_document.js 、サヌバヌ䞊で起こる゚ラヌをキャッチされたした。 芁玄するず、

  • _document.jsは_サヌバヌ偎のみ_であり、サヌバヌ偎でレンダリングされた最初のドキュメントマヌクアップを倉曎するために䜿甚されたす。
  • _app.jsは_クラむアント偎のみ_であり、ペヌゞの初期化に䜿甚されたす。

したがっお、サヌバヌで゚ラヌが発生するず、 process.onを介しおSentryに゚ラヌがスロヌされ、クラむアントはデフォルトの゚ラヌペヌゞたたは_error.jsをレンダリングしたす。

うたくいけば、これが圹立぀でしょう https 

_app.jsはクラむアント偎のみではありたせんが、 componentDidCatchは

@timneutkensさお、それは私の脳を少ししわにしたす。 前回芋た時からドキュメントが曎新されお_app.jsがクラむアントサむドではないこずを詳しく説明しおいただけたすか

@timneutkensおそらく、どこで、なぜ゚ラヌをキャッチするのか説明できたすか たくさんの意芋があるようです。

@timneutkensさお、それは私の脳を少ししわにしたす。 前回芋た時からドキュメントが曎新されお_app.jsがクラむアントサむドではないこずを詳しく説明しおいただけたすか

こんにちはリヌロブ
あなたの䟋のマヌゞリク゚ストに぀いお質問を投皿したした
https://github.com/zeit/next.js/pull/7360#issuecomment -514318899

その質問に加えお...私はサヌバヌ偎のrenderで゚ラヌをスロヌしようずしたしたraiseErrorInRendertrueで状態を開始したので、サヌバヌ偎の最初のレンダリングはすでに゚ラヌをスロヌしたす、そしおその゚ラヌもSentryによっおキャプチャされたせんでした。

アプリケヌションでそれをテストしたしたかそれらのサヌバヌ偎の゚ラヌは実際にキャプチャされおいたすか Next9を䜿甚しおいたす。

それが実際に圓おはたり、クラむアント偎の゚ラヌのみがキャプチャされおいる堎合は、_document.jsファむルをオヌバヌラむドする理由もありたせん。

助けおくれおありがずう

@timneutkensさお、それは私の脳を少ししわにしたす。 前回芋た時からドキュメントが曎新されお_app.jsがクラむアントサむドではないこずを詳しく説明しおいただけたすか

質問に答えるず、_appは、ペヌゞを初期化するためにAppコンポヌネントが定矩されおいる堎所です。 ペヌゞ倉曎の間に氞続的なレむアりトが必芁な堎合すべおのペヌゞが同じ_appを利甚する、たたはreduxを利甚する堎合など、これをオヌバヌラむドしたす。 したがっお、サヌバヌ偎で発生する最初のレンダリングでさえ、_appのコンテンツをレンダリングしたすクラむアント偎のみではありたせん。

その質問に加えお...私はサヌバヌ偎のrenderで゚ラヌをスロヌしようずしたしたraiseErrorInRendertrueで状態を開始したので、サヌバヌ偎の最初のレンダリングはすでに゚ラヌをスロヌしたす、そしおその゚ラヌもSentryによっおキャプチャされたせんでした。

その゚ラヌを歩哚に衚瀺させるために他の方法で管理したしたか _errorのgetInitialPropsでキャプチャしようずしたしたが、歩哚では䜕も衚瀺されたせん。 珟圚、サヌバヌ䞊の゚ラヌをキャプチャする信頌できる方法を1぀芋぀けおいたせん。そのうちのいく぀かはほずんどの堎合、API障害に接続されおいる堎合衚瀺されたすが、゚ラヌテストペヌゞから単玔な゚ラヌを取埗しお歩哚に衚瀺するこずはできたせんでした。

その質問に加えお...私はサヌバヌ偎のrenderで゚ラヌをスロヌしようずしたしたraiseErrorInRendertrueで状態を開始したので、サヌバヌ偎の最初のレンダリングはすでに゚ラヌをスロヌしたす、そしおその゚ラヌもSentryによっおキャプチャされたせんでした。

その゚ラヌを歩哚に衚瀺させるために他の方法で管理したしたか _errorのgetInitialPropsでキャプチャしようずしたしたが、歩哚では䜕も衚瀺されたせん。 珟圚、サヌバヌ䞊の゚ラヌをキャプチャする信頌できる方法を1぀芋぀けおいたせん。そのうちのいく぀かはほずんどの堎合、API障害に接続されおいる堎合衚瀺されたすが、゚ラヌテストペヌゞから単玔な゚ラヌを取埗しお歩哚に衚瀺するこずはできたせんでした。

残念ながら違いたす。 私が実装しようずしおいる解決策は、テンプレヌトずしお䟋オヌバヌラむドされた_document.jsファむルを陀くを䜿甚しお、クラむアント偎で発生する゚ラヌをキャプチャするこずです。ナヌザヌが私に報告しない限り、知っおいたす。 サヌバヌ偎では、ログ行をログファむルに盎接リダむレクトするだけだず思いたす。 すべおの゚ラヌを同じ堎所に眮きたかったので、これは間違いなく最善の解決策ではありたせんが、そうするこずで、少なくずもアプリケヌションで発生する可胜性のある゚ラヌに関する情報を埗るこずができたす。

あなたはそれをどう思いたすか ありがずう

その質問に加えお...私はサヌバヌ偎のrenderで゚ラヌをスロヌしようずしたしたraiseErrorInRendertrueで状態を開始したので、サヌバヌ偎の最初のレンダリングはすでに゚ラヌをスロヌしたす、そしおその゚ラヌもSentryによっおキャプチャされたせんでした。

その゚ラヌを歩哚に衚瀺させるために他の方法で管理したしたか _errorのgetInitialPropsでキャプチャしようずしたしたが、歩哚では䜕も衚瀺されたせん。 珟圚、サヌバヌ䞊の゚ラヌをキャプチャする信頌できる方法を1぀芋぀けおいたせん。そのうちのいく぀かはほずんどの堎合、API障害に接続されおいる堎合衚瀺されたすが、゚ラヌテストペヌゞから単玔な゚ラヌを取埗しお歩哚に衚瀺するこずはできたせんでした。

残念ながら違いたす。 私が実装しようずしおいる解決策は、テンプレヌトずしお䟋オヌバヌラむドされた_document.jsファむルを陀くを䜿甚しお、クラむアント偎で発生する゚ラヌをキャプチャするこずです。ナヌザヌが私に報告しない限り、知っおいたす。 サヌバヌ偎では、ログ行をログファむルに盎接リダむレクトするだけだず思いたす。 すべおの゚ラヌを同じ堎所に眮きたかったので、これは間違いなく最善の解決策ではありたせんが、そうするこずで、少なくずもアプリケヌションで発生する可胜性のある゚ラヌに関する情報を埗るこずができたす。

あなたはそれをどう思いたすか ありがずう

それはたさに私たちが今しおいるこずです、それは少し䞍栌奜ですが、私たちが思い぀くこずができる最高のものです。 しかし、サヌバヌ偎の゚ラヌの䞀郚が歩哚に衚瀺されるため、歩哚たたはnext.jsのいずれかで䜕かが起こっおいるに違いないず思いたす。 単玔な䟋ずより耇雑な䟋の䞡方を詊しおみたしたが、どちらも同じように動䜜するため、この動䜜はセットアップずは関係がないこずを少なくずもある皋床確信しおいたす。

このスレッドの人々は、 https//github.com/zeit/next.js/pull/8684および関連するバグに興味があるかもしれたせん。 未凊理の䟋倖の12の異なるテストがあり、Next.jsが凊理する䟋倖ず凊理しない䟋倖を理解するために、さたざたなテストを行うこずができたす。

この問題に関するニュヌスはありたすか

私の解決策は、 reduxを䜿甚しお、ノヌドフェッチデヌタ゚ラヌをstate redux保存するこずです。次に、 _app.jsのcomponentDidMountで、䜕かを実行したすナヌザヌぞのアラヌトたたぱラヌ埌の芁求バック゚ンドぞ。
コヌドはnext-antd-scaffold_server-errorにありたす。

========>状態

import {
  SERVER_ERROR,
  CLEAR_SERVER_ERROR
} from '../../constants/ActionTypes';

const initialState = {
  errorType: []
};

const serverError = (state = initialState, { type, payload }) => {
  switch (type) {
    case SERVER_ERROR: {
      const { errorType } = state;
      errorType.includes(payload) ? null : errorType.push(payload);
      return {
        ...state,
        errorType
      };
    }
    case CLEAR_SERVER_ERROR: {
      return initialState;
    }
    default:
      return state;
  }
};

export default serverError;

=======>アクション

import {
  SERVER_ERROR
} from '../../constants/ActionTypes';

export default () => next => action => {
  if (!process.browser && action.type.includes('FAIL')) {
    next({
      type: SERVER_ERROR,
      payload: action.type 
    });
  }
  return next(action);
};

=======> _app.js

...
componentDidMount() {
    const { store: { getState, dispatch } } = this.props;
    const { errorType } = getState().serverError;
    if (errorType.length > 0) {
      Promise.all(
        errorType.map(type => message.error(`Node Error, Code${type}`))
      );
      dispatch(clearServerError());
    }
  }
...

_unortodox_゜リュヌションが倧奜きです

function installErrorHandler(app) {
  const _renderErrorToHTML = app.renderErrorToHTML.bind(app)
  const errorHandler = rollbar.errorHandler()

  app.renderErrorToHTML = (err, req, res, pathname, query) => {
    if (err) {
      errorHandler(err, req, res, () => {})
    }

    return _renderErrorToHTML(err, req, res, pathname, query)
  }

  return app
}
// ¯\_(ツ)_/¯

404゚ラヌの堎合はerr匕数がnullになるため、このメ゜ッドは404゚ラヌには適甚できたせん。

Elastic APMノヌドクラむアントhttps://www.npmjs.com/package/elastic-apm-nodeでこれを解決したした

興味のある方ぞ

next.config.js 

webpack: (config, { isServer, webpack }) => {
      if (!isServer) {
        config.node = {
          dgram: 'empty',
          fs: 'empty',
          net: 'empty',
          tls: 'empty',
          child_process: 'empty',
        };

        // ignore apm (might use in nextjs code but dont want it in client bundles)
        config.plugins.push(
          new webpack.IgnorePlugin(/^(elastic-apm-node)$/),
        );
      }

      return config;
} 

次に、 _error.jsレンダリング関数でcaptureErrorを手動で呌び出すこずができたす。

function Error({ statusCode, message, err }) {

const serverSide = typeof window === 'undefined';

  // only run this on server side as APM only works on server
  if (serverSide) {
    // my apm instance (imports elastic-apm-node and returns  captureError)
    const { captureError } = require('../src/apm'); 

    if (err) {
      captureError(err);
    } else {
      captureError(`Message: ${message}, Status Code: ${statusCode}`);
    }
  }

}

やあみんな Expressサヌバヌを远加せずにNext.jsでExpressスタむルアヌキテクチャ甚のNPMラむブラリを起動したした。 サヌバヌの゚ラヌ凊理の課題に圹立぀堎合がありたす。 興味のある方は是非チェックしおみおください。 https://github.com/oslabs-beta/connext-js

getServerSidePropsで発生する䟋倖をキャッチおよび凊理するこずに成功した人はいたすか

getServerSidePropsで発生する䟋倖をキャッチおよび凊理するこずに成功した人はいたすか

䞍明確ですが、フレヌムワヌクはクラむアントずサヌバヌの䞡方で゚ラヌをログに蚘録する慣甚的な方法を提䟛するず思いたす🀷‍♂

getServerSidePropsで発生する䟋倖をキャッチおよび凊理するこずに成功した人はいたすか

@stephankaag

はい、このようなものが私のために働いた

たず、クラッシュレポヌトを凊理するミドルりェアを䜜成したす。 Sentryを返すだけでは機胜しないため、 SentryをCrashReporterクラスにラップしたした぀たり、 req.getCrashReporter = () => Sentry 。

// crash-reporter.js

const Sentry = require("@sentry/node");

class CrashReporter {
  constructor(){
    Sentry.init({ dsn: process.env.SENTRY_DSN });
  }
  captureException(ex){
    return Sentry.captureException(ex);
  }
}

function crashReporterMiddleware(req, res, next) {
  req.getCrashReporter = () => new CrashReporter();
  next();
}

module.exports = crashReporterMiddleware;

次に、もちろん、Next.jsリク゚ストハンドラヌが蚭定される前に、ミドルりェアをアプリにロヌドしたす。

// server.js

const crashReporterMiddleware = require("./middleware/crash-reporter")

...

app.use(crashReporterMiddleware);

...

setHandler((req, res) => {
  return handle(req, res);
});

その埌、どこに電話しおもgetServerSideProps 

// _error.js

export async function getServerSideProps({req, res, err}) {
  const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
  const crashReporter = req.getCrashReporter();
  const eventId = crashReporter.captureException(err);
  req.session.eventId = eventId;
  return {
    props: { statusCode, eventId }
  }
}
このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡