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

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 管理后台所有修改,添加,删除的操作都要记录;操作日志的统计不影响主程序的性能

需求说明


  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日志并进行多维度分析。
相关文章
|
4月前
|
存储 Go
Go 浅析主流日志库:从设计层学习如何集成日志轮转与切割功能
本文将探讨几个热门的 go 日志库如 logrus、zap 和官网的 slog,我将分析这些库的的关键设计元素,探讨它们是如何支持日志轮转与切割功能的配置。
111 0
Go 浅析主流日志库:从设计层学习如何集成日志轮转与切割功能
|
4天前
|
分布式计算 DataWorks 关系型数据库
DataWorks操作报错合集之在DataWorks中设置了一个任务节点的调度时间,并将其发布到生产环境,但到了指定时间(例如17:30)却没有产生运行实例和相关日志如何解决
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
18 0
|
3天前
|
运维 监控 Go
Golang深入浅出之-Go语言中的日志记录:log与logrus库
【4月更文挑战第27天】本文比较了Go语言中标准库`log`与第三方库`logrus`的日志功能。`log`简单但不支持日志级别配置和多样化格式,而`logrus`提供更丰富的功能,如日志级别控制、自定义格式和钩子。文章指出了使用`logrus`时可能遇到的问题,如全局logger滥用、日志级别设置不当和过度依赖字段,并给出了避免错误的建议,强调理解日志级别、合理利用结构化日志、模块化日志管理和定期审查日志配置的重要性。通过这些实践,开发者能提高应用监控和故障排查能力。
8 1
|
3天前
|
Prometheus 监控 Cloud Native
【Go语言专栏】Go语言中的日志记录与监控
【4月更文挑战第30天】Go语言在软件开发和运维中扮演重要角色,提供灵活的日志记录机制和与多种监控工具的集成。内置`log`包支持基本日志记录,而第三方库如`zap`、`zerolog`和`logrus`则扩展了更多功能。监控方面,Go应用可与Prometheus、Grafana、Jaeger等工具配合,实现系统指标收集、可视化和分布式追踪。健康检查通过HTTP端点确保服务可用性。结合日志和监控,能有效提升Go应用的稳定性和性能。
|
3天前
|
中间件 Go
【Go语言专栏】Go语言中的中间件与路由处理
【4月更文挑战第30天】本文探讨了Go语言中的路由和中间件处理。路由负责根据URL映射到处理器,`net/http`包提供基础支持,而Gin和Echo等第三方库则提供更强大功能。中间件在请求处理链中执行预处理任务,如日志记录和认证。`net/http`包通过嵌套处理器实现中间件,而Gin和Echo则有更简洁的中间件接口。通过路由和中间件,可构建高效、结构良好的Web应用。建议进一步阅读官方文档以深化理解。
|
5天前
|
Java Go API
Go语言企业级日志管理
Go语言企业级日志管理
12 0
|
6天前
|
Dubbo Java Serverless
Serverless 应用引擎操作报错合集之Nacos中nacos启动正常,访问白页,启动日志显示正常如何解决
Serverless 应用引擎(SAE)是阿里云提供的Serverless PaaS平台,支持Spring Cloud、Dubbo、HSF等主流微服务框架,简化应用的部署、运维和弹性伸缩。在使用SAE过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
12 0
Serverless 应用引擎操作报错合集之Nacos中nacos启动正常,访问白页,启动日志显示正常如何解决
|
10天前
|
监控 JavaScript Java
|
2月前
|
域名解析 缓存 网络协议
阿里云DNS常见问题之阿里云DNS的操作日志查不到如何解决
阿里云DNS(Domain Name System)服务是一个高可用和可扩展的云端DNS服务,用于将域名转换为IP地址,从而让用户能够通过域名访问云端资源。以下是一些关于阿里云DNS服务的常见问题合集:
|
2月前
|
SQL NoSQL Java
【七】springboot整合AOP实现日志操作
【七】springboot整合AOP实现日志操作
45 0