Skip to content
This repository has been archived by the owner on Oct 11, 2024. It is now read-only.

Add type suffixes to all keys when logging #275

Merged
merged 4 commits into from
Jul 18, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Improve handling of nested map types
  • Loading branch information
albrow committed Jul 17, 2019
commit d7880596a74026085e9a55d709013c66175564b8
24 changes: 21 additions & 3 deletions loghooks/key_suffix_hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@ package loghooks
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"reflect"
"strings"

log "github.com/sirupsen/logrus"
)

var errNestedMapType = errors.New("nested map types are not supported")

// KeySuffixHook is a logger hook that adds suffixes to all keys based on their
// type.
type KeySuffixHook struct{}

// NewKeySuffixHook creates and returns a new KeySuffixHook with the given peer ID.
// NewKeySuffixHook creates and returns a new KeySuffixHook.
func NewKeySuffixHook() *KeySuffixHook {
return &KeySuffixHook{}
}
Expand All @@ -30,7 +33,20 @@ func (h *KeySuffixHook) Fire(entry *log.Entry) error {
for key, value := range entry.Data {
typ, err := getTypeForValue(value)
if err != nil {
return err
if err == errNestedMapType {
// We can't safely log nested map types, so replace the value with a
// string.
newKey := fmt.Sprintf("%s_json_string", key)
delete(entry.Data, key)
mapString, err := json.Marshal(value)
if err != nil {
return err
}
entry.Data[newKey] = string(mapString)
continue
} else {
return err
}
}
newKey := fmt.Sprintf("%s_%s", key, typ)
delete(entry.Data, key)
Expand Down Expand Up @@ -66,7 +82,9 @@ func getTypeForValue(val interface{}) (string, error) {
case reflect.Array, reflect.Slice:
return "array", nil
case reflect.Map:
return "object", nil
// Nested map types can't be efficiently indexed because they allow for
// arbitrary keys. We don't allow them.
return "", errNestedMapType
case reflect.Struct:
return getSafeStructTypeName(underlyingType)
default:
Expand Down
22 changes: 15 additions & 7 deletions loghooks/key_suffix_hook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"fmt"
"testing"

"github.com/stretchr/testify/require"

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

type myStruct struct {
Expand Down Expand Up @@ -99,10 +99,6 @@ func TestGetTypeForValue(t *testing.T) {
input: [...]int{},
expected: "array",
},
{
input: map[string]int{},
expected: "object",
},
{
input: myStruct{},
expected: "loghooks_myStruct",
Expand All @@ -128,4 +124,16 @@ func TestGetTypeForValue(t *testing.T) {
}
}

// case reflect.Struct:
func TestKeySuffixHookWithNestedMapType(t *testing.T) {
hook := NewKeySuffixHook()
entry := &log.Entry{
Data: log.Fields{
"myMap": map[string]int{"one": 1},
},
}
require.NoError(t, hook.Fire(entry))
expectedData := log.Fields{
"myMap_json_string": `{"one":1}`,
}
assert.Equal(t, expectedData, entry.Data)
}