20 Star 164 Fork 26

qiqi / orange

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
log.go 7.46 KB
一键复制 编辑 原始数据 按行查看 历史
qiqi 提交于 2020-11-27 12:53 . 日志写入问题修复
package logger
import (
"bytes"
"fmt"
"strings"
"sync"
"time"
)
type LogLevel int
const LevelColorSetClear = "\033[0m"
const maxLogSyncLine = 1000
const (
_oddNumberErrMsg = "Ignored key without a value."
_nonStringKeyErrMsg = "Ignored key-value pairs with non-string keys."
)
const (
// different colors log text:
_ = iota + 30 // black
ColorRed // red
ColorGreen // green
ColorYellow // yellow
ColorBlue // blue
ColorMagenta // magenta
_ // cyan
ColorWhite // white
)
// LogType
const (
TextType = "text"
JsonType = "json"
)
// MessageLevel
const (
NOTSET = iota
DEBUG = LogLevel(10 * iota) // DEBUG = 10
INFO = LogLevel(10 * iota) // INFO = 20
NOTICE = LogLevel(10 * iota) // INFO = 30
WARNING = LogLevel(10 * iota) // WARNING = 40
ERROR = LogLevel(10 * iota) // ERROR = 50
CRITICAL = LogLevel(10 * iota) // CRITICAL = 60
)
// LevelColorFlag, MessageLevel color flag.
var LevelColorFlag = []string{
DEBUG: colorSet(ColorWhite, 0),
INFO: colorSet(ColorGreen, 0),
NOTICE: colorSet(ColorBlue, 0),
WARNING: colorSet(ColorYellow, 0),
ERROR: colorSet(ColorRed, 1),
CRITICAL: colorSet(ColorMagenta, 1),
}
var LevelString = map[LogLevel]string{
DEBUG: "DEBUG",
INFO: "INFO",
NOTICE: "NOTICE",
WARNING: "WARNING",
ERROR: "ERROR",
CRITICAL: "CRITICAL",
}
func colorSet(l LogLevel, way int) string {
return fmt.Sprintf("\033[%d;%dm", way, LogLevel(l))
}
// Logger main logger struct
type Logger struct {
Level LogLevel
Record *Record
Format *Message
StreamHandler *StreamMessageHandler
SyncInterval int
}
// loggerFileMap
type loggerFileMap struct {
LoggerMap map[string]*Logger
}
// loggerFileChan
type loggerFileChan struct {
LogMsg []byte
LogFile string
}
const MaxWarnLogFileCount = 20
var loggerFiles loggerFileMap
var logMsgChan chan loggerFileChan
var mutex sync.Mutex
func (log *loggerFileMap) newLogFile(fileName string, loggerHandler *Logger) *Logger {
mutex.Lock()
defer mutex.Unlock()
if loggerHandler == nil {
if handler, ok := log.LoggerMap[fileName]; ok {
return handler
}
return nil
}
if log.LoggerMap == nil || len(log.LoggerMap) == 0 {
log.LoggerMap = make(map[string]*Logger, 0)
}
log.LoggerMap[fileName] = loggerHandler
if len(log.LoggerMap) >= MaxWarnLogFileCount {
loggerHandler.Warning("The log files is too more, it will reduced system performance")
}
return loggerHandler
}
func (log *loggerFileMap) closeAll() {
mutex.Lock()
defer mutex.Unlock()
for k, item := range log.LoggerMap {
item.StreamHandler.LogFileHandler.Close()
delete(log.LoggerMap, k)
}
}
// New get logger struct
func New(level LogLevel, logType string, logDir string, syncInterval int) *Logger {
if logMsgChan == nil {
logMsgChan = make(chan loggerFileChan, 1000)
}
logDir = strings.TrimRight(logDir, "/")
stream := &StreamMessageHandler{
LogDir: logDir,
LogFileName: "default",
LogExt: ".log",
LogBuffer: bytes.NewBuffer([]byte{}),
}
if logDir != "" {
stream.LogFilePath = fmt.Sprintf("%s/%s%s", stream.LogDir, stream.LogFileName, stream.LogExt)
}
stream.LogFileHandler = openLogFile(stream.LogFilePath)
if syncInterval > 0 {
go func() {
for {
time.Sleep(time.Duration(syncInterval) * time.Millisecond)
stream.SyncLog()
}
}()
}
loggerHandler := &Logger{
Level: level,
Format: &Message{
FormatType: logType,
},
StreamHandler: stream,
SyncInterval: syncInterval,
}
loggerFiles.newLogFile(stream.LogFileName, loggerHandler)
go func() {
for {
select {
case logData := <-logMsgChan:
// logFileItem defalut.log or other logfile
logFileItem := loggerFiles.newLogFile(logData.LogFile, nil)
if logFileItem == nil {
logFileItem = loggerFiles.newLogFile(stream.LogFileName, nil)
}
if logFileItem == nil {
return
}
logFileItem.StreamHandler.Write(logData.LogMsg)
if loggerHandler.SyncInterval == 0 {
go logFileItem.StreamHandler.SyncLog()
}
}
}
}()
return loggerHandler
}
// log, sed message to handler.
func (l *Logger) log(level LogLevel, format string, a ...interface{}) {
if level < l.Level {
return
}
l.Record = GetMessageRecord(level, format, a...)
l.Record.LogFile = l.StreamHandler.LogFileName
if l.StreamHandler != nil {
logMsgChan <- loggerFileChan{
LogFile: l.StreamHandler.LogFileName,
LogMsg: l.Format.GetMessage(l.Record),
}
}
}
// logw, sed message to handler with kv format.
func (l *Logger) logw(level LogLevel, message string, kv ...interface{}) {
if level < l.Level {
return
}
l.Record = GetMessageKVRecord(level, message, kv...)
l.Record.LogFile = l.StreamHandler.LogFileName
if l.StreamHandler != nil {
logMsgChan <- loggerFileChan{
LogFile: l.StreamHandler.LogFileName,
LogMsg: l.Format.GetMessage(l.Record),
}
}
}
// LogDeferClose close handler
func (l *Logger) LogDeferClose() {
l.StreamHandler.SyncLog()
loggerFiles.closeAll()
}
// LogFile, change default log file name.
func (l *Logger) LogFile(fileName string) *Logger {
logFileItem := loggerFiles.newLogFile(fileName, nil)
if logFileItem != nil {
return logFileItem
}
stream := &StreamMessageHandler{
LogFileName: fileName,
LogExt: l.StreamHandler.LogExt,
LogDir: l.StreamHandler.LogDir,
LogBuffer: bytes.NewBuffer([]byte{}),
}
if l.StreamHandler.LogDir != "" {
stream.LogFilePath = fmt.Sprintf("%s/%s%s", stream.LogDir, stream.LogFileName, stream.LogExt)
}
stream.LogFileHandler = openLogFile(stream.LogFilePath)
newHandler := &Logger{
Level: l.Level,
Format: l.Format,
StreamHandler: stream,
SyncInterval: l.SyncInterval,
}
if l.SyncInterval > 0 {
go func() {
for {
stream.SyncLog()
time.Sleep(time.Duration(l.SyncInterval) * time.Millisecond)
}
}()
}
loggerFiles.newLogFile(fileName, newHandler)
return newHandler
}
// Debug, record DEBUG message.
func (l *Logger) Debug(format string, a ...interface{}) {
l.log(DEBUG, format, a...)
}
// Info, record INFO message.
func (l *Logger) Info(format string, a ...interface{}) {
l.log(INFO, format, a...)
}
// Notice, record INFO message.
func (l *Logger) Notice(format string, a ...interface{}) {
l.log(NOTICE, format, a...)
}
// Warning, record WARNING message.
func (l *Logger) Warning(format string, a ...interface{}) {
l.log(WARNING, format, a...)
}
// Error, record ERROR message.
func (l *Logger) Error(format string, a ...interface{}) {
l.log(ERROR, format, a...)
}
// Critical, record CRITICAL message.
func (l *Logger) Critical(format string, a ...interface{}) {
l.log(CRITICAL, format, a...)
}
// Debugw, record DEBUG message with kv format
func (l *Logger) Debugw(message string, kv ...interface{}) {
l.logw(DEBUG, message, kv...)
}
// Infow, record INFO message with kv format.
func (l *Logger) Infow(message string, kv ...interface{}) {
l.logw(INFO, message, kv...)
}
// Noticew, record INFO message with kv format.
func (l *Logger) Noticew(message string, kv ...interface{}) {
l.logw(NOTICE, message, kv...)
}
// Warningw, record WARNING message with kv format.
func (l *Logger) Warningw(message string, kv ...interface{}) {
l.logw(WARNING, message, kv...)
}
// Errorw, record ERROR message with kv format.
func (l *Logger) Errorw(message string, kv ...interface{}) {
l.logw(ERROR, message, kv...)
}
// Criticalw, record CRITICAL message with kv format.
func (l *Logger) Criticalw(message string, kv ...interface{}) {
l.logw(CRITICAL, message, kv...)
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/zhucheer/orange.git
git@gitee.com:zhucheer/orange.git
zhucheer
orange
orange
v0.3.2

搜索帮助

344bd9b3 5694891 D2dac590 5694891