Skip to content

Commit

Permalink
Added a backend for the default Go logger
Browse files Browse the repository at this point in the history
  • Loading branch information
Keith James committed Jul 23, 2019
1 parent 2c72a88 commit cbee2c6
Show file tree
Hide file tree
Showing 5 changed files with 315 additions and 0 deletions.
25 changes: 25 additions & 0 deletions dlog/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2019. Genome Research Ltd. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License,
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @file doc.go
* @author Keith James <[email protected]>
*/

/*
Package dlog is a log (https://golang.org/pkg/log/) backend for
logshim (http://github.com/kjsanger/logshim).
*/
package dlog
207 changes: 207 additions & 0 deletions dlog/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
/*
* Copyright (C) 2019. Genome Research Ltd. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License,
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @file log.go
* @author Keith James <[email protected]>
*/

package dlog

import (
"fmt"
"io"
"log"
"strings"
"time"

"github.com/kjsanger/logshim"
)

type levelName string

const (
errorLevel levelName = "ERROR"
warnLevel levelName = "WARN"
// noticeLevel levelName = "NOTICE"
infoLevel levelName = "INFO"
debugLevel levelName = "DEBUG"
)

func translateLevel(level logshim.Level) (levelName, error) {
var (
lvn levelName
err error
)

switch level {
case logshim.ErrorLevel:
lvn = errorLevel
case logshim.WarnLevel:
lvn = warnLevel
case logshim.NoticeLevel:
fallthrough
case logshim.InfoLevel:
lvn = infoLevel
case logshim.DebugLevel:
lvn = debugLevel
default:
lvn = warnLevel
err = fmt.Errorf("invalid log level %d, defaulting to "+
"WARN level", level)
}

return lvn, err
}

type StdLogger struct {
name string
Level logshim.Level
*log.Logger
}

func New(writer io.Writer, level logshim.Level) *StdLogger {
lg := log.New(writer, "", log.LstdFlags|log.Lshortfile)

_, err := translateLevel(level)
if err != nil {
log.Print(errorLevel, "log configuration error", err)
level = logshim.WarnLevel
}

return &StdLogger{"StdLog", level, lg}
}

func (log *StdLogger) Name() string {
return log.name
}

func (log *StdLogger) Err(err error) logshim.Message {
effectiveLevel := logshim.InfoLevel
if err != nil {
effectiveLevel = logshim.ErrorLevel
}

active := log.Level >= effectiveLevel
msg := &stdMessage{active, effectiveLevel, &strings.Builder{}}
msg.Err(err)
return msg
}

func (log *StdLogger) Error() logshim.Message {
active := log.Level >= logshim.ErrorLevel
msg := &stdMessage{active, logshim.ErrorLevel, &strings.Builder{}}
return msg
}

func (log *StdLogger) Warn() logshim.Message {
active := log.Level >= logshim.WarnLevel
msg := &stdMessage{active, logshim.WarnLevel, &strings.Builder{}}
return msg
}

func (log *StdLogger) Notice() logshim.Message {
active := log.Level >= logshim.NoticeLevel
msg := &stdMessage{active, logshim.InfoLevel, &strings.Builder{}}
return msg
}

func (log *StdLogger) Info() logshim.Message {
active := log.Level >= logshim.InfoLevel
msg := &stdMessage{active, logshim.InfoLevel, &strings.Builder{}}
return msg
}

func (log *StdLogger) Debug() logshim.Message {
active := log.Level >= logshim.DebugLevel
msg := &stdMessage{active, logshim.DebugLevel, &strings.Builder{}}
return msg
}

type stdMessage struct {
active bool
level logshim.Level
builder *strings.Builder
}

func (msg *stdMessage) Err(err error) logshim.Message {
if msg.active {
msg.builder.WriteString(fmt.Sprintf(" error: %v", err))
}
return msg
}

func (msg *stdMessage) Bool(key string, val bool) logshim.Message {
if msg.active {
msg.builder.WriteString(fmt.Sprintf(" %s: %v", key, val))
}
return msg
}

func (msg *stdMessage) Int(key string, val int) logshim.Message {
if msg.active {
msg.builder.WriteString(fmt.Sprintf(" %s: %d", key, val))
}
return msg
}

func (msg *stdMessage) Int64(key string, val int64) logshim.Message {
if msg.active {
msg.builder.WriteString(fmt.Sprintf(" %s: %d", key, val))
}
return msg
}

func (msg *stdMessage) Uint64(key string, val uint64) logshim.Message {
if msg.active {
msg.builder.WriteString(fmt.Sprintf(" %s: %d", key, val))
}
return msg
}

func (msg *stdMessage) Str(key string, val string) logshim.Message {
if msg.active {
msg.builder.WriteString(fmt.Sprintf(" %s: %s", key, val))
}
return msg
}

func (msg *stdMessage) Time(key string, val time.Time) logshim.Message {
if msg.active {
msg.builder.WriteString(fmt.Sprintf(" %s: %v", key, val))
}
return msg
}

func (msg *stdMessage) Msg(val string) {
if msg.active {
lvn, err := translateLevel(msg.level)
if err != nil {
// This should never happen because the Logger constructor corrects
// invalid level values.
log.Print(errorLevel, "log configuration error", err)
}

msg.builder.WriteString(" ")
msg.builder.WriteString(val)
log.Print(lvn, msg.builder.String())
// Once this method is called, deactivate for all future calls
msg.active = false
}
}

func (msg *stdMessage) Msgf(format string, a ...interface{}) {
msg.Msg(fmt.Sprintf(format, a...))
}
69 changes: 69 additions & 0 deletions dlog/log_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (C) 2019. Genome Research Ltd. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License,
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @file log_test.go
* @author Keith James <[email protected]>
*/

package dlog

import (
"os"
"testing"

"github.com/pkg/errors"
"github.com/stretchr/testify/assert"

"github.com/kjsanger/logshim"
)

func TestNew(t *testing.T) {
for _, level := range logshim.Levels() {
logger := New(os.Stderr, level)
assert.NotNil(t, logger, "StdLogger level %d was nil", level)
}
}

func TestStdLogger_Err(t *testing.T) {
log := New(os.Stderr, logshim.ErrorLevel)
assert.NotNil(t, log.Err(errors.New("test error")),
"Err() should return a Message")
}

func TestStdLogger_Error(t *testing.T) {
log := New(os.Stderr, logshim.ErrorLevel)
assert.NotNil(t, log.Error(), "Error() should return a Message")
}

func TestStdLogger_Warn(t *testing.T) {
log := New(os.Stderr, logshim.ErrorLevel)
assert.NotNil(t, log.Warn(), "Warn() should return a Message")
}

func TestStdLogger_Notice(t *testing.T) {
log := New(os.Stderr, logshim.ErrorLevel)
assert.NotNil(t, log.Notice(), "Notice() should return a Message")
}

func TestStdLogger_Info(t *testing.T) {
log := New(os.Stderr, logshim.ErrorLevel)
assert.NotNil(t, log.Info(), "Info() should return a Message")
}

func TestStdLogger_Debug(t *testing.T) {
log := New(os.Stderr, logshim.ErrorLevel)
assert.NotNil(t, log.Debug(), "Debug() should return a Message")
}
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
module github.com/kjsanger/logshim

go 1.12

require (
github.com/pkg/errors v0.8.1
github.com/stretchr/testify v1.3.0
)
9 changes: 9 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=

0 comments on commit cbee2c6

Please sign in to comment.