Skip to main content

[WebService] Bugsnag API 使用筆記

使用版本 @ 7.0.0

安裝(搭配 React)#

$ npm install --save @bugsnag/js @bugsnag/plugin-react

載入:

// ES module-style importimport Bugsnag from '@bugsnag/js';import BugsnagPluginReact from '@bugsnag/plugin-react';

使用:

Bugsnag.start({  apiKey: 'YOUR_API_KEY',  plugins: [new BugsnagPluginReact(React)],  otherOptions: value,});

套用到 React:

const ErrorBoundary = Bugsnag.getPlugin('react');

回報錯誤訊息(notify)#

Reporting handled errors

// Bugsnag.notify(err, onError, cb)import Bugsnag from '@bugsnag/js';
Bugsnag.notify(new Error('Something broke!'));
// 使用 onError functionBugsnag.notify(new Error('Bad, but not fatal'), (event) => {  // return false 就不會送出  if (event.getUser().id === '1') return false;
  event.severity = 'info';  event.context = 'component-space-246';  event.setUser('1', 'bugs.nag@bugsnag.com', 'B. Nag');  event.addMetadata('hyperflopz', { count: 23 });});
// 使用 callbackBugsnag.notify(new Error('uh oh'), null, function (err, event) {  if (err) {    console.log('Failed to send report because of:\n' + err.stack);  } else {    console.log('Successfully sent report "' + event.errors[0].errorMessage + '"');  }});

客製化錯誤訊息(metadata)#

Customizing error reports @ Bugsnag Docs

Bugsnag.addMetadata(section, key, value)Bugsnag.addMetadata(section, { [key]: value,})

在 v7 之後,原本的 beforeSend 改名為 onError,裡面接收的參數從 report 改名為 event;原先的 updateMetaData 也改為 addMetadata。詳細的說明可以參考升級指南(Upgrading)

⚠️ 留意原本是用大駝峰的 metaData 修正為 metadata

export const bugsnagClient = bugsnag({  apiKey: BUGSNAG_API_KEY,  onError: (event) => {    // 透過 addMetadata 更新資料到 metadata 中,如此不會覆蓋原有的 metadata    // 添加 user 資料    event.setUser(id, email, name);    event.addMetadata('user', state?.personalInfo);
    // 添加 device 資料    event.addMetadata('device', state?.deviceInfo);
    // 添加其他客製化資料    event.addMetadata('project', state?.app);    event.addMetadata('networkQuality', state?.webRTC?.networkQuality);  },});

客製化 breadcrumb#

Customizing breadcrumbs @ Bugsnag Docs

Bugsnag.leaveBreadcrumb('Preference updated', metadata, 'state');

透過 onBreadcrumb

Bugsnag.start({  apiKey: BUGSNAG_API_KEY,  onError: (event) => {    /*...*/  },  onBreadcrumb: (breadcrumb) => {    /* breadcrumb 物件 { message, metadata, timestamp, type } */    if (breadcrumb.type === 'navigation' && breadcrumb.metadata.to === '/home') {      return false;    }    breadcrumb.metadata.to = stripQueryString(breadcrumb.metadata.to);    breadcrumb.metadata.path = state?.path;  },});

⚠️ 如果在 log 會留下 breadcrumb 的話,在 onBreadcrumb 中使用 console.log 可能會導致無窮迴圈。

客製化 logger#

Configuration options > logger @ bugsnag

const logger = {  debug: (message) => console.log('[bugsnag] debug: ', message),  info: (message) => console.info('[bugsnag] info: ', message),  warn: (message) => console.warn('[bugsnag] warn: ', message),  error: (message) => console.error('[bugsnag] error: ', message),};
Bugsnag.start({  apiKey: BUGSNAG_API_KEY,  ...(process.env.NODE_ENV === 'development' && { logger }),});

上傳 SourceMap#

uploading source maps @ BugSnag > Build & deploy integrations > Node.js/npm scripts

問題解決#

在 Chrome Extension 或第三方服務使用 Bugsnag#

如果有使用 Bugsnag 這類第三方的錯誤通知程式,需要留意使用的方式略有不同:

參考:How can I get error reports from browser extensions? @ bugsnag docs

For v.7x.x

// v7.x.xexport const bugsnagClient = Bugsnag.createClient({  //...  onError: (event) => {    event.errors.map((error) => {      return error.stacktrace.map(function (frame) {        frame.file = frame.file.replace(          /chrome-extension:/g,          'chrome_extension:'        );        return frame;      });    });  }})
module.export bugsnagClient;

另外,由於在 Chrome Extension 中有可能需要同時在 content-script 和 background 中使用 bugsnagClient,因此需使用 createClient 並 export 這個 client,並可以在 onError 的時候透過不同的 context 來區別:

export const bugsnagClient = Bugsnag.createClient({  apiKey: BUGSNAG_API_KEY,  plugins: [new BugsnagPluginReact(React)],  appVersion,  releaseStage: process.env.NODE_ENV || 'development',  // FIXME:  // enabledReleaseStages: ['production'],  ...(process.env.NODE_ENV === 'development' && { logger }),  onError: (event) => {    event.errors.map((error) => {      // ...    });
    // 使用 context 來區分是在 background 或 front (content-script, iframe) 被呼叫    if (event.context.includes('background')) {      event.context = 'background';    } else if (event.context.includes('index')) {      event.context = 'front-side';    }  },});

⚠️ 即使 background 和 front-side(content-script, iframe)是 import 同一支檔案的 bugsnagClient,但因為是在不同的環境下,所以載到的 bugsnagClient 會是獨立的,也就是在不同的 execution context。

For v6.x.x

// v6.x.xbugsnag({  beforeSend: function (report) {    report.stacktrace = report.stacktrace.map(function (frame) {      frame.file = frame.file.replace(/chrome-extension:/g, 'chrome_extension:');      return frame;    });  },});