Skip to content

Commit

Permalink
Allow injecting test helper into mapped loggers.
Browse files Browse the repository at this point in the history
* Allow testing helper calls. This will allow tests to pass through calling function names.
* Require Go 1.9
* Clarify documentation of new methods.

#6
  • Loading branch information
birkirb committed Aug 29, 2018
1 parent a2d14d8 commit 5deefcd
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 4 deletions.
11 changes: 10 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
language: go
go: 1.4

go:
- 1.9 # Earliest supported due to introduction of testing#T.helper
- 1.11

sudo: false

go_import_path: gopkg.in/birkirb/loggers.v1

install: true
57 changes: 57 additions & 0 deletions mappers/advanced.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
package mappers

// TestHelper describes a *testing.T helper.
// See: https://golang.org/pkg/testing/#T.Helper
type TestHelper interface {
Helper()
}

// AdvancedMap maps a standard logger to an advanced logger interface.
type AdvancedMap struct {
standardMap
t TestHelper
}

// NewAdvancedMap returns an advanced logger that is mapped via mapper.
Expand All @@ -16,62 +23,112 @@ func NewAdvancedMap(m LevelMapper) *AdvancedMap {
return &a
}

// NewAdvancedMapTesting returns an advanced logger that is mapped via mapper.
// A TestHelper can be passed that will then be invoked (when not nil) on each
// log statement marking that function call as a test helper call and causing
// file/line information to be skipped.
func NewAdvancedMapTesting(m LevelMapper, t TestHelper) *AdvancedMap {
var a AdvancedMap

if m != nil {
a.LevelMapper = m
}
a.t = t
return &a
}

// Debug should be used when logging exessive debug info.
func (a *AdvancedMap) Debug(v ...interface{}) {
if a.t != nil {
a.t.Helper()
}
a.LevelPrint(LevelDebug, v...)
}

// Debugf works the same as Debug but supports formatting.
func (a *AdvancedMap) Debugf(format string, v ...interface{}) {
if a.t != nil {
a.t.Helper()
}
a.LevelPrintf(LevelDebug, format, v...)
}

// Debugln works the same as Debug but supports formatting.
func (a *AdvancedMap) Debugln(v ...interface{}) {
if a.t != nil {
a.t.Helper()
}
a.LevelPrintln(LevelDebug, v...)
}

// Info is a general function to log something.
func (a *AdvancedMap) Info(v ...interface{}) {
if a.t != nil {
a.t.Helper()
}
a.LevelPrint(LevelInfo, v...)
}

// Infof works the same as Info but supports formatting.
func (a *AdvancedMap) Infof(format string, v ...interface{}) {
if a.t != nil {
a.t.Helper()
}
a.LevelPrintf(LevelInfo, format, v...)
}

// Infoln works the same as Info but supports formatting.
func (a *AdvancedMap) Infoln(v ...interface{}) {
if a.t != nil {
a.t.Helper()
}
a.LevelPrintln(LevelInfo, v...)
}

// Warn is useful for alerting about something wrong.
func (a *AdvancedMap) Warn(v ...interface{}) {
if a.t != nil {
a.t.Helper()
}
a.LevelPrint(LevelWarn, v...)
}

// Warnf works the same as Warn but supports formatting.
func (a *AdvancedMap) Warnf(format string, v ...interface{}) {
if a.t != nil {
a.t.Helper()
}
a.LevelPrintf(LevelWarn, format, v...)
}

// Warnln works the same as Warn but supports formatting.
func (a *AdvancedMap) Warnln(v ...interface{}) {
if a.t != nil {
a.t.Helper()
}
a.LevelPrintln(LevelWarn, v...)
}

// Error should be used only if real error occures.
func (a *AdvancedMap) Error(v ...interface{}) {
if a.t != nil {
a.t.Helper()
}
a.LevelPrint(LevelError, v...)
}

// Errorf works the same as Error but supports formatting.
func (a *AdvancedMap) Errorf(format string, v ...interface{}) {
if a.t != nil {
a.t.Helper()
}
a.LevelPrintf(LevelError, format, v...)
}

