云优采集接口(基于uniClound从零开始搭建一个前端日志监控日志系统)
优采云 发布时间: 2022-03-21 20:12云优采集接口(基于uniClound从零开始搭建一个前端日志监控日志系统)
写在前面
Serverless是近几年比较流行的概念,也是大前端发展的一个重要方向。无服务器的兴起已经存在了一段时间。早在几年前,微信就推出了微信小程序云开发功能。它不需要搭建服务器,只需要利用平台提供的能力快速开发服务即可。同时提供云数据库、云存储、云功能等功能,大大降低了开发者的开发成本,深受开发者的喜爱。就在去年 uni-app 还推出了自己的无服务器服务 - uniCloud。
uniCloud 是阿里云和腾讯云的 serverless 服务上 DCloud 的一个包。它由IaaS层(阿里云和腾讯云提供的硬件和网络)和PaaS层(DCloud提供的开发环境)组成。————————— uniCloud官网
与其他云开发产品相比,uniCloud具有以下优势:
uniCloud开发可以配合自带的HbuilderX编辑器实现1+1大于2的效果;它可以无缝连接uni-app和uni-ui,实现产品、UI和服务的有机统一。提供云功能URLization功能,非uni-apps开发的系统也可以轻松访问,使产品更加通用和通用。默认情况下,云函数只被自己的应用通过前端的 uniCloud.callFunction 调用,不会暴露给外网。一旦 URL 化,开发人员需要注意业务和资源安全。
云函数 URL 化是 uniCloud 为开发者提供的 HTTP 访问服务,允许开发者通过 HTTP URL 访问云函数。场景一:如App端微信支付,需要配置服务器回调地址。在这种情况下,需要一个 HTTP URL。场景二:非uni-app开发的系统,如果要连接uniiCloud读取数据,还需要通过HTTP URL访问。
下面这篇文章将基于uniClound从零开始搭建一个前端日志监控系统。
日志监控系统介绍
本文的主要目的是介绍serverless和uniClound入门,重点介绍采集和日志的展示。为了简化系统日志数据主要来自两个方面:一是Vue的全局错误捕获,二是请求响应*敏*感*词*拦截的后端API请求错误。该系统的简单说明如下:
Vue全局错误捕获的简单实现
根据Vue的官方文档,Vue的全局错误捕获只需要配置Vue.config.errorHandler即可。为了让我们的日志监控系统更加完善和通用,除了Vue的错误信息,我们还需要采集发生的错误。时间(uniCloud有时区差异,建议使用时间戳来表示时间),出错的项目名称project。Vue全局错误捕获方法实现如下,其中addVueLog是我们要通过云函数实现的API接口,后面会介绍该接口的实现。
// my-vatchvueerror.js
/****************************************************
* @description 捕获Vue全局错误
* @param {*} err 异常错误
* @param {*} vm 页面示例
* @param {*} info 错误说明
* @return {*}
* @author mingyong.g
****************************************************/
export default function(err, vm, info) {
const route = (vm.$page && vm.$page.route) || (vm.$mp && vm.$mp.page.route); // 获取uni-app项目的页面路由
let log = { // 日志对象
err: err.toString(),
info,
route,
time: new Date().getTime(),
project:"test"
};
addVueLog(log); // 新增日志的接口
}
在 main.js 中配置错误捕获功能
// main.js
import catchVueError from "../my-vatchvueerror";
Vue.config.errorHandler = catchVueError;
响应*敏*感*词*错误日志采集
下面是一个 axios 的响应*敏*感*词*的例子。关于API错误日志,我们需要关心以下信息:
请求体是请求的参数。响应正文是收录错误描述的响应数据日志发生的时间。uniCloud 存在时区差异。建议使用时间戳来指示错误日志所在的项目。
下面的代码是一个axios响应*敏*感*词*的简单实现,其中addApiLog就是我们要通过云函数实现的API接口,接口的实现后面会介绍。这里将收录请求参数的response.config和收录响应数据的response.data作为aspect的参数直接传入,其他公共信息在接口内部实现。
// 响应拦截
service.interceptors.response.use(
(response) => {
let data = response.data;
/*
* 此处如果后台响应体中字段Msg = "ok" 则认为接口响应有效,否则视为错误响应
* 注意:这部分逻辑需根据业务和后端接口规范适当调整
*/
if (data.Msg == "ok" ) {
return data;
} else {
addApiLog(response.config, data); // 日志采集接口
return Promise.reject(data);
}
},
(err) => {
let errMsg = "";
if (err && err.response.status) {
switch (err.response.status) {
case 401:
errMsg = "登录状态失效,请重新登录";
router.push("/login");
break;
case 403:
errMsg = "拒绝访问";
break;
case 408:
errMsg = "请求超时";
break;
case 500:
errMsg = "服务器内部错误";
break;
case 501:
errMsg = "服务未实现";
break;
case 502:
errMsg = "网关错误";
break;
case 503:
errMsg = "服务不可用";
break;
case 504:
errMsg = "网关超时";
break;
case 505:
errMsg = "HTTP版本不受支持";
break;
default:
errMsg = err;
break;
}
} else {
errMsg = err;
}
addApiLog(err.config, { statusCode: err.response.status, Msg: err.response.data }); // 日志采集接口
return Promise.reject(errMsg);
}
);
uniCloud 管理员
为了简化开发工作,uniiCloud提供了基于uni-app、uni-ui和uniiCloud的应用后台管理框架。
uniCloud admin功能介绍其基于uni-app的宽屏适配,可自动适配PC宽屏和移动端。它基于 uniCloud,是一种无服务器云开发。它基于 uni-id 并使用 uni-id 的用户帐户、角色和权限系统。————————— uniCloud官网
uniCloud界面
创建项目
按照官方教程,首先在HBuilderX3.0+版本新建一个uni-app项目,选择uniiCloud admin项目模板。
创建完成后,可以按照云服务空间初始化向导来初始化项目,创建并绑定云服务空间
跑步
进入admin项目,在uniCloud/cloudfunctions/common/uni-id中填写自己的passwordSecret字段(用来加密密码存储的key)和tokenSecret字段(生成token需要的key,测试时跳过) /config.json文件也可以通过这篇文章)右键uniiCloud目录运行云服务空间初始化向导,初始化数据库并上传部署云功能(如果云服务空间已经创建绑定,跳过这一步),点击HBuilderX工具栏运行[Ctrl+r] -> Run to browser。如果是连接本地的云函数调试环境,上一步的云函数是不能上传的,但是数据库还是需要初始化的。从启动后的登录页面底部,
登录uniiCloud控制台:/找到上面第3步创建的云服务空间,这里我创建的服务空间是gmyl
点击详情进入云服务空间,可以看到uniCloud admin默认为我们创建了如下云数据表: 6. opendb-admin-menus : 左侧菜单树管理表7.@ > opendb-verify-codes : 验证码记录表8. uni-id-log : uniCloud登录日志9. uni-id-log : 权限表10. uni-id-roles :角色配置表 11. uni-id-users : 账户表
uniCloud admin 提供了一套完整的后台管理解决方案。我们的目的是构建一个简单的日志监控系统。有些功能这里暂时不用。现在 uniCloud 管理员关注应用程序的可扩展性。言归正传,除了上述框架自带的数据表,我们还需要创建一个数据表来存储日志数据。在这里,我创建了两个表来分别存储 Vue 日志和 API 日志。
{
"bsonType": "object",
"required": [],
"permission": {
"read": false,
"create": false,
"update": false,
"delete": false
},
"properties": {
"_id": {
"description": "ID,系统自动生成"
},
"project": {
"bsonType": "onject",
"description": "项目名称",
"trim": "both"
},
"url": {
"bsonType": "onject",
"description": "页面路由信息",
"trim": "both"
},
"errmsg": {
"bsonType": "onject",
"description": "错误描述",
"trim": "both"
},
"errtype": {
"bsonType": "string",
"description": "错误类型",
"trim": "both"
},
"occurrence_timestamp": {
"bsonType": "timestamp",
"description": "问题发生时间"
},
"state": {
"bsonType": "int",
"description": "0 待处理 1:已处理 ",
"trim": "both"
},
"handle_timestamp": {
"bsonType": "timestamp",
"description": "问题修复时间"
},
"reason": {
"bsonType": "string",
"description": "问题原因",
"trim": "both"
},
"solution": {
"bsonType": "string",
"description": "解决办法",
"trim": "both"
}
}
}
创建云函数
回到HbuilderX找到刚才创建的项目,依次展开uniCloud>>cloudfunctions,右键cloudfunctions点击新建的云函数addVueLog
一个初始的云函数结构如下,其中前端传递的参数是通过event.body获取的。接下来的主要任务是将前端传递的日志对象存储到云数据库中。使用云函数操作云数据库的教程可以参考官方文档:uniapp.dcloud.io/uniCloud/cf-database,这里不再赘述。
// 初始云函数
'use strict';
exports.main = async (event, context) => {
//event为客户端上传的参数
console.log('event : ', event)
//返回数据给客户端
return event
};
// 将数据写入云数据库
'use strict';
const db = uniCloud.database();
exports.main = async (event, context) => {
//event为客户端上传的参数
let data = event.body ? JSON.parse(event.body) : event;
if (event.project == "" && !event.body) { // 判断数据是否有效
return {
Msg: "Invalid Data!",
Data: "",
Count: 0
}
} else {
const dbCmd = db.command
const $ = dbCmd.aggregate
let res = await db.collection('vuelog_db').add(data) // 向表vuelog_db插入一条数据
//返回数据给客户端
return {
Data: "",
Msg: "ok",
Count: 0
}
}
};
云函数url化
开启云函数url化前,先上传部署云函数,找到对应的云函数,右键上传部署。
如果上传成功,可以在uniCloud控制台的云功能列表中找到刚刚上传的云功能。
登录uniiCloud后台,选择要管理的服务空间。点击左侧菜单栏的【云功能】,进入云功能页面。点击待配置云功能的【详情】按钮,配置访问路径。
云函数url化后,可以像通用API接口一样调用。这里的add_vuelog是Vue全局错误捕获方法中addVueLog接口的实现。
运行测试
在postman、test add_vuelogAPI等API调试工具中,不再演示测试过程,云函数调用成功,云数据库会新增一条记录。
addApiLog 的实现同上。至此,实现了一个日志系统的数据采集和存储功能。
数据显示
虽然数据展示部分很重要,但并不是本次开发的重点。这里直接使用uniCloud提供的schema2code(HBuilderX 3.1.0+支持)函数生成数据列表页。
对schema2code生成的数据稍作修改,将uni-list组件替换为uni-table组件。
项目
页面路由
错误描述
错误类型
原因
解决方案
发生时间
修复时间
状态
操作
搜索
{{ item.project }}
{{ item.url }}
{{ item.errmsg }}
{{ item.errtype }}
{{ item.reason }}
{{ item.solution }}
已修复
待修复
处理
删除
{{ engine.name }}
页面写好后,别忘了在uniiCloud admin自带的菜单管理中注册路由信息。如果没有注册路由信息,则页面无法在左侧菜单栏中显示。
再次优化
为了让界面更加美观,结合uni-app插件市场的ReportPro数据报表(云功能版)和秋云ucharts echarts高性能跨端图表组件升级页面首页,使数据板。这是效果的渲染。实现逻辑引用云函数操作云数据库:/uniCloud/cf-database
好的!这里实现了整个简单的日志监控系统。现在就试试吧!
一些个人感受
之所以做这样一个项目,一方面是在技术的研究和探索中。早在2019年就接触过微信小程序的云开发模式,但一直都在做一些技术探索和了解。没有真正的动手实践;另一方面,随着我们自己开发的一些项目的实施,难免会出现错误和bug。过去,由于用户反馈出现错误,然后处理滞后,导致用户体验非常差。随着时间的推移,用户很容易丢失产品。信心甚至会引起怀疑。由此产生了为这个项目谋生的想法,而我熟悉的uni-app也推出了云开发模式,于是这个项目就诞生了。
来说说severless的感觉吧。无服务器意味着无服务器。这里的serverless是开发用的,服务器直接由云服务器提供商提供和管理。这样,开发者只需要关注业务,前后端的差别就越来越小了。以本项目为例,整个过程没有后端参与,也没有编写SQL语句。一系列开发的API接口固然方便,但也带来一定的局限性。有了Serverless,我们不需要过多关注服务器的运维,也不需要关心我们不熟悉的领域。我们只需要专注于业务开发和产品实施。我们需要关心的事情更少,但我们可以做的事情更多。serverless 模型将进一步扩展前端边界。现在的前端开发已经不是以前的前端开发了。前端不仅可以是网页,还可以是小程序、APP、桌面程序。现在前端也可以是服务器了!
阿特伍德定律:任何可以用 JavaScript 编写的应用程序,最终都会用 JavaScript 编写。任何可以用 JavaScript 编写的应用程序,最终都会用 JavaScript 编写。写在最后
一个完整的日志监控系统还应该包括一个消息通知模块,这也是我最初的架构中设想和规划的。由于消息通知是借助第三方服务实现的,是一个相对独立的功能模块,所以我将其独立出来。出来,后面会单独整理成一个文章,介绍uniCloud云功能如何调用第三方API,如何使用npm安装第三方服务。
最后,本文同步发布在个人G公众号“前端知识营”,点击关注获取更多优质有趣内容。以后会整理好项目的源码,放到公众号上供大家参考。感兴趣的朋友可以点击下方链接关注!前端知识营
(超过)