diff --git a/logp/core.go b/logp/core.go index 04884b8..eb518a9 100644 --- a/logp/core.go +++ b/logp/core.go @@ -151,6 +151,48 @@ func ConfigureWithOutputs(defaultLoggerCfg Config, outputs ...zapcore.Core) erro return nil } +// ConfigureWithCore configures the global logger to use the passed in +// core. It is assumed that an output has already been defined with +// the core and a new one should not be created. The loggerCfg is +// only used to set selectors and level. This is useful if a part of +// your code uses logp but the log output is already handled. Normal +// use cases should use Configure or ConfigureWithOutput. +func ConfigureWithCore(loggerCfg Config, core zapcore.Core) error { + var ( + sink zapcore.Core + level zap.AtomicLevel + ) + + level = zap.NewAtomicLevelAt(loggerCfg.Level.ZapLevel()) + sink = wrappedCore(core) + + // Enabled selectors when debug is enabled. + selectors := make(map[string]struct{}, len(loggerCfg.Selectors)) + if loggerCfg.Level.Enabled(DebugLevel) && len(loggerCfg.Selectors) > 0 { + for _, sel := range loggerCfg.Selectors { + selectors[strings.TrimSpace(sel)] = struct{}{} + } + + // Default to all enabled if no selectors are specified. + if len(selectors) == 0 { + selectors["*"] = struct{}{} + } + + sink = selectiveWrapper(sink, selectors) + } + + root := zap.New(sink, makeOptions(loggerCfg)...) + storeLogger(&coreLogger{ + selectors: selectors, + rootLogger: root, + globalLogger: root.WithOptions(zap.AddCallerSkip(1)), + logger: newLogger(root, ""), + level: level, + observedLogs: nil, + }) + return nil +} + // ConfigureWithTypedOutput configures the global logger to use typed outputs. // // If a log entry matches the defined key/value, this entry is logged using the diff --git a/logp/core_test.go b/logp/core_test.go index f355519..aa48784 100644 --- a/logp/core_test.go +++ b/logp/core_test.go @@ -19,6 +19,7 @@ package logp import ( "bufio" + "bytes" "encoding/json" "errors" "io" @@ -699,6 +700,42 @@ func TestCloserLoggerCoreWith(t *testing.T) { } } +func TestConfigureWithCore(t *testing.T) { + testMsg := "The quick brown fox jumped over the lazy dog." + var b bytes.Buffer + core := zapcore.NewCore( + zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), + zapcore.AddSync(&b), + zapcore.InfoLevel) + err := ConfigureWithCore(Config{}, core) + if err != nil { + t.Fatalf("Unexpected err: %s", err) + } + Info(testMsg) + var r map[string]interface{} + + err = json.Unmarshal(b.Bytes(), &r) + if err != nil { + t.Fatalf("unable to json unmarshal '%s': %s", b.String(), err) + } + + val, prs := r["msg"] + if !prs { + t.Fatalf("expected 'msg' field not present in '%s'", b.String()) + } + if val != testMsg { + t.Fatalf("expected msg of '%s', got '%s'", testMsg, val) + } + + val, prs = r["level"] + if !prs { + t.Fatalf("expected 'level' field not present in '%s'", b.String()) + } + if val != "info" { + t.Fatalf("expected log.level of 'info', got '%s'", val) + } +} + func strField(key, val string) zapcore.Field { return zapcore.Field{Type: zapcore.StringType, Key: key, String: val} }