先看实例

package main

import (
	"log"
	"os"
)

func init() {
	// 配置日志输出格式
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	// 配置前缀
	log.SetPrefix("order:")
	// 配置输出位置
	logFile, err := os.OpenFile("./test.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		log.Panic("打开日志文件异常")
	}
	log.SetOutput(logFile)
}

func main() {
	log.Println("golang,log标准库测试")
}

输出结果

运行程序,会创建一个test.log文件。文件的内容如下:

order:2022/09/14 10:03:19 main.go:22: golang,log标准库测试

标准库日志log

log包提供了简单的日志功能,该包中定义了一个结构体Logger,该结构体有一些方法实现日志功能。

logger结构体

type Logger struct {
	mu        sync.Mutex // ensures atomic writes; protects the following fields
	prefix    string     // prefix on each line to identify the logger (but see Lmsgprefix)
	flag      int        // properties
	out       io.Writer  // destination for output
	buf       []byte     // for accumulating text to write
	isDiscard int32      // atomic boolean: whether out == io.Discard
}

日志的输出格式

日志的输出格式可以通过Flag标记来控制,可以使用的常量有以下几个:

const (
	Ldate         = 1 << iota     // the date in the local time zone: 2009/01/23
	Ltime                         // the time in the local time zone: 01:23:23
	Lmicroseconds                 // microsecond resolution: 01:23:23.123123.  assumes Ltime.
	Llongfile                     // full file name and line number: /a/b/c/d.go:23
	Lshortfile                    // final file name element and line number: d.go:23. overrides Llongfile
	LUTC                          // if Ldate or Ltime is set, use UTC rather than the local time zone
	Lmsgprefix                    // move the "prefix" from the beginning of the line to before the message
	LstdFlags     = Ldate | Ltime // initial values for the standard logger
)

logrus简介

logrus是目前github上star数量最多的日志库。logrus功能强大,性能高效,而且具备高度灵活性,logrus是一个可插拔的,结构化的日志框架,提供了自定义插件的功能,如docker prometheus等,都是用了logrus来记录日志

logrus特性

  • GitHub访问地址:https://github.com/sirupsen/logrus
  • 完全兼容golang标准库日志模块: logrus拥有六种日志级别: debug、info,warn、error、fatal和panic,这是golang标准库日志模块的API的超集。如果您的项目使用标准库日志模块,完全可以以最低的代价迁移到logrus上
  • 可扩展的Hook机制:允许使用者通过hook的方式将日志分发到任意地方,如本地文件系统、标准输出、logstash、elasticsearch或
    者mq等,或者通过hook定义日志内容和格式等
  • 可选的日志输出格式:logrus内置了两种日志格式,JSONFrmatter和TextFormatter,如果这两个格式不满足需求,可以自己动手实现接口Formatter,来定义自己的日志格式
  • Field机制: logrus鼓励通过Field机制进行精细化的、结构化的日志记录,而不是通过几长的消息来记录日志。

logrus实例

安装logrus

go get github.com/sirupsen/logrus

实例

package main

import log "github.com/sirupsen/logrus"

func main() {
	log.Info("golang ,logrus")
}

运行结果

time="2022-09-15T11:32:40+08:00" level=info msg="golang ,logrus"

logrus日志级别

logrus支持如下日志级别:
Debug,Info,Warn,Error,Fatal和Panic

package main

import log "github.com/sirupsen/logrus"

func main() {
	// 设置日志级别
	// log.SetLevel(log.InfoLevel)
	log.SetLevel(log.ErrorLevel)
	// 下面输出,日志级别由低到高,输出情况由上面的日志级别控制
	// 例如:设置日志级别为 ErrorLevel,则 infor、debug、warn不再输出
	log.Info("info")
	log.Debug("debug")
	log.Warn("warn")
	log.Error("error")
	log.Panic("panic")
	log.Fatal("fatal")
}

日志格式

logrus支持俩种日志格式,普通文本和json数据,当然也可以自己自定义

package main

