【Go】自定义log 日志信息

一、改写 log.Printf和log.Println

1、简介

(1)go 源码中支持格式化输出信息的包名称有 fmt 、log 两种包类型;
(2)两种包类型,均包含 Printf() 接口和 Println() 接口;
(3)两者的区别:
	(a)fmt包适合通用的格式化输出,如打印普通消息、调试输出等;
	(b)log包适合用于正式的日志记录,提供时间戳、日志级别、日志标记和自定义输出等特性,能够更好地记录和
		追踪程序的运行状态。
(4)log 包虽然能输出时间戳,但默认输出的时间戳是 0 时区的时间,在显示上面感觉不是那么的习惯,比如北京时
	间是上午八点,则 log 输出的时间为 0 点,正好相差八个小时。

2、自定义 Printf 和 Println

  若想直观输出时间戳信息,则需要通过自定义接口的形式来解决此问题,此时需要涉及到 time 包,来实现时区设置,如北京地区则为东八区,这样的一个转换。
  代码示例如下:

1)东八区设置(两种写法都可以):
// var now = time.Now().In(time.FixedZone("CST", 8*3600)) 
now := time.Now().In(time.FixedZone("Asia/Shanghai", 8*3600))2)自定义 Printf() 接口:
func Printf(format string, v ...interface{}) {
	now := time.Now().In(time.FixedZone("Asia/Shanghai", 8*3600)) 
	message := now.Format("2006-01-02 15:04:05") + "  " + format
	fmt.Printf(message, v...)
}3)自定义 Println() 接口:
func Println(values ...interface{}) {
	now := time.Now().In(time.FixedZone("Asia/Shanghai", 8*3600))
	message := now.Format("2006-01-02 15:04:05") + "  "
	fmt.Printf("%s", message)
	fmt.Println(values...)
}

二、Gin web 默认输出 log 改写

  默认模式下,gin web 输出log信息包含信息有:时间戳、状态码、相应时间、客户端IP、HTTP 请求方法、路由信息,其中时间戳输出默认也为 0 时区时间,则改写时间戳代码如下:

1)输出信息颜色标识,在终端显示HTTP状态码相应的颜色,此时需要 ASNI 编码:
const (
	green   = "\033[97;42m"
	white   = "\033[90;47m"
	yellow  = "\033[90;43m"
	red     = "\033[97;41m"
	blue    = "\033[97;44m"
	magenta = "\033[97;45m"
	cyan    = "\033[97;46m"
	reset   = "\033[0m"
)2)区分 HTTP 状态码颜色标识:
func StatusCodeColor(code int) string {
	switch {
		case code >= http.StatusContinue && code < http.StatusOK:
			return white
		case code >= http.StatusOK && code < http.StatusMultipleChoices:
			return green
		case code >= http.StatusMultipleChoices && code < http.StatusBadRequest:
			return white
		case code >= http.StatusBadRequest && code < http.StatusInternalServerError:
			return yellow
		default:
			return red
	}
}3)区分 HTTP 请求方法颜色标识:
func MethodColor(method string) string {
	switch method {
		case http.MethodGet:
			return blue
		case http.MethodPost:
			return cyan
		case http.MethodPut:
			return yellow
		case http.MethodDelete:
			return red
		case http.MethodPatch:
			return green
		case http.MethodHead:
			return magenta
		case http.MethodOptions:
			return white
		default:
			return reset
	}
}4)终止颜色标识:
func ResetColor() string {
	return reset
}5)自定义log中间件,此处是使用的 logrus 组件,源码包位置: 
"github.com/sirupsen/logrus"6)demo:
package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"time"

	"github.com/sirupsen/logrus"
	"github.com/gin-gonic/gin"
)

func main() {
	// 创建一个新的引擎实例
	r := gin.New()
	
	// 创建一个新的logrus Logger实例
	log := logrus.New()

	// 自定义logrus中间件
	r.Use(logrusMiddleware(log))

	// 定义路由
	r.GET("/", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "hello world",
		})
	})

	// 启动Gin服务器
	r.Run(":8080")
}

// 自定义中间件
func logrusMiddleware(log *logrus.Logger) gin.HandlerFunc {

	return func(c *gin.Context) {
		startTime := time.Now().In(time.FixedZone("Asia/Shanghai", 8*3600))
		// 处理请求
		c.Next()

		fmt.Printf("[GIN] %v |%s %3d %s| %13v | %15s |%s %-7s %s %#v\n",
			startTime.Format("2006/01/02 - 15:04:05"),
			StatusCodeColor(c.Writer.Status()), c.Writer.Status(), ResetColor(),
			time.Since(startTime),
			c.ClientIP(),
			MethodColor(c.Request.Method), c.Request.Method, ResetColor(),
			c.Request.URL.Path,
		)
	}
}

三、实现 c语言 “FUNCTION”, “LINE

  log模块自带的日志功能,同样能够显示代码路径,行号,日期等信息,但其显示的路径是文件的绝对路径,打印日志显得太繁琐不够简练,当代码运行出错时,若只想打印文件的相对路径且只保留上一级目录,函数名和行号,因此改写示例代码如下:

// 输出信息如下: 2024-11-28 16:35:15  [error][xxx/xxx.go:23 - function]
func PrintfErr(format string, v ...interface{}) {
	var pcs [32]uintptr

	n := runtime.Callers(2, pcs[:]) // 跳过两层调用栈
	frames := runtime.CallersFrames(pcs[:n])
	frame, _ := frames.Next()

	// 解析函数名和文件路径
	funcName := frame.Function
	filePath := frame.File
	line := frame.Line

	// 提取函数名(去除包路径和文件名)
	funcNameParts := strings.Split(funcName, ".")
	funcName = funcNameParts[len(funcNameParts)-1]

	// 处理文件路径,只保留到上一级目录
	dir, fileName := filepath.Split(filePath)
	parentDir := filepath.Dir(dir)
	relativePath := filepath.Join(filepath.Base(parentDir), fileName)

	logMessage := fmt.Sprintf("[error][%s:%d - %s] ", relativePath, line, funcName)

	now := time.Now().In(time.FixedZone("Asia/Shanghai", 8*3600))
	message := now.Format("2006-01-02 15:04:05") + "  " + logMessage + format
	fmt.Printf(message, v...)
	fmt.Println()
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鸿之运

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值