本文为稀土技术社区首发签约文章,14天内制止转载,14天后未获授权制止转载,侵权必究!

前言

还记得小编之前的一篇文章 – 怎么优雅的解决 Qiankun 下 Sentry 反常上报无法主动区别项目的问题 ? 吗?在这篇文章中,小编针对 QiankunSentry 反常上报无法主动区别项目的问题,供给了一种行之有效的解决计划,切实协助了不少同学,成就感直接拉满,。

不过在后续运用进程中,小编发现该计划并不完好。运用 Sentry 时,假如敞开了功能监控功能,客户端上报的功能指标数据,会和之前的反常数据一样,全部上签到主运用对应的 project 中。出现这种状况,当然是不合理的,咱们需求功能指标数据也和反常数据一样,能上签到正确的 project 中, 便利开发人员去做功能剖析。

有了之前的经历,这个问题解决起来能够说是十分简略,就是阻拦功能指标数据上报接口,将数据做分发,然后从头上报。本文,小编会在之前的反常上报解决计划的基础上,增加功能指标数据上报解决计划,给我们供给一个完好版的解决计划。

本文的目录结构:

  • 解决计划

    • 阻拦数据上报接口

    • 数据分发、重组 url

  • 结束语

解决计划

简略来说,不管是反常数据上报分发,仍是功能指标数据上报分发,咱们的解决思路都是分为 3 步:

  1. 经过自界说 transport 去阻拦数据上报接口;

  2. 对反常(功能指标)数据做分发,然后重组上报接口需求的 url

  3. 运用新的 url 从头上报数据;

阻拦数据上报接口

阻拦数据上报接口,咱们能够直接复用本来的技术计划,代码如下:

  • 6.x 版别

    // 6.x 版别
    import { Transports, init } from '@sentry/browser';
    import { Integrations } from '@sentry/tracing';
    const fetchImpl = (url, options) => {
        // 依据 options 中的反常(功能指标)信息,回来新的 url 和 options
        const [newUrl, newOptions] = sentryFilter(url, options);
        // 运用原生的 fetch 去上报数据
        return originFetch(newUrl, newOptions);
    }
    // 经过承继的方式,界说一个 CustomerTransport
    class CustomerTransport extends Transports.FetchTransport {
        constructor(options) {
            // 将自界说 fetchImpl 传入
            super(options, fetchImpl)
        }
    }
    init({
        dsn: 'xxxx',
        enabled: true,
        integrations: [
            // 功能监控有必要运用 BrowserTracing
            new Integrations.BrowserTracing({
                idleTimeout: 2000,
            }),
        ],
        // 假如要敞开功能监控,tracesSampleRate 有必要要有值
        tracesSampleRate: 1,
        // 运用自界说的 CustomerTransport
        transport: CustomerTransport,
        // 其他装备项
        ...
    });
    
  • 7.x 版别

    import { init, makeFetchTransport } from '@sentry/browser';
    import { Integrations } from '@sentry/tracing';
    const CustomeTransport = (options) => {
        const fetchImpl = (url, options) => {
            // 依据 options 中的反常(功能指标)信息,回来新的 url 和 options
            const [newUrl, newOptions] = sentryFilter(url, options);
            // 运用原生的 fetch 去上报数据
            return window.fetch(newUrl, newOptions);
        };
        // 7.x 版别不需求承继 Transports.FetchTransport
        return makeFetchTransport(options, fetchImpl);
    };
    init({
        dsn: 'xxxx',
        enabled: true,
        integrations: [
            // 功能监控有必要运用 BrowserTracing
            new Integrations.BrowserTracing({
                idleTimeout: 2000,
            }),
        ],
        // 假如要敞开功能监控,tracesSampleRate 有必要要有值
        tracesSampleRate: 1,
        // 运用自界说的 CustomerTransport
        transport: CustomerTransport,
        // 其他装备项
        ...
    });
    

数据分发、重组 url

不管是反常数据上报,仍是功能指标数据上报,上报接口的 url 其实都是由 project 对应的 dsn 信息转化而来的。

详细的转化进程如下:

// https://62187b367e474822bb9cb733c8a89814@sentry.byai.com/56
dsn - https://{param1}@{param2}/{param3}
                      ||
                      v
errorUrl - https://{param2}/api/{param3}/store/?sentry_key={param1}&sentry_version=7 
performanceUrl - https://{param2}/api/{param3}/envelope/?sentry_key={param1}&sentry_version=7 

反常上报的 url 和功能指标上报的 url 看起来几乎一样,只需关键字不同。其间,反常上报 url 的关键字是 store,功能指标手上报 url 的关键字是 envelope

只需咱们能依据上报的反常(功能指标)数据找到正确的 project,就能够依据 projectdsn 重组 url

首要,咱们来创立一个 project 注册表。

