golang之log rotate
操作系统: CentOS 6.9_x64
go语言版本: 1.8.3
问题描述
golang的log模块提供的有写日志功能,示例代码如下:
/*
golang log example
E-Mail : Mike_Zhang@live.com
*/
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]// :: logTest1.go:: test debug message
[Info]// :: logTest1.go:: test info message
[root@local t2]#
go语言的log模块没有提供log rotate接口,但实际开发中我们需要该功能:
我们不希望单个日志过大,否则文本编辑器无法打开,查看比较困难;
更不希望占用太大的存储空间,可以指定最多存多少个日志文件。
解决方案
借助带缓冲的channel来实现。
示例代码如下:
/*
golang log rotate example
E-Mail : Mike_Zhang@live.com
*/ package main import (
"fmt"
"log"
"os"
"time"
) const (
BACKUP_COUNT =
MAX_FILE_BYTES = *
) func doRotate(fPrefix string) {
for j := BACKUP_COUNT; j >= ; j-- {
curFileName := fmt.Sprintf("%s_%d.log",fPrefix,j)
k := j-
preFileName := fmt.Sprintf("%s_%d.log",fPrefix,k) if k == {
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, ) 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, )
go logWorker(msgQueue) for j := ; j <= ; j++ {
msgQueue <- fmt.Sprintf("msg_%d", j)
time.Sleep( * 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,更多功能需自行开发。
好,就这些了,希望对你有帮助。
本文github地址:
https://github.com/mike-zhang/mikeBlogEssays/blob/master/2017/20170614_golang之logRotate.rst
欢迎补充
golang之log rotate的更多相关文章
- Golang官方log包详解
Golang官方log包详解 以下全是代码, 详解在注释中, 请从头到尾看 // Copyright 2009 The Go Authors. All rights reserved. // Use ...
- linux log rotate
今天老大提醒我产线kafka自身的log文件积累了好几个月了,我才发现原来kafka的log4j并删除old log. 第一反应是采用linux自带的logrotate功能,在/etc/logrota ...
- golang package log
package main import ( "log" "os" ) var logger *log.Logger func main() { file, er ...
- Golang中log与fmt区别
关于使用log与使用fmt的区别 最初的就是直接打印出来,之后一点点升级,比如加上输出的时间,加上goroutine之间的并发操作(打印信息并不能一定按照你规定好的顺序输出来 每次输出的顺序可能会不同 ...
- Golang Learn Log #0
Print/Printf 区别 Print: 可以打印出字符串, 和变量 fmt.Println(var) //right fmt.Println("string") //righ ...
- golang基础学习---log
package main import ( "log" ) func init() { log.SetPrefix("TRACE: ") log.SetFlag ...
- Golang 标准库log的实现
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://gotaly.blog.51cto.com/8861157/1406905 前 ...
- Golang 标准库提供的Log(一)
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://gotaly.blog.51cto.com/8861157/1405754 G ...
- 关于Relay Log无法自己主动删除的问题(Neither --relay-log nor --relay-log-index were used)
今天查看mysql err日志.发现mysql重新启动时总会有例如以下日志出现: [Warning] Neither --relay-log nor --relay-log-index were us ...
随机推荐
- 手机端可以和PC端同时在线-java QRCode 实现网站扫码登录(即支持同帐号多设备同时登录)
微信扫码测试地址:: http://sms.reyo.cn 用户名:aa 密码:123456 扫码登录实现方式很多,比如ajax轮询,http长连接(comet...),websocket,event ...
- UICollectionViewFlowLayout使用示例
UICollectionViewFlowLayout使用示例 效果 源码 https://github.com/YouXianMing/iOS-Project-Examples // // ViewC ...
- MyBatis入参类型是List时判断非空
一.参数list时,先判断是否为空,否则会报错. 二.mybatis ${}与#{}的区别 简单来说#{} 解析的是占位符?可以防止SQL注入, 比如打印出来的语句 select * from tab ...
- ntp测试
cmd下 w32tm /stripchart /computer:time1.aliyun.com linux ntpdate ntp1.aliyun.com
- C#和java之间的一些差异与共性
C#与java之间的一些共性和差异整理 隐藏:与java中的重写几乎一致,但是需要添加new关键字让编译器知道,否则会有警告 虚方法:1.声明为virtual的方法就是虚方法,在子类中使用overri ...
- 【翻译自mos文章】Windows平台下的 Oraagent Memory Leak
来源于: Oraagent Memory Leak (文档 ID 1956840.1) APPLIES TO: Oracle Database - Enterprise Edition - Versi ...
- [转]分析MySQL数据类型的长度【mysql数据字段 中length和decimals的作用!熟悉mysql必看】
转载自:http://blog.csdn.net/daydreamingboy/article/details/6310907 分析MySQL数据类型的长度 MySQL有几种数据类型可以限制类型的&q ...
- 【转】你真的懂select Socket模型吗?
转自:http://www.cppblog.com/xvsdf100/archive/2013/12/10/204689.html 只要接触过c/c++网路编程人都可能会知道select io ...
- 案例导入和导出Scott用户
ylbtech-Oracle:案例导入和导出Scott用户 导入和导出Scott用户 1. 导出Scott用户下的所有对象返回顶部 1.1, Microsoft Windows [版本 ] 版权所有 ...
- RV32I指令集
RV32I是最基本的32位Base指令集,它支持32位寻址空间,支持字节地址访问,仅支持小端格式(little-endian,高地址高位,低地址地位),寄存器也是32位整数寄存器.RV32I指令集的目 ...