go使用gin框架日志模块

1.gin默认日志使用

package init
import (
	"fmt"
	"gin/global"
	"github.com/gin-gonic/gin"
	"io"
	"net/http"
	"os"
	"path"
	"runtime/debug"
	"time"
)

func LoggerToFile() gin.LoggerConfig {
	if _, err := os.Stat(global.Settings.LogsAddress); os.IsNotExist(err) {
		err = os.MkdirAll(global.Settings.LogsAddress, 0777)
		if err != nil {
			panic(fmt.Errorf("create log dir '%s' error: %s", global.Settings.LogsAddress, err))
		}
	}
	timeStr := time.Now().Format("2006-01-02")
	fileName := path.Join(global.Settings.LogsAddress, "success_"+timeStr+".log")
	os.Stderr, _ = os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
	var conf = gin.LoggerConfig{
		Formatter: func(param gin.LogFormatterParams) string {
			return fmt.Sprintf("%s - %s  %s  %s %s %s  %d  %s  %s\n",
				param.TimeStamp.Format("2006-01-02 15:04:05"),
				param.ClientIP,
				param.Method,
				param.Path,
				param.Request.PostForm.Encode(),
				param.Request.Proto,
				param.StatusCode,
				param.Latency,
				param.ErrorMessage,
			)
		},
		Output: io.MultiWriter(os.Stdout, os.Stderr),
	}
	return conf
}

func Recover(c *gin.Context) {
	defer func() {
		if err := recover(); err != nil {
			if _, errDir := os.Stat(global.Settings.LogsAddress); os.IsNotExist(errDir) {
				errDir = os.MkdirAll(global.Settings.LogsAddress, 0777)
				if errDir != nil {
					panic(fmt.Errorf("create log dir '%s' error: %s", global.Settings.LogsAddress, errDir))
				}
			}
			timeStr := time.Now().Format("2006-01-02")
			fileName := path.Join(global.Settings.LogsAddress, "error_"+timeStr+".log")
			f, errFile := os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
			if errFile != nil {
				fmt.Println(errFile)
			}
			timeFileStr := time.Now().Format("2006-01-02 15:04:05")
			_, _ = f.WriteString("panic error time:" + timeFileStr + "\n")
			_, _ = f.WriteString(fmt.Sprintf("%v", err) + "\n")
			_, _ = f.WriteString("stacktrace from panic:" + string(debug.Stack()) + "\n")
			_ = f.Close()
			c.JSON(http.StatusOK, gin.H{
				"code": http.StatusInternalServerError,
				"msg":  fmt.Sprintf("%v", err),
			})
			//终止后续接口调用,不加的话recover到异常后,还会继续执行接口里后续代码
			c.Abort()
		}
	}()
	c.Next()
}

使用

package router
func Router() *gin.Engine {
	r := gin.Default()
	r.Use(gin.LoggerWithConfig(init.LoggerToFile()))
	//错误日志执行
	r.Use(init.Recover)
	return r
}

成功日志、失败日志为多个文件
2.使用logrus

package log

import (
	"fmt"
	"gin/global"
	"gin/utils"
	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
	"net"
	"net/http"
	"os"
	"path"
	"strings"
	"time"
)