const PROJECT_CONFIG = {
  'project-1': {
    // 子运用唯一标识
    project: 'project-1',
    // dsn 重组今后的反常上报 url
    errorUrl:
      'https://sentry.xxx.com/api/1/store/?sentry_key=a&sentry_version=7',
    // 反常数据分发办法
    errorCheck: (url: string) => url.includes('/project-1/'),
    // dsn 重组今后的功能指标上报 url
    performanceUrl:
      'https://sentry.xxx.com/api/1/envelope/?sentry_key=a&sentry_version=7',
    // 功能指标数据分发办法
    performanceCheck: (url: string) => url.includes('/project-1/'),
  },
  'project-2': {
    project: 'project-2',
    errorUrl:
      'https://sentry.xxx.com/api/2/store/?sentry_key=b&sentry_version=7',
    errorCheck: (url: string) => url.includes('/project-2/'),
    performanceUrl:
      'https://sentry.xxx.com/api/2/envelope/?sentry_key=b&sentry_version=7',
    performanceCheck: (url: string) => url.includes('/project-2/'),
  },
  'project-3': {
    project: 'project-3',
    errorUrl:
      'https://sentry.xxx.com/api/3/store/?sentry_key=c&sentry_version=7',
    errorCheck: (url: string) => url.includes('/project-3/'),
    performanceUrl:
      'https://sentry.xxx.com/api/56/envelope/?sentry_key=a&sentry_version=7',
    performanceCheck: (url: string) => url.includes('/project-3/'),
  },
  'project-4': {
    project: 'project-4',
    errorUrl:
      'https://sentry.xxx.com/api/4/store/?sentry_key=d&sentry_version=7',
    errorCheck: (url: string) => url.includes('/project-4/'),
    performanceUrl:
      'https://sentry.xxx.com/api/56/envelope/?sentry_key=a&sentry_version=7',
    performanceCheck: (url: string) => url.includes('/project-4/'),
  },
  ...
};

上述 project 注册表中的 errorUrlperformanceUrl 是数据分发今后重组的 url,依据实际项目中各个 project 真实的 dsn 信息生成;errorCheckperformanceCheckproject 分发的判别办法。

接下来,咱们来实现数据分发,分为反常数据分发和功能指标数据分发:

  • 反常数据分发

    反常数据的分发,需求剖析反常追踪栈中产生反常的文件对应的 url

    const findErrorProject = (filename: string) => {
        const keys = Object.keys(PROJECT_CONFIG);
        for (const key of keys) {
            const project = PROJECT_CONFIG[key];
            // 找到能够分发的项目
            if (project.errorCheck(filename)) {
                return project;
            }
        }
        // 没有回来 null
        return null;
    };
    const sentryErrorFilter = (url: string, options: any) => {
        let project = null;
        // 拿到 sentry 生成的反常信息
        const error = JSON.parse(options.body).exception;
        if (error && error.values && error.values.length) {
            // 找到反常追踪栈信息
            const stacktrace = error.values[0].stacktrace;
            if (stacktrace && stacktrace.frames && stacktrace.frames.length) {
                // 找到产生反常的文件对应的文件名
                const filename = stacktrace.frames[stacktrace.frames.length - 1].filename;
                // 依据文件名判别是那个子运用
                project = findErrorProject(filename);
            }
        }
        return project
            // 能找到子运用,回来重组今后的 url
            ? [project.errorUrl, { release: project.project, ...options }]
            // 没有匹配的子运用,回来本来的 url
            : [url, options];
    };
    
  • 功能数据分发

    功能数据的分发就比较简略了,直接依据当前运用的路由信息判别即可。

    const findPerformanceProject = (pathname: string) => {
        const keys = Object.keys(PROJECT_CONFIG);
        for (const key of keys) {
            const project = PROJECT_CONFIG[key];
            // 找到能够分发的项目
            if (project.performanceCheck(pathname)) {
                return project;
            }
        }
        // 没有回来 null
        return null;
    };
    const sentryProformanceFilter = (url: string, options: any) => {
        // 运用当前路由信息
        const pathname = window.location.pathname;
        // 依据路由信息判别是哪个子运用
        const project = findPerformanceProject(pathname);
        return project 
            // 能找到子运用,回来重组今后的 url
            ? [project.performanceUrl, options]
            // 没有匹配的子运用,回来本来的 url
            : [url, options];
    };
    

最后,咱们来实现怎么区别反常数据上报和功能指标数据上报。 办法也十分简略。假如是功能指标数据上报, Sentry 会给上报的数据增加 type: 'transaction' 信息。经过这一点,能够很便利的区别反常数据和功能指标数据,代码如下:

const sentryFilter = (url, options) => {
  const body = options.body || '';
  // 功能
  if (body.includes('"type":"transaction"')) {
    return sentryProformanceFilter(url, options);
  } else {
    return sentryErrorFilter(url, options);
  }
};

这就是 Qiankun 架构下关于反常监控和功能监控的完好版技术计划了。亲测有效哦!

结束语

到这里,关于怎么运用 Sentry 做反常监控、功能监控就暂时告一段落了。

简略做一下回顾。小编经过 6 篇文章,梳理了 Sentry 做反常、功能监控的原理, 怎么主动推送 Sentry 告警, 怎么剖析功能监控数据。阅读完这 6 篇文章,想必我们对 Sentry 的运用已经有一个初步的知道了吧。

其实,关于 Sentry 的运用,小编也只是了解一些皮毛, 还需求再持续深化了解。后续小编还会持续跟进,将自己新的运用心得总结出来,感兴趣的小伙伴们能够一向重视哦。