Next.js: Cara menangkap dan menangani kesalahan untuk melaporkan log di sisi server

Dibuat pada 2 Mei 2017  ·  74Komentar  ·  Sumber: vercel/next.js

Hai,
Saya berada dalam situasi di mana kami ingin mengirim kesalahan, baik di sisi server dan klien, ke alat Sentry.

Aplikasi kami menggunakan Express sebagai server khusus. Pada dasarnya kami membuat aplikasi ekspres, menerapkan beberapa middlewares tetapi mendelegasikan semua pekerjaan sebenarnya ke pegangan 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());

Dengan pendekatan ini next.js mengambil kendali atas proses rendering dan kesalahan apa pun ditangkap oleh next.js dan satu-satunya cara saya harus memprosesnya adalah mengganti file halaman _error.js .

Di dalam file _error.js saya memerlukan cara universal untuk melaporkan kesalahan ke Sentry. Saat ini ada dua perpustakaan ( raven untuk node dan raven-js javascript). Masalahnya adalah saya tidak dapat mengimpor keduanya karena raven berfungsi untuk SSR tetapi gagal ketika webpack membuat bundel, dan juga raven-js gagal karena ketergantungan XMLHTTPRequest juga.

Apakah ada cara agar saya dapat diberi tahu tentang kesalahan next.js di sisi server?

story feature request

Komentar yang paling membantu

Harus menyukai solusi _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
}
// ¯\_(ツ)_/¯

Semua 74 komentar

Untuk kesalahan pencatatan di sisi klien, kami telah melakukan hal berikut:
https://Gist.github.com/jgautheron/044b88307d934d486f59ae87c5a5a5a0

Ini pada dasarnya mengirimkan kesalahan ke server, yang pada akhirnya dicetak ke stdout dan ditangkap oleh driver logging Docker .
Kami telah berhasil menangkap kesalahan SSR dengan react-guard tanpa perlu menimpa file inti Berikutnya.

Saya juga mengalami masalah ini. Saya bertanya-tanya: apakah cukup mengembalikan janji yang ditolak dari handleRequest sudah cukup? Artinya, mengubah kode di sini menjadi:

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;
     })
}

Kemudian, dalam kode pengguna:

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 Apakah menurut Anda perubahan yang saya usulkan langsung di atas akan berhasil? Jika demikian, dengan senang hati mengirimkan PR

Setuju untuk mengulang kesalahan sehingga kita bisa bermain-main dengannya.
Juga perlu re-throw di renderToHTML juga...

Saya juga dalam situasi di mana kami ingin mengirim kesalahan, baik di sisi server dan klien, ke layanan yang mirip dengan Sentry.

Saya percaya bahwa fitur yang paling berharga dari layanan/alat tersebut adalah untuk melaporkan masalah yang paling tidak terduga, yang menurut pengalaman saya adalah kesalahan yang tidak tertangkap di alam liar (yaitu sisi klien). Sayangnya, seperti yang ditekankan sebelumnya dalam masalah terkait #2334, penangan sisi klien Next.js menyimpan kesalahan ini untuk diri mereka sendiri, tanpa cara yang mungkin untuk meneruskannya ke Sentry dari alat lain tersebut.

Apa yang sangat mengganggu kami adalah ini: halaman yang dirender sisi server dengan benar dirender ulang sebagai halaman kesalahan jika pengecualian yang tidak tertangkap terjadi sebelum React rendering di sisi klien . Ini dapat dilihat sebagai fitur hebat, tetapi juga pengalaman pengembang yang membuat frustrasi, karena pada dasarnya merusak manfaat dari menyajikan dokumen yang sudah dirender, pada sebagian besar klien.

Berikut adalah halaman contoh yang menggambarkan masalah:

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>;

Kode di atas dapat dengan sempurna dirender di sisi server dan dikirimkan ke klien, hanya untuk menjadi Flash Konten yang Tidak Diinginkan sebelum seluruh halaman diganti di sisi klien oleh pesan ”Terjadi kesalahan tak terduga” di sebagian besar browser , tanpa cara apa pun yang memungkinkan untuk melaporkan kesalahan ke Penjaga (atau layanan/alat lainnya).

"Kesalahan menelan" ini juga mencegah pengaruh apa pun dari penangan kesalahan standar, yang penolakan yang tidak

Kemungkinan solusi sisi klien

Sejauh yang saya tahu, jenis kesalahan sisi klien pra-React ini terjadi di blok try / catch di klien/index.js Next.js di mana Component akan dirender ditetapkan ulang ke nilai ErrorComponent (saat ini baris 67-72 ).

