Skip to content

Commit

Permalink
Implement TextUnmarshaller interface for Level type
Browse files Browse the repository at this point in the history
Since the implementation of the TextMarshaller interface
we could not unmarshal previously json marshalled Level value.
Fixes #873
  • Loading branch information
dgsb committed Dec 26, 2018
1 parent 2067ea4 commit ff695da
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
@@ -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
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
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 ff695da

Please sign in to comment.