go语言日志库lagan
本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.
概述
lagan取名来自于宜家的水龙头"拉根"。源码仓库链接:https://gitee.com/jdhxyy/lagan
开源
功能
- 支持日志在终端实时打印
- 支持日志保存在文件
- 支持日志文件自动分割
- 支持终端交互控制日志输出级别等功能
源码
// Copyright 2019-2021 The TZIOT Authors. All rights reserved.
// 日志包.可打印实时日志或者流日志
// Authors: jdh99 <jdh821@163.com>
// lagan取名来自于宜家的水龙头"拉根"
package lagan
import (
"fmt"
"log"
"os"
"time"
)
// FilterLevel 过滤日志级别类型
type FilterLevel uint8
// 过滤日志级别
const (
LevelOff FilterLevel = iota
LevelDebug
LevelInfo
LevelWarn
LevelError
)
var gLevelCh = [...]byte{'O', 'D', 'I', 'W', 'E'}
const (
// 日志级别
LogLevelOff = 0
LogLevelDebug = 1
LogLevelInfo = 2
LogLevelWarn = 3
LogLevelError = 4
// 日志文件默认大小.单位:M字节
LogFileSizeDefault = 10
)
type LogItem struct {
name string
level int
}
var gInfoLogger, gInfoLoggerStd *log.Logger
var gIsPause = false
var gLogFileSize = 0
var gLogFileMaxSize = LogFileSizeDefault * 1024 * 1024
var gLogFile *os.File = nil
var gFilterLevel FilterLevel = LogLevelInfo
var gIsLoad = false
// Load 模块载入
// logFileMaxSize是日志文件切割的大小.单位:M字节.如果传入0,则使用默认切割文件大小
func Load(logFileMaxSize int) error {
if logFileMaxSize != 0 {
gLogFileMaxSize = logFileMaxSize * 1024 * 1024
}
gInfoLoggerStd = log.New(os.Stdout, "", log.LstdFlags)
err := createLogFile()
if err == nil {
gIsLoad = true
go input()
}
return err
}
func createLogFile() error {
_ = os.Mkdir("log", os.ModePerm)
file := "log/" + time.Now().Format("20060102-150405") + ".txt"
logFile, err := os.Create(file)
if err != nil {
fmt.Println("create log file fail!", err.Error())
return err
}
if gLogFile != nil {
_ = gLogFile.Close()
}
gLogFile = logFile
gInfoLogger = log.New(gLogFile, "", log.LstdFlags)
gLogFileSize = 0
return nil
}
func input() {
var s string
var err error
for {
_, err = fmt.Scanln(&s)
if err != nil {
continue
}
if s == "help" {
printHelp()
continue
}
if s == "filter_error" {
SetFilterLevel(LevelError)
fmt.Println("set level:ERROR")
Resume()
continue
}
if s == "filter_warn" {
SetFilterLevel(LevelWarn)
fmt.Println("set level:WARN")
Resume()
continue
}
if s == "filter_info" {
SetFilterLevel(LevelInfo)
fmt.Println("set level:INFO")
Resume()
continue
}
if s == "filter_debug" {
SetFilterLevel(LevelDebug)
fmt.Println("set level:debug")
Resume()
continue
}
if s == "filter_off" {
SetFilterLevel(LevelOff)
fmt.Println("set level:OFF")
Resume()
continue
}
if s == "pause" {
Pause()
fmt.Println("pause print")
continue
}
if s == "resume" {
Resume()
fmt.Println("resume print")
continue
}
}
}
func printHelp() {
fmt.Println("*******************************************")
fmt.Println(" lagan help shell ")
fmt.Printf("current level:%c,is pause:%v\n", gLevelCh[gFilterLevel], IsPause())
fmt.Println("help:print help")
fmt.Println("filter_error:filter error level")
fmt.Println("filter_warn:filter warn level")
fmt.Println("filter_info:filter info level")
fmt.Println("filter_debug:filter debug level")
fmt.Println("filter_off:filter off level")
fmt.Println("pause:pause log")
fmt.Println("resume:resume log")
fmt.Println("*******************************************")
}
// SetFilterLevel 设置日志级别
func SetFilterLevel(level FilterLevel) {
gFilterLevel = level
}
// 显示过滤日志等级
func GetFilterLevel() FilterLevel {
return gFilterLevel
}
// Print 日志打印
func Print(tag string, level FilterLevel, format string, a ...interface{}) {
if gIsLoad == false || gIsPause || gFilterLevel == LevelOff || level < gFilterLevel {
return
}
prefix := fmt.Sprintf("%c/%s", gLevelCh[level], tag)
newFormat := prefix + ": " + format
s := fmt.Sprintf(newFormat, a...)
gInfoLogger.Println(s)
gInfoLoggerStd.Println(s)
gLogFileSize += len(s)
if gLogFileSize > gLogFileMaxSize {
_ = createLogFile()
}
}
// PipBoyPrintHex 打印16进制字节流
// tag是标记,在字节流打印之前会打印此标记
func PrintHex(tag string, level FilterLevel, bytes []uint8) {
if gIsLoad == false || gIsPause || gFilterLevel == LevelOff || level < gFilterLevel {
return
}
s := "\n**** : "
for i := 0; i < 16; i++ {
s += fmt.Sprintf("%02x ", i)
}
s += "\n---- : "
for i := 0; i < 16; i++ {
s += fmt.Sprintf("-- ")
}
for i := 0; i < len(bytes); i++ {
if i%16 == 0 {
s += fmt.Sprintf("\n%04x : ", i)
}
s += fmt.Sprintf("%02x ", bytes[i])
}
prefix := fmt.Sprintf("%c/%s", gLevelCh[level], tag)
newFormat := prefix + ": " + "%s"
s1 := fmt.Sprintf(newFormat, s)
gInfoLogger.Println(s1)
gInfoLoggerStd.Println(s1)
gLogFileSize += len(s1)
if gLogFileSize > gLogFileMaxSize {
_ = createLogFile()
}
}
// Pause 暂停日志打印
func Pause() {
gIsPause = true
}
// Resume 恢复日志打印
func Resume() {
gIsPause = false
}
// IsPause 是否暂停打印
func IsPause() bool {
return gIsPause
}
// Debug 打印debug信息
func Debug(tag string, format string, a ...interface{}) {
Print(tag, LevelDebug, format, a...)
}
// Info 打印info信息
func Info(tag string, format string, a ...interface{}) {
Print(tag, LevelInfo, format, a...)
}
// Warn 打印warn信息
func Warn(tag string, format string, a ...interface{}) {
Print(tag, LevelWarn, format, a...)
}
// Error 打印error信息
func Error(tag string, format string, a ...interface{}) {
Print(tag, LevelError, format, a...)
}
示例
package main
import "gitee.com/jdhxyy/lagan"
const Tag = "testlog"
func main () {
// 日志模块载入.全局载入一次,参数是分割文件大小,默认是10M
_ = lagan.Load(0)
// 默认输出级别是info,本行不会打印
lagan.Debug(Tag, "debug test print")
lagan.Info(Tag, "info test print")
lagan.Warn(Tag, "warn test print")
lagan.Error(Tag, "error test print")
}
输出:
2021/02/09 19:12:23 I/testlog: info test print
2021/02/09 19:12:23 W/testlog: warn test print
2021/02/09 19:12:23 E/testlog: error test print
在本地会新建log文件夹,并新建日志文件。
二进制流打印
package main
import "gitee.com/jdhxyy/lagan"
const Tag = "testlog"
func main () {
_ = lagan.Load(0)
arr := make([]uint8, 100)
for i := 0; i < 100; i++ {
arr[i] = uint8(i)
}
lagan.Info(Tag, "print hex")
lagan.PrintHex(Tag, lagan.LevelInfo, arr)
}
输出:
2021/02/09 19:43:51 I/testlog: print hex
2021/02/09 19:43:51 I/testlog:
**** : 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
---- : -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
0000 : 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
0010 : 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
0020 : 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
0030 : 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
0040 : 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
0050 : 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
0060 : 60 61 62 63
终端交互
*******************************************
lagan help shell
current level:I,is pause:false
help:print help
filter_error:filter error level
filter_warn:filter warn level
filter_info:filter info level
filter_debug:filter debug level
filter_off:filter off level
pause:pause log
resume:resume log
*******************************************
可以在终端敲对应的命令控制日志功能。