54、Go语言基础 - 日志系统 - 记录日志

作者: 温新

分类: 【Go基础】

阅读: 317

时间: 2023-12-05 00:45:30

hi,我是温新

Go 语言中提供了一个简易的 log 包,使用这个包可以方便的实现日志记录功能。这些日志基于 fmt 包的打印再结合 panic 之类的函数来进行一般的打印、抛出错误处理。

如果想把日志保存到文件,或结合日志做更复杂的功能,log 包就无法满足需求了。可以使用第三方日志系统实现,如 Logrus 或 Seelog。

log 包

log.New函数用于创建自定义的日志记录器。

func New(out io.Writer, prefix string, flag int) *Logger
  • out(参数):表示日志的输出目标,通常是一个实现io.Writer接口的对象,可以是文件、标准输出、网络连接等。
  • prefix(参数):表示每条日志消息的前缀,用于标识不同的日志记录器。
  • flag(参数):表示日志的格式选项,通常是一组位掩码标志,控制日志的输出格式和内容。

基本案例

package main

import (
	"log"
	"os"
)

func main() {
	// 创建一个新的日志记录器,输出到标准错误(os.Stderr)
	logger := log.New(os.Stderr, "【Log 日志:】", log.Ldate|log.Ltime)

	// 记录日志消息
	logger.Print("这是一条普通日志消息")
	logger.Println("这是一条日志消息")
	logger.Printf("这是一条格式化的日志消息:%s", "Hello, Go")

	// 直接使用默认全局日志记录器 log 记录日志消息
	log.Print("直接输出日志")
	log.Printf("这是一条格式化的日志消息:%s %d", "Hello, Go!", 42)
	log.Fatal("这是一条致命的日志消息,将终止程序执行")
}

代码解释:

  • 导入标准库中的log包。
  • 创建一个新的日志记录器(logger),使用log.New函数。这个记录器将日志输出到标准错误(os.Stderr),并使用前缀 "【Log 日志:】",以及日期和时间信息。
  • 使用logger.Println方法记录一条普通的日志消息,该消息会被写入日志输出。
  • 使用logger.Printf方法记录一条格式化的日志消息,可以在消息中插入变量。这种方式更适合复杂的日志消息。
  • 最后使用默认的全局日志记录器log直接记录日志消息。

日志写入文件

package main

import (
	"log"
	"os"
)

func main() {
	// 创建一个新的日志文件 "mydir1/app.log"
	file, err := os.Create("mydir1/app.log")

	// 检查是否成功创建日志文件
	if err != nil {
		log.Fatal("无法创建日志文件:", err)
	}

	// 使用 defer 关闭日志文件,确保程序结束时文件被正确关闭
	defer file.Close()

	// 创建自定义的日志记录器,将日志消息输出到文件
	logger := log.New(file, "【app 文件记录】:", log.Ldate|log.Ltime)
	// 记录日志消息,使用自定义的日志记录器 logger
	logger.Println("这是一条日志消息")
}

这个示例演示了如何创建自定义的日志记录器,将日志消息记录到文件中。如果文件创建成功,日志消息将被写入文件,否则程序将终止并记录错误。

Logrus 日志

Logrus 是一个流行的 Go 语言日志库,提供了丰富的功能和灵活的配置选项,它是结构化 logger,与标准库 logger 完全API兼容。

Logrus 的特点如下:

  • 多种日志级别: 支持多种日志级别,包括 Debug、Info、Warning、Error、Fatal 和 Panic 等。这使得您可以根据需要记录不同级别的日志消息。
  • 丰富的格式化选项: 可以自定义日志消息的格式。可以配置时间戳、日志级别、自定义字段等信息。
  • 输出目标: 支持将日志消息输出到不同的目标,如控制台、文件、网络等。
  • 日志滚动: 支持日志滚动,允许按照大小或时间来切割日志文件,以避免日志文件过大。
  • Hook系统: 提供了一个 hook 系统,允许添加自定义的处理程序,以便在记录日志时执行特定的操作,如发送日志到第三方服务。
  • 字段标签: 允许为日志消息添加自定义字段,这对于记录额外的上下文信息非常有用。

基本案例

