当前位置:网站首页>go语言的日志实现(打印日志、日志写入文件、日志切割)
go语言的日志实现(打印日志、日志写入文件、日志切割)
2022-08-04 22:34:00 【ydl1128】
Go语言内置的log包实现了简单的日志服务。
log包定义了Logger类型,该类型提供了一些格式化输出的方法。本包也提供了一个预定义的“标准”logger,可以通过调用函数Print系列(Print|Printf|Println)、Fatal系列(Fatal|Fatalf|Fatalln)、和Panic系列(Panic|Panicf|Panicln)来使用,比自行创建一个logger对象更容易使用。
Logger
package main
import (
"log"
)
func main() {
log.Println("这是一条测试的日志。")
v := "很普通的"
log.Printf("这是一条%s日志。\n", v)
log.Fatalln("这是一条会触发fatal的日志。")
log.Panicln("这是一条会触发panic的日志。")
}
标准logger的配置
SetFlags函数用来设置标准logger的输出配置。
const (
// 控制输出日志信息的细节,不能控制输出的顺序和格式。
// 输出的日志在每一项后会有一个冒号分隔:例如2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
Ldate = 1 << iota // 日期:2009/01/23
Ltime // 时间:01:23:23
Lmicroseconds // 微秒级别的时间:01:23:23.123123(用于增强Ltime位)
Llongfile // 文件全路径名+行号: /a/b/c/d.go:23
Lshortfile // 文件名+行号:d.go:23(会覆盖掉Llongfile)
LUTC // 使用UTC时间
LstdFlags = Ldate | Ltime // 标准logger的初始值
)
func main() {
log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
log.Println("这是一条很普通的日志。")
}
配置日志前缀(SetPrefix)
func main() {
log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
log.Println("这是一条很普通的日志。")
log.SetPrefix("[哈哈哈]")
log.Println("这是一条很普通的日志。")
}
配置日志输出位置
SetOutput函数用来设置标准logger的输出目的地,默认是标准错误输出。
func init() {
logFile, err := os.OpenFile("./xx.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
fmt.Println("open log file failed, err:", err)
return
}
log.SetOutput(logFile)
log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
}
创建新logger对象
log标准库中还提供了一个创建新logger对象的构造函数–New,支持我们创建自己的logger示例。New函数的签名如下:
func New(out io.Writer, prefix string, flag int) *Logger
New创建一个Logger对象。其中,参数out设置日志信息写入的目的地。参数prefix会添加到生成的每一条日志前面。参数flag定义日志的属性(时间、文件等等)。
举个例子:
func main() {
logger := log.New(os.Stdout, "<New>", log.Lshortfile|log.Ldate|log.Ltime)
logger.Println("这是自定义的logger记录的日志。")
}
//<New>2017/06/19 14:06:51 main.go:34: 这是自定义的logger记录的日志。
补充:Go内置的log库功能有限,例如无法满足记录不同级别日志的情况,需要选择使用第三方的日志库,如logrus、zap等。
日志库级别
package log
import (
"errors"
"fmt"
"strings"
"time"
)
type LogLevel uint16
//日志常量
const (
UNKNOW LogLevel = iota
DEBUG
TRACE
INFO
WARNIG
ERROR
FATAL
)
//解析日志级别
func paraLogLevel(s string) (LogLevel,error) {
s = strings.ToLower(s)
switch s {
case "debug":
return DEBUG,nil
case "tarce":
return TRACE,nil
case "info":
return INFO,nil
case "warnig":
return WARNIG,nil
case "error":
return ERROR,nil
case "fatal":
return FATAL,nil
default:
err:= errors.New("无效的日志级别")
return UNKNOW,err
}
}
//定义日志级别机构提
type Logger struct{
Level LogLevel
}
//构造器
func NewLog(levelLog string) Logger {
level, err := paraLogLevel(levelLog)
if err !=nil{
panic(err)
}
return Logger{
Level: level,
}
}
//是否能够打印某个级别的日志
func (l Logger) enable(logLevel LogLevel) bool {
return l.Level >logLevel
}
func (l Logger) Debug(msg string) {
if l.enable(DEBUG){
now := time.Now()
fmt.Printf("[%s] [Debug] %s",now.Format("2006-01-02 15:04:05"),msg);
}
}
func (l Logger) Info(msg string) {
if l.enable(INFO){
now := time.Now()
fmt.Printf("[%s] [Info] %s",now.Format("2006-01-02 15:04:05"),msg);
}
}
func (l Logger) Warning(msg string) {
if l.enable(WARNIG){
now := time.Now()
fmt.Printf("[%s] [Warning] %s",now.Format("2006-01-02 15:04:05"),msg);
}
}
func (l Logger) Error(msg string) {
if l.enable(ERROR){
now := time.Now()
fmt.Printf("[%s] [Error] %s",now.Format("2006-01-02 15:04:05"),msg);
}
}
func (l Logger) Fatal(msg string) {
if l.enable(FATAL){
now := time.Now()
fmt.Printf("[%s] [Fatal] %s",now.Format("2006-01-02 15:04:05"),msg);
}
}
import "gostudy/log"
func main() {
newLog := log.NewLog("warnig")
newLog.Debug("这是debug日志")
newLog.Info("这是info日志")
newLog.Warning("这是Warning日志")
newLog.Error("这是ERROR日志")
newLog.Fatal("这是FATAL日志")
}
打印结果:[2022-08-04 10:41:56] [Debug] 这是debug日志[2022-08-04 10:41:56] [Info] 这是info日志
runtime.Caller

