昨天把基礎寫完了,今天把debug等4個層級所需要的function與middleware搞定
先來想想debug,我們想要知道一些變數的值,在log/logging.go補上
type V struct {
Key string
Value interface{}
}
// wrap logger debug
func Debug(msg string, params ...interface{}) {
Logger.Debug(msg,
zap.Any("FuncData", debug.GetFuncData(1)),
zap.Any("param", params),
)
}
使用時呼叫log.Debug("some msg", &V{"variable_name", variable})
,就能直接print資訊在console上
接著是info,照著上面的構想,只要紀錄一些訊息與工作階段就好,補上
// wrap logger info
func Info(c *gin.Context, taskStatus string, msg string) {
LogHandle(c, NewLogData(taskStatus, &LogErrorData{appErr.ErrorDataStruct{-1, msg}}, nil))
}
// a short cup of request success info
func Success(c *gin.Context) {
LogHandle(c, NewLogData(TaskOK, nil, nil))
}
解釋:
最後是warn與error,這部份就要用到ErrorHandle來處理錯誤了,補上
// handle for custom private message for logger
func LogErrorHandle(c *gin.Context, taskStatus string, errorData *LogErrorData, errorMeta *LogErrorMeta, CustomMsg ...string) {
nld := NewLogData(taskStatus, errorData, errorMeta)
if len(CustomMsg) > 1 {
nld.ErrorData.Msg = CustomMsg[1]
}
LogHandle(c, nld)
}
// wrap logger warn, warn apperr.Error() can be ""
// first custom msg should be message return to front end
// second msg should be message for logging
func Warn(c *gin.Context, code int, err error, CustomMsg ...string) {
errorReturn := appErr.ErrorHandle(c, code, err, 1, CustomMsg...) // skip this wrap
LogErrorHandle(c, TaskFail, &LogErrorData{*errorReturn.ErrorData}, &LogErrorMeta{*errorReturn.ErrorMeta}, CustomMsg...)
}
// wrap logger error
// first custom msg should be message return to front end
// second msg should be message for logging
// if stack is true, the call stack will start form skip(start from 0)
func Error(c *gin.Context, code int, err error, skip int, CustomMsg ...string) {
errorReturn := appErr.ErrorHandle(c, code, err, skip+1, CustomMsg...) // skip this wrap
LogErrorHandle(c, TaskError, &LogErrorData{*errorReturn.ErrorData}, &LogErrorMeta{*errorReturn.ErrorMeta}, CustomMsg...)
}
解釋:
if err != nil
,就能直接call log.Warn(c, code, err, "client msg", "local msg")
或 log.Error來處理錯誤了現在來寫middleware來處理這些log,在middleware下創建log.go,寫入
package middleware
import (
"app/logger"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"time"
)
const (
timeFormat = time.RFC3339
utc = true
)
// Requests with errors are logged using zap.Error().
// Requests with A known error are logged using zap.Warn().
// Requests without errors are logged using zap.Info().
func Logging() gin.HandlerFunc {
return func(c *gin.Context) {
// some evil middlewares modify this values
path := c.Request.URL.Path
query := c.Request.URL.RawQuery
start := time.Now()
c.Next()
end := time.Now()
latency := end.Sub(start)
if utc {
end = end.UTC()
}
// get logger msg
var (
LogMsg *log.LogDataStruct
ok = false
)
value, exist := c.Get(log.LogCtxKey)
if exist {
LogMsg, ok = value.(*log.LogDataStruct)
}
if !ok || !exist || LogMsg == nil {
LogMsg = &log.LogDataStruct{
TaskStatus: log.TaskUnknow,
}
}
// check apperr
var lv zapcore.Level
if LogMsg.TaskStatus == log.TaskFail {
lv = zap.WarnLevel
} else if LogMsg.TaskStatus == log.TaskError {
lv = zap.ErrorLevel
} else {
lv = zap.InfoLevel
}
// write logger
if ce := log.Logger.Check(lv, path); ce != nil {
ce.Write(
zap.Int("status", c.Writer.Status()),
zap.String("method", c.Request.Method),
zap.String("path", path),
zap.String("query", query),
zap.String("ip", c.ClientIP()),
zap.String("user-agent", c.Request.UserAgent()),
zap.String("time", end.Format(timeFormat)),
zap.Duration("latency", latency),
zap.Object("LogMsg", LogMsg),
)
}
}
}
解釋:
最後在router/main.go使用use就大功告成了
r := gin.New()
r.Use(middleware.Logging()) // 注意順序!!
r.Use(middleware.ErrorHandle())
基礎的環境建置完成,之後就要接資料庫處理API了
目前的工作環境
.
├── app
│ ├── apperr
│ │ ├── error.go
│ │ └── handle.go
│ ├── config
│ │ └── app
│ │ ├── app.yaml
│ │ └── error.yaml
│ ├── go.mod
│ ├── go.sum
│ ├── log
│ │ ├── logger.go
│ │ └── logging.go
│ ├── main.go
│ ├── middleware
│ │ ├── error.go
│ │ └── log.go
│ ├── router
│ │ ├── host_switch.go
│ │ └── main.go
│ ├── serve
│ │ ├── main.go
│ │ └── main_test.go
│ ├── setting
│ │ └── setting.go
│ └── util
│ └── debug
│ ├── stack.go
│ └── stack_test.go
└── database