Skip to content

Commit 4babd25

Browse files
authored
configure logging from a zap.Core (#218)
* configure logging from a zap.Core
1 parent 5104a90 commit 4babd25

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

logp/core.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,48 @@ func ConfigureWithOutputs(defaultLoggerCfg Config, outputs ...zapcore.Core) erro
151151
return nil
152152
}
153153

154+
// ConfigureWithCore configures the global logger to use the passed in
155+
// core. It is assumed that an output has already been defined with
156+
// the core and a new one should not be created. The loggerCfg is
157+
// only used to set selectors and level. This is useful if a part of
158+
// your code uses logp but the log output is already handled. Normal
159+
// use cases should use Configure or ConfigureWithOutput.
160+
func ConfigureWithCore(loggerCfg Config, core zapcore.Core) error {
161+
var (
162+
sink zapcore.Core
163+
level zap.AtomicLevel
164+
)
165+
166+
level = zap.NewAtomicLevelAt(loggerCfg.Level.ZapLevel())
167+
sink = wrappedCore(core)
168+
169+
// Enabled selectors when debug is enabled.
170+
selectors := make(map[string]struct{}, len(loggerCfg.Selectors))
171+
if loggerCfg.Level.Enabled(DebugLevel) && len(loggerCfg.Selectors) > 0 {
172+
for _, sel := range loggerCfg.Selectors {
173+
selectors[strings.TrimSpace(sel)] = struct{}{}
174+
}
175+
176+
// Default to all enabled if no selectors are specified.
177+
if len(selectors) == 0 {
178+
selectors["*"] = struct{}{}
179+
}
180+
181+
sink = selectiveWrapper(sink, selectors)
182+
}
183+
184+
root := zap.New(sink, makeOptions(loggerCfg)...)
185+
storeLogger(&coreLogger{
186+
selectors: selectors,
187+
rootLogger: root,
188+
globalLogger: root.WithOptions(zap.AddCallerSkip(1)),
189+
logger: newLogger(root, ""),
190+
level: level,
191+
observedLogs: nil,
192+
})
193+
return nil
194+
}
195+
154196
// ConfigureWithTypedOutput configures the global logger to use typed outputs.
155197
//
156198
// If a log entry matches the defined key/value, this entry is logged using the

logp/core_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package logp
1919

2020
import (
2121
"bufio"
22+
"bytes"
2223
"encoding/json"
2324
"errors"
2425
"io"
@@ -699,6 +700,42 @@ func TestCloserLoggerCoreWith(t *testing.T) {
699700
}
700701
}
701702

703+
func TestConfigureWithCore(t *testing.T) {
704+
testMsg := "The quick brown fox jumped over the lazy dog."
705+
var b bytes.Buffer
706+
core := zapcore.NewCore(
707+
zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()),
708+
zapcore.AddSync(&b),
709+
zapcore.InfoLevel)
710+
err := ConfigureWithCore(Config{}, core)
711+
if err != nil {
712+
t.Fatalf("Unexpected err: %s", err)
713+
}
714+
Info(testMsg)
715+
var r map[string]interface{}
716+
717+
err = json.Unmarshal(b.Bytes(), &r)
718+
if err != nil {
719+
t.Fatalf("unable to json unmarshal '%s': %s", b.String(), err)
720+
}
721+
722+
val, prs := r["msg"]
723+
if !prs {
724+
t.Fatalf("expected 'msg' field not present in '%s'", b.String())
725+
}
726+
if val != testMsg {
727+
t.Fatalf("expected msg of '%s', got '%s'", testMsg, val)
728+
}
729+
730+
val, prs = r["level"]
731+
if !prs {
732+
t.Fatalf("expected 'level' field not present in '%s'", b.String())
733+
}
734+
if val != "info" {
735+
t.Fatalf("expected log.level of 'info', got '%s'", val)
736+
}
737+
}
738+
702739
func strField(key, val string) zapcore.Field {
703740
return zapcore.Field{Type: zapcore.StringType, Key: key, String: val}
704741
}

0 commit comments

Comments
 (0)