func Log() gin.HandlerFunc {
	return func(c *gin.Context) {
		if _, err := os.Stat(global.Settings.LogsAddress); os.IsNotExist(err) {
			err = os.MkdirAll(global.Settings.LogsAddress, 0777)
			if err != nil {
				panic(fmt.Errorf("create log dir '%s' error: %s", global.Settings.LogsAddress, err))
			}
		}
		timeStr := time.Now().Format(time.DateOnly)
		fileName := path.Join(global.Settings.LogsAddress, timeStr+".log")
		os.Stderr, _ = os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
		//实例化
		logger := logrus.New()
		//设置输出
		logger.Out = os.Stderr
		//设置日志级别
		logger.SetLevel(logrus.InfoLevel)
		//打印方法
		logger.SetReportCaller(true)
		//设置日志格式
		logger.SetFormatter(&logrus.TextFormatter{TimestampFormat: time.DateTime})
		// 开始时间
		startTime := time.Now()
		// 处理请求
		c.Next()
		// 结束时间
		endTime := time.Now()
		// 执行时间
		latencyTime := endTime.Sub(startTime)
		method := c.Request.Method
		url := c.Request.RequestURI
		form := c.Request.PostForm.Encode()
		statusCode := c.Writer.Status()
		clientIP := c.Request.Header.Get("X-Real-IP")
		if clientIP == "" {
			clientIP = c.Request.Header.Get("X-Forwarded-For")
		}
		if clientIP == "" {
			clientIP, _, _ = net.SplitHostPort(c.Request.RemoteAddr)
		}
		if strings.Contains(clientIP, ":") {
			clientIP = strings.Split(clientIP, "%")[0]
		}
		errormessage := c.Errors.ByType(gin.ErrorTypePrivate).String()
		// 日志格式
		if len(c.Errors) > 0 {
			logger.Errorf(errormessage)
		} else {
			msg := fmt.Sprintf(" %s  %s  %s  %s  %d  %s  %s", clientIP, method, url, form, statusCode, latencyTime, errormessage)
			if statusCode == http.StatusOK {
				logger.Info(msg)
			} else {
				logger.Error(msg)
			}
		}
	}
}
func Write(msg string) {
	setOutPutFile(logrus.InfoLevel, "info")
	logrus.Info(msg)
}

func Debug(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.DebugLevel, "debug")
	logrus.WithFields(fields).Debug(args)
}

func Info(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.InfoLevel, "info")
	logrus.WithFields(fields).Info(args)
}

func Warn(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.WarnLevel, "warn")
	logrus.WithFields(fields).Warn(args)
}

// 执行完程序结束
func Fatal(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.FatalLevel, "fatal")
	logrus.WithFields(fields).Fatal(args)
}

func Error(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.ErrorLevel, "error")
	logrus.WithFields(fields).Error(args)
}

func Panic(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.PanicLevel, "panic")
	logrus.WithFields(fields).Panic(args)
}

func Trace(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.TraceLevel, "trace")
	logrus.WithFields(fields).Trace(args)
}
func setOutPutFile(level logrus.Level, logName string) {
	if _, err := os.Stat(global.Settings.LogsAddress); os.IsNotExist(err) {
		err = os.MkdirAll(global.Settings.LogsAddress, 0777)
		if err != nil {
			panic(fmt.Errorf("create log dir '%s' error: %s", global.Settings.LogsAddress, err))
		}
	}

	timeStr := time.Now().Format(time.DateOnly)
	fileName := path.Join(global.Settings.LogsAddress, logName+"_"+timeStr+".log")
	var err error
	os.Stderr, err = os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
	if err != nil {
		fmt.Println("open log file err", err)
	}
	logrus.SetOutput(os.Stderr)
	logrus.SetLevel(level)
	logrus.SetFormatter(&logrus.TextFormatter{TimestampFormat: time.DateTime})
	return
}
func Recover(c *gin.Context) {
	defer func() {
		if err := recover(); err != nil {
			if _, errDir := os.Stat(global.Settings.LogsAddress); os.IsNotExist(errDir) {
				errDir = os.MkdirAll(global.Settings.LogsAddress, 0777)
				if errDir != nil {
					panic(fmt.Errorf("create log dir '%s' error: %s", global.Settings.LogsAddress, errDir))
				}
			}
			timeStr := time.Now().Format(time.DateOnly)
			fileName := path.Join(global.Settings.LogsAddress, timeStr+".log")
			f, errFile := os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
			if errFile != nil {
				fmt.Println(errFile)
			}
			timeFileStr := time.Now().Format(time.DateTime)
			_, _ = f.WriteString("panic error time:" + timeFileStr + "\n")
			_, _ = f.WriteString(fmt.Sprintf("%v", err) + "\n")
			_ = f.Close()
			utils.ReturnError(c, http.StatusInternalServerError, fmt.Sprintf("%v", err))
			//终止后续接口调用,不加的话recover到异常后,还会继续执行接口里后续代码
			c.Abort()
		}
	}()
	c.Next()
}

使用

package router
func Router() *gin.Engine {
	r := gin.Default()
	r.Use(log.Log())
	//错误日志执行
	r.Use(init.Recover)
	return r
}

成功日志、失败日志为一个文件 调用方法会写入多个文件 生成多个文件
3.mysql日志

