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

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

需求说明


  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

相关实践学习
通过日志服务实现云资源OSS的安全审计
本实验介绍如何通过日志服务实现云资源OSS的安全审计。
相关文章
|
4月前
|
存储 监控 算法
防止员工泄密软件中文件访问日志管理的 Go 语言 B + 树算法
B+树凭借高效范围查询与稳定插入删除性能,为防止员工泄密软件提供高响应、可追溯的日志管理方案,显著提升海量文件操作日志的存储与检索效率。
148 2
|
11月前
|
JavaScript 前端开发 中间件
在 Pinia 中如何使用中间件进行日志记录?
在 Pinia 中如何使用中间件进行日志记录?
572 162
|
安全 Go
用 Zap 轻松搞定 Go 语言中的结构化日志
在现代应用程序开发中,日志记录至关重要。Go 语言中有许多日志库,而 Zap 因其高性能和灵活性脱颖而出。本文详细介绍如何在 Go 项目中使用 Zap 进行结构化日志记录,并展示如何定制日志输出,满足生产环境需求。通过基础示例、SugaredLogger 的便捷使用以及自定义日志配置,帮助你在实际开发中高效管理日志。
520 1
|
11月前
|
存储 JSON Go
PHP 日志系统的最佳搭档:一个 Go 写的远程日志收集服务
为了不再 SSH 上去翻日志,我写了个 Go 小脚本,用来接收远程日志。PHP 负责记录日志,Go 负责存储和展示,按天存储、支持 API 访问、可远程管理,终于能第一时间知道项目炸了。
239 10
|
SQL Java Serverless
实时计算 Flink版操作报错合集之在写入SLS(Serverless Log Service)时出现报错,该如何排查
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
JSON 中间件 Go
go语言后端开发学习(四) —— 在go项目中使用Zap日志库
本文详细介绍了如何在Go项目中集成并配置Zap日志库。首先通过`go get -u go.uber.org/zap`命令安装Zap,接着展示了`Logger`与`Sugared Logger`两种日志记录器的基本用法。随后深入探讨了Zap的高级配置,包括如何将日志输出至文件、调整时间格式、记录调用者信息以及日志分割等。最后,文章演示了如何在gin框架中集成Zap,通过自定义中间件实现了日志记录和异常恢复功能。通过这些步骤,读者可以掌握Zap在实际项目中的应用与定制方法
784 1
go语言后端开发学习(四) —— 在go项目中使用Zap日志库
|
中间件 Go 数据库
slog 简介:用于 Go 的结构化日志
slog 简介:用于 Go 的结构化日志
|
存储 JSON 前端开发
一文搞懂 Go 1.21 的日志标准库 - slog
一文搞懂 Go 1.21 的日志标准库 - slog
774 2
|
Java Serverless 应用服务中间件
函数计算操作报错合集之JVM启动时找不到指定的日志目录,该如何解决
Serverless 应用引擎(SAE)是阿里云提供的Serverless PaaS平台,支持Spring Cloud、Dubbo、HSF等主流微服务框架,简化应用的部署、运维和弹性伸缩。在使用SAE过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
289 1
|
监控 数据管理 关系型数据库
数据管理DMS使用问题之是否支持将操作日志导出至阿里云日志服务(SLS)
阿里云数据管理DMS提供了全面的数据管理、数据库运维、数据安全、数据迁移与同步等功能,助力企业高效、安全地进行数据库管理和运维工作。以下是DMS产品使用合集的详细介绍。