開發與維運

Sentry(v20.12.1) K8S 雲原生架構探索,JavaScript Enriching Events(豐富事件信息)

Add Context


自定義上下文允許您將任意數據附加到事件。通常,此上下文在其生命週期中捕獲的任何 issue 之間都是共享的。您無法搜索這些,但可以在 issue 頁面上查看它們:

微信圖片_20220611121756.png

Structured Context

附加自定義 data 的最佳實踐是通過結構化上下文。上下文必須始終是一個 dictionary 或 map,它的值可以是任意的。使用 setContext 並給 context 一個唯一的名稱:

Sentry.setContext("character", {
  name: "Mighty Fighter",
  age: 19,
  attack_type: "melee",
});

Size Limitations

發送上下文時,請考慮有效負載大小限制。Sentry 不建議在上下文中發送整個應用程序狀態和大數據 blob。如果超過最大有效負載大小,Sentry 將響應 413 Payload Too Large,並拒絕該事件。使用 keepalive: true 時,該請求可能會永遠保持待處理狀態。

Passing Context Directly

從我們的 JavaScript SDK 5.16.0 版本開始,可以將某些上下文數據直接提供給 captureExceptioncaptureMessage 調用。提供的數據將與當前範圍內已經存儲的數據合併,除非使用回調方法明確將其清除。

此功能有三種不同的變體形式:

  1. 包含可更新屬性的普通對象
  2. 我們將從中提取屬性的 Scope 實例
  3. 回調函數,它將接收當前 scope 作為參數並允許修改

我們允許傳遞以下上下文 keys:tags, extra, contexts, user, level, fingerprint

Example Usages

Sentry.captureException(new Error("something went wrong"), {
  tags: {
    section: "articles",
  },
});

顯式清除已經存儲在 scope 中的內容:

Sentry.captureException(new Error("clean as never"), scope => {
  scope.clear();
  scope.setTag("clean", "slate");
  return scope;
});

使用 Scope 實例傳遞數據(其屬性仍將與全局 scope 合併):

const scope = new Sentry.Scope();
scope.setTag("section", "articles");
Sentry.captureException(new Error("something went wrong"), scope);

使用 Scope 實例傳遞數據並忽略全局配置的 Scope 屬性:

const scope = new Sentry.Scope();
scope.setTag("section", "articles");
Sentry.captureException(new Error("something went wrong"), () => scope);

Clearing Context

Context 保留在當前 scope 內,因此在每個操作(請求等)結束時將其清除。您還可以 push 和 pop 自己的作用域,以將上下文數據應用於特定的代碼塊或函數。

Sentry 支持兩種不同的 scope 來設置上下文:

  1. global scope,Sentry 在操作結束時不會丟棄
  2. 用戶創建的 scope

這將在以後的所有事件中更改:

這將在以後的所有事件中更改:

僅針對在 withScope 回調中捕獲的錯誤,將更改此狀態,然後自動將其恢復為先前的值:

Sentry.withScope(function(scope) {
  scope.setUser(someUser);
  Sentry.captureException(error);
});

如果你想從作用域中(Scope)刪除全局配置的數據,你可以調用:

Sentry.configureScope(scope => scope.clear());

Additional Data

除了結構化上下文(structured contexts),Sentry 還支持通過 setExtra 添加非結構化 "Additional Data"。Additional Data 已經廢棄,而應使用結構化上下文,並應儘可能避免使用。

Identify Users

用戶包含一些關鍵信息,這些信息構成了 Sentry 中的唯一身份。每個選項都是可選的,但必須存在一個選項才能使Sentry SDK 捕獲用戶:

id: 您的用戶內部標識符。

username: 用戶名。通常用作比內部 ID 更好的標籤。

email: username 的替代或補充。Sentry 知道電子郵件地址,並且可以顯示諸如 Gravatars 之類的內容並解鎖消息傳遞功能。

ip_address: 用戶的 IP 地址。如果用戶未經身份驗證,Sentry 將 IP 地址用作用戶的唯一標識符。Sentry 將嘗試從 HTTP 請求數據中提取此信息(如果有)。設置為 "{{auto}}",以使 Sentry 從 connection 中推斷 IP 地址。

此外,您可以提供保留名稱之外的任意 key/value 對,Sentry SDK 會將這些 key/value 對與 user 一起存儲。

