diff --git a/context.go b/context.go index c79f69e..bbdcbbc 100644 --- a/context.go +++ b/context.go @@ -73,12 +73,12 @@ func (c *Context) GetAllLoggerTags() []string { names[k] = v } } - labels := make([]string, 0, len(names)) + tags := make([]string, 0, len(names)) for name := range names { - labels = append(labels, name) + tags = append(tags, name) } - sort.Strings(labels) - return labels + sort.Strings(tags) + return tags } func (c *Context) getLoggerModule(name string, tags []string) *module { @@ -214,15 +214,22 @@ func (c *Context) ApplyConfig(config Config, labels ...Labels) { // ResetLoggerLevels iterates through the known logging modules and sets the // levels of all to UNSPECIFIED, except for which is set to WARNING. -func (c *Context) ResetLoggerLevels() { +// If labels are provided, then only loggers that have the provided labels +// will be reset. +func (c *Context) ResetLoggerLevels(labels ...Labels) { + label := mergeLabels(labels) + c.modulesMutex.Lock() defer c.modulesMutex.Unlock() + // Setting the root module to UNSPECIFIED will set it to WARNING. for _, module := range c.modules { + if !module.hasLabelIntersection(label) { + continue + } + module.setLevel(UNSPECIFIED) } - // We can safely just wipe everything here. - c.modulesTagConfig = make(map[string]Level) } func (c *Context) write(entry Entry) { diff --git a/context_test.go b/context_test.go index 01588bc..2f55900 100644 --- a/context_test.go +++ b/context_test.go @@ -261,7 +261,7 @@ func (*ContextSuite) TestApplyConfigTags(c *gc.C) { }) } -func (*ContextSuite) TestApplyConfigLabelsAppliesToNewLoggers(c *gc.C) { +func (*ContextSuite) TestApplyConfigTagsAppliesToNewLoggers(c *gc.C) { context := loggo.NewContext(loggo.WARNING) context.ApplyConfig(loggo.Config{"#one": loggo.TRACE}) @@ -289,7 +289,7 @@ func (*ContextSuite) TestApplyConfigLabelsAppliesToNewLoggers(c *gc.C) { }) } -func (*ContextSuite) TestApplyConfigLabelsAppliesToNewLoggersWithMultipleTags(c *gc.C) { +func (*ContextSuite) TestApplyConfigTagsAppliesToNewLoggersWithMultipleTags(c *gc.C) { context := loggo.NewContext(loggo.WARNING) // Invert the order here, to ensure that the config order doesn't matter, @@ -312,7 +312,7 @@ func (*ContextSuite) TestApplyConfigLabelsAppliesToNewLoggersWithMultipleTags(c }) } -func (*ContextSuite) TestApplyConfigLabelsResetLoggerLevels(c *gc.C) { +func (*ContextSuite) TestApplyConfigTagsResetLoggerLevels(c *gc.C) { context := loggo.NewContext(loggo.WARNING) context.ApplyConfig(loggo.Config{"#one": loggo.TRACE}) @@ -339,7 +339,93 @@ func (*ContextSuite) TestApplyConfigLabelsResetLoggerLevels(c *gc.C) { }) } -func (*ContextSuite) TestApplyConfigTagsAddative(c *gc.C) { +func (*ContextSuite) TestApplyConfigTagsResetLoggerLevelsUsingLabels(c *gc.C) { + context := loggo.NewContext(loggo.WARNING) + + context.ApplyConfig(loggo.Config{"#one": loggo.TRACE}) + context.ApplyConfig(loggo.Config{"#two": loggo.DEBUG}) + + context.GetLogger("a", "one").ChildWithLabels("b", loggo.Labels{"x": "y"}) + context.GetLogger("c.d", "one") + context.GetLogger("e", "two") + + // If a label is available on a logger, then resetting the levels should + // not remove the label. + + context.ResetLoggerLevels() + + c.Assert(context.Config(), gc.DeepEquals, + loggo.Config{ + "": loggo.WARNING, + }) + c.Assert(context.CompleteConfig(), gc.DeepEquals, + loggo.Config{ + "": loggo.WARNING, + "a": loggo.UNSPECIFIED, + "a.b": loggo.UNSPECIFIED, + "c": loggo.UNSPECIFIED, + "c.d": loggo.UNSPECIFIED, + "e": loggo.UNSPECIFIED, + }) +} + +func (*ContextSuite) TestApplyConfigTagsResetLoggerLevelsUsingLabelsRemoval(c *gc.C) { + context := loggo.NewContext(loggo.WARNING) + + context.ApplyConfig(loggo.Config{"#one": loggo.TRACE}) + context.ApplyConfig(loggo.Config{"#two": loggo.DEBUG}) + + context.GetLogger("a", "one").ChildWithLabels("b", loggo.Labels{"x": "y"}).ChildWithTags("g", "one") + context.GetLogger("c.d", "one") + context.GetLogger("e", "two") + context.GetLogger("f") + + // Ensure that the logger that matches exactly the label is removed, + // including it's children. So we observe hierarchy in the removal. + + c.Assert(context.Config(), gc.DeepEquals, + loggo.Config{ + "": loggo.WARNING, + "a": loggo.TRACE, + "a.b.g": loggo.TRACE, + "c.d": loggo.TRACE, + "e": loggo.DEBUG, + }) + c.Assert(context.CompleteConfig(), gc.DeepEquals, + loggo.Config{ + "": loggo.WARNING, + "a": loggo.TRACE, + "a.b": loggo.UNSPECIFIED, + "a.b.g": loggo.TRACE, + "c": loggo.UNSPECIFIED, + "c.d": loggo.TRACE, + "e": loggo.DEBUG, + "f": loggo.UNSPECIFIED, + }) + + context.ResetLoggerLevels(loggo.Labels{"x": "y"}) + + c.Assert(context.Config(), gc.DeepEquals, + loggo.Config{ + "": loggo.WARNING, + "a": loggo.TRACE, + "c.d": loggo.TRACE, + "e": loggo.DEBUG, + }) + c.Assert(context.CompleteConfig(), gc.DeepEquals, + loggo.Config{ + "": loggo.WARNING, + "a": loggo.TRACE, + "a.b": loggo.UNSPECIFIED, + "a.b.g": loggo.UNSPECIFIED, + "c": loggo.UNSPECIFIED, + "c.d": loggo.TRACE, + "e": loggo.DEBUG, + "f": loggo.UNSPECIFIED, + }) +} + +func (*ContextSuite) TestApplyConfigTagsAdditive(c *gc.C) { context := loggo.NewContext(loggo.WARNING) context.ApplyConfig(loggo.Config{"#one": loggo.TRACE}) context.ApplyConfig(loggo.Config{"#two": loggo.DEBUG}) diff --git a/logger.go b/logger.go index 40905a6..3ef67db 100644 --- a/logger.go +++ b/logger.go @@ -112,6 +112,11 @@ func (logger Logger) Tags() []string { return logger.getModule().tags } +// Labels returns the configured labels of the logger's module. +func (logger Logger) Labels() Labels { + return logger.getModule().labels +} + // EffectiveLogLevel returns the effective min log level of // the receiver - that is, messages with a lesser severity // level will be discarded. @@ -140,15 +145,6 @@ func (logger Logger) Logf(level Level, message string, args ...interface{}) { logger.LogCallf(2, level, message, args...) } -// LogWithlabelsf logs a printf-formatted message at the given level with extra -// labels. The given labels will be added to the log entry. -// A message will be discarded if level is less than the the effective log level -// of the logger. Note that the writers may also filter out messages that are -// less than their registered minimum severity level. -func (logger Logger) LogWithLabelsf(level Level, message string, extraLabels map[string]string, args ...interface{}) { - logger.logCallf(2, level, message, extraLabels, args...) -} - // LogCallf logs a printf-formatted message at the given level. // The location of the call is indicated by the calldepth argument. // A calldepth of 1 means the function that called this function. @@ -157,12 +153,12 @@ func (logger Logger) LogWithLabelsf(level Level, message string, extraLabels map // Note that the writers may also filter out messages that // are less than their registered minimum severity level. func (logger Logger) LogCallf(calldepth int, level Level, message string, args ...interface{}) { - logger.logCallf(calldepth+1, level, message, nil, args...) + logger.logCallf(calldepth+1, level, message, args...) } // logCallf is a private method for logging a printf-formatted message at the // given level. Used by LogWithLabelsf and LogCallf. -func (logger Logger) logCallf(calldepth int, level Level, message string, extraLabels map[string]string, args ...interface{}) { +func (logger Logger) logCallf(calldepth int, level Level, message string, args ...interface{}) { module := logger.getModule() if !module.willWrite(level) { return @@ -205,10 +201,6 @@ func (logger Logger) logCallf(calldepth int, level Level, message string, extraL for k, v := range logger.impl.labels { entry.Labels[k] = v } - // Add extra labels if there's any given. - for k, v := range extraLabels { - entry.Labels[k] = v - } module.write(entry) } diff --git a/logger_test.go b/logger_test.go index 6bba10d..2361a49 100644 --- a/logger_test.go +++ b/logger_test.go @@ -36,6 +36,29 @@ func (s *LoggerSuite) TestInheritedLabels(c *gc.C) { logger := context.GetLogger("testing") + nestedLoggerWithLabels := logger. + ChildWithLabels("nested", loggo.Labels{"foo": "bar"}) + deepNestedLoggerWithLabels := nestedLoggerWithLabels. + ChildWithLabels("nested", loggo.Labels{"foo": "baz"}). + ChildWithLabels("deepnested", loggo.Labels{"fred": "tim"}) + + loggerWithTagsAndLabels := logger. + ChildWithLabels("nested-labels", loggo.Labels{"hello": "world"}). + ChildWithTags("nested-tag", "tag1", "tag2") + + c.Check(nestedLoggerWithLabels.Labels(), gc.DeepEquals, loggo.Labels{"foo": "bar"}) + c.Check(deepNestedLoggerWithLabels.Labels(), gc.DeepEquals, loggo.Labels{"foo": "baz", "fred": "tim"}) + c.Check(loggerWithTagsAndLabels.Labels(), gc.DeepEquals, loggo.Labels{"hello": "world"}) +} + +func (s *LoggerSuite) TestInheritedLabelsInLogs(c *gc.C) { + writer := &loggo.TestWriter{} + context := loggo.NewContext(loggo.INFO) + err := context.AddWriter("test", writer) + c.Assert(err, gc.IsNil) + + logger := context.GetLogger("testing") + nestedLoggerWithLabels := logger. ChildWithLabels("nested", loggo.Labels{"foo": "bar"}) deepNestedLoggerWithLabels := nestedLoggerWithLabels.