Sentry(v20.12.1) K8S 雲原生架構探索,SENTRY FOR JAVASCRIPT Source Maps 詳解

系列

  1. Sentry-Go SDK 中文實踐指南
  2. 一塊兒來刷 Sentry For Go 官方文檔之 Enriching Events
  3. Snuba:Sentry 新的搜索基礎設施(基於 ClickHouse 之上)
  4. Sentry 10 K8S 雲原生架構探索,Vue App 1 分鐘快速接入
  5. Sentry(v20.12.1) K8S雲原生架構探索,玩轉前/後端監控與事件日誌大數據分析,高性能高可用+可擴展可伸縮集羣部署
  6. Sentry(v20.12.1) K8S 雲原生架構探索,Sentry JavaScript SDK 三種安裝加載方式
  7. Sentry(v20.12.1) K8S 雲原生架構探索,SENTRY FOR JAVASCRIPT SDK 配置詳解
  8. Sentry(v20.12.1) K8S 雲原生架構探索, SENTRY FOR JAVASCRIPT 手動捕獲事件基本用法

Sentry 支持經過 source maps(源代碼映射)對 JavaScript 進行 un-minifying,這容許您以原始的未轉換形式查看從堆棧跟蹤中得到的源代碼上下文。這對於調試壓縮後的代碼(例如,UglifyJS)或從高級語言編譯的代碼(如 TypeScriptES6)特別有用。前端

Sentry 將經過抓取堆棧跟蹤中的 URL 自動獲取源代碼(source code)和源代碼映射(source maps)。可是,您可能有正當的理由在 Sentry 中 disabling the JavaScript source fetching in Sentry(在 Sentry 中禁用 JavaScript 源代碼獲取)。vue

Capturing Source Maps

大多數現代 JavaScript 編譯器都支持 source maps。下面你會發現咱們推薦的說明,但咱們也提供了各類經常使用工具的說明:node

  • Webpack
  • TypeScript
  • UglifyJS
  • SystemJS

咱們建議使用 Sentry's Webpack plugin 來配置 source maps 並在構建過程當中自動上傳它們:webpack

npm install --save-dev @sentry/webpack-plugin
or
yarn add --dev @sentry/webpack-plugin

接下來,您須要爲咱們的 API 生成 access token。在您的組織設置中,導航到 Developer Settings,create a new internal integration,並提供一個適合您組織的名稱。重要: 選擇 Releases -> Admin,針對權限。git

Releases -> Admin 權限在其餘 API 文檔中也稱爲 'project:releases'。github

你能夠經過它的文檔機制來配置 sentry-cli,或者在初始化插件時簡單地綁定所需的參數:web

const SentryWebpackPlugin = require("@sentry/webpack-plugin");

module.exports = {
  // other configuration
  configureWebpack: {
    plugins: [
      new SentryWebpackPlugin({
        // sentry-cli configuration
        authToken: process.env.SENTRY_AUTH_TOKEN,
        org: "exmaple-org",
        project: "example-project",

        // webpack specific configuration
        include: ".",
        ignore: ["node_modules", "webpack.config.js"],
      }),
    ],
  },
};

在 Vue 2.x 中,應使用 vue.config.js 而不是 webpack.config.js,並使用 include: "./dist" 而不是 include: "."算法

Hosting Publicly

默認狀況下,Sentry 將在已編譯的 JavaScript 文件中查找源映射指令(source map directives),這些指令位於最後一行,並具備如下格式:docker

//# sourceMappingURL=<url>

當 Sentry 遇到這樣一個指令時,它將解析與它所在的源文件相關的 source map URL,並嘗試使用 HTTP 請求獲取它。typescript

例如,若是您有一個壓縮的 JavaScript 文件位於 http://example.org/js/app.min.js,而且在該文件的最後一行中,則找到如下指令:

//# sourceMappingURL=app.js.map

Sentry 將嘗試從 http://example.org/js/app.js.map 獲取 app.js.map

另外,在生成源代碼映射時,你能夠指定源代碼映射所在的絕對 URL:

//# sourceMappingURL=http://example.org/js/app.js.map

雖然從服務器使 source maps 可用於 Sentry 是最天然的集成(natural integration),但並不老是建議這樣作:

  • Sentry 可能並不老是可以訪問您的服務器。
  • 若是您沒有在您的 asset URLs 中指定版本,可能存在版本不匹配
  • 額外的延遲可能意味着源映射對全部錯誤都不可用。

因爲這些緣由,最好的作法是預先上傳 source maps 給 Sentry(見下文)。