識別用戶:

Sentry.setUser({ email: "[email protected]" });

您還可以清除當前設置的 user:

Sentry.configureScope(scope => scope.setUser(null));

Set Transaction Name

當前 transaction 名稱用於對 Performance 產品中的 transactions 進行分組,並用 failure 點註釋錯誤事件。

transaction 名稱可以引用當前的 Web 應用程序路由或正在執行的當前 task。例如:

  • GET /api/{version}/users/
  • UserListView
  • myapp.tasks.renew_all_subscriptions

理想情況下,transaction 名稱不包含諸如用戶 ID 之類的變量值,但具有較低的基數,同時仍可以唯一地標識您所關心的代碼。

我們的許多框架集成已經設置了 transaction 名稱。自己設定:

Sentry.configureScope(scope => scope.setTransactionName("UserListView"));

這將覆蓋當前正在運行的 transaction 的名稱。

Customize Tags

Tags 是既可索引又可搜索的 key/value 字符串對。Tags 具有強大的 UI 功能,例如過濾器(filters)和標籤分佈圖(tag-distribution maps)。Tags 還可以幫助您快速訪問相關事件,並查看一組事件的標籤分佈(tag distribution)。Tags 的常見用法包括主機名(hostname),平臺版本(platform version)和用戶語言(user language)。

我們將自動為一個事件的所有 tags 建立索引,以及 Sentry 看到標籤的頻率和最後一次。我們還將跟蹤不同 tags 的數量,並可以幫助您確定各種 issues 的熱點。

定義 tags 很容易,並將它們綁定到 current scope,確保 scope 內的所有未來事件都包含相同的標籤:

Sentry.setTag("page_locale", "de-at");

某些 tags 由 Sentry 自動設置。強烈建議您不要覆蓋這些 tags,而應使用自己的名稱命名。

一旦開始發送標記的數據(tagged data),您將在 Sentry Web UI 中看到它:Project 頁面側欄中的過濾器(filters),在事件內進行彙總以及在聚合事件(aggregated event)的 tags 頁面上。

image.gif

Attachments


Sentry 可以通過在事件旁邊存儲其他文件(例如日誌文件)作為附件來增強崩潰報告。附件使崩潰中的文件不僅可以上傳到Sentry,而且可以持久保存以進行進一步調查。

Uploading Attachments

要添加 attachment,請創建一個事件處理器(event processor),該事件處理器以 multipart form data 請求的形式將文件上傳到附件端點。這需要使用其 ID 將附件與事件相關聯:

public attachmentUrlFromDsn(dsn: Dsn, eventId: string) {
  const { host, path, projectId, port, protocol, user } = dsn;
  return `${protocol}://${host}${port !== '' ? `:${port}` : ''}${
    path !== '' ? `/${path}` : ''
  }/api/${projectId}/events/${eventId}/attachments/?sentry_key=${user}&sentry_version=7&sentry_client=custom-javascript`;
}
Sentry.addGlobalEventProcessor((event: Event) => {
  try {
    const client = Sentry.getCurrentHub().getClient();
    const endpoint = attachmentUrlFromDsn(
      client.getDsn(),
      event.event_id
    );
    const formData = new FormData();
    formData.append(
      'my-attachment',
      new Blob([JSON.stringify({ logEntries: ["my log"] })], {
        type: 'application/json',
      }),
      'logs.json'
    );
    fetch(endpoint, {
      method: 'POST',
      body: formData,
    }).catch((ex) => {
      // we have to catch this otherwise it throws an infinite loop in Sentry
      console.error(ex);
    });
    return event;
  } catch (ex) {
    console.error(ex);
  }
});

Sentry 每個事件最多允許 100MB 的附件,包括崩潰報告文件(如果適用)。超過此大小的上傳將被 HTTP 錯誤 413 Payload Too Large 拒絕,並且數據將立即被丟棄。要添加更大或更多的文件,請考慮使用輔助存儲選項。

附件存留 30 天;如果超出了配額中包含的總存儲空間,則不會存儲附件。您可以隨時刪除附件或其包含的事件。刪除附件不會影響您的配額(quota) - Sentry 存儲附件後立即將其計入您的配額。

Access to Attachments

要限制對附件的訪問,請導航到您組織的 General Settings,然後選擇 Attachments Access 下拉菜單來設置適當的訪問權限 - 您的組織的任何成員、組織帳單所有者、成員(member)、管理員(admin)、經理(manager)或所有者(owner)。

