diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 5733318..68417ca 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -11,9 +11,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go 1.22 - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: - go-version: '^1.22.0' + go-version: '^1.22.1' id: go - name: Check out code into the Go module directory uses: actions/checkout@master @@ -33,9 +33,9 @@ jobs: # runs-on: self-hosted steps: - name: Set up Go 1.22 - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: - go-version: '^1.22.0' + go-version: '^1.22.1' id: go - name: Check out code into the Go module directory uses: actions/checkout@master @@ -54,9 +54,9 @@ jobs: # runs-on: ubuntu-latest # steps: # - name: Set up Go 1.22 - # uses: actions/setup-go@v4 + # uses: actions/setup-go@v5 # with: - # go-version: '^1.22.0' + # go-version: '^1.22.1' # id: go # - name: Check out code into the Go module directory # uses: actions/checkout@master @@ -75,9 +75,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go 1.22 - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: - go-version: '^1.22.0' + go-version: '^1.22.1' id: go - name: Check out code into the Go module directory uses: actions/checkout@master diff --git a/go.mod b/go.mod index 4a6ea83..68b2f93 100644 --- a/go.mod +++ b/go.mod @@ -5,9 +5,9 @@ go 1.22 require ( github.com/gin-gonic/gin v1.9.1 github.com/redis/go-redis/v9 v9.5.1 - github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.9.0 go.uber.org/zap v1.27.0 + gopkg.in/natefinch/lumberjack.v2 v2.2.1 ) require ( diff --git a/go.sum b/go.sum index e50a684..578f6b9 100644 --- a/go.sum +++ b/go.sum @@ -71,8 +71,6 @@ github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLB github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -102,7 +100,6 @@ golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= @@ -118,6 +115,8 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/handlers.go b/handlers.go index 49def95..0b2893d 100644 --- a/handlers.go +++ b/handlers.go @@ -37,8 +37,8 @@ func ShortToLongHandler() gin.HandlerFunc { } type LongToShortParams struct { - LongUrl string `form:"longUrl" binding:"required"` - ShortKey string `form:"shortKey"` + LongUrl string `form:"longUrl" json:"longUrl" binding:"required"` + ShortKey string `form:"shortKey" json:"shortKey" binding:"omitempty"` } // LongToShortHandler creates a short URL from a long URL diff --git a/logger.go b/logger.go index fbe5eab..265d3c8 100644 --- a/logger.go +++ b/logger.go @@ -1,142 +1,112 @@ package main import ( - "fmt" "os" "path" "time" "github.com/gin-gonic/gin" - "github.com/sirupsen/logrus" "go.uber.org/zap" "go.uber.org/zap/zapcore" + "gopkg.in/natefinch/lumberjack.v2" ) var logger *zap.SugaredLogger +const ( + logFileMaxSize = 50 // 日志文件最大大小(MB) + logFileMaxBackups = 10 // 最多保留的备份文件数量 + logFileMaxAge = 7 // 日志文件最长保留天数 + logFileCompress = false // 是否压缩备份文件 +) + func InitLogger() { // 创建 logs 目录 - if dir, err := os.Getwd(); err == nil { - logFilePath := dir + "/logs/" - if err := os.MkdirAll(logFilePath, 0777); err != nil { - panic("create log dir failed") - } - } + createLogPath() // 初始化 zap logger initZapLogger() } -// 定义 gin logger -func initLoggerForGin() *logrus.Logger { - logFilePath := "" +// createLogPath 创建 logs 目录 +func createLogPath() error { if dir, err := os.Getwd(); err == nil { - logFilePath = dir + "/logs/" - } - if err := os.MkdirAll(logFilePath, 0777); err != nil { - fmt.Println(err.Error()) - } - logFileName := "access.log" - - // 日志文件 - fileName := path.Join(logFilePath, logFileName) - if _, err := os.Stat(fileName); err != nil { - if _, err := os.Create(fileName); err != nil { - panic("create log file failed") + logFilePath := dir + "/logs/" + if err := os.MkdirAll(logFilePath, 0777); err != nil { + panic("create log path failed: " + err.Error()) } } - - // 写入文件 - src, err := os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY, os.ModeAppend) - if err != nil { - fmt.Println("err", err) - } - - // 实例化 - _logger := logrus.New() - - // 设置输出 - _logger.SetOutput(src) - // logger.Out = src - - // 设置日志级别 - _logger.SetLevel(logrus.DebugLevel) - - // 设置日志格式 - _logger.Formatter = &logrus.JSONFormatter{} - - return _logger + return nil } -// gin 文件日志 -func LoggerToFile() gin.HandlerFunc { - _logger := initLoggerForGin() - return func(c *gin.Context) { - logMap := make(map[string]any) - - // 开始时间 - startTime := time.Now() - logMap["startTime"] = startTime.Format("2006-01-02 15:04:05") - - // 处理请求 - c.Next() - - // 结束时间 - endTime := time.Now() - logMap["endTime"] = endTime.Format("2006-01-02 15:04:05") - - // 执行时间 - logMap["latencyTime"] = endTime.Sub(startTime).Microseconds() - - // 请求方式 - logMap["reqMethod"] = c.Request.Method - - // 请求路由 - logMap["reqUri"] = c.Request.RequestURI - - // 状态码 - logMap["statusCode"] = c.Writer.Status() - - // 请求IP - logMap["clientIP"] = c.ClientIP() - - // 请求 UA - logMap["clientUA"] = c.Request.UserAgent() - - // 日志格式 - // logJson, _ := json.Marshal(logMap) - // _logger.Info(string(logJson)) - - _logger.WithFields(logrus.Fields{ - "startTime": logMap["startTime"], - "endTime": logMap["endTime"], - "latencyTime": logMap["latencyTime"], - "reqMethod": logMap["reqMethod"], - "reqUri": logMap["reqUri"], - "statusCode": logMap["statusCode"], - "clientIP": logMap["clientIP"], - "clientUA": logMap["clientUA"], - }).Info() +// getLogPath 获取 logs 目录 +func getLogPath() string { + if dir, err := os.Getwd(); err == nil { + return dir + "/logs/" } + return "" } // 定义 zap logger func initZapLogger() { - fileWriteSyncer := getLogWriter() encoder := getEncoder() - core := zapcore.NewCore(encoder, zapcore.NewMultiWriteSyncer(fileWriteSyncer, zapcore.AddSync(os.Stdout)), zapcore.DebugLevel) + core := zapcore.NewCore(encoder, zapcore.AddSync(os.Stdout), zapcore.DebugLevel) - _logger := zap.New(core) - defer _logger.Sync() - - logger = _logger.Sugar() + logger = zap.New(core).Sugar() } +// getEncoder 获取 zap encoder func getEncoder() zapcore.Encoder { return zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig()) } -func getLogWriter() zapcore.WriteSyncer { - file, _ := os.Create("./logs/runtime.log") - return zapcore.AddSync(file) +// initGinLogger 初始化 gin logger +func initGinLogger() *zap.Logger { + logPath := getLogPath() + logFileName := "access.log" + + // 日志文件 + logFile := path.Join(logPath, logFileName) + + lumberJackLogger := &lumberjack.Logger{ + Filename: logFile, + MaxSize: logFileMaxSize, // 日志文件最大大小(MB) + MaxBackups: logFileMaxBackups, // 最多保留的备份文件数量 + MaxAge: logFileMaxAge, // 日志文件最长保留天数 + Compress: logFileCompress, // 是否压缩备份文件 + } + writeSyncer := zapcore.AddSync(lumberJackLogger) + + encoderConfig := zap.NewProductionEncoderConfig() + encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder + encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder + encoderConfig.EncodeCaller = nil + encoderConfig.EncodeDuration = zapcore.SecondsDurationEncoder + encoder := zapcore.NewConsoleEncoder(encoderConfig) + + core := zapcore.NewCore(encoder, writeSyncer, zapcore.InfoLevel) + + return zap.New(core, zap.AddCaller()) +} + +// initServiceLogger 初始化服务日志 +func initServiceLogger() gin.HandlerFunc { + _logger := initGinLogger() + return func(c *gin.Context) { + start := time.Now() + path := c.Request.URL.Path + + c.Next() + + _logger.Info( + "request", + zap.String("time", start.Format(time.RFC3339)), + zap.String("method", c.Request.Method), + zap.String("ip", c.ClientIP()), + zap.String("user-agent", c.Request.UserAgent()), + zap.String("path", path), + zap.Int("status", c.Writer.Status()), + zap.Duration("latency", time.Since(start)), + ) + } } diff --git a/main.go b/main.go index d34954d..583a283 100644 --- a/main.go +++ b/main.go @@ -92,7 +92,7 @@ func run() { router := gin.Default() // logger - router.Use(LoggerToFile()) + router.Use(initServiceLogger()) // static files router.LoadHTMLGlob("public/*.html")