最近在学fiber框架,关于日志处理我纠结了好长一段时间,我一直在纠结到底怎么样才能像 logback-spring.xml
实现同样的日志处理。。。怪我自己思维定势了,老是用Java的思维想去实现。
全局错误日志,用中间件来处理,有error错误,就将错误信息格式化输出到控制台,同时输出到文件。
import (
"fmt"
"github.com/gofiber/fiber/v2"
"go-web1/log"
"go-web1/sys/controller"
"go-web1/sys/model"
"net"
"net/http"
"os"
"strings"
"time"
)
func main() {
app := fiber.New()
// 中间件
app.Use(Logger()) // 使用日志中间件
app.Listen(fmt.Sprintf(":%d", 8080))
}
// 统一的日志格式化输出中间件
func Logger() fiber.Handler {
return func(c *fiber.Ctx) error {
start := time.Now()
// 处理请求
err := c.Next()
var logMessage string
if err != nil {
// 记录日志
logMessage = fmt.Sprintf("[%s] %s %s - %s ==> [Error] %s\n", start.Format("2006-01-02 15:04:05"), c.Method(), c.Path(), time.Since(start), err.Error())
} else {
// 记录日志
logMessage = fmt.Sprintf("[%s] %s %s - %s\n", start.Format("2006-01-02 15:04:05"), c.Method(), c.Path(), time.Since(start))
}
// 输出到控制台
fmt.Print(logMessage)
// 输出到文件
filename := "logs/" + time.Now().Format("2006-01-02") + ".log"
file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Error("日志文件的打开错误 : " + err.Error())
return err
}
defer file.Close()
if _, err := file.WriteString(logMessage); err != nil {
log.Error("写入日志文件错误 : " + err.Error())
}
return err
}
}
// ......省略其他代码
全局日志输出,输出的日志都是api层的日志信息,有的时候我们在其他地方也需要打印日志信息,并且把它们也输出到文件中,并且日志的格式要和全局日志的输出格式一致。
我们先在项目根目录建一个 log
文件夹,里面建一个 log.go
文件,在这里实现自定义日志输出
import (
"fmt"
"os"
"path/filepath"
"runtime"
"time"
)
func Info(msg string) {
logOut(msg, "Info")
}
func Debug(msg string) {
logOut(msg, "Debug")
}
func Error(msg string) {
logOut(msg, "Error")
}
// 日志格式化输出
func logOut(msg string, level string) {
start := time.Now()
// 获取调用的文件和行号
_, file, line, _ := runtime.Caller(2)
file = filepath.Base(file)
// 使用日志包记录日志,并包括级别、文件名和行号
logMsg := fmt.Sprintf("[%s] - %s ==> [%s:%d] [%s] %s\n",
start.Format("2006-01-02 15:04:05"),
time.Since(start),
file,
line,
level,
msg,
)
fmt.Print(logMsg) // 打印到控制台
logOutFile(logMsg) // 输出到文件
}
// 日志输出到文件
func logOutFile(msg string) {
// 输出到文件
filename := "logs/" + time.Now().Format("2006-01-02") + ".log"
file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
fmt.Println("日志文件的打开错误 :", err)
}
defer file.Close()
if _, err := file.WriteString(msg); err != nil {
fmt.Println("写入日志文件错误 :", err)
}
}
使用
// 在获取公钥的接口,输出错误日志
// 获取公钥
func GetKey(c *fiber.Ctx) error {
err := errors.New("全局日志输出:获取公钥错误")
log.Info("自定义日志输出:获取公钥错误")
log.Debug("自定义日志输出:获取公钥错误")
log.Error("自定义日志输出:获取公钥错误")
//return c.Status(200).JSON(config.Success(util.GetPublicKey()))
return err
}
输出
控制台
[2023-09-15 16:13:06] - 11.3557ms ==> [login_controller.go:15] [Info] 自定义日志输出:获取公钥错误
[2023-09-15 16:13:06] - 0s ==> [login_controller.go:16] [Debug] 自定义日志输出:获取公钥错误
[2023-09-15 16:13:06] - 55.5µs ==> [login_controller.go:17] [Error] 自定义日志输出:获取公钥错误
[2023-09-15 16:13:06] GET /sys/getKey - 12.5681ms ==> [Error] 全局日志输出:获取公钥错误
日志文件
[2023-09-15 16:13:06] - 11.3557ms ==> [login_controller.go:15] [Info] 自定义日志输出:获取公钥错误
[2023-09-15 16:13:06] - 0s ==> [login_controller.go:16] [Debug] 自定义日志输出:获取公钥错误
[2023-09-15 16:13:06] - 55.5µs ==> [login_controller.go:17] [Error] 自定义日志输出:获取公钥错误
[2023-09-15 16:13:06] GET /sys/getKey - 12.5681ms ==> [Error] 全局日志输出:获取公钥错误
可以看到,控制台和日志文件输出的是一样的。