Penulis dan pengelola Next.js yang terhormat, demi kontrol atas apa yang dirender, menurut Anda apa yang dapat diterima/mungkin di antara ide-ide berikut:

  • perkenalkan pengait di blok catch di klien/index.js untuk menangani kesalahan semacam ini?
  • mengirimkan kesalahan ke penangan penolakan onerror/onunhandled, jika ada yang terdeteksi?
  • memberikan opsi untuk mengulang kesalahan?
  • memberikan opsi untuk tidak menampilkan komponen kesalahan?
  • memberikan opsi untuk menampilkan komponen kesalahan khusus?

perkenalkan pengait di blok tangkap itu di klien/index.js untuk menangani kesalahan semacam ini?
mengirimkan kesalahan ke penangan penolakan onerror/onunhandled, jika ada yang terdeteksi?

Ini adalah sesuatu yang telah kita bicarakan secara internal. Dan kami akan segera menangani.

Saya menggunakan Sentry.io untuk melaporkan kesalahan dan solusi yang kami terapkan adalah:

1- Konfigurasi raven-node di sisi server
2- Konfigurasikan ravenjs di sisi klien (kami membuatnya di _document .

Dengan dua langkah ini kami menangkap pengecualian yang tidak tertangani baik di klien maupun server.

3- Buat halaman _error . Setiap kesalahan yang dihasilkan setelah nextjs menangani permintaan (tidak peduli apakah sisi klien atau server) halaman itu dirender. Dalam metode getInitialProps dari halaman _error, kami melaporkan kesalahan kepada penjaga.

Cara untuk memutuskan bagaimana memuat jika raven-node atau ravenjs diselesaikan dengan mengimpor secara dinamis tergantung apakah kita berada di klien const Raven = require('raven-js'); atau sisi server const Raven = require('raven'); .
Perhatikan bahwa kami telah mengonfigurasi webpack untuk tidak menggabungkan modul raven (sisi server) memperbarui next.config.js dengan:

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- Konfigurasikan ravenjs di sisi klien (kami membuatnya di _document.

Bisakah Anda menunjukkan kepada saya bagaimana Anda mengonfigurasi raven-js pada _document.js ? Ini tidak berfungsi untuk saya, ketika terjadi kesalahan, tidak ada yang terjadi pada penjaga.

Apakah saya perlu mengirim semua kesalahan secara manual di halaman _error.js ke penjaga?

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

Next.js masih menampilkan kesalahan ke console.error di server selama Anda tidak menyetelnya ke quiet .

Dengan Sentry, Anda dapat mengaktifkan autoBreadcrumbs untuk menangkap output ini , dan kemudian menangkap pesan Anda sendiri secara manual. Judul akan kurang deskriptif, tetapi masih akan berisi jejak tumpukan penuh.

Contoh implementasi:

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);
  });

Ini adalah contoh yang sangat dibuat-buat yang diadaptasi dari kode kita yang sebenarnya. Saya belum mengujinya dalam formulir ini . Beri tahu saya jika itu rusak.

Tentu saja, masih akan lebih baik jika Next.js dapat meneruskan kesalahan tersebut ke Express, sehingga kita dapat menggunakan integrasi Sentry/Express di luar kotak.

@tusgavomelo Maaf, untuk balasan yang terlambat.

Kami memiliki pembaruan. Di aplikasi kami, kami memiliki file pembantu dengan metode yang bertanggung jawab untuk mendapatkan instance Raven dengan mempertimbangkan jika kami berada di sisi klien atau server.

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;
};

Kode ini menjalankan kedua sisi server (ketika permintaan tiba) dan sisi klien. Apa yang telah kita lakukan adalah mengkonfigurasi webpack ( file next.config.js ) untuk menghindari bundel paket raven .

@acanimal bisakah Anda memberikan contoh yang berfungsi? Sepertinya saya tidak mendapatkan jejak tumpukan penuh? atau mungkin Anda dapat memposting _error.js ?

Saya melakukan sesuatu seperti RavenInstance.captureException(err) di _error.js , tetapi saya tidak dapat melihat jenis kesalahan yang terjadi serta di mana?

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>
    )
  }
}

Ini sepertinya tempat untuk meminta dukungan pencatat kustom karena quiet harus disetel ke false untuk mencegah layar pembersihan berikutnya pada pembuatan ulang modul dan dengan demikian menghapus kesalahan dari tampilan, namun satu-satunya peretasan yang dapat diterapkan di sini memerlukan menyetel quiet ke false.

Detail kesalahan juga tersedia di aliran stderr.
process.stderr.write = error => yourErrorLog(error);

Harus menyukai solusi _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
}
// ¯\_(ツ)_/¯

Versi ringkas tentang cara mendapatkan Raven yang benar untuk node dan browser tanpa konfigurasi webpack khusus. Terinspirasi dari komentar @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

Inti

rekap cepat untuk siapa saja yang menyelidiki masalah ini.

// 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$/));

terima kasih atas komentar @acanimal .

