介绍

sentry是一个开源的监控系统,能支持服务端与客户端的监控,还有个强大的后台错误分析、报警平台。
本篇文章主要介绍 搭建sentry、使用sentry、接入企业微信推送 …


搭建sentry

这里推荐使用docker-compose来搭建。
github:https://github.com/getsentry/sentry

1.安装docker

sudo yum -y install docker-io

2.启动docker

service docker start

3.安装Docker-compose:

curl -L https://github.com/docker/compose/releases/download/1.9.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

4.克隆 git clone https://github.com/getsentry/onpremise.git 按照remind.md 一步步操作

如果执行过程中一切正常的话,在浏览器中输入http://ip:9000 就进入 Sentry 的登录页面了,使用上面创建的管理员用户名和密码登录系统。

docker 平板微信 docker 微信推送_vue.js


使用sentry

搭建好之后,我们开始创建sentry项目并且把Sentry代码植入业务项目。

创建Sentry项目

搭建好sentry之后,直接登录。

选择创建项目(vue 或者 react):

docker 平板微信 docker 微信推送_前端_02

vue项目代码植入

创建项目之后,以vue项目为例,可以在sentry网站看到以下代码。

docker 平板微信 docker 微信推送_docker 平板微信_03


我们将代码植入main.js。

// main.js 

import Vue from "vue";
import Router from "vue-router";
import * as Sentry from "@sentry/vue";
import { BrowserTracing } from "@sentry/tracing";

Vue.use(Router);

const router = new Router({
  // ...
});

