Codebase list golang-github-go-kit-kit / d3553b5
Add SwapLogger. Chris Hines 8 years ago
2 changed file(s) with 59 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
22 // The fundamental interface is Logger. Loggers create log events from
33 // key/value data.
44 package log
5
6 import "sync/atomic"
57
68 // Logger is the fundamental interface for all log operations. Implementations
79 // must be safe for concurrent use by multiple goroutines. Log creates a log
5759 func (f LoggerFunc) Log(keyvals ...interface{}) error {
5860 return f(keyvals...)
5961 }
62
63 // SwapLogger wraps another logger that may be safely replaced while other
64 // goroutines use the SwapLogger concurrently.
65 type SwapLogger struct {
66 logger atomic.Value
67 }
68
69 type loggerStruct struct {
70 Logger
71 }
72
73 // NewSwapLogger returns a pointer to a new SwapLogger that wraps logger.
74 func NewSwapLogger(logger Logger) *SwapLogger {
75 l := &SwapLogger{}
76 l.Swap(logger)
77 return l
78 }
79
80 // Log implements the Logger interface by calling Log on the currently wrapped
81 // logger.
82 func (l *SwapLogger) Log(keyvals ...interface{}) error {
83 return l.logger.Load().(loggerStruct).Log(keyvals...)
84 }
85
86 // Swap replaces the currently wrapped logger with logger. Swap may be called
87 // concurrently with calls to Log from other goroutines.
88 func (l *SwapLogger) Swap(logger Logger) {
89 l.logger.Store(loggerStruct{logger})
90 }
110110 logger.Log("k", "v")
111111 }
112112 }
113
114 func TestSwapLogger(t *testing.T) {
115 buf := &bytes.Buffer{}
116 json := log.NewJSONLogger(buf)
117 logger := log.NewSwapLogger(json)
118
119 if err := logger.Log("k", "v"); err != nil {
120 t.Error(err)
121 }
122 if got, want := buf.String(), `{"k":"v"}`+"\n"; got != want {
123 t.Errorf("got %v, want %v", got, want)
124 }
125
126 buf.Reset()
127 prefix := log.NewPrefixLogger(buf)
128 logger.Swap(prefix)
129
130 if err := logger.Log("k", "v"); err != nil {
131 t.Error(err)
132 }
133 if got, want := buf.String(), "k=v\n"; got != want {
134 t.Errorf("got %v, want %v", got, want)
135 }
136 }
137
138 func TestSwapLoggerConcurrency(t *testing.T) {
139 testConcurrency(t, log.NewSwapLogger(discard))
140 }