Skip to content
This repository has been archived by the owner on Feb 9, 2022. It is now read-only.

Commit

Permalink
Refactor API
Browse files Browse the repository at this point in the history
This change makes the exported Logger type a struct that wraps an interface.
This makes it possible to only define cosmetic methods on this struct, instead
of polluting the interface definition.
  • Loading branch information
Dmitriy Kalinin and Pieter Noordhuis committed Mar 7, 2013
1 parent 273887d commit 79a2f31
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 174 deletions.
5 changes: 3 additions & 2 deletions config_test.go
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ func (s *ConfigSuite) TestReInitLevel(c *C) {


for _, level := range levels { for _, level := range levels {
Init(&Config{Level: level}) Init(&Config{Level: level})
logger := NewLogger("reinit").(*BaseLogger)
c.Assert(logger.level, Equals, level) l := NewLogger("reinit")
c.Assert(l.Level(), Equals, level)
} }
} }
194 changes: 117 additions & 77 deletions logger.go
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -6,26 +6,13 @@ import (
"log" "log"
) )


type Logger interface { type L interface {
json.Marshaler Level() LogLevel

Log(x LogLevel, m string, d map[string]interface{})
Log(level LogLevel, m string, d map[string]interface{}) }

Fatal(m string)
Error(m string)
Warn(m string)
Info(m string)
Debug(m string)
Debug1(m string)
Debug2(m string)


Fatalf(f string, a ...interface{}) type Logger struct {
Errorf(f string, a ...interface{}) L
Warnf(f string, a ...interface{})
Infof(f string, a ...interface{})
Debugf(f string, a ...interface{})
Debug1f(f string, a ...interface{})
Debug2f(f string, a ...interface{})
} }


