欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

golang之log rotate详解

程序员文章站 2022-03-20 16:39:51
操作系统: centos 6.9_x64 go语言版本: 1.8.3 问题描述 golang的log模块提供的有写日志功能,示例代码如下: /* gola...

操作系统: centos 6.9_x64

go语言版本: 1.8.3

问题描述

golang的log模块提供的有写日志功能,示例代码如下:

/*
golang log example

*/
package main

import (
  "log"
  "os"
)

func main() {
  logfile,err := os.create("test1.log")
  defer logfile.close()
  if err != nil {
    log.fatalln("open file error!")
  }
  logger := log.new(logfile,"[debug]",log.ldate | log.ltime | log.lshortfile)
  logger.println("test debug message")
  logger.setprefix("[info]")
  logger.println("test info message")

}

运行效果:

[root@local t2]# go build logtest1.go
[root@local t2]# ./logtest1
[root@local t2]# cat test1.log
[debug]2017/06/13 23:18:36 logtest1.go:19: test debug message
[info]2017/06/13 23:18:36 logtest1.go:21: test info message
[root@local t2]#

go语言的log模块没有提供log rotate接口,但实际开发中我们需要该功能:

我们不希望单个日志过大,否则文本编辑器无法打开,查看比较困难;

更不希望占用太大的存储空间,可以指定最多存多少个日志文件。

解决方案

借助带缓冲的channel来实现。

示例代码如下:

/*
  golang log rotate example

*/

package main

import (
  "fmt"
  "log"
  "os"
  "time"
)

const (
  backup_count = 5
  max_file_bytes = 2 * 1024
)

func dorotate(fprefix string) {
  for j := backup_count; j >= 1; j-- {
    curfilename := fmt.sprintf("%s_%d.log",fprefix,j)
    k := j-1
    prefilename := fmt.sprintf("%s_%d.log",fprefix,k)

    if k == 0 {
      prefilename = fmt.sprintf("%s.log", fprefix)
    }
    _,err := os.stat(curfilename)
    if err == nil {
      os.remove(curfilename)
      fmt.println("remove : ", curfilename)
    }
    _,err = os.stat(prefilename)
    if err == nil {
      fmt.println("rename : ", prefilename, " => ", curfilename)
      err = os.rename(prefilename, curfilename)
      if err != nil {
        fmt.println(err)
      }
    }
  }
}

func newlogger(fprefix string) (*log.logger, *os.file) {
  var logger *log.logger
  filename := fmt.sprintf("%s.log", fprefix)
  fmt.println("filename :", filename)
  logfile, err := os.openfile(filename, os.o_rdwr|os.o_create|os.o_append, 0666)

  if err != nil {
    fmt.println("open file error!")
  } else {
    logger = log.new(logfile, "[debug]", log.ldate|log.ltime|log.lshortfile)
  }
  return logger, logfile
}

func logworker(msgqueue <-chan string) {
  fprefix := "msg"
  logger, logfile := newlogger(fprefix)
  for msg := range msgqueue {
    logger.println(msg)
    fi, err2 := logfile.stat()
    if err2 == nil {
      if fi.size() > max_file_bytes {
        logfile.close()
        dorotate(fprefix)
        logger,logfile = newlogger(fprefix)
      }
    }
  }
  logfile.close()
}

func main() {
  msgqueue := make(chan string, 1000)
  go logworker(msgqueue)

  for j := 1; j <= 1000; j++ {
    msgqueue <- fmt.sprintf("msg_%d", j)
    time.sleep(1 * time.second)
  }
  close(msgqueue)
  return
}

运行效果如下:

[root@local t2]# ./logrotatetest1
filename : msg.log
rename : msg.log => msg_1.log
filename : msg.log
rename : msg_1.log => msg_2.log
rename : msg.log => msg_1.log
filename : msg.log
rename : msg_2.log => msg_3.log
rename : msg_1.log => msg_2.log
rename : msg.log => msg_1.log
filename : msg.log
^c

讨论

这里只是个简单的示例代码,实现了log rotate,更多功能需自行开发。

好,就这些了,希望对你有帮助。

以上这篇golang之log rotate详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。