package init
import (
	"fmt"
	"gin/global"
	"gopkg.in/natefinch/lumberjack.v2"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"io"
	"log"
	"os"
	"time"
)

func InitMysqlDB() {
	mysqlInfo := global.Settings.Mysqlinfo
	// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True",
		mysqlInfo.Name, mysqlInfo.Password, mysqlInfo.Host,
		mysqlInfo.Port, mysqlInfo.DBName)
	global.DB, _ = gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: getGormLogger(),
	})
}
func getGormLogger() logger.Interface {
	var logMode logger.LogLevel

	switch global.Settings.Mysqlinfo.LogMode {
	case "silent":
		logMode = logger.Silent
	case "error":
		logMode = logger.Error
	case "warn":
		logMode = logger.Warn
	case "info":
		logMode = logger.Info
	default:
		logMode = logger.Info
	}
	return logger.New(getGormLogWriter(), logger.Config{
		SlowThreshold:             200 * time.Millisecond, // 慢 SQL 阈值
		LogLevel:                  logMode,                // 日志级别
		IgnoreRecordNotFoundError: false,                  // 忽略ErrRecordNotFound(记录未找到)错误
	})
}

// 自定义 gorm Writer
func getGormLogWriter() logger.Writer {
	var writer io.Writer
	// 是否启用日志文件
	if global.Settings.Mysqlinfo.EnableFileLogWriter {
		// 自定义 Writer
		writer = &lumberjack.Logger{
			Filename:   global.Settings.LogsAddress + "/" + global.Settings.Mysqlinfo.Logfile,
			MaxSize:    global.Settings.LogConfig.MaxSize,
			MaxBackups: global.Settings.LogConfig.MaxBackups,
			MaxAge:     global.Settings.LogConfig.MaxAge,
			Compress:   global.Settings.LogConfig.Compress,
		}
	} else {
		// 默认 Writer
		writer = os.Stdout
	}
	writer = io.MultiWriter(writer, os.Stdout)
	return log.New(writer, "\r\n", log.LstdFlags)
}

使用该配置文件可生成sql.log在指定文件夹下
配置文件为:

logsAddress: './logs/'
mysql:
  name: 'root'
  host: '192.168.1.9'
  port: 3306
  password: 'root'
  dbName: 'test'
  logfile: 'sql.log'
  logmode: 'info'
  #开启日志写入
  enable_file_log_writer: true
 log:
  maxsize: 500
  maxbackups: 3
  maxage: 28
  compress: true

读取配置文件生成global公共变量

package init
import (
	"gin/config"
	"gin/global"
	"github.com/spf13/viper"
)

func InitConfig() {
	// 实例化viper
	v := viper.New()
	//文件的路径如何设置
	v.SetConfigFile("./config.yaml")
	if err := v.ReadInConfig(); err != nil {
		panic(err)
	}
	serverConfig := config.ServerConfig{}
	//给serverConfig初始值
	if err := v.Unmarshal(&serverConfig); err != nil {
		panic(err)
	}
	// 传递给全局变量
	global.Settings = serverConfig
}

配置映射读取

package config

type ServerConfig struct {
	Mysqlinfo     MysqlConfig     `mapstructure:"mysql"`
	LogsAddress   string          `mapstructure:"logsAddress"`
	LogConfig     LogConfig       `mapstructure:"log"`
}
type MysqlConfig struct {
	Host                string `mapstructure:"host"`
	Port                int    `mapstructure:"port"`
	Name                string `mapstructure:"name"`
	Password            string `mapstructure:"password"`
	DBName              string `mapstructure:"dbName"`
	Logfile             string `mapstructure:"logfile"`
	LogMode             string `mapstructure:"logmode"`
	EnableFileLogWriter bool   `mapstructure:"enable_file_log_writer"`
}
type LogConfig struct {
	MaxSize    int  `mapstructure:"maxsize"`
	MaxBackups int  `mapstructure:"maxbackups"`
	MaxAge     int  `mapstructure:"maxage"`
	Compress   bool `mapstructure:"compress"`
}

全局变量生成

package global

var ( Settings config.ServerConfig
		DB       *gorm.DB)

具体使用方法为global.DB.Raw()即可

  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值