golang自动轮转日志文件多策略实现插件库rollingwriter的使用

Golang自动轮转日志文件多策略实现插件库rollingwriter的使用

RollingWriter是一个自动轮转的io.Writer实现,可以与日志记录器良好配合使用。

主要特性

  • 支持多种轮转策略的自动日志轮转
  • 实现了go io.Writer接口,提供并行安全的写入器
  • 自动清理保留最大数量的轮转文件
  • 用户可以轻松实现自己的管理器

组件结构

RollingWriter包含两个独立部分:

  1. Manager:决定何时根据策略轮转文件

    • WithoutRolling:不进行轮转
    • TimeRolling:按时间轮转
    • VolumeRolling:按文件大小轮转
  2. IOWriter:实现io.Writer并执行IO写入

    • Writer:非并行安全的写入器
    • LockedWriter:通过锁保证并行安全
    • AsyncWriter:并行安全的异步写入器
    • BufferWriter:将多次写入合并为一个file.Write()

快速开始示例

package main

import (
	"github.com/arthurkiller/rollingwriter"
)

func main() {
	// 配置轮转策略
	config := rollingwriter.Config{
		LogPath:       "./logs",       // 日志目录
		FileName:      "app.log",      // 日志文件名
		MaxRemain:     7,              // 保留的旧日志文件最大数量
		RollingPolicy: rollingwriter.TimeRolling, // 按时间轮转
		RollingTimePattern: "0 0 0 * * *", // 每天午夜轮转
	}

	// 创建写入器
	writer, err := rollingwriter.NewWriterFromConfig(&config)
	if err != nil {
		panic(err)
	}

	// 写入日志
	writer.Write([]byte("hello, world\n"))
	
	// 确保在程序退出前关闭写入器
	defer writer.Close()
}

完整示例Demo

package main

import (
	"log"
	"time"

	"github.com/arthurkiller/rollingwriter"
)

func main() {
	// 配置按大小轮转的写入器
	sizeConfig := rollingwriter.Config{
		LogPath:       "./logs",
		FileName:      "size_rolling.log",
		MaxRemain:     5,                      // 保留5个旧日志文件
		RollingPolicy: rollingwriter.VolumeRolling, // 按大小轮转
		RollingVolume: 10 * 1024 * 1024,      // 每个日志文件最大10MB
	}

	sizeWriter, err := rollingwriter.NewWriterFromConfig(&sizeConfig)
	if err != nil {
		log.Fatal(err)
	}
	defer sizeWriter.Close()

	// 配置按时间轮转的写入器
	timeConfig := rollingwriter.Config{
		LogPath:       "./logs",
		FileName:      "time_rolling.log",
		MaxRemain:     7,                      // 保留7个旧日志文件
		RollingPolicy: rollingwriter.TimeRolling, // 按时间轮转
		RollingTimePattern: "0 0 12 * * *",    // 每天中午12点轮转
	}

	timeWriter, err := rollingwriter.NewWriterFromConfig(&timeConfig)
	if err != nil {
		log.Fatal(err)
	}
	defer timeWriter.Close()

	// 模拟日志写入
	for i := 0; i < 1000; i++ {
		msg := time.Now().Format("2006-01-02 15:04:05") + " - Log message " + string(i) + "\n"
		
		// 写入大小轮转日志
		if _, err := sizeWriter.Write([]byte(msg)); err != nil {
			log.Printf("Error writing to size rolling log: %v", err)
		}
		
		// 写入时间轮转日志
		if _, err := timeWriter.Write([]byte(msg)); err != nil {
			log.Printf("Error writing to time rolling log: %v", err)
		}
		
		time.Sleep(time.Second)
	}
}

性能基准测试

goos: darwin
goarch: amd64
pkg: github.com/arthurkiller/rollingwriter
BenchmarkWrite-4                          300000              5952 ns/op               0 B/op          0 allocs/op
BenchmarkParallelWrite-4                  200000              7846 ns/op               0 B/op          0 allocs/op
BenchmarkAsynWrite-4                      200000              7917 ns/op           16324 B/op          1 allocs/op
BenchmarkParallelAsynWrite-4              200000              8632 ns/op           12513 B/op          1 allocs/op
BenchmarkLockedWrite-4                    200000              5829 ns/op               0 B/op          0 allocs/op
BenchmarkParallelLockedWrite-4            200000              7796 ns/op               0 B/op          0 allocs/op
BenchmarkBufferWrite-4                    200000              6943 ns/op            1984 B/op          4 allocs/op
BenchmarkParallelBufferWrite-4           1000000              1026 ns/op            7129 B/op          1 allocs/op
PASS
ok      github.com/arthurkiller/rollingWriter   14.867s

RollingWriter提供了灵活的日志轮转解决方案,可以根据项目需求选择不同的轮转策略和写入器类型。


更多关于golang自动轮转日志文件多策略实现插件库rollingwriter的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang自动轮转日志文件多策略实现插件库rollingwriter的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang自动轮转日志文件多策略实现:rollingwriter使用指南

什么是rollingwriter

rollingwriter是一个功能强大的Golang日志轮转库,它提供了多种日志轮转策略,包括按时间、按文件大小、按文件行数等,并且支持多种压缩和归档选项。

