前端日志监控,对接钉钉,实现实时报警

339 阅读2分钟

项目上线后,遇到问题怎么办?线上问题难以重现怎么办?如何在线上快速定位问题所在,减少错误发生次数?

相信每一位前端开发者都遇到过这种头疼的问题。

现在我就分享一种简单的方法:实现了监控页面错误、接口错误,实时上传日志,并发送消息到钉钉群。

前提条件

需要开通unicloud,创建两个表:my-interface-error、my-page-error、一个云函数dingding_message

前两张表你可以自定义需要收集的字段;发送钉钉消息的代码,请自行实现。

以下程序仅供参考

核心文件

// 线上日志报告
import { getCurrentFullpath } from '@/common/nav.js';
import { pageUrl }  from '@/project.config.js'
import store from '@/store/index.js'

const db = uniCloud.database()

const platform = process.env.VUE_APP_PLATFORM
const projectName = process.env.VUE_APP_NAME
const device = uni.getSystemInfoSync().system

/**
 * 采集 接口异常
 * @param {String} interface_name 接口地址
 * @param {String} errorcode 返回状态
 * @param {Object} content 数据
 */
export async function collectInterfaceLog(interface_name, errorcode, content) {
	const mobile = store.getters['ZG_user/mobile']
	const log = {
		projectName,
		platform,
		mobile,
		content,
		interface_name,
		errorcode,
	}
	// console.warn('report.interface error',log)
	if (process.env.NODE_ENV === 'development') return
	const res = await db.collection('my-interface-error').add(log)
	const logId = res.result?.id || ''
	const link = `${pageUrl}alone/#/pages_h5/interface-error?id=${logId}`
	const link2 = `dingtalk://dingtalkclient/page/link?url=${encodeURIComponent(link)}&pc_slide=false`
	uniCloud.callFunction({
		name: 'dingding_message',
		data: {
			type: 1,
			data: {
				"msgtype": "actionCard",
				"actionCard": {
					"title": "接口报错",
					"text": `接口名称:${interface_name} \n\n 错误代码:${errorcode} \n\n  用户手机:${mobile} \n\n 访问平台:${platform} \n\n 项目名称:${projectName}`,
					"btnOrientation": "0",
					"btns": [{
							"title": "查看详情",
							"actionURL": link
						},
						{
							"title": "在浏览器查看",
							"actionURL": link2
						}
					]
				}
			}
		}
	})
}
/**
 * 采集 前端错误
 * @param {Object} content 错误信息
 */
export async function collectErrorLog(content) {
	const route = getCurrentFullpath()
	const mobile = store.getters['ZG_user/mobile']
	const log = {
		projectName,
		platform,
		mobile,
		content,
		device,
		route,
	}
	// console.warn('report.page error',log)
	if (process.env.NODE_ENV === 'development') return
	const res = await db.collection('my-page-error').add(log)
	const logId = res.result?.id || ''
	const link = `${pageUrl}alone/#/pages_h5/page-error?id=${logId}`
	uniCloud.callFunction({
		name: 'dingding_message',
		data: {
			type: 1,
			data: {
				"msgtype": "actionCard",
				"actionCard": {
					"title": "页面报错",
					"text": `错误消息:${content.message} \n\n 用户手机:${mobile} \n\n 访问平台:${platform} \n\n 项目名称:${projectName}`,
					"btnOrientation": "0",
					"btns": [{
						"title": "查看详情",
						"actionURL": link
					}]
				}
			}
		}
	})
}

接入页面错误报告

App.vue

import { collectErrorLog } from '@/common/report.js'
import { throttle } from '@/common/helper.js'

const uploadVueError = throttle(collectErrorLog,1000,3000)

export default {
        onLaunch() {

        },
        // 此处只能监听到.vue文件的错误
        onError(error) {
                uploadVueError({
                        message: error.message,
                        error_stack: error.stack,
                })
        },
        onPageNotFound() {
                uni.reLaunch({
                        url: '/pages/error'
                })
        }
}

接入接口错误报告

function errorListen(response, options) {
	try {
		const requestPath = options.url.replace(baseUrl, '')
		const statusCode = `${response.statusCode}`
		const content = {
			requestPath,
			requestParams: options.data,
			response,
		}
		collectInterfaceLog(requestPath, statusCode, content)
	} catch (e) {
		console.error(e);
	}
}