type BaseLogger struct { type BaseLogger struct {
Expand All @@ -34,102 +21,155 @@ type BaseLogger struct {
level LogLevel level LogLevel
} }


func (x *BaseLogger) Log(l LogLevel, m string, d map[string]interface{}) { func (l *BaseLogger) active(x LogLevel) bool {
if !x.active(l) { return l.level.Priority >= x.Priority
}

func (l *BaseLogger) Level() LogLevel {
return l.level
}

func (l *BaseLogger) Log(x LogLevel, m string, d map[string]interface{}) {
if !l.active(x) {
return return
} }


record := NewRecord(x.name, l, m, d) r := NewRecord(l.name, x, m, d)
for _, s := range l.sinks {
s.AddRecord(r)
s.Flush()
}


for _, sink := range x.sinks { if x == LOG_FATAL {
sink.AddRecord(record) panic(m)
sink.Flush()
} }
} }


func (x *BaseLogger) Fatal(m string) { func (l *BaseLogger) MarshalJSON() ([]byte, error) {
x.Log(LOG_FATAL, m, nil) sinks := "["
panic(m) for i, sink := range l.sinks {
m, err := json.Marshal(sink)
if err != nil {
log.Println(err)
}
sinks += string(m)
if i != len(l.sinks)-1 {
sinks += ","
}
}
sinks += "]"
msg := fmt.Sprintf("{\"level\": \"%s\", \"sinks\": %s}", l.level.Name, sinks)
return []byte(msg), nil
} }


func (x *BaseLogger) Error(m string) { func (l Logger) Fatal(m string) {
x.Log(LOG_ERROR, m, nil) l.Log(LOG_FATAL, m, nil)
} }


func (x *BaseLogger) Warn(m string) { func (l Logger) Error(m string) {
x.Log(LOG_WARN, m, nil) l.Log(LOG_ERROR, m, nil)
} }


func (x *BaseLogger) Info(m string) { func (l Logger) Warn(m string) {
x.Log(LOG_INFO, m, nil) l.Log(LOG_WARN, m, nil)
} }


func (x *BaseLogger) Debug(m string) { func (l Logger) Info(m string) {
x.Log(LOG_DEBUG, m, nil) l.Log(LOG_INFO, m, nil)
} }


func (x *BaseLogger) Debug1(m string) { func (l Logger) Debug(m string) {
x.Log(LOG_DEBUG1, m, nil) l.Log(LOG_DEBUG, m, nil)
} }


func (x *BaseLogger) Debug2(m string) { func (l Logger) Debug1(m string) {
x.Log(LOG_DEBUG2, m, nil) l.Log(LOG_DEBUG1, m, nil)
} }


func (x *BaseLogger) Fatalf(f string, a ...interface{}) { func (l Logger) Debug2(m string) {
x.Fatal(fmt.Sprintf(f, a...)) l.Log(LOG_DEBUG2, m, nil)
} }


func (x *BaseLogger) Errorf(f string, a ...interface{}) { func (l Logger) Fatald(d map[string]interface{}, m string) {
x.Error(fmt.Sprintf(f, a...)) l.Log(LOG_FATAL, m, d)
} }


func (x *BaseLogger) Warnf(f string, a ...interface{}) { func (l Logger) Errord(d map[string]interface{}, m string) {
x.Warn(fmt.Sprintf(f, a...)) l.Log(LOG_ERROR, m, d)
} }


func (x *BaseLogger) Infof(f string, a ...interface{}) { func (l Logger) Warnd(d map[string]interface{}, m string) {
x.Info(fmt.Sprintf(f, a...)) l.Log(LOG_WARN, m, d)
} }


func (x *BaseLogger) Debugf(f string, a ...interface{}) { func (l Logger) Infod(d map[string]interface{}, m string) {
x.Debug(fmt.Sprintf(f, a...)) l.Log(LOG_INFO, m, d)
} }


func (x *BaseLogger) Debug1f(f string, a ...interface{}) { func (l Logger) Debugd(d map[string]interface{}, m string) {
x.Debug1(fmt.Sprintf(f, a...)) l.Log(LOG_DEBUG, m, d)
} }


func (x *BaseLogger) Debug2f(f string, a ...interface{}) { func (l Logger) Debug1d(d map[string]interface{}, m string) {
x.Debug2(fmt.Sprintf(f, a...)) l.Log(LOG_DEBUG1, m, d)
} }


func (x *BaseLogger) MarshalJSON() ([]byte, error) { func (l Logger) Debug2d(d map[string]interface{}, m string) {
sinks := "[" l.Log(LOG_DEBUG2, m, d)
for i, sink := range x.sinks {
m, err := json.Marshal(sink)
if err != nil {
log.Println(err)
}
sinks += string(m)
if i != len(x.sinks)-1 {
sinks += ","
}
}
sinks += "]"
msg := fmt.Sprintf("{\"level\": \"%s\", \"sinks\": %s}", x.level.Name, sinks)
return []byte(msg), nil
} }


func (x *BaseLogger) active(level LogLevel) bool { func (l Logger) Fatalf(f string, a ...interface{}) {
if x.level.Priority >= level.Priority { l.Log(LOG_FATAL, fmt.Sprintf(f, a...), nil)
return true }
}
func (l Logger) Errorf(f string, a ...interface{}) {
l.Log(LOG_ERROR, fmt.Sprintf(f, a...), nil)
}

func (l Logger) Warnf(f string, a ...interface{}) {
l.Log(LOG_WARN, fmt.Sprintf(f, a...), nil)
}

func (l Logger) Infof(f string, a ...interface{}) {
l.Log(LOG_INFO, fmt.Sprintf(f, a...), nil)
}

func (l Logger) Debugf(f string, a ...interface{}) {
l.Log(LOG_DEBUG, fmt.Sprintf(f, a...), nil)
}

func (l Logger) Debug1f(f string, a ...interface{}) {
l.Log(LOG_DEBUG1, fmt.Sprintf(f, a...), nil)
}

func (l Logger) Debug2f(f string, a ...interface{}) {
l.Log(LOG_DEBUG2, fmt.Sprintf(f, a...), nil)
}

func (l Logger) Fataldf(d map[string]interface{}, f string, a ...interface{}) {
l.Log(LOG_FATAL, fmt.Sprintf(f, a...), d)
}

func (l Logger) Errordf(d map[string]interface{}, f string, a ...interface{}) {
l.Log(LOG_ERROR, fmt.Sprintf(f, a...), d)
}

func (l Logger) Warndf(d map[string]interface{}, f string, a ...interface{}) {
l.Log(LOG_WARN, fmt.Sprintf(f, a...), d)
}

func (l Logger) Infodf(d map[string]interface{}, f string, a ...interface{}) {
l.Log(LOG_INFO, fmt.Sprintf(f, a...), d)
}

func (l Logger) Debugdf(d map[string]interface{}, f string, a ...interface{}) {
l.Log(LOG_DEBUG, fmt.Sprintf(f, a...), d)
}


return false func (l Logger) Debug1df(d map[string]interface{}, f string, a ...interface{}) {
l.Log(LOG_DEBUG1, fmt.Sprintf(f, a...), d)
} }


// For testing func (l Logger) Debug2df(d map[string]interface{}, f string, a ...interface{}) {
func NumLogger() int { l.Log(LOG_DEBUG2, fmt.Sprintf(f, a...), d)
return len(loggers)
} }
32 changes: 25 additions & 7 deletions logger_test.go
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ type LoggerSuite struct {


var _ = Suite(&LoggerSuite{}) var _ = Suite(&LoggerSuite{})


func NumLogger() int {
return len(loggers)
}

func (s *LoggerSuite) SetUpTest(c *C) { func (s *LoggerSuite) SetUpTest(c *C) {
cfg := Config{} cfg := Config{}
s.nSink = newNullSink() s.nSink = newNullSink()
Expand All @@ -29,13 +33,27 @@ func (s *LoggerSuite) TestLoggersNum(c *C) {
c.Assert(len(loggers), Equals, 0) c.Assert(len(loggers), Equals, 0)
} }


func (s *LoggerSuite) TestLoggerLevelActive(c *C) { func (s *LoggerSuite) TestLogLevel(c *C) {
// active is a private method of BaseLogger bl := &BaseLogger{
logger := NewLogger("bar").(*BaseLogger) name: "bar",
logger.level = LOG_INFO level: LOG_INFO,
higherLevels := []LogLevel{LOG_WARN, LOG_ERROR, LOG_FATAL} sinks: []Sink{&nullSink{}},
for _, level := range higherLevels { }
c.Assert(logger.active(level), Equals, true)
higher := []LogLevel{LOG_INFO, LOG_WARN, LOG_ERROR}
for _, l := range higher {
s := &nullSink{}
bl.sinks = []Sink{s}
bl.Log(l, "hello", nil)
c.Assert(len(s.records), Equals, 1)
}

lower := []LogLevel{LOG_DEBUG, LOG_DEBUG1, LOG_DEBUG2, LOG_ALL}
for _, l := range lower {
s := &nullSink{}
bl.sinks = []Sink{s}
bl.Log(l, "hello", nil)
c.Assert(len(s.records), Equals, 0)
} }
} }


Expand Down
21 changes: 10 additions & 11 deletions steno.go
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -46,20 +46,19 @@ func NewLogger(name string) Logger {
loggersMutex.Lock() loggersMutex.Lock()
defer loggersMutex.Unlock() defer loggersMutex.Unlock()


logger := loggers[name] l := loggers[name]

if l == nil {
if logger == nil { bl := &BaseLogger{
baseLogger := new(BaseLogger) name: name,

sinks: config.Sinks,
baseLogger.name = name level: computeLevel(name),
baseLogger.sinks = config.Sinks }
baseLogger.level = computeLevel(name)


logger = baseLogger loggers[name] = bl
loggers[name] = logger l = bl
} }


return logger return Logger{l}
} }