Instal keduanya raven (abaikan dengan webpack seperti yang disarankan dalam komentar sebelumnya) dan raven-js , lalu buat pembantu untuk membuat instance Raven isomorfik, misalnya 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;

Kemudian Anda dapat menggunakannya di pages/_error.js dan itu akan berfungsi baik di sisi server dan klien.

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;

Ini adalah PR saya untuk plugin wepback peta sumber Rollbar https://github.com/thredup/rollbar-sourcemap-webpack-plugin/pull/56 dengan dukungan Next.js :)

@tusgavomelo , Bisakah Anda menguraikan cara memanfaatkan kesalahan yang ada di aliran?
"process.stderr.write = error => yourErrorLog(error);"

Di mana kita harus menulis baris kode ini, untuk mencatat kesalahan ke konsol Node?

Itu hanya sisi Klien.
Rollbar.error('some error')

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

@teekey99 Apakah Anda memiliki solusi serupa untuk @sentry/browser ? Mungkin perbarui dengan contoh penjaga?

@sheerun Saya telah menggunakan raven dan raven-js sejauh ini. Saya sadar bahwa itu mungkin akan ditinggalkan karena semua fitur baru sekarang ditambahkan ke @sentry/node dan @sentry/browser . Masalahnya adalah saya belum menggunakan perpustakaan baru ini di proyek saya, tetapi saya akan mencoba untuk memeriksanya. Jika saya memiliki contoh yang berfungsi, saya akan membalasnya.

Contoh dengan penjaga baru-baru ini diperbarui.

@timneutkens Saya mengerti tetapi tidak mendukung kesalahan sisi server karena Sentry diinisialisasi di dalam Aplikasi di mana sudah terlambat untuk menangkap kesalahan server. Solusi yang tepat mungkin akan menggunakan @sentry/node suatu tempat

@sheerun Saya mengalami masalah yang sama. Menggunakan @sentry/node bukanlah hal yang sepele. Readme untuk contoh Sentry ini menyarankan untuk menggunakan server khusus, yang sudah kami miliki di aplikasi yang sedang saya kerjakan. Untuk menangkap pengecualian di server Express.js kustom kami, Anda perlu memasukkan kesalahan middleware pengendali kesalahan Sentry sebagai middleware penanganan kesalahan pertama . Jika Anda memasukkan penangan kesalahan Sentry langsung setelah penangan Berikutnya, kesalahan telah ditelan oleh titik itu dan Sentry tidak melihatnya.

Saya telah menggunakan @sentry/browser di getInitialProps dari _error.js dan tampaknya berfungsi baik di sisi klien maupun di sisi server. Saya tidak tahu apakah @sentry/browser seharusnya memiliki dukungan sisi server, tetapi saya mendapatkan acara ke Sentry.

Meskipun saya juga memanggil Sentry.init() melalui @sentry/node di file entri server Express khusus, jadi mungkin itu mengatur beberapa status global yang digunakan SSR.

Berikut adalah inti dari pengaturan yang saya gunakan: https://Gist.github.com/mcdougal/7bf001417c3dc4b579da224b12776691

Menarik!

Pasti ada semacam keadaan global yang terjadi di sini (yang agak menakutkan, dan mungkin rapuh dan tidak diinginkan). Menerapkan perubahan Anda di _error.js :

  • __Tanpa__ mengonfigurasi Sentry di server khusus:

    • Saat berjalan dalam mode pengembangan atau produksi (yaitu dengan aplikasi saya dibangun), tidak ada yang dilaporkan ke Sentry ketika terjadi kesalahan sisi server, tetapi saya mendapatkan beberapa kesalahan ReferenceError: XMLHttpRequest is not defined di log server

  • __Setelah mengonfigurasi__ Penjaga di server khusus:

    • Pengecualian sisi server saya dilaporkan, tetapi saya juga mendapatkan Error: Sentry syntheticException aneh yang direkam di Sentry

Akan lebih baik untuk memahami apa solusi resminya. Dokumen berikutnya tampaknya merekomendasikan penggunaan komponen <App> kustom sekarang, dan itulah yang dilakukan oleh contoh "dengan Sentry", tetapi ini hanya berfungsi untuk sisi klien.

Pelaporan kesalahan pasti tidak akan terjadi sampai Aplikasi pertama kali dirender. Berikutnya bisa gagal cara sebelumnya misalnya saat merender Halaman. Mungkin kebetulan itu berfungsi dalam beberapa kasus setelah aplikasi dirender di sisi server pertama kali, tetapi yang pasti itu bukan solusi lengkap.

Contoh dengan penjaga juga tidak berfungsi untuk saya @timneutkens. Menjalankan proyek dan mengujinya dengan DSN saya yang sebenarnya memberikan respons 400 dan tidak ada yang sampai ke penjaga (versi 7 dari api).

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