Sentry.init({
  Vue,
  dsn: "http://3d603aa24cf64cafbe930a4ba21369f0@172.18.254.211:9000/3",
  integrations: [
    new BrowserTracing({
      routingInstrumentation: Sentry.vueRouterInstrumentation(router),
      tracingOrigins: ["localhost", "my-site-url.com", /^\//],
    }),
  ],
  // Set tracesSampleRate to 1.0 to capture 100%
  // of transactions for performance monitoring.
  // We recommend adjusting this value in production
  tracesSampleRate: 1.0,
});

// ...

new Vue({
  router,
  render: h => h(App),
}).$mount("#app");

利用webpack上传sourcemap

在webpack.config.js增加SentryWebpackPlugin的插件配置

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

module.exports = {
  // other configuration
  configureWebpack: {
    plugins: [
      new SentryWebpackPlugin({
        include: ".", 
        ignore: ["node_modules", "webpack.config.js"],
        configFile: ".sentryclirc",
      }),
    ],
  },
};

include, ignoreFile, ignore, configFile 是官方文档demo上的属性,

其中只有include是必填项,其他都是可选。

include:指定路径让sentry-cli来检测有没有.map与.js文件,如果有就会上传到sentry。

需要关注的可选的属性:

ignore: 忽略文件夹或文件不要被检测。 一般都会将node_moudules与webpack.config.js忽略掉。

configFile: “.sentryclirc”, 配置文件

.sentryclirc 是放在根目录的
.sentryclirc 配置:

[auth]
token = 8a8991288dd541b59659d5a218cba9ed95c7787a7dae42a0ada73c219bca5a3d   //  Settings - Account - API - Auth Tokens
[defaults]
url = https://sentry.**t.cn/   // 搭建的sentry地址
org = sentry   // Organization Settings
project = 91xft-zhengliuji-admin  // 创建的项目名称

上传成功后 可以在sentry后台看到:

docker 平板微信 docker 微信推送_docker_04

没有上传sourcemap的报错信息展示如下 (看不到具体内容,因为是压缩混淆文件):

docker 平板微信 docker 微信推送_docker 平板微信_05

上传sourcemap的报错信息展示如下(能看到具体报错信息):

docker 平板微信 docker 微信推送_vue.js_06


sentry && 企业微信应用做推送

一、开通机器人权限

先找公司行政部门开通企业微信机器人权限。开通相关权限后,会发现此时就可以往公司企业微信群里添加相关机器人,如下图所示:

docker 平板微信 docker 微信推送_微信_07

创建一个机器人,叫日志监控机器人,专门用来进行 Sentry 的错误告警上报,如下图所示。

docker 平板微信 docker 微信推送_docker_08

进入Sentry服务器,找到相应项目,并点击设置按钮。

docker 平板微信 docker 微信推送_前端_09

将刚才生成的企业微信机器人的 Webhook 复制到 Sentry 服务器的相应项目中,点击保存,至此大功告成,是不是很激动!!!

docker 平板微信 docker 微信推送_docker_10

点击测试插件按钮,发现企业微信机器人并没有收到相关日志提醒,咦,这是怎么回事,难道是复制的姿势不对?

造成这一问题的主要原因是 Sentry 调用 webhook 发送的数据报文格式和企业微信机器人要求的数据报文格式不一致造成的,如下所示:

企业微信机器人要求的数据报文格式:

{
    "msgtype": "text",
    "text": {
        "content": "广州今日天气:29度,大部分多云,降雨概率:60%",
        "mentioned_list":["wangqing","@all"],
        "mentioned_mobile_list":["13800001111","@all"]
    }
}

Sentry发送的数据报文格式:

{
  id: '7',
  project: 'ii-admin-pro',
  project_name: 'ii-admin-pro',
  project_slug: 'ii-admin-pro',
  logger: null,
  level: 'error',
  culprit: 'raven.scripts.runner in main',
  message: 'This is an example Python exception',
  url: 'http://sentry.xxxxxxx.com/organizations/sentry/issues/7/?referrer=webhooks_plugin',
  triggering_rules: [],
  event: {
    event_id: 'f602ac321ee04bc28a20c9f4d446ef48',
    level: 'error',
    version: '5',
    type: 'default',
    logentry: {
      formatted: 'This is an example Python exception',
      message: null,
      params: null
    },
    logger: '',
    modules: { 'my.package': '1.0.0' },
    platform: 'python',
    timestamp: 1622734089.769465,
    received: 1622734089.7702,
    environment: 'prod',
    user: {
      id: '1',
      email: 'sentry@example.com',
      ip_address: '127.0.0.1',
      username: 'sentry',
      name: 'Sentry',
      geo: [Object]
    },
    request: {
      url: 'http://example.com/foo',
      method: 'GET',
      data: [Object],
      query_string: [Array],
      cookies: [Array],
      headers: [Array],
      env: [Object],
      inferred_content_type: 'application/json',
      fragment: null
    },
    ...
  }
}

针对数据报文格式不一致的问题,此时就需要搭建一个 Node 服务,将 Sentry 的数据报文做下转换,并按照企业微信机器人的数据报文格式进行发送。

二、搭建 Node 服务

笔者基于 egg.js 快速搭建了一个 Node 服务,路由配置如下:

docker 平板微信 docker 微信推送_docker_11

在 app/controller/robot/sentry.js 文件中创建 SentryController,用来负责数据报文的转换,代码所示:

'use strict';

const Controller = require('egg').Controller;
const request = require('../../utils/request');
const { SENTRY_HOOKS } = require('../../utils/const');
const { fmtDateTime, genProjectOwners } = require('../../utils/utils');

class SentryController extends Controller {
  /**
   * 接收Sentry发送过来的Webhook
   */
  async recvSentryWebhook() {
    const {
      params,
      request: { body },
    } = this.ctx;

    const ROBOT_DATA = {
      msgtype: 'markdown',
      markdown: {
        content: `!!!前端项目<font color=\"warning\">${body.project_name}</font>发生错误:
> 错误原因: <font color=\"info\">${body.culprit}</font>
> 错误时间: <font color=\"info\">${fmtDateTime()}</font>
> 错误级别: <font color=\"info\">${body.level}</font>
> 错误链接: [查看日志](${body.url})
\n
请以下同事注意:${genProjectOwners(SENTRY_HOOKS[params.name].owners)}`,
      },
    };

    const result = await request({
      url: SENTRY_HOOKS[params.name].sentry_hook,
      method: 'POST',
      headers: {
        'content-type': 'application/json',
      },
      data: JSON.stringify(ROBOT_DATA),
    });

    this.ctx.body = {
      code: '0',
      data: result,
      msg: '提醒成功',
    };
  }
}

module.exports = SentryController;

utils/utils.js文件

/**
 * 对当前时间进行格式化
 */
const fmtDateTime = () => {
  let date = new Date();

  let year = date.getFullYear();
  let month = date.getMonth() + 1;
  let hour = date.getHours();
  let min = date.getMinutes();

  month = month < 10 ? `0${month}` : month;
  hour = hour < 10 ? `0${hour}` : hour;
  min = min < 10 ? `0${min}` : min;

  return `${year}-${month}-${date.getDate()} ${hour}:${min}`;
};

/**
 * 生成项目负责人
 */
const genProjectOwners = (owners) => {
  return owners.map((item) => `<@${item}> `).join('');
};

module.exports = {
  fmtDateTime,
  genProjectOwners,
};

utils/const.js
主要用来存储配置常量,后续有新的项目,只需往常量文件中添加新的项目配置即可

docker 平板微信 docker 微信推送_前端_12


其中:

  • owners 存放的是企业微信用户的 userid,userid 即企业邮箱的前缀,举例:xiaoli@xxxx.com,userid 则是 xiaoli;

代码编写完后,接下来就是将项目部署上线了,笔者采用的是 pm2 来管理线上 Node 服务,运行pm2 deploy ecosystem.yaml production,将本地代码同步到线上,并重启 Node 服务(关于项目部署,不是本文重点,此处略过)。

将线上接口地址复制到 Sentry 服务器相应的 Webhooks 地址中,保存后点击测试插件按钮,测试日志监控机器人是否生效,如下所示:

docker 平板微信 docker 微信推送_前端_13


这时,企业微信群成功收到 Sentry 发送过来的日志提醒,如下所示:

docker 平板微信 docker 微信推送_前端_14


至此,大功告成!

注意事项:
开发过程中如果你的 Sentry 服务是部署在线上,不在本地局域网内,那么你本地在进行 Node 服务调试时是收不到 Sentry 发送的日志告警的,此时需要做内网穿透或者将你的node服务搭到线上,关于这一点要注意下!!!本人在这一问题曾卡壳一两天。