微信圖片_20220611121957.png

默認情況下,啟用存儲後,將授予所有成員訪問權限。如果成員無權訪問該項目,則無法下載附件。該按鈕將在 Sentry 中顯示為灰色。成員只能查看附件已存儲。

Viewing Attachments

附件顯示在所顯示事件的 Issue Details 頁面的底部。

微信圖片_20220611122022.png

或者,附件也會顯示在 Issue Details 頁面上的 Attachments 選項卡中,您可以在其中查看附件的類型以及相關事件。單擊 Event ID,以打開該特定事件的 Issue Details 信息。

微信圖片_20220611122013.png

Breadcrumbs

Sentry 使用 breadcrumbs 創建事件發生之前的事件線索。這些事件與傳統日誌非常相似,但是可以記錄更豐富的結構化數據。

此頁面概述了手動 breadcrumb 錄製(recording)和自定義(customization)。瞭解有關 Issue Details 頁面上顯示的信息的更多信息,以及如何過濾 breadcrumbs 以快速解決 Using Breadcrumbs 中的問題。

Manual Breadcrumbs

每當發生有趣的事情時,您都可以手動添加 breadcrumbs。例如,如果用戶進行身份驗證或發生其他狀態更改,則可以手動記錄一個麵包屑。

Sentry.addBreadcrumb({
  category: "auth",
  message: "Authenticated user " + user.email,
  level: Sentry.Severity.Info,
});

可用的 breadcrumb keys 包括 type, category, message, level, timestamp(許多SDK會自動為您設置)和 data,在此處可以放置您希望包含麵包屑的任何其他信息。使用這六個 key 以外的 key 不會導致錯誤,但是會導致在由 Sentry 處理事件時刪除數據。

Automatic Breadcrumbs

SDK 及其相關的集成將自動記錄許多類型的 breadcrumbs。例如,瀏覽器 JavaScript SDK 將自動記錄所有 location 更改。

Customize Breadcrumbs

SDK 允許您通過 before_breadcrumb 掛鉤自定義 breadcrumbs。此掛鉤傳遞了已經組裝好的 breadcrumb,並且在某些SDK 中傳遞了可選 hint。該函數可以修改 breadcrumb 或通過返回 null 決定完全放棄它:

Sentry.init({
  // ...
  beforeBreadcrumb(breadcrumb, hint) {
    return breadcrumb.category === "ui.click" ? null : breadcrumb;
  },
});

User Feedback

當用戶遇到錯誤時,Sentry 可以收集其他反饋。當您通常可以呈現簡單的錯誤頁面(經典的500.html)時,這種類型的反饋非常有用。

要收集 feedback,請使用可嵌入的 JavaScript widget,該小部件將請求並收集用戶的姓名,電子郵件地址以及發生的情況的描述。提供反饋後,Sentry 會將反饋與原始事件配對,從而使您對問題有更多見解。

下面的屏幕截圖提供了 User Feedback 小部件的示例,儘管您的個性化可能因您的自定義而有所不同:

微信圖片_20220611122049.png

Collecting Feedback

要集成 widget,您需要運行 2.1 版或更高版本的 JavaScript SDK。該 widget 將使用您的公共 DSN 進行身份驗證,然後傳遞在後端生成的 Event ID。

如果您希望使用 widget 的替代產品,或者沒有 JavaScript 前端,則可以使用 User Feedback API。

確保您有可用的 JavaScript SDK:

<script
  src="https://browser.sentry-cdn.com/6.0.1/bundle.min.js"
  integrity="sha384-z2Rmh4rfoBkdxaENH00ggKo5Bx8b2SJs+MWQrjWx4DbET95Z
  r2mxV2Vet3CCj4iW"
  crossorigin="anonymous"
></script>

如果您使用的是 React 或 Angular 之類的框架,則收集用戶反饋的最佳位置是您的錯誤處理組件。(有關示例,請參閱特定於平臺的文檔。)如果您不使用框架,則可以在發送事件之前使用 beforeSend 收集反饋:

<script>
  Sentry.init({
    dsn: "https://[email protected]/0",
    beforeSend(event, hint) {
      // Check if it is an exception, and if so, show the report dialog
      if (event.exception) {
        Sentry.showReportDialog({ eventId: event.event_id });
      }
      return event;
    },
  });