@mcdougal tidak berfungsi untuk saya. Sudah tidak cukup bagus untuk memiliki pengaturan sisi server global yang entah bagaimana menggelembung ke klien, tetapi bahkan dengan peretasan itu saya akan mendapatkan tanggapan penjaga 301.

Saya tidak melihat bagaimana pengaturan yang di-host-sendiri oleh penjaga saya dapat memiliki kesalahan konfigurasi, karena tidak banyak opsi dan ini berjalan di banyak proyek.

Saya menggunakan @sentry/browser dengan cara yang sama seperti yang direkomendasikan dalam contoh with-sentry, dan tampaknya mengirimkan kesalahan baik dari server maupun klien ke penjaga saya. Saya tidak memiliki konfigurasi khusus, hanya kode yang sama seperti contoh.

@Jauny Apakah Anda yakin itu dikirim dari server? Bagaimana Anda menguji itu? Readme dari contoh bahkan tampaknya menunjukkan bahwa itu tidak akan berfungsi di server.

@timrogers ya memang buruk, saya berasumsi kesalahan yang diuji berasal dari server tetapi sebenarnya dipicu dari klien :(

Tampaknya contoh with-sentry saat ini tidak menangkap kesalahan yang dilemparkan ke getInitialProps, hanya kesalahan di pohon render aplikasi.. Dalam kasus saya, sebagian besar kesalahan berasal dari getInitialProps.

@sheerun Bisakah Anda mencoba solusi mcdougal di atas? Itu tidak sempurna (kesalahan penjaga sintetis yang aneh) tetapi saya mendapat kesan bahwa itu semua kesalahan dan ingin tahu apakah itu tidak benar. Jika benar, contoh with-sentry mungkin perlu diperbarui dengan itu hingga Next.js dapat memberi saran tentang cara melakukannya dengan lebih baik (idealnya membuatnya agar penangan kesalahan server.js sentry tidak dilewati?).

Tampaknya ini berfungsi dengan dua masalah utama:

  1. Mungkin karena kode sisi server asinkron tidak perlu dikompilasi ke dalam kode regenerator, jejak tumpukan sisi server dalam produksi sering terpotong di internal/process/next_tick.js dan tidak ada penyebab kesalahan yang terlihat sama sekali.
  2. Penanganan kesalahan tidak akan berfungsi jika kesalahan dilemparkan sebelum penangan permintaan berikutnya dipanggil (mis. dalam kode server khusus)

Sebenarnya setelah pengujian lebih lanjut getInitialProps of custom Error untuk beberapa alasan bahkan tidak diaktifkan dalam produksi ketika kesalahan terjadi misalnya di dalam custom _app's getInitialProps..

Ya, saya pasti mendapatkan perilaku aneh setelah berlari dengan upaya saya selama beberapa hari. Sepertinya masalah utama yang kita hadapi adalah:

  1. Mengimpor @sentry/browser untuk CSR dan @sentry/node untuk SSR
  2. Menemukan tempat untuk meletakkan penanganan kesalahan yang selalu dipicu untuk CSR dan SSR

Saya telah berpikir untuk mencoba menggunakan impor malas dan status global untuk menyelesaikan #1 , seperti

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);

Mungkin impor dinamis Next dapat digunakan, tetapi saya belum terlalu mengenalnya. Saya juga tidak yakin akibat dari pemanggilan require setiap kali kode penanganan kesalahan terpicu. Saya akan memperbarui jika/ketika saya mencoba ini.

Sejauh masalah #2 , sepertinya kemungkinannya adalah:

  1. _app.componentDidCatch , yang tidak aktif untuk SSR
  2. _error.getInitialProps , yang memiliki banyak masalah
  3. ... sesuatu yang lain? Apakah ada yang bisa kita lakukan untuk SSR di fungsi penangan server Berikutnya?

Perasaan saya adalah bahwa akan ada cara untuk melakukan ini di server dengan menyuntikkan penangan kesalahan Sentry sebelum Next, tapi saya belum mencobanya.

Saat ini, Next tidak menyediakan kait untuk membantu Anda melakukannya. Jika kami menemukan ini berfungsi, kami dapat menambahkannya

Ada risiko bahwa ini tidak akan berhasil karena Next menangkap terlalu dini.

@mcdougal Ah &#!% Saya sangat senang ketika solusi Anda mungkin cukup baik untuk memeriksa cakupan klien/server penjaga yang diperlukan untuk membawa kami ke produksi.

Maafkan ketidaktahuan saya sepenuhnya, tetapi apakah kita hanya perlu mengizinkan kita untuk menonaktifkan penangan kesalahannya secara kondisional sehingga penangan kesalahan penjaga nodejs menjadi yang pertama? Beberapa flag di next.config.js disebut "disableErrorHandler"?