安装

go get github.com/arthurkiller/rollingwriter

基本使用

1. 简单示例

package main

import (
	"log"
	"os"
	"time"

	"github.com/arthurkiller/rollingwriter"
)

func main() {
	// 配置rollingwriter
	config := rollingwriter.Config{
		LogPath:                "./logs",      // 日志目录
		TimeTagFormat:          "20060102",    // 时间格式
		FileName:               "app.log",     // 基础文件名
		MaxRemain:              3,             // 保留的旧日志文件数量
		RollingPolicy:          rollingwriter.TimeRolling, // 按时间轮转
		RollingTimePattern:     "* * * * * *", // 每分钟轮转一次
		WriterMode:             "none",        // 不压缩
		BufferWriterThershould: 8 * 1024,      // 8KB缓冲区
	}

	// 创建writer
	writer, err := rollingwriter.NewWriterFromConfig(&config)
	if err != nil {
		log.Fatal(err)
	}

	// 设置log输出
	log.SetOutput(writer)

	// 模拟日志输出
	for i := 0; i < 100; i++ {
		log.Printf("This is a test log message %d", i)
		time.Sleep(time.Second)
	}
}

多种轮转策略

1. 按时间轮转

config := rollingwriter.Config{
	LogPath:            "./logs",
	TimeTagFormat:      "20060102",
	FileName:           "time_rotate.log",
	MaxRemain:          7,  // 保留7天的日志
	RollingPolicy:      rollingwriter.TimeRolling,
	RollingTimePattern: "0 0 0 * * *", // 每天午夜轮转
}

2. 按文件大小轮转

config := rollingwriter.Config{
	LogPath:       "./logs",
	TimeTagFormat: "20060102",
	FileName:      "size_rotate.log",
	MaxRemain:     10, // 保留10个旧日志文件
	RollingPolicy: rollingwriter.VolumeRolling,
	RollingVolumeSize: "100MB", // 每个日志文件最大100MB
}

3. 按文件行数轮转

config := rollingwriter.Config{
	LogPath:       "./logs",
	TimeTagFormat: "20060102",
	FileName:      "line_rotate.log",
	MaxRemain:     5, // 保留5个旧日志文件
	RollingPolicy: rollingwriter.LineRolling,
	RollingLine:   100000, // 每10万行轮转一次
}

高级配置

1. 压缩轮转后的日志

config := rollingwriter.Config{
	LogPath:       "./logs",
	FileName:      "compressed.log",
	RollingPolicy: rollingwriter.VolumeRolling,
	RollingVolumeSize: "50MB",
	WriterMode:    "lock", // 使用lock模式
	Compress:      true,   // 启用压缩
	CompressSuffix: ".gz", // 压缩后缀
}

2. 异步写入

config := rollingwriter.Config{
	LogPath:       "./logs",
	FileName:      "async.log",
	RollingPolicy: rollingwriter.VolumeRolling,
	RollingVolumeSize: "100MB",
	Async:         true,      // 启用异步写入
	BufferSize:    4096,      // 缓冲区大小
}

3. 自定义文件名格式

config := rollingwriter.Config{
	LogPath:       "./logs",
	FileName:      "custom",
	TimeTagFormat: "2006-01-02-15-04-05",
	RollingPolicy: rollingwriter.TimeRolling,
	RollingTimePattern: "* * * * * *", // 每分钟轮转
	MaxRemain:     60, // 保留60个文件
}

最佳实践

1. 与标准log包集成

func setupLogger() {
	config := rollingwriter.Config{
		LogPath:       "./logs",
		FileName:      "app.log",
		RollingPolicy: rollingwriter.TimeRolling,
		RollingTimePattern: "0 0 0 * * *", // 每天轮转
		MaxRemain:     7,
		Async:        true,
	}
	
	writer, err := rollingwriter.NewWriterFromConfig(&config)
	if err != nil {
		panic(err)
	}
	
	log.SetOutput(writer)
	log.SetFlags(log.LstdFlags | log.Lshortfile)
}

2. 与logrus集成

import (
	"github.com/sirupsen/logrus"
	"github.com/arthurkiller/rollingwriter"
)

func setupLogrus() *logrus.Logger {
	config := rollingwriter.Config{
		LogPath:       "./logs",
		FileName:      "logrus.log",
		RollingPolicy: rollingwriter.VolumeRolling,
		RollingVolumeSize: "100MB",
		MaxRemain:     10,
	}
	
	writer, err := rollingwriter.NewWriterFromConfig(&config)
	if err != nil {
		panic(err)
	}
	
	logger := logrus.New()
	logger.SetOutput(writer)
	logger.SetFormatter(&logrus.JSONFormatter{})
	
	return logger
}

注意事项

  1. 确保日志目录有写入权限
  2. 合理设置MaxRemain参数,避免磁盘空间被占满
  3. 生产环境中建议启用异步写入以提高性能
  4. 对于高频日志,考虑使用缓冲区减少IO操作

rollingwriter提供了灵活且强大的日志轮转功能,可以根据实际需求组合不同的策略和选项,是Golang项目中管理日志文件的优秀选择。

回到顶部