開發與維運

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

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

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

Capturing Source Maps

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

  • Webpack
  • TypeScript
  • UglifyJS
  • SystemJS

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

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,針對權限。

Releases -> Admin 權限在其他 API 文檔中也稱為 'project:releases'。

你可以通過它的文檔機制來配置 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: "."

Hosting Publicly


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

//# sourceMappingURL=<url>

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

例如,如果您有一個壓縮的 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 應用程序的情況並不少見。例如:

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

例如,如果你有以下內容:

您可以使用 ~/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 調用將不需要更新。

Leave a Reply

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