@Enalmada Saya tidak berpikir Anda ingin menonaktifkan penangan kesalahan Berikutnya karena itu akan membuat halaman kesalahan yang bagus. Anda hanya ingin memasukkan middleware lain sebelum itu. Saya pikir itu akan berhasil, tetapi saya harus mencobanya.

Bahkan dengan perbaikan itu, saya masih merasa penanganan kesalahan sisi klien tidak berfungsi sebaik yang saya harapkan :(

Seluruh masalah ini memalukan dan ini benar-benar penghalang untuk menjalankan Next dalam produksi dengan aman.

FYI saya mengimpor di mana-mana @sentry/node dan memasukkan yang berikut ke next.config.js:

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

yang bisa lebih baik dari eval dari @mcdougal

Berikut adalah catatan tambahan saya tentang komponen _app khusus dan penanganan kesalahan:

  1. _app.js digunakan untuk SEMUA halaman, termasuk _error.js atau halaman seperti 404 jadi Anda benar-benar ingin memastikan tidak ada kesalahan yang muncul saat ctx.err diteruskan ke sana..
  2. Jangan lupa untuk memanggil Component.getInitialProps di getInitialProps aplikasi karena akan mencegah getInitialProps dari _error.js dipanggil (panggil bahkan jika ctx.err ada)
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
  }
}

Sejauh ini saya menemukan pengaturan pelaporan kesalahan yang benar di next.js prosedur yang sangat rapuh :(

terima kasih @sheerun yang terlihat seperti perhentian yang bagus menuju arah yang benar. Saya setuju bahwa penanganan kesalahan berikutnya tidak optimal sekarang, akan sangat bagus untuk melihat beberapa modul/middleware yang dapat diperluas ditambahkan sehingga kami dapat menambahkan penanganan kesalahan di atasnya, dll.

Kurangnya perpustakaan isomorfik seperti penjaga juga membuat segalanya menjadi rumit, karena itu berarti kita tidak dapat mengimpor salah satu perpustakaan di komponen kita, kita perlu melakukannya secara dinamis saat runtime untuk selalu memeriksa apakah kesalahan muncul di sisi server atau browser.

Apakah ada pembaruan untuk masalah ini? Apa yang saya coba sejauh ini adalah sebagai berikut: Saya memindahkan semua kode pelacakan kami ke _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 }
    }

ditambah dengan penambahan next.config.js dari @sheerun dan menginisialisasi penjaga di server.js juga if (!isServer) { config.resolve.alias['@sentry/node$'] = '@sentry/browser' }
ini tampaknya melacak semua kesalahan di sisi klien, tetapi di sisi server sepertinya hanya melacak kesalahan pertama yang terjadi setelah restart server. Kesalahan selanjutnya di server tidak dilacak. Dengan pendekatan ini saya tidak memiliki SyntheticErrors di log, tetapi hanya kesalahan nyata.

Tetap saja ini terasa cukup meretas bagi saya dan karena pelacakan sisi server hanya berfungsi pertama kali, itu masih tidak dapat digunakan.

Saya juga menambahkan bagian ini dari contoh 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)
        // }
    }

tetapi saya tidak sepenuhnya yakin apakah ini diperlukan

Dalam kasus saya dengan bekerja tanpa masalah. Anda juga tidak boleh masuk penjaga
_app.js konstruktor tetapi di luar kelas ini sepenuhnya

Pada Rabu, 21 November 2018 pukul 14:53 abraxxas [email protected] menulis:

Apakah ada pembaruan untuk masalah ini? Apa yang saya coba sejauh ini adalah sebagai berikut: I
memindahkan semua kode pelacakan kami ke _app.js

`
konstruktor(args: apa saja) {
super(args)
Penjaga.init({
dsn: 'bla',
lingkungan: 'lokal',
})
Sentry.configureScope(lingkup => {
scope.setTag('errorOrigin', isServer ? 'SSR' : 'Klien')
})
}

static async getInitialProps({ Komponen, router, ctx }: any) {
biarkan 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 }

}

`

ditambah dengan penambahan next.config.js dari @sheerun
https://github.com/sheerun dan menginisialisasi penjaga di server.js juga jika
(!isServer) { config.resolve.alias['@sentry/node$'] = '@sentry/browser' }
ini tampaknya melacak semua kesalahan di sisi klien, tetapi di sisi server
sepertinya hanya melacak kesalahan pertama yang terjadi setelah restart
server. Kesalahan selanjutnya di server tidak dilacak. Dengan ini
pendekatan saya tidak memiliki SyntheticErrors di log, tetapi hanya kesalahan nyata.

Tetap saja ini terasa cukup meretas bagi saya dan karena pelacakan sisi server adalah
hanya bekerja pertama kali masih tidak dapat digunakan.


Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/zeit/next.js/issues/1852#issuecomment-440668980 , atau bisukan
benang
https://github.com/notifications/unsubscribe-auth/AAR2DeIhoOj6PdWRA2VqiEZyrO5Jui8vks5uxVrHgaJpZM4NOQlp
.

