生产上的问题你不会用 sourcemap 定位吗?(二)

简介: 生产上的问题你不会用 sourcemap 定位吗?

Edge 浏览器

image.png

image.png

异常监控系统

这里以 sentry 为例 简单演示 一下,大致包括:

  • 接入 sentry
  • 异常捕获
  • 添加 sourcemap

首先,在 Sentry 监控平台上注册/登录拥有自己的账号,然后可以构建一个对应的项目(首次注册登录会有指引),项目创建好以后会生成一个 dsn,在接入 sentry 时需要传入。

其次,按照引导页的提示在你的项目(以 vue3 为例)中安装依赖 npm install --save @sentry/vue @sentry/tracing

最后,在你项目入口文件(main.js)中初始化接入 Sentry 即可:

import { createApp } from "vue";
import { createRouter } from "vue-router";
import * as Sentry from "@sentry/vue";
import { BrowserTracing } from "@sentry/tracing";
const app = createApp({
  // ...
});
const router = createRouter({
  // ...
});
Sentry.init({
  app,
  dsn: "https://x@x.ingest.sentry.io/x",
  integrations: [
    new BrowserTracing({
      routingInstrumentation: Sentry.vueRouterInstrumentation(router),
      tracePropagationTargets: ["localhost", ...],
    }),
  ],
  // Set tracesSampleRate to 1.0 to capture 100%
  // of transactions for performance monitoring.
  // We recommend adjusting this value in production
  tracesSampleRate: 1.0,
});
app.use(router);
app.mount("#app");
复制代码

经过以上处理,默认情况下 Sentry 已经可以自动获取到错误信息了,如:

image.png

image.png

image.png

显然,没有接入 sourcemap 的错误信息在 sentry 中也无法进行快速定位,因此下一步就是需要给 sentry 上传 sourcemap 相关的文件。

sentry 上传 sourcemap 流程sentry 文档

  • 安装 webpack 插件:npm install --save-dev @sentry/webpack-plugin
  • 配置 webpack 插件
// vue.config.js
  const { defineConfig } = require('@vue/cli-service')
  const SentryWebpackPlugin = require('@sentry/webpack-plugin')
  module.exports = defineConfig({
    configureWebpack(config) {
      if (process.env.NODE_ENV === 'production') {
        config.devtool = 'hidden-source-map'
        config.plugins.push(
          new SentryWebpackPlugin({
            include: './dist',
            ignoreFile: '.gitignore',
            ignore: ['node_modules', 'webpack.config.js'],
            configFile: './.sentryclirc',
            release: '0.0.1',
            urlPrefix: '~/js/',
          }),
        )
      }
    },
  })
复制代码
  • 在项目根目录下新建 .sentryclirc 文件
[auth]
token = 在 sentry 平台生成
[defaults]
url = https://sentry.io/ // 如果是自己部署的就填部署地址,如果不是就不改
org = sentry 平台的 org
project = sentry 平台的 project
复制代码
  • 如皋设置 release 字段,那么要保证 main.js 中的 Sentry。init({...}) 和  SentryWebpackPlugin 中的要保持一致性,或者都不设置
  • 构建产物 npm run build
  • 进入 dist 目录通过 http-server  启动本地服务模拟生产环境产生错误
  • 进入 sentry 中查看异常信息,上传 sourcemap 文件后,错误信息如下:
  • image.png

手动映射

通常情况下为了安全性,不推荐使用 浏览器 映射的方式,虽然这种方式对你来说很简便,但也为别有用心的人提供了便捷,因此,通常都会有接入对应的 监控平台,当然除此之外还可以通过 手动映射 的方式进行定位:

  • 安装 source map 库:npm install source-map
  • 新建 sourcemap.js
