## 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 等來做日志分析