Saya sudah mencoba memindahkannya dan perilakunya masih sama. @sheerun bisakah Anda memposting inti minimal dari pengaturan Anda? Saya mencoba mengaturnya dengan cuplikan yang Anda berikan dan saya tidak bisa membuatnya berfungsi. Semuanya tampak terlalu rumit untuk apa yang saya harapkan menjadi tugas yang agak sederhana :( Apakah Anda juga menginisialisasi penjaga di server atau hanya di _app.js di luar kelas?

Saya akan memperbarui contoh penjaga resmi tetapi saya khawatir itu akan ditolak karena "terlalu rumit" Saya dapat mencoba memposting sesuatu ketika saya akan menemukan waktu ..

@sheerun Bahkan upaya untuk memperbarui ke contoh resmi akan sangat berharga. Saya merasa itu akan digabungkan jika itu benar-benar kompleksitas minimum yang diperlukan untuk membuat penjaga ssr bekerja tanpa SyntheticErrors atau hanya merekam kesalahan server pertama yang terjadi. Kemudian kita bisa pergi dari sana untuk mencari cara untuk membuatnya lebih baik atau mendorong peningkatan inti nextjs atau dukungan isomorfik penjaga.

Jadi sekarang kita memiliki contoh kerja yang kompleks, apa langkah selanjutnya untuk memperbaiki situasi:

Satu-satunya hal yang dibutuhkan di next.js adalah kemampuan untuk menambahkan middleware khusus di next.config.js dan sesuatu seperti next.browser.js untuk konfigurasi plugin universal (isomorfik) (next.config.js digunakan antara lain untuk konfigurasi webpack, yang berarti hal lain yang didefinisikan dalam file ini tidak dapat digunakan dalam kode aplikasi, karena akan menyebabkan ketergantungan melingkar).

Untuk next.browser.js next.js dapat menentukan konfigurasi seperti dekorator untuk komponen Aplikasi atau Dokumen. Dengan cara ini saya dapat menerapkan integrasi penjaga sepenuhnya sebagai plugin.

EDIT: Saya tidak tahu apakah ada tiket untuk ini, tapi saya pikir @timneutkens sudah mengekstrak server berikutnya ke dalam paket terpisah. Saya pikir antarmuka plugin terbaik adalah seperti:

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

Saya telah menerapkan proposal API semacam itu di # 6922

Ini memungkinkan untuk menambahkan dekorator ke kode server khusus karena kontrak diubah menjadi yang tidak secara otomatis memanggil .listen() sehingga memungkinkan next.js untuk menghiasnya lebih lanjut sebelum membuat instance

Saya mengalami banyak masalah menggunakan contoh with-sentry , jadi saya membuka PR untuk contoh yang jauh lebih sederhana. Itu tidak memiliki semua lonceng dan peluit, tetapi itu berhasil untuk saya.

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

Coba ini di kustom _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>
    );
  }
}

Dan ini dalam kustom _app.js :

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

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

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

Ini membantu saya.