const { SourceMapConsumer } = require('source-map')
   const fs = require('fs')
   const rawSourceMap = fs.readFileSync('./dist/js/app.dde017e5.js.map', 'utf-8')
   // 填入错误信息
   originalPositionFor('app.dde017e5.js:1:11871')
   function originalPositionFor(errInfo) {
     const [budleName, line, column] = errInfo.split(':')
     SourceMapConsumer.with(rawSourceMap, null, (consumer) => {
       const originalPosition = consumer.originalPositionFor({
         line: parseInt(line),
         column: parseInt(column),
       })
       console.log('bundle name = ', budleName)
       console.log('original position = ', originalPosition)
     })
复制代码
  • 演示如下:

image.png

image.png

image.png

sourcemap 的映射原理

.map 文件中有 mappings 字段,其内容很难让人不注意,毕竟和其他内容相比看起来太与众不同了:

image.png

实际上,mappingsBase64 VLQ 编码形式存储了映射到源代码 行、列 等相关信息。

为什么使用 Base64 VLQ 编码?

源代码通常都是很庞大的,单纯使用 数字 表示 行信息列信息 会使得整个 .map 文件体积变大,而 Base64 VLQ 是一种 压缩数字 内容的编码方式,因此可以用来减少文件体积。

由于 Base64 所能表示的数字存在 上限,如果需要表示超过上限的数字该怎么办,实际上只有 每个分号中的第一串英文 是用来表示代码的 第几行、第几列 的绝对位置外,后面的都是相对于之前的位置来做 加减法 的。

可以通过 BASE64 VLQ CODEC 这个网站了解具体的映射关系.

mappings 的组成

mappings 的内容主要由三部分组成:

  • 英文串
  • 每段英文串表示 运行时代码开发时代码 位置关联的 base64VLQ 编码内容
  • 每段英文串拥由 5 部分组成:
  • 运行时代码所在的列,通常源代码经压缩后只有 1行,因此不需要存储行信息,只需要存储列信息
  • 对应 sources 字段下标,即对应哪个源文件
  • 开发时代码的第几行
  • 开发时代码的第几列
  • 对应 names 字段下标,即对应哪个变量名
  • 逗号 ,
  • 用于分隔一行代码中的内容或位置,例如 "var a = 1;console.log(a);" 相当于 "var, a, =, 1, console, log"
  • 分号 ;
  • 表示 运行时代码 的行信息,用来定位是编译后代码的第几行,如果启用代码压缩那么就不会有 分号,因为代码会被压缩在一行上

简单解析 mappings

下面以 console.log(1); 为例子简单介绍下对应关系,毕竟源码内容复杂的不好分析:

// main.js
console.log(1);
// main.js.map
{
  "version": 3,
  "file": "main.js",
  "mappings": "AAAAA,QAAQC,IAAI",
  "sources": ["webpack://vue3-wp5/./src/main.js"],
  "sourcesContent": ["console.log(1);\n"],
  "names": ["console", "log"],
  "sourceRoot": ""
}
复制代码

还是先关注 mappings 字段,其内容由于是编码后的内容,为了更直观的看到其代表的具体数字内容,我们可以通过 BASE64 VLQ CODEC 网站来得到结果:

image.png

现在,我们知道了 "AAAAA,QAAQC,IAAI" 对应 [0,0,0,0,0], [8,0,0,8,1], [4,0,0,4],结合上述其内容就表示:

  • [0,0,0,0,0] 对应 console
  • 0 :编译代码 第 0
  • 0 :对应 sources[0],即 main.js
  • 0 :源代码 第 0
  • 0 :源代码 第 0
  • 0 :对应 names[0],即 console
  • [8,0,0,8,1] 对应 log
  • 8 :编译代码 第 8,其实是 第 8+0=8
  • 0 :对应 sources[0],即 main.js
  • 0 :源代码 第 0
  • 8 :源代码 第 8,其实是 第 8+0=8
  • 1 :对应 names[1],即 log
  • [4,0,0,4] 对应 1
  • 4 :编译代码 第 4,其实是 第 8+4=12
  • 0 :对应 sources[0],即 main.js
  • 0 :源代码 第 0
  • 4 :源代码 第 4,其实是 8+4=12
  • 不是变量,因此没有和 names 相关信息

是不是有些奇怪,明明 1 的位置比 log 的位置更靠后,为什么编码显示的列数却更小,别忘了下面这个规则:

实际上只有 每个分号中的第一串英文 是用来表示代码的 第几行、第几列 的绝对位置外,后面的都是相对于之前的位置来做 加减法

即实际显示的列号数应为:

image.png

最后

以上就是对 sourcemap 相关内容的介绍,希望本文对你有所帮助!!!

说个题外话,有人好奇我哪有那么内容要写,其实大多文章内容只是将自己需要解决或者同事遇到的问题进行总结和扩展而已,所以大多数文章的想法就来源于此,其次我认为写文章的原则就是:写出来的文章首先要保证自己有收获! 另外,更多的是看看各位掘友对同一个问题都会有什么更好的方案!


目录
相关文章
|
2月前
|
前端开发 JavaScript
cypress 如何定位元素?
cypress 如何定位元素?
cypress 如何定位元素?
|
9月前
|
JavaScript 应用服务中间件 nginx
vuecli3打包项目上线之后报错怎么使用本地的sourcemap文件定位调试?
vuecli3打包项目上线之后报错怎么使用本地的sourcemap文件定位调试?
79 0
|
2月前
|
安全 算法 JavaScript
安卓逆向 -- 关键代码定位与分析技术
安卓逆向 -- 关键代码定位与分析技术
77 0
|
10月前
|
JavaScript 前端开发
Cypress 基础 - 元素的定位
Cypress 基础 - 元素的定位
|
存储 Web App开发 JSON
生产上的问题你不会用 sourcemap 定位吗?(一)
生产上的问题你不会用 sourcemap 定位吗?
336 0
|
API 开发工具 开发者
打入高德内部获取到的 — Flutter 高德定位的使用方案
定位是我们开发中常用的功能,为了帮助大家理解,我从"高德总部"搞出来了这一份方案~
打入高德内部获取到的 — Flutter 高德定位的使用方案
生产环境日志还用notepad++?难怪定位慢,UltraEdit了解一下
最近这两天运营部门反馈有会员的会员卡开卡时间与相关页面显示的开卡时间不一致,需要定位确定哪个时间是准确的。对于线上数据异常问题一定要谨慎处理,因为很有可能会是用户的某些非常规操作导致部分场景漏测。
生产环境日志还用notepad++?难怪定位慢,UltraEdit了解一下
|
传感器 数据处理
VM系列振弦采集读取模块激励方法
什么是振弦传感器采集读数模块:指针对振弦传感器的特性而设计的传感器激励、读数模块。具有集成度高、功能模块化、数字接口的一系列特性,能完成振弦 传感器的激励、信号检测、数据处理、质量评估等专用针对性功能,进行传感器频率和温度物理量模数转换,进而通过数字接口实现数据交互。振弦传感器读数模块是振弦传感器与数字化、信息化之间的核心转换单元。
VM系列振弦采集读取模块激励方法
|
存储 运维 监控
如何定位线上问题?
「你是怎么定位线上问题的?」 这个面试题我在两年社招的时候遇到过,前几天面试也遇到了。我觉得我每一次都答得中规中矩,今天来梳理复盘下,下次又被问到的时候希望可以答得更好。
122 0
文件定位
文件定位
97 0