</script>

Customizing the Widget

您可以根據組織的需要自定義窗口小部件,尤其是為了本地化目的。所有選項都可以通過 showReportDialog 調用傳遞。

Sentry 的自動語言檢測 override(例如 lang=de

Param Default
eventId 手動設置事件的ID。
dsn 手動設置要報告的dsn。
user 手動設置 user data [具有下面列出的 key 的對象]。
user.email 用戶的電子郵件地址。
user.name 用戶名。
lang [automatic] – 覆蓋 Sentry 的語言代碼
title 看來我們遇到了問題。
subtitle 我們的團隊已收到通知。
subtitle2 如果您想提供幫助,請告訴我們下面發生的情況。– 在小屏幕分辨率下不可見
labelName 名稱
labelEmail Email
labelComments 發生了什麼?
labelClose 關閉
labelSubmit 提交
errorGeneric 提交報告時發生未知錯誤。請再試一次。
errorFormEntry 有些字段無效。請更正錯誤,然後重試。
successMessage 您的反饋已發送。謝謝!
onLoad n/a

Scopes and Hubs


捕獲事件並將其發送到 Sentry 後,SDK 會將事件數據與當前作用域(scope)中的額外信息合併。SDK 通常會在框架集成中為您自動管理 scopes,而您無需考慮它們。但是,您應該知道什麼是 scope 以及如何利用它來發揮自己的優勢。

What's a Scope, what's a Hub

您可以將 hub 視為我們的 SDK 用於將事件路由到 Sentry 的中心點。調用 init() 時,將創建一個 hub,並在其上創建一個 client 和一個 blank scope。然後,該 hub 與當前線程相關聯,並將在內部保存一堆 scopes。

scope 將包含應與事件一起發送的有用信息。例如,contexts 或 breadcrumbs 存儲在 scope 上。當推入作用域時,它將繼承父作用域的所有數據,並且當其彈出時,所有修改都將還原。

默認的 SDK 集成將智能地推送和彈出作用域。例如,Web 框架集成將在您的路由(routes)或控制器(controllers)周圍創建和銷燬作用域。

How do the Scope and Hub Work

當您開始使用 SDK 時,將自動為您創建一個 scope 和 hub。hub 不太可能直接與之交互,除非您正在編寫集成或希望創建或銷燬作用域。另一方面,作用域更多地面向用戶。您可以隨時調用 configure-scope 修改存儲在 scope 上的數據。例如,這用於 modify the context。

當您在內部調用諸如 capture_event 之類的全局函數時,Sentry 會發現當前的 hub 並要求其捕獲事件。然後,hub 將在內部將事件與最高 scope 的數據合併。

Configuring the Scope

使用範圍時,最有用的操作是 configure-scope 函數。它可用於重新配置當前 scope。例如,這可用於添加自定義標籤或向 sentry 告知當前已通過身份驗證的用戶。

Sentry.configureScope(function(scope) {
  scope.setTag("my-tag", "my value");
  scope.setUser({
    id: 42,
    email: "[email protected]",
  });
});

這也可以在註銷時取消用戶設置時應用:

Sentry.configureScope(scope => scope.setUser(null));

Local Scopes

我們還支持一鍵式推送和配置 scope。通常將其稱為 with-scopepush-scope,如果您只想發送一個特定事件的數據,這也非常有用。在下面的示例中,我們使用該函數將 leveltag 附加到僅一個特定錯誤:

Sentry.withScope(function(scope) {
  scope.setTag("my-tag", "my value");
  scope.setLevel("warning");
  // will be tagged with my-tag="my value"
  Sentry.captureException(new Error("my error"));
});
// will not be tagged with my-tag
Sentry.captureException(new Error("my other error"));

儘管此示例看起來與 configure-scope 相似,但有很大的不同,從某種意義上說 configure-scope 實際上會更改當前的 active scope,所有對 configure-scope 的後續調用都將保留所做的更改。

另一方面,使用 with-scope 會創建當前作用域的副本,並保持隔離狀態,直到函數調用完成。因此,您可以在此處不想設置其他位置的上下文信息,也可以通過在作用域上調用 clear 來根本不附加任何上下文信息,而“全局”範圍保持不變。

Leave a Reply

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