new

New 方法用于创建一个新的 Logrus 日志记录器,作为日志记录的起点。

func New() *Logger

New(函数):Logrus 包中的一个构造函数,用于创建新的 Logger 实例。

SetLevel

SetLevel 方法用于设置 Logrus 日志记录器的日志级别。日志级别控制了哪些级别的日志消息将被记录。

func (l *Logger) SetLevel(level Level)
  • l(参数):Logrus 日志记录器,通常是一个已创建的 Logger 实例。
  • level:要设置的日志级别,它是 logrus.Level 类型的枚举值,包括 logrus.DebugLevellogrus.InfoLevellogrus.WarnLevellogrus.ErrorLevellogrus.FatalLevellogrus.PanicLevel 等。
package main

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

func main() {
	// 创建一个新的 Logrus 日志记录器
	log := logrus.New()

	// 配置日志级别(例如,设置 为Info,只输出 Info 及以上级别的日志)
	log.SetLevel(logrus.InfoLevel)

	// 添加日志输出(例如,输出到控制台)
	log.Out = os.Stdout

	// 记录日志消息
	log.Debug("这是一条 Debug 级别的日志")
	log.Info("这是一条 Info 级别的日志")
	log.Warn("这是一条 Warn 级别的日志")
	log.Error("这是一条 Error 级别的日志")
}

New 方法用于创建一个新的 Logrus 日志记录器,您可以根据需要配置其级别、输出目标和其他属性。这个示例演示了如何创建一个基本的 Logrus 日志记录器,并记录不同级别的日志消息。

WithFields

WithFields 方法用于创建一个新的 logrus.Entry 对象,允许您附加字段(键值对形式)以提供额外的上下文信息。

func (entry *Entry) WithFields(fields Fields) *Entry
  • entry(参数):logrus.Entry 对象,通常是现有的日志记录对象。
  • fields(参数):一个 logrus.Fields 对象,包含要添加到日志记录的字段信息。
package main

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

func main() {
	// 创建一个新的 Logrus 日志记录器
	log := logrus.New()

	// 配置日志级别为 Info
	log.SetLevel(logrus.InfoLevel)

	// 输出到标准错误流
	log.Out = os.Stderr

	// 创建一个 Entry 对象,开始记录日志
	entry := log.WithFields(logrus.Fields{
		"app":     "MyApp",
		"version": "1.0",
	})

	// 记录带有字段的日志消息
	entry.Info("应用程序已启动")

	// 创建一个新的 Entry,可以附加不同的字段
	anotherEntry := entry.WithFields(logrus.Fields{
		"user": "王美丽",
	})

	// 记录带有不同字段的日志消息
	anotherEntry.Info("王美丽 登录了应用程序")
}

输出结果

time="2023-10-19T16:28:28+08:00" level=info msg="应用程序已启动" app=MyApp version=1.0
time="2023-10-19T16:28:28+08:00" level=info msg="王美丽 登录了应用程序" app=MyApp user="王美丽" version=1.0

WithFields 方法允许地在不同的日志消息中添加自定义字段,以提供更多的信息和上下文。这对于跟踪应用程序中的不同事件和问题非常有用。

默认字段

package main

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

func main() {
	log := logrus.New()
	log.SetLevel(logrus.InfoLevel)
	log.Out = os.Stderr

	// 记录一条 Info 级别的日志消息
	log.Info("这是一条 Info 级别的日志")
	// 默认字段
	log.WithFields(logrus.Fields{
		"name": "王美丽",
		"age":  19,
	}).Info("欢迎来到 Go 的世界:")
}

输出结果

time="2023-10-19T16:40:30+08:00" level=info msg="这是一条 Info 级别的日志"
time="2023-10-19T16:40:30+08:00" level=info msg="欢迎来到 Go 的世界:" age=19 name="王美丽"

在示例中,我们还演示了如何使用 WithFields 方法添加自定义字段,如用户和操作类型。这些字段将与默认字段一起记录在日志消息中,提供了更多的上下文信息。

Hook

Hook 介绍

Logrus 中的 Hook 是一种机制,允许用户自定义日志消息的处理方式。可以创建自定义 Hook 来执行各种操作,例如将日志消息发送到远程服务器、将日志消息存储到特定数据库等。

