🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## sql日志和持久化 通过第5节, 我们知道了如何获取和打印当前会话的sql. 此时的sql是保存在内存中的, 如果我们想永久保存的话, 也是可以做到的 ## 示例 ```go package main ... func main() { // 链接数据库 connection, err := gorose.Open(DbConfigMaster) if err != nil { panic(err) } // 持久化sql中间件 connection.Use(gorose.NewLogger()) } ``` 通过代码, 我们可以看到, 只需要在链接数据库之后, 调用持久化中间件, 即可实现sql的持久化, 这里的 `connection.Use(gorose.NewLogger())` 到底做了什么操作呢? 1. 我们先看看 `connection.Use()` , 这个是中间件的入口, 可以添加任意多个中间件, 只需要做对应的中间件支持即可 2. `gorose.NewLogger()` 这个是 sql log 中间件的核心部分, 这里是采用了 `gorose` 提供的默认持久化中间件, 是将 sql 保存在log文件中, 默认保存在当前路径, 以日期命名. 既然提供了中间件, 那么, 就意味着, 这里的中间件, 我们完全可以自定义. 我们可以在这里使用其他的任何日志系统来完成 sql 日志的持久化, 以便调试和查找问题之用. 下面, 我们详细分析下, 中间件 和 log 中间件的实现过程 ## 中间件的设计 gorose中, 对于中间件的设计非常简洁, 没有过多的配置和架构, 我们先看下 `connection.Use()` 的代码: ```go // Use : cors func (conn *Connection) Use(options ...func(*Connection)) *Connection { for _, option := range options { option(conn) } return conn } ``` 这里的 Use 是 gorose.Connection 的一个 method, 同时可以接收多个中间件, 接收的中间件是一个常规的闭包函数, 返回 gorose.Connection 指针本身. 这里的 `option(conn)` 就是中间件的具体操作, 接受一个 参数 *gorose.Connection, 具体的中间件只需要完成 *gorose.Connection 对应的绑定即可. 接着, 我们看下 `gorose.NewLogger()` 中间件绑定的实现过程: ## Logger 中间件的实现 cors.go ```go package gorose import "github.com/gohouse/gorose/cors" func NewLogger() func(*Connection) { return func(conn *Connection) { conn.Logger = cors.NewDefaultLogger() } } ``` cors/logger.go ```go package cors import ( "fmt" "os" "time" ) type LoggerHandler interface { Write(sql string, runtime string, datetime string) } type Logger struct { } func (w *Logger) Write(sql string, runtime string, datetime string) { f := readFile(fmt.Sprintf("%v.log", time.Now().Format("2006-01-02"))) defer f.Close() content := fmt.Sprintf("[Datetime: %v][Runtime: %v][Sql: %v]\n", datetime, runtime, sql) //fmt.Println(content) buf := []byte(content) f.Write(buf) } func readFile(filepath string) *os.File { file, err := os.OpenFile(filepath, os.O_WRONLY|os.O_APPEND, 0666) if err != nil && os.IsNotExist(err) { file, err = os.Create(filepath) } return file } func NewDefaultLogger() *Logger { return &Logger{} } ``` 1. cors.go 放置中间件的驱动入口, 也可以放置其他驱动中间件入口. 这里就一个返回中间件具体实现的一个闭包 2. `cors/logger.go` , cors目录中放置中间件的具体实现. 这里定义了一个 ``` type LoggerHandler interface { Write(sql string, runtime string, datetime string) } ``` 接收 `sql(sql语句)`, `runtime(执行消耗时间)`, `datetime(执行时间)` 三个参数. 我们自定义的中间件, 只需要实现该接口即可. 这里, 我们可以使用任何的log系统处理, 如 ELK, hadoop 等来做日志分析