Merge remote-tracking branch 'github/yun'
This commit is contained in:
+13
-6
@@ -14,13 +14,20 @@ func main() {
|
|||||||
loggerx.SetToConsole(),
|
loggerx.SetToConsole(),
|
||||||
// loggerx.SetTimeZone(time.UTC),
|
// loggerx.SetTimeZone(time.UTC),
|
||||||
loggerx.SetTimeZone(time.FixedZone("CST", 8*3600)),
|
loggerx.SetTimeZone(time.FixedZone("CST", 8*3600)),
|
||||||
|
loggerx.SetEscapeHTML(false),
|
||||||
)
|
)
|
||||||
|
log.WriteAsync().Info(ctx, "{ \"a\": 1, \"b\": 2 }")
|
||||||
log.Info(ctx, "哈哈哈2")
|
log.Info(ctx, "哈哈哈2")
|
||||||
log.Info(ctx, "哈哈哈2")
|
log.Info(ctx, "哈哈哈2")
|
||||||
log.Info(ctx, "哈哈哈2")
|
log.Info(ctx, "哈哈哈2\r")
|
||||||
log.Info(ctx, "哈哈哈2")
|
log.Info(ctx, "哈哈哈2\r\n")
|
||||||
log.Info(ctx, "哈哈哈2")
|
log.Info(ctx, "哈哈哈2<b>")
|
||||||
log.Info(ctx, "哈哈哈2")
|
log.Info(ctx, "哈哈哈2<")
|
||||||
log.Info(ctx, "哈哈哈2")
|
log.Info(ctx, "哈哈哈2>")
|
||||||
log.Info(ctx, "哈哈哈2")
|
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
log.WriteAsync().Infof(ctx, "异步 %d", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Second)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package loggerx
|
package loggerx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -32,7 +33,7 @@ func (l *Logger) logger(ctx context.Context, event string, v ...any) {
|
|||||||
|
|
||||||
// writeStr := "[" + event + "]" + nowTime + " " + file + ":" + fmt.Sprintf("%d", line) + " " + funcName + " gid:" + getGID() + " " + traceId + " @data@: " + string(by) + "\n\n"
|
// writeStr := "[" + event + "]" + nowTime + " " + file + ":" + fmt.Sprintf("%d", line) + " " + funcName + " gid:" + getGID() + " " + traceId + " @data@: " + string(by) + "\n\n"
|
||||||
|
|
||||||
for idx,val := range v {
|
for idx, val := range v {
|
||||||
if _, ok := val.(error); ok {
|
if _, ok := val.(error); ok {
|
||||||
v[idx] = fmt.Sprintf("%+v", val)
|
v[idx] = fmt.Sprintf("%+v", val)
|
||||||
}
|
}
|
||||||
@@ -51,7 +52,18 @@ func (l *Logger) logger(ctx context.Context, event string, v ...any) {
|
|||||||
// fd.Stack = string(debug.Stack())
|
// fd.Stack = string(debug.Stack())
|
||||||
}
|
}
|
||||||
|
|
||||||
fdb, _ := json.Marshal(fd)
|
var fdb []byte
|
||||||
|
if l.option.escapeHTML {
|
||||||
|
fdb, _ = json.Marshal(fd)
|
||||||
|
} else {
|
||||||
|
// 非转义
|
||||||
|
var buf bytes.Buffer
|
||||||
|
encoder := json.NewEncoder(&buf)
|
||||||
|
encoder.SetEscapeHTML(false)
|
||||||
|
encoder.Encode(fd)
|
||||||
|
fdb = buf.Bytes()
|
||||||
|
}
|
||||||
|
fdb = bytes.TrimRight(fdb, "\n")
|
||||||
|
|
||||||
ff := []byte("\n[" + event + "]")
|
ff := []byte("\n[" + event + "]")
|
||||||
fdb = append(ff, fdb...)
|
fdb = append(ff, fdb...)
|
||||||
|
|||||||
+2
-1
@@ -2,7 +2,8 @@ package loggerx
|
|||||||
|
|
||||||
import "context"
|
import "context"
|
||||||
|
|
||||||
type Loggerx interface {
|
// 简单使用的日志接口
|
||||||
|
type LoggerInterface interface {
|
||||||
Info(ctx context.Context, args ...any)
|
Info(ctx context.Context, args ...any)
|
||||||
Infof(ctx context.Context, format string, args ...any)
|
Infof(ctx context.Context, format string, args ...any)
|
||||||
Error(ctx context.Context, args ...any)
|
Error(ctx context.Context, args ...any)
|
||||||
|
|||||||
+14
@@ -26,6 +26,7 @@ type Logger struct {
|
|||||||
mu *sync.Mutex
|
mu *sync.Mutex
|
||||||
option loggerOption
|
option loggerOption
|
||||||
channel string
|
channel string
|
||||||
|
writeType writeType // 是否异步落盘,这里作用范围是本条,优先判断这里
|
||||||
}
|
}
|
||||||
|
|
||||||
type filePath struct {
|
type filePath struct {
|
||||||
@@ -49,6 +50,7 @@ func NewLogger(ctx context.Context, opts ...Option) *Logger {
|
|||||||
filePath: &sync.Map{},
|
filePath: &sync.Map{},
|
||||||
mu: &sync.Mutex{},
|
mu: &sync.Mutex{},
|
||||||
option: opt,
|
option: opt,
|
||||||
|
writeType: writeTypeDefault,
|
||||||
}
|
}
|
||||||
|
|
||||||
log.SetOutput(l)
|
log.SetOutput(l)
|
||||||
@@ -87,6 +89,18 @@ func (l *Logger) Channel(ch string) (r *Logger) {
|
|||||||
return &rr
|
return &rr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *Logger) WriteAsync() (r *Logger) {
|
||||||
|
rr := *l
|
||||||
|
rr.writeType = writeTypeAsync
|
||||||
|
return &rr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) WriteSync() (r *Logger) {
|
||||||
|
rr := *l
|
||||||
|
rr.writeType = writeTypeSync
|
||||||
|
return &rr
|
||||||
|
}
|
||||||
|
|
||||||
// 获取TraceField的字段
|
// 获取TraceField的字段
|
||||||
func (l *Logger) GetTraceField() string {
|
func (l *Logger) GetTraceField() string {
|
||||||
return l.option.traceField
|
return l.option.traceField
|
||||||
|
|||||||
+26
@@ -13,6 +13,7 @@ type loggerOption struct {
|
|||||||
isGinLog bool
|
isGinLog bool
|
||||||
isGid bool
|
isGid bool
|
||||||
isPrintFile bool
|
isPrintFile bool
|
||||||
|
writeType writeType // 是否异步罗盘
|
||||||
traceField string // trace字段
|
traceField string // trace字段
|
||||||
errorToInfo bool // 错误日志是否写入info日志
|
errorToInfo bool // 错误日志是否写入info日志
|
||||||
days int // 日志保存天数
|
days int // 日志保存天数
|
||||||
@@ -20,19 +21,31 @@ type loggerOption struct {
|
|||||||
fileSplit FileSplit // 文件切割规则
|
fileSplit FileSplit // 文件切割规则
|
||||||
sizeSplit int // 根据文件大小切割
|
sizeSplit int // 根据文件大小切割
|
||||||
timeZone *time.Location // 时区
|
timeZone *time.Location // 时区
|
||||||
|
escapeHTML bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type writeType uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
// 0.默认(同步) 1.指定同步 2.指定异步
|
||||||
|
writeTypeDefault writeType = iota
|
||||||
|
writeTypeSync
|
||||||
|
writeTypeAsync
|
||||||
|
)
|
||||||
|
|
||||||
func defaultOptions() loggerOption {
|
func defaultOptions() loggerOption {
|
||||||
return loggerOption{
|
return loggerOption{
|
||||||
isGinLog: true,
|
isGinLog: true,
|
||||||
isGid: true,
|
isGid: true,
|
||||||
isPrintFile: true,
|
isPrintFile: true,
|
||||||
|
writeType: writeTypeDefault, // 默认同步
|
||||||
format: "json",
|
format: "json",
|
||||||
dir: "./log",
|
dir: "./log",
|
||||||
traceField: "trace_id",
|
traceField: "trace_id",
|
||||||
days: 7,
|
days: 7,
|
||||||
fileSplit: FileSplitTimeE,
|
fileSplit: FileSplitTimeE,
|
||||||
timeZone: time.Local,
|
timeZone: time.Local,
|
||||||
|
escapeHTML: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,6 +58,13 @@ func SetTraceField(traceField string) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 是否异步写入
|
||||||
|
func SetWriteAsync() Option {
|
||||||
|
return func(o *loggerOption) {
|
||||||
|
o.writeType = writeTypeAsync
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 打印到控制台
|
// 打印到控制台
|
||||||
func SetToConsole() Option {
|
func SetToConsole() Option {
|
||||||
return func(o *loggerOption) {
|
return func(o *loggerOption) {
|
||||||
@@ -158,3 +178,9 @@ func SetSizeSplit(m int) Option {
|
|||||||
o.sizeSplit = m
|
o.sizeSplit = m
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetEscapeHTML(b bool) Option {
|
||||||
|
return func(o *loggerOption) {
|
||||||
|
o.escapeHTML = b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
# 简介
|
# 简介
|
||||||
|
|
||||||
这个是基于原生log实现的日志存储。
|
这个是基于原生log实现的日志存储。
|
||||||
@@ -11,15 +10,17 @@ log.Println("ddddd")
|
|||||||
|
|
||||||
# 用法
|
# 用法
|
||||||
|
|
||||||
|
|
||||||
# 开发计划
|
# 开发计划
|
||||||
|
|
||||||
1. 自动清除过期的日志文件
|
1. [ ] 自动清除过期的日志文件
|
||||||
2. 支持日志文件压缩
|
2. [ ] 支持日志文件压缩
|
||||||
3. 支持日志文件切割
|
3. [X] 支持日志文件切割
|
||||||
4. 支持日志文件归档
|
4. [ ] 支持日志文件归档
|
||||||
5. 支持多种文件分割类型
|
5. [ ] 支持多种文件分割类型
|
||||||
1. 按照时间分割
|
1. [ ] 按照时间分割
|
||||||
2. 按照文件大小分割
|
2. [ ] 按照文件大小分割
|
||||||
3. 按照日志行数分割
|
3. [ ] 按照日志行数分割
|
||||||
6. 支持debug 模式
|
6. [ ] 支持debug 模式
|
||||||
|
7. [X] 添加异步落库,支持全局和单次
|
||||||
|
1. [ ] 优化:异步应该跟实例不应该全局,多实例异步落库将会有BUG
|
||||||
|
8. [X] 添加支持是否转义html
|
||||||
|
|||||||
+40
@@ -2,9 +2,20 @@ package loggerx
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 写入,需要判断同步还是异步
|
||||||
func (l *Logger) write(event string, b []byte) (n int, err error) {
|
func (l *Logger) write(event string, b []byte) (n int, err error) {
|
||||||
|
if l.toAsync(event, b) {
|
||||||
|
// fmt.Println("异步写入")
|
||||||
|
return len(b), nil
|
||||||
|
}
|
||||||
|
return l.store(event, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实际的存储
|
||||||
|
func (l *Logger) store(event string, b []byte) (n int, err error) {
|
||||||
|
|
||||||
if l.option.isPrintFile {
|
if l.option.isPrintFile {
|
||||||
f, err := l.getFile(event, false)
|
f, err := l.getFile(event, false)
|
||||||
@@ -30,3 +41,32 @@ func (l *Logger) write(event string, b []byte) (n int, err error) {
|
|||||||
}
|
}
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var chanStore = make(chan cacheData, 1000)
|
||||||
|
var chanOnce = sync.Once{}
|
||||||
|
|
||||||
|
type cacheData struct {
|
||||||
|
logger *Logger
|
||||||
|
Event string
|
||||||
|
Data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) toAsync(event string, b []byte) bool {
|
||||||
|
chanOnce.Do(func() {
|
||||||
|
go func() {
|
||||||
|
for val := range chanStore {
|
||||||
|
val.logger.store(val.Event, val.Data)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
})
|
||||||
|
|
||||||
|
if l.writeType == writeTypeSync || // 指定同步模式
|
||||||
|
(l.writeType == writeTypeDefault && l.option.writeType != writeTypeAsync) { // 默认同步模式
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 为了避免丢失,还是要阻塞等待
|
||||||
|
chanStore <- cacheData{l, event, b}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user