你用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

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
7月前
|
存储 监控 算法
防止员工泄密软件中文件访问日志管理的 Go 语言 B + 树算法
B+树凭借高效范围查询与稳定插入删除性能,为防止员工泄密软件提供高响应、可追溯的日志管理方案,显著提升海量文件操作日志的存储与检索效率。
229 2
|
安全 Go
用 Zap 轻松搞定 Go 语言中的结构化日志
在现代应用程序开发中,日志记录至关重要。Go 语言中有许多日志库,而 Zap 因其高性能和灵活性脱颖而出。本文详细介绍如何在 Go 项目中使用 Zap 进行结构化日志记录,并展示如何定制日志输出,满足生产环境需求。通过基础示例、SugaredLogger 的便捷使用以及自定义日志配置,帮助你在实际开发中高效管理日志。
666 1
|
11月前
|
开发框架 JSON 中间件
Go语言Web开发框架实践:路由、中间件、参数校验
Gin框架以其极简风格、强大路由管理、灵活中间件机制及参数绑定校验系统著称。本文详解其核心功能:1) 路由管理,支持分组与路径参数;2) 中间件机制,实现全局与局部控制;3) 参数绑定,涵盖多种来源;4) 结构体绑定与字段校验,确保数据合法性;5) 自定义校验器扩展功能;6) 统一错误处理提升用户体验。Gin以清晰模块化、流程可控及自动化校验等优势,成为开发者的优选工具。
|
缓存 前端开发 中间件
[go 面试] 前端请求到后端API的中间件流程解析
[go 面试] 前端请求到后端API的中间件流程解析
|
SQL Java Serverless
实时计算 Flink版操作报错合集之在写入SLS(Serverless Log Service)时出现报错,该如何排查
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
存储 JSON Go
PHP 日志系统的最佳搭档:一个 Go 写的远程日志收集服务
为了不再 SSH 上去翻日志,我写了个 Go 小脚本,用来接收远程日志。PHP 负责记录日志,Go 负责存储和展示,按天存储、支持 API 访问、可远程管理,终于能第一时间知道项目炸了。
340 10
|
消息中间件 缓存 监控
go高并发之路——消息中间件kafka
本文介绍了高并发业务中的流量高峰应对措施,重点讲解了Kafka消息中间件的使用,包括常用的Go语言库sarama及其版本问题,以及Kafka的版本选择建议。文中还详细解释了Kafka生产者的四种分区策略:轮询、随机、按Key和指定分区,并提供了相应的代码示例。
537 1
go高并发之路——消息中间件kafka
|
SQL 中间件 关系型数据库
那些年,我们在Go中间件上踩过的坑
作者总结了过去在Go中间件上踩过的坑,这些坑也促进了阿里内部Go中间件的完善,希望大家学习本文后,不犯同样的错误。
|
JSON 中间件 Go
go语言后端开发学习(四) —— 在go项目中使用Zap日志库
本文详细介绍了如何在Go项目中集成并配置Zap日志库。首先通过`go get -u go.uber.org/zap`命令安装Zap,接着展示了`Logger`与`Sugared Logger`两种日志记录器的基本用法。随后深入探讨了Zap的高级配置,包括如何将日志输出至文件、调整时间格式、记录调用者信息以及日志分割等。最后,文章演示了如何在gin框架中集成Zap,通过自定义中间件实现了日志记录和异常恢复功能。通过这些步骤,读者可以掌握Zap在实际项目中的应用与定制方法
943 1
go语言后端开发学习(四) —— 在go项目中使用Zap日志库
|
监控 中间件 Go
Go 中间件的优雅实现:处理请求的艺术
Go 中间件的优雅实现:处理请求的艺术

热门文章

最新文章