Skip to content

Commit 8509e7c

Browse files
committed
core Check() evaluate level for entry's logger name
The existing code uses a level enabler for each logger that assumes logger names never change, which isn't true when creating a named logger with a parent logger. This CR ensures the core's Check() method evaluates the level based on the zapcore.Entry's logger name. FAB-12611 #done Change-Id: I096c90c1f9b4bea897ebfa33be201cd18098c281 Signed-off-by: Will Lahti <wtlahti@us.ibm.com>
1 parent 99eb596 commit 8509e7c

File tree

6 files changed

+50
-44
lines changed

6 files changed

+50
-44
lines changed

common/flogging/core.go

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,24 +38,14 @@ type EncodingSelector interface {
3838
// from the zapcore.ObjectEncoder would need to be implemented to delegate to
3939
// the correct backend.
4040
//
41-
// Finally, fabric logging can go through initialization multiple times. The
42-
// first is via package initialization where hard-coded defaults are used for
43-
// configuration. The second init is typically after any process configuration
44-
// has been processed. This configuration can come from environment variables,
45-
// command line flags, or config documents.
46-
//
47-
// Since logging can be initialized multiple times, we need to be able to
48-
// handle modification of the type of encoders we are using. While, for legacy
49-
// reasons, a console based encoder is the default, a JSON logger is more likely
50-
// to be desired in production.
51-
//
5241
// This implementation works by associating multiple encoders with a core. When
5342
// fields are added to the core, the fields are added to all of the encoder
5443
// implementations. The core also references the logging configuration to
5544
// determine the proper encoding to use, the writer to delegate to, and the
5645
// enabled levels.
5746
type Core struct {
5847
zapcore.LevelEnabler
48+
Levels *ModuleLevels
5949
Encoders map[Encoding]zapcore.Encoder
6050
Selector EncodingSelector
6151
Output zapcore.WriteSyncer
@@ -71,14 +61,15 @@ func (c *Core) With(fields []zapcore.Field) zapcore.Core {
7161

7262
return &Core{
7363
LevelEnabler: c.LevelEnabler,
64+
Levels: c.Levels,
7465
Encoders: clones,
7566
Selector: c.Selector,
7667
Output: c.Output,
7768
}
7869
}
7970

8071
func (c *Core) Check(e zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
81-
if c.Enabled(e.Level) {
72+
if c.Enabled(e.Level) && c.Levels.Level(e.LoggerName).Enabled(e.Level) {
8273
return ce.AddCore(e, c)
8374
}
8475
return ce

common/flogging/core_test.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,26 @@ func TestCoreWith(t *testing.T) {
4646

4747
func TestCoreCheck(t *testing.T) {
4848
var enabledArgs []zapcore.Level
49+
levels := &flogging.ModuleLevels{}
50+
err := levels.ActivateSpec("warning")
51+
assert.NoError(t, err)
4952
core := &flogging.Core{
5053
LevelEnabler: zap.LevelEnablerFunc(func(l zapcore.Level) bool {
5154
enabledArgs = append(enabledArgs, l)
52-
return l != zapcore.WarnLevel
55+
return l >= zapcore.WarnLevel
5356
}),
57+
Levels: levels,
5458
}
5559

56-
// enabled
60+
// not enabled
5761
ce := core.Check(zapcore.Entry{Level: zapcore.DebugLevel}, nil)
58-
assert.NotNil(t, ce)
62+
assert.Nil(t, ce)
5963
ce = core.Check(zapcore.Entry{Level: zapcore.InfoLevel}, nil)
60-
assert.NotNil(t, ce)
64+
assert.Nil(t, ce)
6165

62-
// not enabled
66+
// enabled
6367
ce = core.Check(zapcore.Entry{Level: zapcore.WarnLevel}, nil)
64-
assert.Nil(t, ce)
68+
assert.NotNil(t, ce)
6569

6670
assert.Equal(t, enabledArgs, []zapcore.Level{zapcore.DebugLevel, zapcore.InfoLevel, zapcore.WarnLevel})
6771
}

common/flogging/logging.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,15 @@ func (s *Logging) Encoding() Encoding {
189189
func (s *Logging) ZapLogger(module string) *zap.Logger {
190190
s.mutex.RLock()
191191
module = strings.Replace(module, "/", ".", -1)
192+
levelEnabler := zap.LevelEnablerFunc(func(l zapcore.Level) bool {
193+
// always return true here because the core's Check()
194+
// method computes the level for the logger name based
195+
// on the active logging spec
196+
return true
197+
})
192198
core := &Core{
193-
LevelEnabler: s.ModuleLevels.LevelEnabler(module),
199+
LevelEnabler: levelEnabler,
200+
Levels: s.ModuleLevels,
194201
Encoders: map[Encoding]zapcore.Encoder{
195202
JSON: zapcore.NewJSONEncoder(s.encoderConfig),
196203
CONSOLE: fabenc.NewFormatEncoder(s.multiFormatter),

common/flogging/logging_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ SPDX-License-Identifier: Apache-2.0
77
package flogging_test
88

99
import (
10+
"bytes"
1011
"errors"
1112
"testing"
1213

@@ -63,3 +64,31 @@ func TestZapLoggerNameConversion(t *testing.T) {
6364
logger := logging.Logger("test/module/name")
6465
assert.True(t, logger.IsEnabledFor(zapcore.DebugLevel))
6566
}
67+
68+
func TestNamedLogger(t *testing.T) {
69+
defer flogging.Reset()
70+
buf := &bytes.Buffer{}
71+
flogging.Global.SetWriter(buf)
72+
73+
t.Run("logger and named (child) logger with different levels", func(t *testing.T) {
74+
defer buf.Reset()
75+
logger := flogging.MustGetLogger("eugene")
76+
logger2 := logger.Named("george")
77+
flogging.ActivateSpec("eugene=info:eugene.george=error")
78+
79+
logger.Info("from eugene")
80+
logger2.Info("from george")
81+
assert.Contains(t, buf.String(), "from eugene")
82+
assert.NotContains(t, buf.String(), "from george")
83+
})
84+
85+
t.Run("named logger where parent logger isn't enabled", func(t *testing.T) {
86+
logger := flogging.MustGetLogger("foo")
87+
logger2 := logger.Named("bar")
88+
flogging.ActivateSpec("foo=fatal:foo.bar=error")
89+
logger.Error("from foo")
90+
logger2.Error("from bar")
91+
assert.NotContains(t, buf.String(), "from foo")
92+
assert.Contains(t, buf.String(), "from bar")
93+
})
94+
}

common/flogging/modulelevels.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
"sync"
1414

1515
"github.com/pkg/errors"
16-
"go.uber.org/zap"
1716
"go.uber.org/zap/zapcore"
1817
)
1918

@@ -122,13 +121,6 @@ func (m *ModuleLevels) cachedLevel(loggerName string) (lvl zapcore.Level, ok boo
122121
return level, ok
123122
}
124123

125-
// LevelEnabler adapts ModuleLevels for use with zap as a zapcore.LevelEnabler.
126-
func (m *ModuleLevels) LevelEnabler(module string) zapcore.LevelEnabler {
127-
return zap.LevelEnablerFunc(func(l zapcore.Level) bool {
128-
return m.Level(module).Enabled(l)
129-
})
130-
}
131-
132124
// Spec returns a normalized version of the active logging spec.
133125
func (m *ModuleLevels) Spec() string {
134126
m.mutex.RLock()

common/flogging/modulelevels_test.go

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -130,23 +130,6 @@ func TestModuleLevelsActivateSpecErrors(t *testing.T) {
130130
}
131131
}
132132

133-
func TestModuleLevelsEnabler(t *testing.T) {
134-
ml := &flogging.ModuleLevels{}
135-
err := ml.ActivateSpec("logger=error")
136-
assert.NoError(t, err)
137-
138-
for _, name := range []string{"logger.one.two", "logger.one", "logger"} {
139-
enabler := ml.LevelEnabler(name)
140-
assert.False(t, enabler.Enabled(zapcore.DebugLevel))
141-
assert.False(t, enabler.Enabled(zapcore.InfoLevel))
142-
assert.False(t, enabler.Enabled(zapcore.WarnLevel))
143-
assert.True(t, enabler.Enabled(zapcore.ErrorLevel))
144-
assert.True(t, enabler.Enabled(zapcore.DPanicLevel))
145-
assert.True(t, enabler.Enabled(zapcore.PanicLevel))
146-
assert.True(t, enabler.Enabled(zapcore.FatalLevel))
147-
}
148-
}
149-
150133
func TestModuleLevelSpec(t *testing.T) {
151134
var tests = []struct {
152135
input string

0 commit comments

Comments
 (0)