Egg.js操作日志模块开发一二

操作日志的意义

操作日志顾名思义,就是记录所有对系统的操作,使得系统运行者对系统的运行了如指掌。
对于toB端或者内部管理系统而言,操作日志可以朔源,清楚找到问题所在,从而解决并且为以后避免提供经验。
对于toC端而言,操作日志可以了解用户行为,提供数据分析可以让公司与开发者开发出更加符合用户体验具有用户粘性的产品。

界面展示

主要展示内容是

用户 | 模块 | 操作类型 | 何种操作 | 操作前内容 | 操作后内容
| :——| ——: | ——: | ——: | ——: | :——: |
admin | 用户管理 | 修改 | 修改bugzhang权限 | 运维管理员 | 超级管理员

存储设计

存储比较灵活,数据库与文件存储可以结合使用,我为了提升数据库性能,将部分敏感操作存入数据库,将次要操作存储入文件。

操作日志表设计

字段名 说明描述 数据类型
id id INTEGER primaryKey autoIncrement
ip ip地址 VARCHAR(255)
userId 用户id INTEGER
user 用户名 VARCHAR(255)
type 操作类型: 1. 添加 2.修改 3. 删除 4.查询 INTEGER
target 操作目标,根据页面的menu页区分: 用户管理、公司业务管理、Doc管理、日志系统、PMU在线模型、监控系统、IDC管理、Wiki文档 VARCHAR(255)
before 操作前内容 VARCHAR(1024)
after 操作后内容 VARCHAR(1024)
content 描述 VARCHAR(255)
remarks 备注信息 VARCHAR(255)

文件存储
前端有页面可以查文件的尾部多少行的页面,类似tail命令。

实现

  • 获取IP地址
    node.js可以轻松获取ip地址。代码如下:
function getClientIP(req) {
    return req.headers['x-forwarded-for'] || // 判断是否有反向代理 IP
        req.connection.remoteAddress || // 判断 connection 的远程 IP
        req.socket.remoteAddress || // 判断后端的 socket 的 IP
        req.connection.socket.remoteAddress;
};
  • 添加日志

日志具有添加的核心方法,该方法用于

* create ({ type, target, content, after, remarks = '' }) {
  const { ctx } = this
  try {
    // 这里有一些属于定时任务的操作,并没有用户状态,所以需要特殊处理
    yield ctx.model.LogOperation.create({
      userId: ctx.user ? ctx.user.id : 0,
      user: ctx.user ? ctx.user.name : '定时任务',
      ip: getClientIP() ? getClientIP : '未知ip'
      type,
      target,
      after,
      content,
      remarks
    })
  } catch (err) {
    ctx.logger.error(err)
  }
}
  • 展示日志
    日志可以被展示在某个页面中,方法非常简单
  * getList ({ limit, offset, where }) {
    const result = yield this.ctx.model.LogOperation.findAndCountAll({
      raw: true,
      offset,
      limit,
      attributes: ['id', 'userId', 'user', 'type', 'content', 'target', 'remarks', ['created_at', 'createdAt']],
      order: [['created_at', 'DESC']],
      where
    })
    return result
  }

装饰器模式

日志记录实际是一种装饰器模式。
装饰器模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对象的新功能,就增加功能来说,装饰器模式相比生成子类更为灵活。
关键实现是: 1、Component 类充当抽象角色,不应该具体实现。 2、修饰类引用和继承 Component 类,具体扩展类重写父类方法。
在日志系统中:日志类就是抽象角色,不具体实现;操作类被日志类修饰,从而实现了本来没有的日志记录功能。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

😉😐😡😈🙂😯🙁🙄😛😳😮:mrgreen:😆💡😀👿😥😎😕