forked from TrueCloudLab/rclone
vendor: update all dependencies to latest versions
This commit is contained in:
parent
8e83fb6fb9
commit
7d3a17725d
4878 changed files with 1974229 additions and 201215 deletions
460
vendor/github.com/pengsrc/go-shared/log/event.go
generated
vendored
Normal file
460
vendor/github.com/pengsrc/go-shared/log/event.go
generated
vendored
Normal file
|
@ -0,0 +1,460 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pengsrc/go-shared/buffer"
|
||||
"github.com/pengsrc/go-shared/convert"
|
||||
)
|
||||
|
||||
// A EventCallerPool is a type-safe wrapper around a sync.BytesBufferPool.
|
||||
type EventCallerPool struct {
|
||||
p *sync.Pool
|
||||
}
|
||||
|
||||
// NewEventCallerPool constructs a new BytesBufferPool.
|
||||
func NewEventCallerPool() EventCallerPool {
|
||||
return EventCallerPool{
|
||||
p: &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &EventCaller{}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Get retrieves a EventCaller from the pool, creating one if necessary.
|
||||
func (p EventCallerPool) Get() *EventCaller {
|
||||
e := p.p.Get().(*EventCaller)
|
||||
|
||||
e.pool = p
|
||||
|
||||
e.Defined = false
|
||||
e.PC = 0
|
||||
e.File = ""
|
||||
e.Line = 0
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
func (p EventCallerPool) put(caller *EventCaller) {
|
||||
p.p.Put(caller)
|
||||
}
|
||||
|
||||
// EventCaller represents the caller of a logging function.
|
||||
type EventCaller struct {
|
||||
pool EventCallerPool
|
||||
|
||||
Defined bool
|
||||
PC uintptr
|
||||
File string
|
||||
Line int
|
||||
}
|
||||
|
||||
// Free returns the EventCaller to its EventCallerPool.
|
||||
// Callers must not retain references to the EventCaller after calling Free.
|
||||
func (ec *EventCaller) Free() {
|
||||
ec.pool.put(ec)
|
||||
}
|
||||
|
||||
// String returns the full path and line number of the caller.
|
||||
func (ec EventCaller) String() string {
|
||||
return ec.FullPath()
|
||||
}
|
||||
|
||||
// FullPath returns a /full/path/to/package/file:line description of the
|
||||
// caller.
|
||||
func (ec EventCaller) FullPath() string {
|
||||
if !ec.Defined {
|
||||
return "undefined"
|
||||
}
|
||||
buf := buffer.GlobalBytesPool().Get()
|
||||
defer buf.Free()
|
||||
buf.AppendString(ec.File)
|
||||
buf.AppendByte(':')
|
||||
buf.AppendInt(int64(ec.Line))
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// TrimmedPath returns a package/file:line description of the caller,
|
||||
// preserving only the leaf directory name and file name.
|
||||
func (ec EventCaller) TrimmedPath() string {
|
||||
if !ec.Defined {
|
||||
return "undefined"
|
||||
}
|
||||
// nb. To make sure we trim the path correctly on Windows too, we
|
||||
// counter-intuitively need to use '/' and *not* os.PathSeparator here,
|
||||
// because the path given originates from Go stdlib, specifically
|
||||
// runtime.Caller() which (as of Mar/17) returns forward slashes even on
|
||||
// Windows.
|
||||
//
|
||||
// See https://github.com/golang/go/issues/3335
|
||||
// and https://github.com/golang/go/issues/18151
|
||||
//
|
||||
// for discussion on the issue on Go side.
|
||||
//
|
||||
// Find the last separator.
|
||||
//
|
||||
idx := strings.LastIndexByte(ec.File, '/')
|
||||
if idx == -1 {
|
||||
return ec.FullPath()
|
||||
}
|
||||
// Find the penultimate separator.
|
||||
idx = strings.LastIndexByte(ec.File[:idx], '/')
|
||||
if idx == -1 {
|
||||
return ec.FullPath()
|
||||
}
|
||||
buf := buffer.GlobalBytesPool().Get()
|
||||
defer buf.Free()
|
||||
// Keep everything after the penultimate separator.
|
||||
buf.AppendString(ec.File[idx+1:])
|
||||
buf.AppendByte(':')
|
||||
buf.AppendInt(int64(ec.Line))
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// A EventPool is a type-safe wrapper around a sync.BytesBufferPool.
|
||||
type EventPool struct {
|
||||
p *sync.Pool
|
||||
}
|
||||
|
||||
// NewEventPool constructs a new BytesBufferPool.
|
||||
func NewEventPool() EventPool {
|
||||
return EventPool{
|
||||
p: &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &Event{}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Get retrieves a Event from the pool, creating one if necessary.
|
||||
func (p EventPool) Get() *Event {
|
||||
e := p.p.Get().(*Event)
|
||||
|
||||
e.buffer = buffer.GlobalBytesPool().Get()
|
||||
e.pool = p
|
||||
|
||||
e.level = MuteLevel
|
||||
e.lw = nil
|
||||
|
||||
e.ctx = nil
|
||||
e.ctxKeys = nil
|
||||
|
||||
e.isEnabled = false
|
||||
e.isCallerEnabled = false
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
func (p EventPool) put(event *Event) {
|
||||
event.buffer.Free()
|
||||
|
||||
event.ctx = nil
|
||||
event.ctxKeys = nil
|
||||
|
||||
p.p.Put(event)
|
||||
}
|
||||
|
||||
// Event represents a log event. It is instanced by one of the with method of
|
||||
// logger and finalized by the log method such as Debug().
|
||||
type Event struct {
|
||||
buffer *buffer.BytesBuffer
|
||||
pool EventPool
|
||||
|
||||
level Level
|
||||
lw LevelWriter
|
||||
|
||||
ctx context.Context
|
||||
ctxKeys *[]interface{}
|
||||
ctxKeysMap *map[interface{}]string
|
||||
|
||||
isEnabled bool
|
||||
isCallerEnabled bool
|
||||
}
|
||||
|
||||
// Free returns the Event to its EventPool.
|
||||
// Callers must not retain references to the Event after calling Free.
|
||||
func (e *Event) Free() {
|
||||
e.pool.put(e)
|
||||
}
|
||||
|
||||
// Message writes the *Event to level writer.
|
||||
//
|
||||
// NOTICE: Once this method is called, the *Event should be disposed.
|
||||
// Calling twice can have unexpected result.
|
||||
func (e *Event) Message(message string) {
|
||||
if !e.isEnabled {
|
||||
return
|
||||
}
|
||||
e.write(message)
|
||||
}
|
||||
|
||||
// Messagef writes the *Event to level writer.
|
||||
//
|
||||
// NOTICE: Once this method is called, the *Event should be disposed.
|
||||
// Calling twice can have unexpected result.
|
||||
func (e *Event) Messagef(format string, v ...interface{}) {
|
||||
if !e.isEnabled {
|
||||
return
|
||||
}
|
||||
e.write(format, v...)
|
||||
}
|
||||
|
||||
// Byte appends string key and byte value to event.
|
||||
func (e *Event) Byte(key string, value byte) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendByte(value) })
|
||||
}
|
||||
|
||||
// Bytes appends string key and bytes value to event.
|
||||
func (e *Event) Bytes(key string, value []byte) *Event {
|
||||
return e.appendField(key, func() {
|
||||
if needsQuote(string(value)) {
|
||||
e.buffer.AppendString(strconv.Quote(string(value)))
|
||||
} else {
|
||||
e.buffer.AppendBytes(value)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// String appends string key and string value to event.
|
||||
func (e *Event) String(key string, value string) *Event {
|
||||
return e.appendField(key, func() {
|
||||
if needsQuote(string(value)) {
|
||||
e.buffer.AppendString(strconv.Quote(value))
|
||||
} else {
|
||||
e.buffer.AppendString(value)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Int appends string key and int value to event.
|
||||
func (e *Event) Int(key string, value int) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendInt(int64(value)) })
|
||||
}
|
||||
|
||||
// Int32 appends string key and int32 value to event.
|
||||
func (e *Event) Int32(key string, value int32) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendInt(int64(value)) })
|
||||
}
|
||||
|
||||
// Int64 appends string key and int64 value to event.
|
||||
func (e *Event) Int64(key string, value int64) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendInt(value) })
|
||||
}
|
||||
|
||||
// Uint appends string key and uint value to event.
|
||||
func (e *Event) Uint(key string, value uint) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendUint(uint64(value)) })
|
||||
}
|
||||
|
||||
// Uint32 appends string key and uint32 value to event.
|
||||
func (e *Event) Uint32(key string, value uint32) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendUint(uint64(value)) })
|
||||
}
|
||||
|
||||
// Uint64 appends string key and uint64 value to event.
|
||||
func (e *Event) Uint64(key string, value uint64) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendUint(value) })
|
||||
}
|
||||
|
||||
// Float32 appends string key and float32 value to event.
|
||||
func (e *Event) Float32(key string, value float32) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendFloat(float64(value), 32) })
|
||||
}
|
||||
|
||||
// Float64 appends string key and float value to event.
|
||||
func (e *Event) Float64(key string, value float64) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendFloat(value, 64) })
|
||||
}
|
||||
|
||||
// Bool appends string key and bool value to event.
|
||||
func (e *Event) Bool(key string, value bool) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendBool(value) })
|
||||
}
|
||||
|
||||
// Time appends string key and time value to event.
|
||||
func (e *Event) Time(key string, value time.Time, format string) *Event {
|
||||
buf := buffer.GlobalBytesPool().Get()
|
||||
defer buf.Free()
|
||||
|
||||
buf.AppendTime(value, format)
|
||||
return e.Bytes(key, buf.Bytes())
|
||||
}
|
||||
|
||||
// Error appends string key and error value to event.
|
||||
func (e *Event) Error(key string, err error) *Event {
|
||||
return e.String(key, err.Error())
|
||||
}
|
||||
|
||||
// Interface appends string key and interface value to event.
|
||||
func (e *Event) Interface(key string, value interface{}) *Event {
|
||||
switch v := value.(type) {
|
||||
case byte:
|
||||
e.Byte(key, v)
|
||||
case []byte:
|
||||
e.Bytes(key, v)
|
||||
case string:
|
||||
e.String(key, v)
|
||||
case int:
|
||||
e.Int(key, v)
|
||||
case int32:
|
||||
e.Int32(key, v)
|
||||
case int64:
|
||||
e.Int64(key, v)
|
||||
case uint:
|
||||
e.Uint(key, v)
|
||||
case uint32:
|
||||
e.Uint32(key, v)
|
||||
case uint64:
|
||||
e.Uint64(key, v)
|
||||
case float32:
|
||||
e.Float32(key, v)
|
||||
case float64:
|
||||
e.Float64(key, v)
|
||||
case bool:
|
||||
e.Bool(key, v)
|
||||
case time.Time:
|
||||
e.Time(key, v, convert.ISO8601Milli)
|
||||
case error:
|
||||
e.Error(key, v)
|
||||
case nil:
|
||||
e.String(key, "nil")
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown field type: %v", value))
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Event) appendField(key string, appendFunc func()) *Event {
|
||||
if !e.isEnabled {
|
||||
return e
|
||||
}
|
||||
|
||||
// Ignore field with empty key.
|
||||
if len(key) <= 0 {
|
||||
return e
|
||||
}
|
||||
|
||||
// Append space if event field not empty.
|
||||
if e.buffer.Len() != 0 {
|
||||
e.buffer.AppendByte(' ')
|
||||
}
|
||||
|
||||
e.buffer.AppendString(key)
|
||||
e.buffer.AppendString("=")
|
||||
|
||||
appendFunc()
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Event) write(format string, v ...interface{}) {
|
||||
defer e.Free()
|
||||
|
||||
if !e.isEnabled {
|
||||
return
|
||||
}
|
||||
|
||||
// Append interested contexts.
|
||||
if e.ctx != nil && e.ctxKeys != nil && e.ctxKeysMap != nil {
|
||||
for _, key := range *e.ctxKeys {
|
||||
if value := e.ctx.Value(key); value != nil {
|
||||
e.Interface((*e.ctxKeysMap)[key], e.ctx.Value(key))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Append caller.
|
||||
if e.isCallerEnabled {
|
||||
ec := newEventCaller(runtime.Caller(callerSkipOffset))
|
||||
e.String("source", ec.TrimmedPath())
|
||||
}
|
||||
|
||||
// Compose and store current log.
|
||||
buf := buffer.GlobalBytesPool().Get()
|
||||
defer buf.Free()
|
||||
|
||||
// Format print message.
|
||||
if format != "" {
|
||||
if len(v) == 0 {
|
||||
fmt.Fprint(buf, format)
|
||||
} else {
|
||||
fmt.Fprintf(buf, format, v...)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprint(buf, v...)
|
||||
}
|
||||
|
||||
// Append filed.
|
||||
buf.AppendByte(' ')
|
||||
buf.AppendBytes(e.buffer.Bytes())
|
||||
|
||||
// Finally write.
|
||||
if _, err := e.lw.WriteLevel(e.level, buf.Bytes()); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "log: could not write event: %v", err)
|
||||
}
|
||||
|
||||
switch e.level {
|
||||
case PanicLevel:
|
||||
panic(buf.String())
|
||||
case FatalLevel:
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func newEventCaller(pc uintptr, file string, line int, ok bool) (ec *EventCaller) {
|
||||
ec = eventCallerPool.Get()
|
||||
|
||||
if ok {
|
||||
ec.PC = pc
|
||||
ec.File = file
|
||||
ec.Line = line
|
||||
ec.Defined = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func newEvent(
|
||||
ctx context.Context,
|
||||
ctxKeys *[]interface{}, ctxKeysMap *map[interface{}]string,
|
||||
level Level, lw LevelWriter,
|
||||
isEnabled bool, isCallerEnabled bool,
|
||||
) (e *Event) {
|
||||
e = eventPool.Get()
|
||||
|
||||
e.level = level
|
||||
e.lw = lw
|
||||
|
||||
e.ctx = ctx
|
||||
e.ctxKeys = ctxKeys
|
||||
e.ctxKeysMap = ctxKeysMap
|
||||
|
||||
e.isEnabled = isEnabled
|
||||
e.isCallerEnabled = isCallerEnabled
|
||||
return
|
||||
}
|
||||
|
||||
func needsQuote(s string) bool {
|
||||
for i := range s {
|
||||
if s[i] < 0x20 || s[i] > 0x7e || s[i] == ' ' || s[i] == '\\' || s[i] == '"' {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const callerSkipOffset = 2
|
||||
|
||||
// eventCallerPool is a pool of newEvent callers.
|
||||
var eventCallerPool = NewEventCallerPool()
|
||||
|
||||
// eventPool is a pool of events.
|
||||
var eventPool = NewEventPool()
|
Loading…
Add table
Add a link
Reference in a new issue