開發與維運

Sentry(v20.12.1) K8S 雲原生架構探索,SENTRY FOR JAVASCRIPT 故障排除

Debugging Additional Data


您可以查看事件的 JSON payload,以瞭解 Sentry 如何在事件中存儲其他數據。數據的形狀可能與描述不完全匹配。

微信圖片_20220611115719.png

有關詳細信息,請參閱關於 Event Payload 文檔。

Max JSON Payload Size


maxValueLength 的默認值為 250,但是如果您的消息較長,則可以根據需要調整此值。請注意,並非每個單個值都受此選項影響。

CORS Attributes and Headers


要了解來自不同來源的腳本引發的 JavaScript 異常,請執行以下兩項操作:

  1. 添加一個 crossorigin=”anonymous” 腳本屬性
<script src="http://another-domain.com/app.js" crossorigin="anonymous"></script>

script 屬性告訴瀏覽器 “anonymously” 地獲取目標文件。當請求此文件時,潛在的用戶識別信息(如 cookie 或 HTTP 憑據)不會被瀏覽器傳輸到服務器。

  1. 添加一個 Cross-Origin HTTP header

Access-Control-Allow-Origin: *

跨域資源共享(CORS)是一組 API(主要是 HTTP headers),這些 API 決定了應如何跨源下載和服務文件。

通過設置 Access-Control-Allow-Origin: *,服務器向瀏覽器指示任何來源都可以獲取該文件。另外,您可以將其限制為您控制的已知來源:

Access-Control-Allow-Origin: https://www.example.com

大多數社區 CDN 正確設置了 Access-Control-Allow-Origin 標頭。

$ curl --head https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.js | \
 grep -i "access-control-allow-origin"
 Access-Control-Allow-Origin: *

instrument.js Line Numbers for Console Log statements

如果在調試時在控制檯顯示 instrument.js,添加 Sentry 到你的框架 blackboxing ,設置如下:/@sentry/,這樣 Chrome 在調試時忽略 SDK stackframes。

Dealing with Ad-Blockers

當您使用我們的 CDN 時,廣告攔截(ad-blocking)或腳本攔截(script-blocking)擴展程序可能會阻止我們的 SDK 無法正確獲取和初始化。因此,對 SDKs API 的任何調用都將失敗,並可能導致您的應用程序行為異常。如果這適用於您的用例,則以下任何一種解決方案都可以緩解此問題。

處理腳本阻止擴展的最好方法是直接通過 npm 使用SDK軟件包,並將其與您的應用程序捆綁在一起。這樣,您可以確保代碼將始終如您所願地存在。

第二種方法是從 CDN 下載 SDK 並自己託管。這樣,SDK 仍將與您的其餘代碼分開,但是您可以確定它不會被阻止,因為它的來源與您網站的來源相同。

您可以使用 curl 或任何其他類似的工具輕鬆獲取它:

curl https://browser.sentry-cdn.com/5.20.1/bundle.min.js -o sentry.browser.5.20.1.min.js -s

最後一個選項是使用 Proxy 防護,即使您調用被阻止的 SDK,也可以確保您的代碼不會中斷。除 Internet Explorer 之外,所有瀏覽器均支持 Proxy,儘管該瀏覽器沒有擴展。同樣,如果您的用戶瀏覽器中沒有安裝 Proxy,它也會被靜默跳過,因此您不必擔心它會破壞任何東西。

將此片段放在包含我們的 CDN bundle 軟件的 <script> 標記上方。可讀格式的代碼段顯示如下:

if ("Proxy" in window) {
  var handler = {
    get: function(_, key) {
      return new Proxy(function(cb) {
        if (key === "flush" || key === "close") return Promise.resolve();
        if (typeof cb === "function") return cb(window.Sentry);
        return window.Sentry;
      }, handler);
    },
  };
  window.Sentry = new Proxy({}, handler);
}

如果你想直接複製和粘貼代碼片段,這裡是縮小過後的:

<script>
  if ("Proxy" in window) {
    var n = {
      get: function(o, e) {
        return new Proxy(function(n) {
          return "flush" === e || "close" === e
            ? Promise.resolve()
            : "function" == typeof n
            ? n(window.Sentry)
            : window.Sentry;
        }, n);
      },
    };
    window.Sentry = new Proxy({}, n);
  }
</script>

Using a Client directly


為了能夠管理多個 Sentry 實例而彼此之間沒有任何衝突,您需要創建自己的 Client。如果您的應用程序集成在其中,這也有助於防止跟蹤任何父應用程序錯誤。在此示例中,我們使用 @sentry/browser,但它也適用於 @sentry/node

