forked from godror/godror
-
Notifications
You must be signed in to change notification settings - Fork 0
/
log.go
133 lines (118 loc) · 3.26 KB
/
log.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright 2017, 2021 The Godror Authors
//
//
// SPDX-License-Identifier: UPL-1.0 OR Apache-2.0
package godror
import (
"context"
"io"
"sync"
"github.com/go-logfmt/logfmt"
"github.com/go-logr/logr"
)
var globalLogger = &swapLogger{}
func SetLogger(logger logr.Logger) {
globalLogger.Swap(logger)
}
func SetLog(f func(...interface{}) error) {
globalLogger.Swap(logr.New(LogFunc(f)))
}
// NewLogfmtLogger returns a Logger, and that logs using logfmt, to the given io.Writer.
func NewLogfmtLogger(w io.Writer) logr.Logger {
enc := logfmt.NewEncoder(w)
return logr.New(LogFunc(func(keyvals ...interface{}) error {
firstErr := enc.EncodeKeyvals(keyvals...)
if err := enc.EndRecord(); err != nil && firstErr == nil {
return err
}
return firstErr
}))
}
type Logger interface {
Log(keyvals ...interface{}) error
}
type LogFunc func(keyvals ...interface{}) error
func (f LogFunc) Log(keyvals ...interface{}) error { return f(keyvals...) }
func (f LogFunc) Init(_ logr.RuntimeInfo) {}
func (f LogFunc) Enabled(_ int) bool { return f != nil }
func (f LogFunc) Info(level int, msg string, keyvals ...interface{}) {
f(append(append(make([]interface{}, 0, 4+len(keyvals)), "lvl", level, "msg", msg), keyvals...)...)
}
func (f LogFunc) Error(err error, msg string, keyvals ...interface{}) {
f(append(append(make([]interface{}, 0, 4+len(keyvals)), "msg", msg, "error", err), keyvals...)...)
}
func (f LogFunc) WithValues(plusKeyVals ...interface{}) logr.LogSink {
return LogFunc(func(keyvals ...interface{}) error {
return f(append(plusKeyVals, keyvals...)...)
})
}
func (f LogFunc) WithName(name string) logr.LogSink {
return f.WithValues("name", name)
}
type swapLogger struct {
mu sync.RWMutex
logger logr.Logger
isSet bool
}
func (sw *swapLogger) IsSet() bool {
if sw == nil {
return false
}
sw.mu.RLock()
isset := sw.isSet
sw.mu.RUnlock()
return isset
}
func (sw *swapLogger) Swap(logger logr.Logger) {
sw.mu.Lock()
sw.logger = logger
sw.isSet = true
sw.mu.Unlock()
}
func (sw *swapLogger) Info(msg string, keyvals ...interface{}) {
sw.logger.Info(msg, keyvals...)
}
func (sw *swapLogger) Error(err error, msg string, keyvals ...interface{}) {
sw.logger.Error(err, msg, keyvals...)
}
func (sw *swapLogger) Log(keyvals ...interface{}) error {
sw.mu.RLock()
logger := sw.logger
sw.mu.RUnlock()
if !logger.Enabled() {
return nil
}
if len(keyvals) >= 2 {
if msgKey, ok := keyvals[0].(string); ok && msgKey == "msg" {
if msg, ok := keyvals[1].(string); ok {
logger.Info(msg, keyvals[2:]...)
return nil
}
}
}
logger.Info("", keyvals...)
return nil
}
type logCtxKey struct{}
func getLogger() Logger {
if globalLogger.IsSet() {
return globalLogger
}
return nil
}
func ctxGetLog(ctx context.Context) Logger {
if ctx != nil {
if lgr, ok := ctx.Value(logCtxKey{}).(Logger); ok {
return lgr
}
}
return getLogger()
}
// ContextWithLogger returns a context with the given logger.
func ContextWithLogger(ctx context.Context, logger Logger) context.Context {
return context.WithValue(ctx, logCtxKey{}, logger)
}
// ContextWithLog returns a context with the given log function.
func ContextWithLog(ctx context.Context, logF func(...interface{}) error) context.Context {
return context.WithValue(ctx, logCtxKey{}, LogFunc(logF))
}