自定义 Hook

为了创建自定义 Hook,需要实现 logrus.Hook 接口的方法。主要的方法包括:

  • Fire(entry *logrus.Entry) error:当有新的日志消息需要处理时,Logrus 会调用此方法。您可以在此方法中执行自定义操作。
  • Levels() []logrus.Level:指定您的 Hook 关心的日志级别。例如,您可以选择只处理 Error 级别及以上的日志消息。

代码示例及解释

package main

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

func main() {
	// 创建一个新的 Logrus 日志记录器
	log := logrus.New()

	// 配置日志级别为 Info
	log.SetLevel(logrus.InfoLevel)

	// 输出到标准错误流
	log.Out = os.Stderr

	// 创建自定义 Hook 实例
	customHook := &CustomHook{}

	// 添加自定义 Hook 到 Logrus
	log.AddHook(customHook)

	// 记录不同级别的日志消息
	log.Info("这是一条 Info 级别的日志,不会触发自定义 Hook")
	log.Warn("这是一条 Warn 级别的日志,会触发自定义 Hook")
}

// CustomHook 是一个自定义的 Logrus Hook
type CustomHook struct {
	// 这里可以定义您的 Hook 所需的任何字段
}

// Fire 方法在有新的日志消息时会被调用
func (hook *CustomHook) Fire(entry *logrus.Entry) error {
	// 在这里执行自定义操作,例如将日志消息发送到远程服务器
	// 这个示例只是打印日志消息,实际情况中应该执行真正的操作
	logMessage := entry.Message
	println("自定义操作: " + logMessage)
	return nil
}

// Levels 方法指定此 Hook 关心的日志级别
func (hook *CustomHook) Levels() []logrus.Level {
	return []logrus.Level{logrus.WarnLevel, logrus.ErrorLevel}
}

输出结果

time="2023-10-19T16:49:43+08:00" level=info msg="这是一条 Info 级别的日志,不会触发自定义 Hook"
自定义操作: 这是一条 Warn 级别的日志,会触发自定义 Hook
time="2023-10-19T16:49:43+08:00" level=warning msg="这是一条 Warn 级别的日志,会触发自定义 Hook"

代码注释:

  • 定义了一个名为 CustomHook 的自定义 Logrus Hook 结构,可以在其中添加任何需要的字段。此示例中没有特定字段。
  • Fire 方法是 logrus.Hook 接口的一部分,会在有新的日志消息时被调用。在此方法中,您可以执行自定义操作,例如将日志消息发送到远程服务器。示例中只是打印日志消息。
  • Levels 方法指定了此 Hook 关心的日志级别,这里选择处理 Warn 和 Error 级别的日志消息。
  • main 函数中,我们创建一个新的 Logrus 日志记录器 log 并配置其级别和输出目标。
  • 创建自定义 Hook 实例 customHook
  • 使用 log.AddHook 方法将自定义 Hook 添加到 Logrus,以便触发处理自定义操作。
  • 我们记录不同级别的日志消息,但只有 Warn 和 Error 级别的消息会触发自定义 Hook 中的操作。

Seelog

Seelog 是一个用于 Go 语言的开源日志记录库,它提供了灵活且强大的日志记录功能。

Seelog 的特点如下:

  • 配置灵活性Seelog 提供了非常灵活的配置选项,允许您定义日志格式、输出目标、级别和过滤器等。
  • 多种输出目标:您可以将日志消息输出到不同的目标,如控制台、文件、网络套接字、SMTP 邮件等。
  • 级别控制:支持不同级别的日志消息,包括 Debug、Info、Warn、Error 和 Critical,您可以根据需要配置哪些级别的消息应该被记录。
  • 格式化:可以自定义日志消息的格式,包括时间戳、级别、文件名、行号等信息。
  • 过滤器Seelog 支持过滤器,可以根据条件过滤出要记录的消息,这有助于控制哪些日志消息会被记录。
package main

import "github.com/cihub/seelog"

func main() {
	defer seelog.Flush()
	seelog.Info("hello seelog")
}
请登录后再评论