// Errorln works the same as Error but supports formatting.
func (a *AdvancedMap) Errorln(v ...interface{}) {
if a.t != nil {
a.t.Helper()
}
a.LevelPrintln(LevelError, v...)
}
18 changes: 18 additions & 0 deletions mappers/contextual.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,24 @@ func NewContextualMap(m ContextualMapper) *ContextualMap {
return &a
}

// NewContextualMapTesting returns an contextual logger that is mapped via mapper.
// A TestHelper can be passed that will then be invoked (when not nil) on each
// log statement marking that function call as a test helper call and causing
// file/line information to be skipped.
func NewContextualMapTesting(m ContextualMapper, t TestHelper) *ContextualMap {
var a ContextualMap
a.t = t

if m != nil {
if am := NewAdvancedMapTesting(m, t); am != nil {
a.AdvancedMap = *am
}
a.ContextualMapper = m
}

return &a
}

// WithField directly maps the loggers method.
func (c *ContextualMap) WithField(key string, value interface{}) loggers.Advanced {
return c.ContextualMapper.WithField(key, value)
Expand Down
13 changes: 10 additions & 3 deletions mappers/stdlib/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,27 @@ type goTestLog struct {
// NewDefaultLogger returns a Contextual logger using a *testing.T with Log/Logf output.
// This allows logging to be redirected to the test where it belongs.
func NewTestingLogger(t *testing.T) loggers.Contextual {
t.Helper()
var g goTestLog
g.logger = t

a := mappers.NewContextualMap(&g)
a.Debug("Now using Go's stdlib testing log (via loggers/mappers/stdlib).")
a := mappers.NewContextualMapTesting(&g, t)
a.Debugf("Now using Go's stdlib testing log (via loggers/mappers/stdlib).")

return a
}

// LevelPrint is a Mapper method
func (l *goTestLog) LevelPrint(lev mappers.Level, i ...interface{}) {
l.logger.Helper()
v := []interface{}{lev}
v = append(v, i...)
l.logger.Log(v...)
}

// LevelPrintf is a Mapper method
func (l *goTestLog) LevelPrintf(lev mappers.Level, format string, i ...interface{}) {
l.logger.Helper()
f := "%s" + format
v := []interface{}{lev}
v = append(v, i...)
Expand All @@ -44,6 +47,7 @@ func (l *goTestLog) LevelPrintf(lev mappers.Level, format string, i ...interface

// LevelPrintln is a Mapper method
func (l *goTestLog) LevelPrintln(lev mappers.Level, i ...interface{}) {
l.logger.Helper()
v := []interface{}{lev}
v = append(v, i...)
l.logger.Log(v...)
Expand All @@ -64,7 +68,7 @@ func (l *goTestLog) WithFields(fields ...interface{}) loggers.Advanced {
}

r := goTestLogPostfixLogger{l, "["+strings.Join(s, ", ")+"]"}
return mappers.NewAdvancedMap(&r)
return mappers.NewAdvancedMapTesting(&r, l.logger)
}

type goTestLogPostfixLogger struct {
Expand All @@ -73,13 +77,15 @@ type goTestLogPostfixLogger struct {
}

func (r *goTestLogPostfixLogger) LevelPrint(lev mappers.Level, i ...interface{}) {
r.logger.Helper()
if len(r.postfix) > 0 {
i = append(i, " ", r.postfix)
}
r.goTestLog.LevelPrint(lev, i...)
}

func (r *goTestLogPostfixLogger) LevelPrintf(lev mappers.Level, format string, i ...interface{}) {
r.logger.Helper()
if len(r.postfix) > 0 {
format = format + " %s"
i = append(i, r.postfix)
Expand All @@ -88,6 +94,7 @@ func (r *goTestLogPostfixLogger) LevelPrintf(lev mappers.Level, format string, i
}

func (r *goTestLogPostfixLogger) LevelPrintln(lev mappers.Level, i ...interface{}) {
r.logger.Helper()
i = append(i, r.postfix)
r.goTestLog.LevelPrintln(lev, i...)
}

0 comments on commit 5deefcd

Please sign in to comment.