能够拿到文件名函数名和行号
可变参数的日志
//......interface{}表示可变的任意参数,可不传也可传任意长度
func (l Logger) Debug(msg string, a ...interface{
}) {
msg = fmt.Sprint(msg,a)
if l.enable(DEBUG){
now := time.Now()
fmt.Printf("[%s] [Debug] %s",now.Format("2006-01-02 15:04:05"),msg);
}
}
实现往文件里面写日志
1.新建fileloger.go文件,用来提供写入日志的功能
package log
import (
"errors"
"fmt"
"os"
"path"
"strings"
"time"
)
type LogLevel uint16
//日志级别
const (
UNKNOW LogLevel = iota
DEBUG
TRACE
INFO
WARNIG
ERROR
FATAL
)
//解析日志
func paraLogLevel(s string) (LogLevel,error) {
s = strings.ToLower(s)
switch s {
case "debug":
return DEBUG,nil
case "tarce":
return TRACE,nil
case "info":
return INFO,nil
case "warnig":
return WARNIG,nil
case "error":
return ERROR,nil
case "fatal":
return FATAL,nil
default:
err:= errors.New("无效的日志级别")
return UNKNOW,err
}
}
//获取日志的字符串格式
func getLogStr (level LogLevel) string {
switch level {
case DEBUG:
return "debug"
case TRACE:
return "tarce"
case INFO:
return "info"
case WARNIG:
return "warnig"
case ERROR:
return "error"
case FATAL:
return "fatal"
default:
return "unknow"
}
}
//定义日志的结构体
type FileLogger struct{
Level LogLevel
filePath string
fileName string
//要打开和写入的文件,一个日志文件一个错误日志文件
fileObj *os.File
errfileObj *os.File
maxFileSize int64
}
//构造函数
func NewFlieLogger(LeveStr ,fp,fn string,size int64) *FileLogger{
level, err := paraLogLevel(LeveStr)
if err != nil {
panic(err)
}
f1 := &FileLogger{
Level: level,
filePath: fp,
fileName: fn,
maxFileSize: size,
}
err= f1.initFile()
if err != nil {
panic(err)
}
return f1
}
//初始化要打开和写入的日志文件的操作
func (f *FileLogger) initFile() (error) {
join := path.Join(f.filePath, f.fileName)
fileObj, err := os.OpenFile(join, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
fmt.Printf("open log fail ,err: %v\n",err)
return err
}
errFileObj, err := os.OpenFile(join+".err", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
fmt.Printf("open log fail ,err: %v\n",err)
return err
}
//日志文件都打开
f.fileObj = fileObj;
f.errfileObj = errFileObj;
return nil
}
//判断级别
func (l FileLogger) enable(logLevel LogLevel) bool {
return l.Level >logLevel
}
//打印日志操作
func (f *FileLogger) Log(leve LogLevel,msg string) {
now := time.Now()
if f.enable(leve){
fmt.Fprintf(f.fileObj,"[%s] [%s] %s",now.Format("2006-01-02 15:04:05"),getLogStr(leve),msg);
}
if leve >ERROR{
fmt.Fprintf(f.errfileObj,"[%s] [%s] %s",now.Format("2006-01-02 15:04:05"),getLogStr(leve),msg);
}
}
func (l FileLogger) Debug(msg string, a ...interface{
}) {
msg = fmt.Sprint(msg,a)
if l.enable(DEBUG){
l.Log(DEBUG,msg)
}
}
func (l FileLogger) Info(msg string, a ...interface{
}) {
msg = fmt.Sprint(msg,a)
if l.enable(WARNIG){
l.Log(WARNIG,msg)
}
}
func (l FileLogger) Warning(msg string, a ...interface{
}) {
msg = fmt.Sprint(msg,a)
if l.enable(WARNIG){
l.Log(WARNIG,msg)
}
}
func (l FileLogger) Error(msg string, a ...interface{
}) {
msg = fmt.Sprint(msg,a)
if l.enable(ERROR){
l.Log(ERROR,msg)
}
}
func (l FileLogger) Fatal(msg string, a ...interface{
}) {
msg = fmt.Sprint(msg,a)
if l.enable(FATAL){
l.Log(FATAL,msg)
}
}
func (f *FileLogger) Colse() {
f.fileObj.Close()
f.errfileObj.Close()
}
2.测试:
func main() {
newLog := log.NewFlieLogger("warnig","./","now.log",100*1024*1024)
newLog.Debug("这是debug日志")
newLog.Info("这是info日志")
newLog.Warning("这是Warning日志")
newLog.Error("这是ERROR日志")
newLog.Fatal("这是FATAL日志")
newLog.Colse()
}
//运行两次后,打印结果:
日志切割(按文件大小切割、按日期切割)
其实就是每次记录文件的大小,超过了就重新写一个文件。
通过Stat()函数拿到文件的一些信息
open, _:= os.Open("文件名")
stat, _, := open.Stat()
stat.Size()//拿到文件大小
日期切割:
拿到文件的名称或者检查下有没有当天的日志文件,没有就创建新增。
边栏推荐
- Leaflets of three bouquet of roses
- ANT1.7 download and configuration method
- Debian防火墙的开关以及状态
- PowerBI scripture series
- 【论文笔记KDD2021】MixGCF: An Improved Training Method for Graph Neural Network-based Recommender Systems
- Open source summer | Cloud server ECS installs Mysql, JDK, RocketMQ
- SRv6网络的安全解决方案
- Lecture 2 Software Life Cycle
- 一招包治pycharm DEBUG报错 UnicodeDecodeError: ‘utf-8‘ codec can‘t decode
- JVM内存配置参数GC日志
猜你喜欢
随机推荐
炽热如初 向新而生|ISC2022 HackingClub白帽峰会圆满举办!
The Record of Reminding myself
Detailed usage of LocalDateTime
[Mock Interview - 10 Years of Work] Are more projects an advantage?
synchronized和ReentrantLock都很丝滑,因为他们都是可重入锁,一个线程多次拿锁也不会死锁,我们需要可重入
One trick to cure pycharm DEBUG error UnicodeDecodeError: 'utf-8' codec can't decode
【TCP/IP 五 ICMP】
一招包治pycharm DEBUG报错 UnicodeDecodeError: ‘utf-8‘ codec can‘t decode
Rt-thread [二] 系统初始化流程
如何在项目中正确使用WebSocket
3D建模师为了让甲方爸爸过稿,还可以这么做,就是在赚血汗钱啊
LeetCode 199: 二叉树的右视图
Hardware factors such as CPU, memory, and graphics card also affect the performance of your deep learning model
直播带货为农产品开拓销售渠道
生成回文数
赶紧进来!!!教你C语言实现扫雷小游戏(文章最后有源码!!!)
阿里巴巴2022届秋招面试真题和答案!
SSM整合完整流程讲解
JVM memory configuration parameter GC log
PowerBI真经连续剧





![MQTT[一]基础知识介绍](/img/25/3ba24127e2258902b2d5ecc7c3727b.png)