Tbh saya sangat bingung di mana tempat yang benar untuk menangkap kesalahan untuk next.js sekarang. Ada _app.tsx, _error.tsx dan _document.tsx ada beberapa komentar yang mengatakan bahwa beberapa hal harus ditangkap di _error.tsx (seperti: https://github.com/zeit/next.js/pull/5727/files #r235981700) tetapi contoh saat ini menggunakan _app.tsx atau _app dan _document.

Saya mencoba kedua cara sekarang dan tampaknya beberapa kesalahan yang terjadi selama ssr tidak tertangkap untuk saya. Tempat mana yang sekarang benar untuk memeriksa kesalahan? Yang paling logis bagi saya tampaknya memeriksa componentDidCatch dari _app dan getInitialProps dari _error karena yang ini disajikan jika terjadi kesalahan. Saya agak bingung dengan keseluruhan bagian process.on di _document

Bisakah seseorang dengan pengetahuan yang lebih mendalam tolong selesaikan pertanyaan ini?

@abraxxas process.on di _document.js menangkap kesalahan yang terjadi di server. Sebagai rekap,

  • _document.js adalah _hanya sisi server_ dan digunakan untuk mengubah markup dokumen awal yang dirender sisi server.
  • _app.js adalah _client-side only_ dan digunakan untuk menginisialisasi halaman.

Oleh karena itu, ketika kesalahan terjadi di server, itu harus melemparkan kesalahan ke Sentry melalui process.on dan kemudian klien akan merender halaman kesalahan default atau _error.js .

Semoga ini bisa membantu: https://leerob.io/blog/configuring-sentry-for-nextjs-apps/

_app.js bukan hanya sisi klien, namun componentDidCatch adalah

@timneutkens Oke, itu sedikit mengernyitkan otak saya. Saya pikir dokumen telah diperbarui sejak terakhir kali saya melihat. Bisakah Anda menjelaskan bagaimana _app.js bukan hanya sisi klien secara lebih rinci?

@timneutkens bisakah Anda menjelaskan di mana dan mengapa Anda menangkap kesalahan? Tampaknya ada begitu banyak pendapat.

@timneutkens Oke, itu sedikit mengernyitkan otak saya. Saya pikir dokumen telah diperbarui sejak terakhir kali saya melihat. Bisakah Anda menjelaskan bagaimana _app.js bukan hanya sisi klien secara lebih rinci?

Halo leerob!
Saya baru saja memposting pertanyaan tentang permintaan gabungan dari contoh Anda:
https://github.com/zeit/next.js/pull/7360#issuecomment -514318899

Menambahkan ke pertanyaan itu... Saya juga mencoba membuat kesalahan dalam render() di sisi server (saya memulai status dengan raiseErrorInRender: true, jadi render pertama, yaitu sisi server, sudah akan menimbulkan kesalahan), dan kesalahan itu juga tidak ditangkap oleh Sentry.

Sudahkah Anda mengujinya di aplikasi Anda, dan apakah kesalahan sisi server itu benar-benar ditangkap? Saya menggunakan Berikutnya 9.

Jika memang demikian, dan hanya kesalahan sisi klien yang ditangkap, juga tidak ada alasan untuk menimpa file _document.js.

Terima kasih sebelumnya atas bantuan apa pun!

@timneutkens Oke, itu sedikit mengernyitkan otak saya. Saya pikir dokumen telah diperbarui sejak terakhir kali saya melihat. Bisakah Anda menjelaskan bagaimana _app.js bukan hanya sisi klien secara lebih rinci?

Menjawab pertanyaan Anda, _app adalah tempat komponen Aplikasi didefinisikan untuk menginisialisasi halaman. Kami akan menimpanya dalam kasus seperti kebutuhan untuk tata letak yang bertahan antara perubahan halaman (semua halaman menggunakan _app yang sama), atau untuk menggunakan redux. Jadi, bahkan render pertama, yang terjadi di sisi server, akan merender konten _app (bukan hanya sisi klien).

Menambahkan ke pertanyaan itu... Saya juga mencoba membuat kesalahan dalam render() di sisi server (saya memulai status dengan raiseErrorInRender: true, jadi render pertama, yaitu sisi server, sudah akan menimbulkan kesalahan), dan kesalahan itu juga tidak ditangkap oleh Sentry.

Sudahkah Anda berhasil dengan cara lain agar kesalahan itu muncul di penjaga? Saya mencoba menangkapnya di getInitialProps dari _error tetapi itu juga tidak menunjukkan apa pun di penjaga. Saat ini saya belum menemukan satu cara yang dapat diandalkan untuk menangkap kesalahan di server, beberapa dari mereka (kebanyakan jika mereka terhubung ke api kegagalan) mereka muncul tetapi saya belum berhasil mendapatkan kesalahan sederhana dari errortestpage muncul di penjaga

Menambahkan ke pertanyaan itu... Saya juga mencoba membuat kesalahan dalam render() di sisi server (saya memulai status dengan raiseErrorInRender: true, jadi render pertama, yaitu sisi server, sudah akan menimbulkan kesalahan), dan kesalahan itu juga tidak ditangkap oleh Sentry.

Sudahkah Anda berhasil dengan cara lain agar kesalahan itu muncul di penjaga? Saya mencoba menangkapnya di getInitialProps dari _error tetapi itu juga tidak menunjukkan apa pun di penjaga. Saat ini saya belum menemukan satu cara yang dapat diandalkan untuk menangkap kesalahan di server, beberapa dari mereka (kebanyakan jika mereka terhubung ke api kegagalan) mereka muncul tetapi saya belum berhasil mendapatkan kesalahan sederhana dari errortestpage muncul di penjaga

Sayangnya tidak. Solusi yang saya pikir akan saya terapkan adalah dengan menggunakan contoh (minus file _document.js yang ditimpa) sebagai templat saya untuk menangkap kesalahan yang terjadi di sisi klien, karena itu adalah kesalahan yang tidak dapat saya kendalikan dan cara untuk melakukannya tahu tentang, kecuali pengguna melaporkan kemudian kepada saya. Di sisi server, saya pikir saya hanya akan mengarahkan ulang baris log apa pun langsung ke file log. Itu jelas bukan solusi terbaik karena saya ingin memiliki semua kesalahan di tempat yang sama, tetapi melakukannya dengan cara itu setidaknya saya akan memiliki informasi tentang kesalahan apa pun yang mungkin terjadi pada aplikasi.

Apa yang kamu pikirkan tentang itu? Terima kasih!

Menambahkan ke pertanyaan itu... Saya juga mencoba membuat kesalahan dalam render() di sisi server (saya memulai status dengan raiseErrorInRender: true, jadi render pertama, yaitu sisi server, sudah akan menimbulkan kesalahan), dan kesalahan itu juga tidak ditangkap oleh Sentry.

Sudahkah Anda berhasil dengan cara lain agar kesalahan itu muncul di penjaga? Saya mencoba menangkapnya di getInitialProps dari _error tetapi itu juga tidak menunjukkan apa pun di penjaga. Saat ini saya belum menemukan satu cara yang dapat diandalkan untuk menangkap kesalahan di server, beberapa dari mereka (kebanyakan jika mereka terhubung ke api kegagalan) mereka muncul tetapi saya belum berhasil mendapatkan kesalahan sederhana dari errortestpage muncul di penjaga

Sayangnya tidak. Solusi yang saya pikir akan saya terapkan adalah dengan menggunakan contoh (minus file _document.js yang ditimpa) sebagai templat saya untuk menangkap kesalahan yang terjadi di sisi klien, karena itu adalah kesalahan yang tidak dapat saya kendalikan dan cara untuk melakukannya tahu tentang, kecuali pengguna melaporkan kemudian kepada saya. Di sisi server, saya pikir saya hanya akan mengarahkan ulang baris log apa pun langsung ke file log. Itu jelas bukan solusi terbaik karena saya ingin memiliki semua kesalahan di tempat yang sama, tetapi melakukannya dengan cara itu setidaknya saya akan memiliki informasi tentang kesalahan apa pun yang mungkin terjadi pada aplikasi.

Apa yang kamu pikirkan tentang itu? Terima kasih!

Itulah tepatnya yang sedang kami lakukan sekarang, ini agak kikuk tetapi yang terbaik yang bisa kami lakukan. Tapi karena beberapa kesalahan sisi server muncul di penjaga untuk kita pasti ada sesuatu yang terjadi baik dengan penjaga atau next.js saya pikir. Saya mencoba dengan contoh sederhana dan yang lebih kompleks dan keduanya berperilaku sama jadi saya setidaknya agak yakin bahwa perilaku ini tidak terkait dengan pengaturan kami

Orang-orang di utas ini mungkin tertarik dengan https://github.com/zeit/next.js/pull/8684 dan bug terkait. Ini memiliki 12 tes berbeda dari pengecualian yang tidak tertangani yang dapat Anda mainkan untuk mendapatkan pemahaman tentang pengecualian apa yang ditangani Next.js untuk Anda dan apa yang tidak.

Ada berita tentang masalah ini?

Solusi saya adalah menggunakan redux simpan kesalahan pengambilan data simpul di state Kemudian di componentDidMount dari _app.js lakukan sesuatu (peringatan untuk pengguna atau permintaan kesalahan posting ke backend).
Kodenya ada di sana

========> nyatakan

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;

=======> tindakan

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());
    }
  }
