Skip to content

Commit

Permalink
Merge pull request #878 from sirupsen/json_level_marshalling
Browse files Browse the repository at this point in the history
Implement TextUnmarshaller interface for Level type
  • Loading branch information
dgsb authored Dec 26, 2018
2 parents 2067ea4 + ff695da commit 6180652
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 30 deletions.
62 changes: 62 additions & 0 deletions level_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package logrus_test

import (
"bytes"
"encoding/json"
"testing"

"github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"
)

func TestLevelJsonEncoding(t *testing.T) {
type X struct {
Level logrus.Level
}

var x X
x.Level = logrus.WarnLevel
var buf bytes.Buffer
enc := json.NewEncoder(&buf)
require.NoError(t, enc.Encode(x))
dec := json.NewDecoder(&buf)
var y X
require.NoError(t, dec.Decode(&y))
}

func TestLevelUnmarshalText(t *testing.T) {
var u logrus.Level
for _, level := range logrus.AllLevels {
t.Run(level.String(), func(t *testing.T) {
require.NoError(t, u.UnmarshalText([]byte(level.String())))
require.Equal(t, level, u)
})
}
t.Run("invalid", func(t *testing.T) {
require.Error(t, u.UnmarshalText([]byte("invalid")))
})
}

func TestLevelMarshalText(t *testing.T) {
levelStrings := []string{
"panic",
"fatal",
"error",
"warning",
"info",
"debug",
"trace",
}
for idx, val := range logrus.AllLevels {
level := val
t.Run(level.String(), func(t *testing.T) {
var cmp logrus.Level
b, err := level.MarshalText()
require.NoError(t, err)
require.Equal(t, levelStrings[idx], string(b))
err = cmp.UnmarshalText(b)
require.NoError(t, err)
require.Equal(t, level, cmp)
})
}
}
42 changes: 25 additions & 17 deletions logrus.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,11 @@ type Level uint32

// Convert the Level to a string. E.g. PanicLevel becomes "panic".
func (level Level) String() string {
switch level {
case TraceLevel:
return "trace"
case DebugLevel:
return "debug"
case InfoLevel:
return "info"
case WarnLevel:
return "warning"
case ErrorLevel:
return "error"
case FatalLevel:
return "fatal"
case PanicLevel:
return "panic"
if b, err := level.MarshalText(); err == nil {
return string(b)
} else {
return "unknown"
}

return "unknown"
}

// ParseLevel takes a string level and returns the Logrus log level constant.
Expand Down Expand Up @@ -69,6 +56,27 @@ func (level *Level) UnmarshalText(text []byte) error {
return nil
}

func (level Level) MarshalText() ([]byte, error) {
switch level {
case TraceLevel:
return []byte("trace"), nil
case DebugLevel:
return []byte("debug"), nil
case InfoLevel:
return []byte("info"), nil
case WarnLevel:
return []byte("warning"), nil
case ErrorLevel:
return []byte("error"), nil
case FatalLevel:
return []byte("fatal"), nil
case PanicLevel:
return []byte("panic"), nil
}

return nil, fmt.Errorf("not a valid lorus level %q", level)
}

// A constant exposing all logging levels
var AllLevels = []Level{
PanicLevel,
Expand Down
13 changes: 0 additions & 13 deletions logrus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -508,19 +508,6 @@ func TestParseLevel(t *testing.T) {
assert.Equal(t, "not a valid logrus Level: \"invalid\"", err.Error())
}

func TestUnmarshalText(t *testing.T) {
var u Level
for _, level := range AllLevels {
t.Run(level.String(), func(t *testing.T) {
assert.NoError(t, u.UnmarshalText([]byte(level.String())))
assert.Equal(t, level, u)
})
}
t.Run("invalid", func(t *testing.T) {
assert.Error(t, u.UnmarshalText([]byte("invalid")))
})
}

func TestGetSetLevelRace(t *testing.T) {
wg := sync.WaitGroup{}
for i := 0; i < 100; i++ {
Expand Down

0 comments on commit 6180652

Please sign in to comment.