import log "github.com/sirupsen/logrus"

func main() {
	// 文本格式
	// log.SetFormatter(&log.TextFormatter{})
    // json格式
	log.SetFormatter(&log.JSONFormatter{})
	log.Info("info")
}

文本格式运行结果

time="2022-09-15T11:44:51+08:00" level=info msg=info

json格式运行结果

{"level":"info","msg":"info","time":"2022-09-15T11:43:36+08:00"}

日志输出

logrus日志输出可以有多种方式,可以是控制台,文件等。

package main

import (
	"os"

	log "github.com/sirupsen/logrus"
)

func main() {
	// 设置输出,标准输出控制台
	log.SetOutput(os.Stdout)
	log.Info("info")
    // 输出到日志文件
	file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY|os.O_CREATE, 0666)
	if err == nil {
		log.SetOutput(file)
	} else {
		log.Info("日志文件创建失败")
	}

	log.Info("info")
}

logrus结构化记录日志,Fields

logrus不推荐使用冗长的消息来记录运行信息,他推荐使用Fields来进行精细化的,结构化的信息记录

package main

import (
	log "github.com/sirupsen/logrus"
)

func main() {
	var event = "下订单"
	var topic = "order"
	var key = 1001
	// log.Fatalf("事件 %s 发送到主题 %s 失败, 使用的key %d", event, topic, key)

	//替代方案
	log.WithFields(log.Fields{
		"event": event,
		"topic": topic,
		"key":   key,
	}).Fatal("事件发送失败")
}

运行结果:

time="2022-09-15T11:54:59+08:00" level=fatal msg="事件发送失败" event="下订单" key=1001 topic=order
exit status 1

输出文件路径函数名称和行号

使用log.SetReportCaller(true),进行设置,默认是false不进行输出

package main

import (
	log "github.com/sirupsen/logrus"
)

func main() {
	// 输出文件路径函数名称和行号,默认是false
	log.SetReportCaller(true)
	log.Info("info")
}

logger

package main

import (
	"os"

	"github.com/sirupsen/logrus"
)

// log实例
var log = logrus.New()

// 初始化配置
func init() {
	// 输出
	log.Out = os.Stdout
	// 格式
	log.Formatter = &logrus.JSONFormatter{}
	// 日志级别
	logrus.SetLevel(logrus.InfoLevel)
}

func main() {
	var event = "下订单"
	var topic = "order"
	var key = 1001

	//替代方案
	log.WithFields(logrus.Fields{
		"event": event,
		"topic": topic,
		"key":   key,
	}).Fatal("事件发送失败")
}

日志本地文件分割

logrus本身不带日志本地分割功能,但是我们可以通过foel-rotatelogs进行日志本地文件分割。每次当我们写入日志的的时候,logrus都会调用file-rotatelogs来判断日志是否要进行切分

package main

import (
	"time"

	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	log "github.com/sirupsen/logrus"
)

func init() {

	path := "message.log"

	/* 日志轮转相关函数

	   `WithLinkName` 为最新的日志建立软连接

	   `WithRotationTime` 设置日志分割的时间,隔多久分割一次

	    WithMaxAge 和 WithRotationCount二者只能设置一个

	    `WithMaxAge` 设置文件清理前的最长保存时间

	    `WithRotationCount` 设置文件清理前最多保存的个数

	*/

	// 下面配置日志每隔 1 分钟轮转一个新文件,保留最近 3 分钟的日志文件,多余的自动清理掉。

	writer, _ := rotatelogs.New(

		path+".%Y%m%d%H%M",

		rotatelogs.WithLinkName(path),
		rotatelogs.WithMaxAge(time.Duration(180)*time.Second),
		rotatelogs.WithRotationTime(time.Duration(60)*time.Second),
	)

	log.SetOutput(writer)

	//log.SetFormatter(&log.JSONFormatter{})

}

func main() {
	for {
		log.Info("hello, world!")
		time.Sleep(time.Duration(2) * time.Second)
	}
}

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