你用Go写过中间件吗?带你用Go实现【操作日志中间件】

本文涉及的产品
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
性能测试 PTS,5000VUM额度
云原生网关 MSE Higress,422元/月
简介: 管理后台所有修改,添加,删除的操作都要记录;操作日志的统计不影响主程序的性能

需求说明


  1. 管理后台所有修改,添加,删除的操作都要记录
  2. 操作日志的统计不影响主程序的性能


需求分析


  1. 把相关代码封装成中间件,独立使用
  2. 合理使用goroutine,不影响主线程的性能


文档说明


  1. 基于golang语言开发
  2. 基于gin网络框架开发
  3. 基于MySQL5.8开发
  4. 把操作日志部分封装成中间件,在rourter文件中引用
  5. 非核心代码已省略,用3个竖着排列的点号.表示


数据库表结构设置


操作日志表


微信图片_20221111180814.jpg


代码


中间件代码


代码分析


  1. 我们可以通过context直接获得请求方式和请求的url
  2. 无法直接获得返回信息,我们可以借助"ResponseWriter",运用拦截器的思想,把返回信息先截取到,再向下继续传递
  3. 像获得客户端ip这类方法封装到util中,方便灵活调用
  4. 我们无法将adminLogs()方法整体设置为goroutine,因为这样会将context的事件传递在新的协程中进行,无法正常传递。
  5. 所以我们再c.Next()事件传递之后,把json解析成结构体,以及保存操作日志到数据库的操作设置为使用goroutine协程操作
  6. 操作日志是没有比较记录查询操作的,所以我们把请求方式为GET的过滤掉


package middleware
//amdin操作日志
import (
    .
    .
    .
  "bytes"
  "encoding/json"
  "fmt"
  "github.com/gin-gonic/gin"
  "strings"
)
type bodyLogWriter struct {
  gin.ResponseWriter
  bodyBuf *bytes.Buffer
}
func (w bodyLogWriter) Write(b []byte) (int, error) {
  w.bodyBuf.Write(b)
  return w.ResponseWriter.Write(b)
}
var CommonLogInterceptor = commonLogInterceptor()
/*
1 使用goroutine和channel实现操作日志的入库保存,尽可能的不影响主程序
2 goroutine协程,提高并发量
3 channel通道
*/
func commonLogInterceptor() gin.HandlerFunc {
  return func(c *gin.Context) {
    adminLogs(c)
  }
}
//获得每次请求返回的code和message
func adminLogs(c *gin.Context) {
  if admin, _ := c.Get("admin"); admin != nil {
    method := c.Request.Method
    url := c.Request.URL.Path
    strBody := ""
    var blw bodyLogWriter
    blw = bodyLogWriter{bodyBuf: bytes.NewBufferString(""), ResponseWriter: c.Writer}
    c.Writer = blw
    c.Next()
    if method != "GET" {
      strBody = strings.Trim(blw.bodyBuf.String(), "\n")
      go func(strBody string) {
        var returnJson api.ReturnJson
        json.Unmarshal([]byte(strBody), &returnJson)
        message := fmt.Sprintf("%v", returnJson.Message)
        adminInfo := admin.(**service.RunningClaims)
        adminId := (*adminInfo).ID
        adminName := (*adminInfo).Account
        var log = model.AdminLog{
          AdminId:   adminId,
          AdminName: adminName,
          Method:    method,
          Url:       url,
          Ip:        util.RemoteIP(c.Request),
          Code:      returnJson.Code,
          Message:   message,
        }
        model.CreateLog(log)
      }(strBody)
    }
  }
}

model层代码


package model
type AdminLog struct {
  ID int `json:"id"`
  AdminId uint `json:"admin_id"`
  AdminName string `json:"admin_name"`
  Method string `json:"method"`
  Ip string `json:"ip"`
  Url string `json:"url"`
  Code int `json:"code"`
  Message string `json:"message"`
}
func CreateLog(log AdminLog)  {
  DB.Create(&log)
}
复制代码


路由代码


package server
import (
  .
  .
  .
  "os"
  "github.com/gin-gonic/gin"
)
// NewRouter 路由配置
func NewRouter() *gin.Engine {
  r := gin.Default()
  // 其他中间件
  .
  .
  .
  // 路由
  v1 := r.Group("/api/v1")
  {
    v1.POST("login", api.Login)
    auth := v1.Group("")
    //登录校验中间件
    auth.Use(middleware.AuthRequired())
    //关键代码:权限角色校验
    auth.Use(middleware.AuthCheckMiddleware)
    //操作日志
    auth.Use(middleware.CommonLogInterceptor)
    {
            .
            .
            .
      // 获取所有学校
      {
        auth.GET("/school/", api.GetSchoolInfo)
      }
      .
      .
      .
    }
  }
  return r
}
复制代码


总结


  1. 以上则是我的实现思路
  2. 还有另外一种思路,计划已消息队列的方式实现,发送通知进行日志的报错


公众号:程序员升级打怪之旅

微信号:wangzhongyang1993

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
7月前
|
缓存 前端开发 中间件
[go 面试] 前端请求到后端API的中间件流程解析
[go 面试] 前端请求到后端API的中间件流程解析
|
3月前
|
消息中间件 缓存 监控
go高并发之路——消息中间件kafka
本文介绍了高并发业务中的流量高峰应对措施,重点讲解了Kafka消息中间件的使用,包括常用的Go语言库sarama及其版本问题,以及Kafka的版本选择建议。文中还详细解释了Kafka生产者的四种分区策略:轮询、随机、按Key和指定分区,并提供了相应的代码示例。
go高并发之路——消息中间件kafka
|
8月前
|
SQL Java Serverless
实时计算 Flink版操作报错合集之在写入SLS(Serverless Log Service)时出现报错,该如何排查
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
5月前
|
SQL 中间件 关系型数据库
那些年,我们在Go中间件上踩过的坑
作者总结了过去在Go中间件上踩过的坑,这些坑也促进了阿里内部Go中间件的完善,希望大家学习本文后,不犯同样的错误。
|
7月前
|
监控 中间件 Go
Go 中间件的优雅实现:处理请求的艺术
Go 中间件的优雅实现:处理请求的艺术
|
8月前
|
Java Serverless 应用服务中间件
函数计算操作报错合集之JVM启动时找不到指定的日志目录,该如何解决
Serverless 应用引擎(SAE)是阿里云提供的Serverless PaaS平台,支持Spring Cloud、Dubbo、HSF等主流微服务框架,简化应用的部署、运维和弹性伸缩。在使用SAE过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
|
8月前
|
监控 数据管理 关系型数据库
数据管理DMS使用问题之是否支持将操作日志导出至阿里云日志服务(SLS)
阿里云数据管理DMS提供了全面的数据管理、数据库运维、数据安全、数据迁移与同步等功能,助力企业高效、安全地进行数据库管理和运维工作。以下是DMS产品使用合集的详细介绍。
|
8月前
|
消息中间件 缓存 中间件
中间件本地事务执行操作
【7月更文挑战第17天】
48 2
|
9月前
|
监控 数据库
neo4j数据插入操作有日志吗
【6月更文挑战第29天】neo4j数据插入操作有日志吗
119 1
|
9月前
|
存储 运维 Java
Spring运维之boot项目开发关键之日志操作以及用文件记录日志
Spring运维之boot项目开发关键之日志操作以及用文件记录日志
90 2