log/删除所有的依赖库;
This commit is contained in:
@@ -1,8 +1,3 @@
|
|||||||
module git.blauwelle.com/go/crate/log
|
module git.blauwelle.com/go/crate/log
|
||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require (
|
|
||||||
git.blauwelle.com/go/crate/runtimehelper v0.1.0
|
|
||||||
git.blauwelle.com/go/crate/synchelper v0.1.0
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
git.blauwelle.com/go/crate/runtimehelper v0.1.0 h1:qNhtnt9YmHXNHKsGRbwD3AZ3pezpOwrbmX1o9Bz532I=
|
|
||||||
git.blauwelle.com/go/crate/runtimehelper v0.1.0/go.mod h1:yVMA0GkO9AS7iuPmalHKeWyv9en0JWj25rY1vpTuHhk=
|
|
||||||
git.blauwelle.com/go/crate/synchelper v0.1.0 h1:4yEXpshkklaws/57P94xN5bA3NmyyKGcZqYmzd6QIK4=
|
|
||||||
git.blauwelle.com/go/crate/synchelper v0.1.0/go.mod h1:2JkfH+7sF0Q0wiIaDOqG42ZLO5JxpcMfSoyy7db4Y2g=
|
|
||||||
@@ -4,8 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.blauwelle.com/go/crate/runtimehelper"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Entry 包含日志所需的全部中间信息并负责输出日志
|
// Entry 包含日志所需的全部中间信息并负责输出日志
|
||||||
@@ -198,10 +196,10 @@ func (entry Entry) log(ctx context.Context, level Level, message string) {
|
|||||||
readonlyEntry.Time = time.Now()
|
readonlyEntry.Time = time.Now()
|
||||||
}
|
}
|
||||||
if newEntry.GetReportCaller() {
|
if newEntry.GetReportCaller() {
|
||||||
readonlyEntry.Caller = runtimehelper.Caller(newEntry.callerSkip)
|
readonlyEntry.Caller = getCaller(newEntry.callerSkip)
|
||||||
}
|
}
|
||||||
if newEntry.GetReportStack() {
|
if newEntry.GetReportStack() {
|
||||||
readonlyEntry.Stack = runtimehelper.Stack(newEntry.callerSkip, 32)
|
readonlyEntry.Stack = getStack(newEntry.callerSkip, 32)
|
||||||
}
|
}
|
||||||
for _, processor := range newEntry.logger.getLevelProcessors(level) {
|
for _, processor := range newEntry.logger.getLevelProcessors(level) {
|
||||||
processor.Process(readonlyEntry)
|
processor.Process(readonlyEntry)
|
||||||
@@ -211,8 +209,8 @@ func (entry Entry) log(ctx context.Context, level Level, message string) {
|
|||||||
// ReadonlyEntry 是日志系统收集到1条日志记录
|
// ReadonlyEntry 是日志系统收集到1条日志记录
|
||||||
type ReadonlyEntry struct {
|
type ReadonlyEntry struct {
|
||||||
Context context.Context `json:"-"`
|
Context context.Context `json:"-"`
|
||||||
Caller runtimehelper.Frame
|
Caller Frame
|
||||||
Stack []runtimehelper.Frame
|
Stack []Frame
|
||||||
Time time.Time
|
Time time.Time
|
||||||
Message string
|
Message string
|
||||||
Fields []KV
|
Fields []KV
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.blauwelle.com/go/crate/synchelper"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Option 配置日志处理对象
|
// Option 配置日志处理对象
|
||||||
@@ -14,9 +12,9 @@ type Option interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WithBufferPool 配置缓冲池
|
// WithBufferPool 配置缓冲池
|
||||||
func WithBufferPool(pool synchelper.BytesBufferPool) Option {
|
func WithBufferPool(pool BytesBufferPool) Option {
|
||||||
return optionFunc(func(cfg *config) {
|
return optionFunc(func(cfg *config) {
|
||||||
cfg.pool = pool
|
cfg.bytesBufferPool = pool
|
||||||
cfg.hasPool = true
|
cfg.hasPool = true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -62,10 +60,10 @@ func newConfig(opts ...Option) *config {
|
|||||||
opt.apply(cfg)
|
opt.apply(cfg)
|
||||||
}
|
}
|
||||||
if !cfg.hasPool {
|
if !cfg.hasPool {
|
||||||
cfg.pool = synchelper.NewBytesBufferPool(512, 4096)
|
cfg.bytesBufferPool = newBytesBufferPool(512, 4096)
|
||||||
}
|
}
|
||||||
if cfg.output == nil {
|
if cfg.output == nil {
|
||||||
cfg.output = synchelper.NewSyncWriter(os.Stderr)
|
cfg.output = newSyncWriter(os.Stderr)
|
||||||
}
|
}
|
||||||
if cfg.timestampFormat == "" {
|
if cfg.timestampFormat == "" {
|
||||||
cfg.timestampFormat = time.RFC3339Nano
|
cfg.timestampFormat = time.RFC3339Nano
|
||||||
@@ -83,7 +81,7 @@ func defaultConfig() *config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
pool synchelper.BytesBufferPool
|
bytesBufferPool BytesBufferPool
|
||||||
output io.Writer
|
output io.Writer
|
||||||
timestampFormat string
|
timestampFormat string
|
||||||
hasPool bool
|
hasPool bool
|
||||||
|
|||||||
38
log/logsdk/logjson/pool.go
Normal file
38
log/logsdk/logjson/pool.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package logjson
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BytesBufferPool interface {
|
||||||
|
Get() *bytes.Buffer
|
||||||
|
Put(buffer *bytes.Buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBytesBufferPool(initialSize, maximumSize int) *bytesBufferPool {
|
||||||
|
return &bytesBufferPool{
|
||||||
|
pool: sync.Pool{
|
||||||
|
New: func() any {
|
||||||
|
return bytes.NewBuffer(make([]byte, 0, initialSize))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
maximumSize: maximumSize,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type bytesBufferPool struct {
|
||||||
|
pool sync.Pool
|
||||||
|
maximumSize int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pool *bytesBufferPool) Get() *bytes.Buffer {
|
||||||
|
return pool.pool.Get().(*bytes.Buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pool *bytesBufferPool) Put(buf *bytes.Buffer) {
|
||||||
|
if buf.Cap() > pool.maximumSize {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pool.pool.Put(buf)
|
||||||
|
}
|
||||||
@@ -7,8 +7,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.blauwelle.com/go/crate/log/logsdk"
|
"git.blauwelle.com/go/crate/log/logsdk"
|
||||||
"git.blauwelle.com/go/crate/runtimehelper"
|
|
||||||
"git.blauwelle.com/go/crate/synchelper"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ logsdk.EntryProcessor = &Processor{}
|
var _ logsdk.EntryProcessor = &Processor{}
|
||||||
@@ -18,7 +16,7 @@ var _ logsdk.EntryProcessor = &Processor{}
|
|||||||
func New(opts ...Option) *Processor {
|
func New(opts ...Option) *Processor {
|
||||||
cfg := newConfig(opts...)
|
cfg := newConfig(opts...)
|
||||||
return &Processor{
|
return &Processor{
|
||||||
bufferPool: cfg.pool,
|
bytesBufferPool: cfg.bytesBufferPool,
|
||||||
output: cfg.output,
|
output: cfg.output,
|
||||||
timeFormat: cfg.timestampFormat,
|
timeFormat: cfg.timestampFormat,
|
||||||
disableTime: cfg.disableTime,
|
disableTime: cfg.disableTime,
|
||||||
@@ -29,7 +27,7 @@ func New(opts ...Option) *Processor {
|
|||||||
|
|
||||||
// Processor 日志处理对象, 把日志处理成 JSON.
|
// Processor 日志处理对象, 把日志处理成 JSON.
|
||||||
type Processor struct {
|
type Processor struct {
|
||||||
bufferPool synchelper.BytesBufferPool
|
bytesBufferPool BytesBufferPool
|
||||||
output io.Writer
|
output io.Writer
|
||||||
timeFormat string
|
timeFormat string
|
||||||
disableTime bool
|
disableTime bool
|
||||||
@@ -51,16 +49,16 @@ func (processor *Processor) Process(entry logsdk.ReadonlyEntry) {
|
|||||||
if entry.Caller.IsValid() {
|
if entry.Caller.IsValid() {
|
||||||
// 1次分配
|
// 1次分配
|
||||||
// 直接取 &entry.Caller 会增加堆内存分配
|
// 直接取 &entry.Caller 会增加堆内存分配
|
||||||
m.Caller = &runtimehelper.Frame{
|
m.Caller = &logsdk.Frame{
|
||||||
Function: entry.Caller.Function,
|
Function: entry.Caller.Function,
|
||||||
File: entry.Caller.File,
|
File: entry.Caller.File,
|
||||||
Line: entry.Caller.Line,
|
Line: entry.Caller.Line,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := processor.bufferPool.Get()
|
buf := processor.bytesBufferPool.Get()
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
defer processor.bufferPool.Put(buf)
|
defer processor.bytesBufferPool.Put(buf)
|
||||||
|
|
||||||
encoder := json.NewEncoder(buf)
|
encoder := json.NewEncoder(buf)
|
||||||
if processor.prettyPrint {
|
if processor.prettyPrint {
|
||||||
@@ -82,8 +80,8 @@ func (processor *Processor) Process(entry logsdk.ReadonlyEntry) {
|
|||||||
type Entry struct {
|
type Entry struct {
|
||||||
Message string `json:"msg"`
|
Message string `json:"msg"`
|
||||||
Time string `json:"time,omitempty"`
|
Time string `json:"time,omitempty"`
|
||||||
Caller *runtimehelper.Frame `json:"caller,omitempty"`
|
Caller *logsdk.Frame `json:"caller,omitempty"`
|
||||||
Stack []runtimehelper.Frame `json:"stack,omitempty"`
|
Stack []logsdk.Frame `json:"stack,omitempty"`
|
||||||
Fields []logsdk.KV `json:"fields,omitempty"`
|
Fields []logsdk.KV `json:"fields,omitempty"`
|
||||||
Level logsdk.Level `json:"level"`
|
Level logsdk.Level `json:"level"`
|
||||||
}
|
}
|
||||||
|
|||||||
24
log/logsdk/logjson/writer.go
Normal file
24
log/logsdk/logjson/writer.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package logjson
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newSyncWriter(writer io.Writer) io.Writer {
|
||||||
|
return &syncWriter{
|
||||||
|
writer: writer,
|
||||||
|
lock: sync.Mutex{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type syncWriter struct {
|
||||||
|
writer io.Writer
|
||||||
|
lock sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *syncWriter) Write(p []byte) (n int, err error) {
|
||||||
|
w.lock.Lock()
|
||||||
|
defer w.lock.Unlock()
|
||||||
|
return w.writer.Write(p)
|
||||||
|
}
|
||||||
52
log/logsdk/runtime.go
Normal file
52
log/logsdk/runtime.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package logsdk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Frame 调用相关信息
|
||||||
|
type Frame struct {
|
||||||
|
Function string `json:"func"`
|
||||||
|
File string `json:"file"`
|
||||||
|
Line int `json:"line"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValid 表示是否有效
|
||||||
|
func (frame Frame) IsValid() bool {
|
||||||
|
return frame.Line > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCaller(skip int) Frame {
|
||||||
|
pc := make([]uintptr, 1)
|
||||||
|
n := runtime.Callers(skip+2, pc)
|
||||||
|
frame, _ := runtime.CallersFrames(pc[:n]).Next()
|
||||||
|
if frame.PC == 0 {
|
||||||
|
return Frame{}
|
||||||
|
}
|
||||||
|
return Frame{
|
||||||
|
Function: frame.Function,
|
||||||
|
File: frame.File,
|
||||||
|
Line: frame.Line,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getStack(skip, maximumFrames int) []Frame {
|
||||||
|
pc := make([]uintptr, maximumFrames)
|
||||||
|
n := runtime.Callers(skip+2, pc)
|
||||||
|
stack := make([]Frame, 0, n)
|
||||||
|
frames := runtime.CallersFrames(pc[:n])
|
||||||
|
for {
|
||||||
|
frame, more := frames.Next()
|
||||||
|
if frame.PC != 0 {
|
||||||
|
stack = append(stack, Frame{
|
||||||
|
Function: frame.Function,
|
||||||
|
File: frame.File,
|
||||||
|
Line: frame.Line,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if !more {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stack
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user