import { BrowserClient } from "@sentry/browser";
const client = new BrowserClient({
  dsn: "___PUBLIC_DSN___",
});
client.captureException(new Error("example"));

儘管上面的示例工作得很好,但是 Client 上缺少諸如 configureScopewithScope 的某些方法,因為 Hub 負責狀態管理。這就是為什麼創建一個新的 Hub 並將其 Client 綁定到它上可能更容易的原因。結果是相同的,但是您還將獲得狀態管理。

import { BrowserClient, Hub } from "@sentry/browser";
const client = new BrowserClient({
  dsn: "___PUBLIC_DSN___",
});
const hub = new Hub(client);
hub.configureScope(function(scope) {
  scope.setTag("a", "b");
});
hub.addBreadcrumb({ message: "crumb 1" });
hub.captureMessage("test");
try {
  a = b;
} catch (e) {
  hub.captureException(e);
}
hub.withScope(function(scope) {
  hub.addBreadcrumb({ message: "crumb 2" });
  hub.captureMessage("test2");
});

Dealing with integrations

Integrations 是在 Client 上設置的,如果你需要處理多個 clients 和 hubs,你必須確保也正確地進行集成處理。下面是一個工作示例,演示如何使用多個 clients 和多個 hubs 運行全局集成。

import * as Sentry from "@sentry/browser";
// Very happy integration that'll prepend and append very happy stick figure to the message
class HappyIntegration {
  constructor() {
    this.name = "HappyIntegration";
  }
  setupOnce() {
    Sentry.addGlobalEventProcessor(event => {
      const self = Sentry.getCurrentHub().getIntegration(HappyIntegration);
      // Run the integration ONLY when it was installed on the current Hub
      if (self) {
        event.message = `\\o/ ${event.message} \\o/`;
      }
      return event;
    });
  }
}
HappyIntegration.id = "HappyIntegration";
const client1 = new Sentry.BrowserClient({
  dsn: "___PUBLIC_DSN___",
  integrations: [...Sentry.defaultIntegrations, new HappyIntegration()],
  beforeSend(event) {
    console.log("client 1", event);
    return null; // Returning null does not send the event
  },
});
const hub1 = new Sentry.Hub(client1);
const client2 = new Sentry.BrowserClient({
  dsn: "___PUBLIC_DSN___", // Can be a different DSN
  integrations: [...Sentry.defaultIntegrations, new HappyIntegration()],
  beforeSend(event) {
    console.log("client 2", event);
    return null; // Returning null does not send the event
  },
});
const hub2 = new Sentry.Hub(client2);
hub1.run(currentHub => {
  // The hub.run method makes sure that Sentry.getCurrentHub() returns this hub during the callback
  currentHub.captureMessage("a");
  currentHub.configureScope(function(scope) {
    scope.setTag("a", "b");
  });
});
hub2.run(currentHub => {
  // The hub.run method makes sure that Sentry.getCurrentHub() returns this hub during the callback
  currentHub.captureMessage("x");
  currentHub.configureScope(function(scope) {
    scope.setTag("c", "d");
  });
});

Third Party Promise Libraries

當您包含並配置 Sentry 時,我們的 JavaScript SDK 會自動將 global handlers 附加到 capture 未捕獲的 exceptions 和未處理的 promise rejections。您可以通過在 GlobalHandlers 集成中將 onunhandledrejection 選項設置為 false 來禁用此默認行為,並手動掛鉤到每個事件 handler,然後直接調用 Sentry.captureExceptionSentry.captureMessage

如果您使用第三方庫來實現 promises,則可能還需要管理您的配置。另外,請記住,瀏覽器經常實施安全措施,當提供來自不同來源的腳本文件時,這些措施會阻止錯誤報告。

Supported Browsers

Sentry 的 JavaScript SDK 支持以下瀏覽器:

Android Firefox Chrome IE iPhone Edge Safari
4.4 latest latest IE 10
iOS12 latest latest
5.0 IE 11 iOS13
6.0
7.1
8.1
9.0
10.0

Support for <= IE 11

在 5.7.0 版之前,我們的 JavaScript SDK 需要為舊版瀏覽器(如IE 11和更低版本)提供一些 polyfill。如果您正在使用它,請先升級到最新版本或在下面添加腳本標籤,然後再加載我們的 SDK。

<script src="https://polyfill.io/v3/polyfill.min.js?features=Promise%2CObject.assign%2CString.prototype.includes%2CNumber.isNaN"></script>

我們需要以下polyfill:

  • Promise
  • Object.assign
  • Number.isNaN
  • String.prototype.includes


此外,請記住在 HTML 頁面頂部定義一個有效的 HTML 文檔類型,以確保 IE 不會進入兼容模式。

Leave a Reply

Your email address will not be published. Required fields are marked *