func loggersInJson() string { func loggersInJson() string {
Expand Down
12 changes: 6 additions & 6 deletions steno_test.go
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ func (s *StenoSuite) TestLoggersInJson(c *C) {


func (s *StenoSuite) TestSetLoggerRegexp(c *C) { func (s *StenoSuite) TestSetLoggerRegexp(c *C) {
// level is a field of BaseLogger, hence type cast is needed // level is a field of BaseLogger, hence type cast is needed
logger1 := NewLogger("test").(*BaseLogger) logger1 := NewLogger("test").L.(*BaseLogger)
logger2 := NewLogger("test2").(*BaseLogger) logger2 := NewLogger("test2").L.(*BaseLogger)
logger3 := NewLogger("test3").(*BaseLogger) logger3 := NewLogger("test3").L.(*BaseLogger)


c.Assert(logger1.level, Equals, LOG_INFO) c.Assert(logger1.level, Equals, LOG_INFO)
c.Assert(logger2.level, Equals, LOG_INFO) c.Assert(logger2.level, Equals, LOG_INFO)
Expand All @@ -70,9 +70,9 @@ func (s *StenoSuite) TestSetLoggerRegexp(c *C) {


func (s *StenoSuite) TestClearLoggerRegexp(c *C) { func (s *StenoSuite) TestClearLoggerRegexp(c *C) {
// level is a field of BaseLogger, hence type cast is needed // level is a field of BaseLogger, hence type cast is needed
logger1 := NewLogger("test").(*BaseLogger) logger1 := NewLogger("test").L.(*BaseLogger)
logger2 := NewLogger("test2").(*BaseLogger) logger2 := NewLogger("test2").L.(*BaseLogger)
logger3 := NewLogger("test3").(*BaseLogger) logger3 := NewLogger("test3").L.(*BaseLogger)


c.Assert(logger1.level, Equals, LOG_INFO) c.Assert(logger1.level, Equals, LOG_INFO)
c.Assert(logger2.level, Equals, LOG_INFO) c.Assert(logger2.level, Equals, LOG_INFO)
Expand Down
Loading

0 comments on commit 79a2f31

Please sign in to comment.