Working Behind a Firewall

推薦的解決方案是將您的 source artifacts 上傳到 Sentry,但有時有必要容許來自 Sentry 內部 IP 的通訊。有關 Sentry 的公共IP 的更多信息,請參見:IP Ranges

Secure Access to Source Maps

若是你想保密你的 source maps 而且選擇不直接上傳你的 source maps 到 Sentry,你能夠在你的項目設置中啓用 「Security Token」 選項。

這將致使 Sentry 服務器對來自 「Allowed Domains」 的 URL 的出站請求附加 HTTP 標頭 X-Sentry-Token 標頭:

GET /assets/bundle.min.js
X-Sentry-Token: {token}

token 是您在項目設置中定義的安全值。而後,您能夠配置您的 web 服務器,以容許在此 header/token 對 存在時訪問您的 source maps。你也能夠覆蓋默認的 header 名稱(X-Sentry-Token)並使用 HTTP Basic Authentication,例如經過傳遞 Authorization: Basic {encoded_password}

Multiple Origins

能夠從多個來源訪問 web 應用程序的狀況並很多見。例如:

  • 網站能夠在 httpshttp 上運行
  • 地理位置網址:例如 https://us.example.com, https://eu.example.com
  • 多個靜態 CDN:例如 https://static1.example.com, https://static2.example.com
  • 客戶特定的域(domains)/子域(subdomains

在這種狀況下,相同的 JavaScript 和 source map 文件可能位於兩個或多個不一樣的源。在這種狀況下,咱們建議在路徑上使用特殊的波浪號(~)前綴。

例如,若是你有如下內容:

  • https://static1.example.com/js/app.js
  • https://static2.example.com/js/app.js

您可使用 ~/js/app.js 的 URL 進行上傳。 這將告訴 Sentry 忽略域,並將 artifact 用於任何來源。

此外,您還可使用多個名稱上傳同一文件。在後臺,Sentry 會將這些重複數據刪除。

~前綴告訴 Sentry,對於給定的 URL,任何 路徑爲 /js/app.js 的協議和主機名的組合都應該使用這個工件(artifact)。只有當您的 source/source map 文件在全部可能的 protocol/hostname 組合上都相同時,才使用此方法。若是找到完整的 URL, Sentry 將優先使用,高於波浪前綴路徑。

Tools

SystemJS

SystemJS 是 Angular 2 項目的默認模塊加載器。SystemJS 構建工具可用於 bundle,transpile 和 minify 用於生產環境的源代碼,並可配置爲輸出 source maps。

builder.bundle("src/app.js", "dist/app.min.js", {
  minify: true,
  sourceMaps: true,
  sourceMapContents: true,
});

上面的示例配置會將您原始的(original),未經轉換(un-transformed)的源代碼內聯到生成的 source map 文件中。 Sentry要求 source map(s) 和原始源文件都執行反向轉換。若是您選擇不內聯源文件,則除了源映射外,還必須使這些源文件對 Sentry 可用(請參見下文)。

TypeScript

TypeScript 編譯器能夠輸出 source maps。將 sourceRoot 屬性配置爲 /,以從生成的源代碼引用中去除構建路徑前綴。這容許 Sentry 匹配源文件相對於你的源根文件夾:

{
  "compilerOptions": {
    "sourceMap": true,
    "inlineSources": true,
    "sourceRoot": "/"
  }
}

UglifyJS

UglifyJS 是一種流行的工具,可用於壓縮生產源代碼。經過消除空格,重寫變量名,刪除無效代碼分支等,它能夠大大減小文件的大小。

咱們強烈建議您使用更高級別的 bundler(或 transpiler),由於 UglifyJS 配置可能會變得很是複雜,沒法達到預期的效果。

若是你正在使用 UglifyJS 來壓縮你的源代碼,下面的命令將額外生成一個 source map,將壓縮的代碼映射回原始源代碼:

uglifyjs app.js \
  -o app.min.js.map \
  --source-map url=app.min.js.map,includeSources

Webpack

Webpack 是一個強大的構建工具,能夠解析、捆綁和壓縮 JavaScript 模塊。它還支持各類 loaders 來轉換高級語言、引用樣式表或包含靜態資源。

Sentry 提供了一個方便的 Webpack plugin,能夠配置 source maps,並在構建時將它們上傳到 Sentry。對於上傳源到 Sentry,推薦使用這個過程:

npm install --save-dev @sentry/webpack-plugin
or
yarn add --dev @sentry/webpack-plugin

您能夠經過其 documented mechanisms 來配置 sentry-cli,或者在初始化插件時僅綁定必需的參數:

const SentryWebpackPlugin = require("@sentry/webpack-plugin");

module.exports = {
  // other configuration
  configureWebpack: {
    plugins: [
      new SentryWebpackPlugin({
        // sentry-cli configuration
        authToken: process.env.SENTRY_AUTH_TOKEN,
        org: "exmaple-org",
        project: "example-project",

        // webpack specific configuration
        include: ".",
        ignore: ["node_modules", "webpack.config.js"],
      }),
    ],
  },
};

在 Vue 2.x 中,應使用 vue.config.js 而不是 webpack.config.js,並使用 include: "./dist" 而不是 include: "."

SentryWebpackPlugin 設置爲最後一個正在運行的插件,不然,該插件接收到的結果 source maps 可能不是最終的。

Advanced Usage

若是您但願手動上傳 source maps,請將 Webpack 配置爲輸出 source maps:

module.exports = {
  output: {
    path: path.join(__dirname, "dist"),
    filename: "[name].js",
    sourceMapFilename: "[name].js.map",
  },
  // other configuration
};

若是使用 SourceMapDevToolPlugin 進行 source map 生成的更細粒度控制,請關閉 noSources,以便 Sentry 在事件堆棧跟蹤中顯示正確的源代碼上下文。

此外,Webpack 插件將自動設置 window.SENTRY_RELEASE,所以您的 Sentry.init 調用將不須要更新。

Troubleshooting

Source maps 有時可能很難上手。若是您遇到問題:

Verify a release is configured in your SDK

要定位和應用已上傳的 source maps,須要經過 CLI 或 API 建立 release(以及上傳的正確 artifacts),而且須要在 SDK 配置中指定新建立的 release 的名稱。

要驗證這一點,請從 Sentry UI 打開 issue 並檢查是否配置了 release。若是屏幕右側的 Release 旁邊顯示 "not configured" 或 "N/A"(或若是你沒有看到一個 release 標籤在標籤列表),則須要返回並 tag your errors。若是設置正確,您將看到 "Release: my_example_release"。

Verify artifacts are uploaded

一旦您的 release 被正確配置而且問題被標記,您能夠經過導航到 [Project] » Project Settings » Source Maps 來找到上傳到 Sentry 的工件(artifacts)。

此外,請確保全部必要的文件均可用。爲了讓 Sentry 去 de-minify 你的堆棧跟蹤,您必須同時提供兩個壓縮的文件(例如,app.min.js)以及相應的 source maps。若是 source map 文件不包含原始 source code(sourcesContent),則必須另外提供原始 source code。或者,sentry-cli 會自動將源代碼(若是缺乏)嵌入到 source maps 中。

Verify sourceMappingURL is present

一些 CDN 自動從靜態文件(包括 JavaScript 文件)中刪除註釋。這可能會致使 JavaScript 文件中沒有 sourceMappingURL 指令,由於它被視爲註釋。例如,CloudFlare 有一個名爲 Auto-Minify 的功能,若是它被啓用,它將剝離 sourceMappingURL

仔細檢查部署的最終 JavaScript 文件是否有 sourceMappingURL

或者,您能夠在壓縮的文件上設置 SourceMap HTTP header,而不是 sourceMappingURL。若是存在此標頭,Sentry 將使用它來發現 source map 的位置。

Verify artifact names match sourceMappingURL value

bundled 或 minified 的 JavaScript 文件的最後一行的 sourceMappingURL 註釋告訴Sentry(或瀏覽器)在哪裏找到相應的 source map。這能夠是絕對的 URL,相對路徑或文件名自己。將工件(artifacts)上傳到 Sentry 時,必須使用文件解析到的值來命名 source map 文件。

也就是說,若是你的文件相似於:

// -- end script.min.js
//# sourceMappingURL=script.min.js.map

並託管在 http://example.com/js/script.min.js 上,而後 Sentry 將在 http://example.com/js/script.min.js.map 上查找 source map 文件。所以,您上傳的工件(artifact)必須命名爲 http://example.com/js/script.min.js.map (或 ~/js/script.min.js.map)。

或者,若是你的文件相似於:

//-- end script.min.js
//# sourceMappingURL=https://example.com/dist/js/script.min.js.map

而後你上傳的工件(artifact)也應該命名爲 https://example.com/dist/js/script.min.js.map (或者 ~/dist/js/script.min.js.map )。

最後,若是你的文件相似於:

//-- end script.min.js
//# sourceMappingURL=../maps/script.min.js.map

而後你上傳的工件應該命名爲 https://example.com/dist/maps/script.min.js.map (或者 ~/dist/maps/script.min.js.map)。

Verify artifact names match stack trace frames

若是您上傳了 source maps,但它們沒有應用到 Sentry 中的某個 issue 中的代碼中,請查看事件的 JSON 並查找 abs_path,以查看咱們試圖解析文件的確切位置 — 例如,http://localhost:8000/scripts/script.js(對於堆棧跟蹤中的每一幀,abs_path 將出現一次 - 將其與未被非 deminified 的文件匹配。)。在事件發生日期旁邊的 issue 頁面頂部能夠找到一個指向 JSON 視圖的連接。上載的工件名稱(uploaded artifact names)必須與這些值匹配。

若是您的 dynamic values in your path(路徑中有動態值)(例如:https://www.site.com/{some_value}/scripts/script.js),則可能須要使用 rewriteFrames integration 來更改 abs_path 值。

Using sentry-cli

若是您的 sourceMappingURL 註釋相似於:

// -- end script.min.js (located at http://localhost:8000/scripts/script.min.js)
//# sourceMappingURL=script.min.js.map

正確上傳這些文件的示例,sentry-cli 命令以下所示(假設您位於 /scripts 目錄中,並從一個更高的目錄運行 Web 服務器,這就是爲何咱們使用 --url-prefix 選項):

sentry-cli releases files VERSION upload-sourcemaps . --url-prefix '~/scripts'

此命令上傳當前目錄中的全部 JavaScript 文件。Sentry 中的 Artifacts 頁面如今應以下所示:

~/scripts/script.js
~/scripts/script.min.js
~/scripts/script.min.js.map

或者,您能夠指定要上傳的文件。 例如:

sentry-cli releases files VERSION upload-sourcemaps script.min.js script.min.js.map --url-prefix '~/scripts'

您也可使用絕對 URL 上傳它。例如:

sentry-cli releases files VERSION upload-sourcemaps . --url-prefix 'http://localhost:8000/scripts'

Using the API

您也可使用咱們的API 來上傳工件,遵循這裏解釋的相同命名約定。

curl -X POST \
  https://sentry.io/api/0/organizations/ORG_SLUG/releases/VERSION/files/ \
  -H 'Authorization: Bearer AUTH_TOKEN' \
  -H 'content-type: multipart/form-data' \
  -F file=@script.min.js.map \
  -F 'name=~/scripts/script.min.js.map'

Using the ~

~ 在 Sentry 中用於替換 scheme 和 domain。這不是一個問題!

http://example.com/dist/js/script.js 將匹配 ~/dist/js/script.jshttp://example.com/dist/js/script.js

可是將不匹配 ~/script.js

Verify artifacts are uploaded before errors occur

Sentry 但願在某個 release 中出現錯誤以前,將 source code 和 source maps 上傳到 Sentry。

若是您在 Sentry 捕獲錯誤以後上傳工件,Sentry 將不會返回並追溯地對這些錯誤應用任何源註釋。只有在工件上傳後觸發的新錯誤纔會受到影響。

Verify your source maps are built correctly

咱們維護了一個在線驗證工具,能夠用來測試您的 source maps 與 hosted(託管) 源:https://sourcemaps.io

另外,若是你正在使用 Sentry CLI 上傳 source maps 到 Sentry,你可使用 --validate 命令行選項來驗證你的 source maps 是否正確。

Verify your source maps work locally

若是發現 Sentry 沒有正確映射文件名,行或列映射,則應驗證 source maps 是否在本地運行。爲此,您能夠將 Node.js 與Mozilla 的 source-map library 一塊兒使用。

首先,將 source-map 做爲 npm 模塊全局安裝:

npm install -g source-map

而後,編寫一個腳本,該腳本讀取您的 source map 文件並測試映射。這是一個例子:

var fs = require("fs"),
  path = require("path"),
  sourceMap = require("source-map");

// file output by Webpack, Uglify, and so forth
var GENERATED_FILE = path.join(".", "app.min.js.map");

// line and column located in your generated file (for example, the source of your error
// from your minified file)
var GENERATED_LINE_AND_COLUMN = { line: 1, column: 1000 };

var rawSourceMap = fs.readFileSync(GENERATED_FILE).toString();
new sourceMap.SourceMapConsumer(rawSourceMap).then(function(smc) {
  var pos = smc.originalPositionFor(GENERATED_LINE_AND_COLUMN);

  // should see something like:
  // { source: 'original.js', line: 57, column: 9, name: 'myfunc' }
  console.log(pos);
});

若是您經過 Sentry 在本地得到相同(不正確)的結果,請仔細檢查您的 source map 生成配置。

Verify your source files are not too large

對於單個 artifact,Sentry 接受的最大文件大小爲 40 MB

用戶一般會達到此限制,由於他們在臨時構建階段傳輸源文件。例如,在 Webpack/Browserify 合併全部源文件以後,但在壓縮以前。若是可能,請發送原始源文件。

Verify artifacts are not gzipped

Sentry API 當前僅適用於以純文本(UTF-8 編碼)上傳的 source maps 和 source files。若是文件以壓縮格式(例如 gzip)上傳,則將沒法正確解釋它們。

這種狀況有時會發生在生成預壓縮小文件的構建腳本和插件中。例如,Webpack 的壓縮插件。您須要禁用這些插件,並在將生成的 source maps/source files 上傳到 Sentry 後執行壓縮。

Verify workers are sharing the same volume as web (if running as docker on premise)

Sentry 在其 workers 中進行 source map 計算。這意味着 workers 須要訪問經過前端上傳的文件。仔細檢查 cron workers 和 web workers 是否能夠從同一個磁盤讀/寫文件。

Uploading Source Maps

咱們建議將上傳 source maps 做爲構建過程的一部分,但您也能夠將它們與源文件一塊兒公開提供。

建議的上傳 source maps 的方法是使用 sentry-cli。若是您使用 Sentry Wizard 來設置項目,則它已經建立了全部必要的配置以上傳 source maps。不然,請遵循 CLI 配置文檔來設置您的項目。

您須要設置構建系統以建立 release 並附加各類源文件。爲了使 Sentry 縮小堆棧跟蹤的大小,必須同時提供縮小的文件(例如app.min.js)和相應的源映射。若是源映射文件不包含原始源代碼(sourcesContent),則還必須提供原始源文件。另外,sentry-cli 將自動將源(若是缺乏)嵌入到 source maps 中。

Sentry 使用 Releases 將正確的 source maps 與您的事件進行匹配。要建立新 release,請運行如下命令(例如,在發佈期間):

sentry-cli releases new <release_name>

release 名稱必須是在您的組織內惟一的,而且與 SDK 初始化代碼中的 release 選項匹配。而後,使用 upload-sourcemaps 命令掃描文件夾中的 source maps,進行處理並將其上傳到 Sentry。

sentry-cli releases files <release_name> upload-sourcemaps /path/to/files

您能夠經過導航找到上傳到 Sentry 的工件:[Project] » Project Settings » Source Maps

此命令會將全部以 .js 和 .map 結尾的文件上傳到指定的 release。若是您想更改這些擴展名(例如,上傳 typescript 源),請使用 --ext 選項:

sentry-cli releases files <release_name> upload-sourcemaps --ext ts --ext map /path/to/files

到目前爲止,版本處於草稿狀態((「unreleased」)。 一旦全部 source maps 都已上傳,而且您的應用已成功發佈,請使用如下命令完成 release:

sentry-cli releases finalize <release_name>

爲了方便起見,您也能夠將 --finalize flag 傳遞給 new 命令,該命令將當即完成 release。

你沒必要必定上傳源文件(由 source maps 引用),可是沒有它們,分組算法就不會那麼強大,UI 也不會顯示任何上下文相關的源文件。

有關更多信息,請參閱咱們 Releases API documentation

web 應用程序能夠從多個來源訪問並很多見。請參閱咱們關於如何處理此問題的多個來源的文檔。

Validating Files

要確保 source maps 自己是有效的,而且正確上傳,這多是一個至關具備挑戰性的問題。爲了幫助實現這一點,咱們維護了一個在線驗證工具,可用於根據託管源測試源映射:https://sourcemaps.io

此外,當使用 sentry-cli 上傳源映射時,能夠在中使用 --validate 標誌,這將嘗試本地解析源映射並查找引用。請注意,在某些已知狀況下,當設置正確時,validate 標誌將指示失敗(若是您有對外部源映射的引用,則驗證工具將指示失敗)。

除了驗證步驟以外,您還能夠檢查如下內容:

  • 確保您的文件的 URL 前綴正確。這很容易出錯。
  • 爲 minimized 的文件上傳匹配的源映射。
  • 確保服務器上的 minified 文件確實引用了您的文件。

中文文檔陸續同步到:

我是爲少。
微信:uuhells123。
公衆號:黑客下午茶。
謝謝點贊支持👍👍👍!
相關文章
相關標籤/搜索