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。
公众号:黑客下午茶。
谢谢点赞支持👍👍👍!
相关文章
相关标签/搜索