...

Harus menyukai solusi _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
}
// ¯\_(ツ)_/¯

Metode ini tidak dapat diterapkan pada kesalahan 404 karena argumen err akan menjadi nol ketika kesalahan 404.

Saya memecahkan ini untuk klien simpul APM Elastis ( https://www.npmjs.com/package/elastic-apm-node )

Bagi siapa saja yang tertarik:

Dalam 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;
} 

Kemudian di _error.js render func Anda dapat memanggil captureError secara manual:

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}`);
    }
  }

}

Hai semua! Kami baru saja meluncurkan pustaka NPM untuk arsitektur gaya Express di Next.js tanpa menambahkan server Express. Ini mungkin berguna untuk tantangan penanganan kesalahan server Anda! Check it out jika Anda tertarik. https://github.com/oslabs-beta/connext-js

Adakah yang berhasil menangkap (dan menangani) pengecualian yang terjadi di getServerSideProps ?

Adakah yang berhasil menangkap (dan menangani) pengecualian yang terjadi di getServerSideProps ?

Tidak jelas, Anda akan berpikir kerangka kerja akan menyediakan cara idiomatis untuk mencatat kesalahan baik klien maupun server ️

Adakah yang berhasil menangkap (dan menangani) pengecualian yang terjadi di getServerSideProps ?

@stephankaag

ya, sesuatu seperti ini berhasil untuk saya:

pertama buat middleware untuk menangani pelaporan kerusakan. Saya telah membungkus Sentry di dalam kelas CrashReporter karena hanya mengembalikan Sentry tidak akan berfungsi (yaitu 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;

selanjutnya, tentu saja, muat middleware ke dalam aplikasi Anda sebelum handler permintaan Next.js disetel:

// server.js

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

...

app.use(crashReporterMiddleware);

...

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

lalu ke mana pun Anda menelepon 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 }
  }
}
Apakah halaman ini membantu?
0 / 5 - 0 peringkat