log: make it easier to add parameters to JSON logging

This commit is contained in:
Nick Craig-Wood 2020-12-30 13:06:43 +00:00
parent acbcb1ea9d
commit e972f2c98a
3 changed files with 49 additions and 9 deletions

View file

@ -368,7 +368,7 @@ func (s *StatsInfo) Transferred() []TransferSnapshot {
func (s *StatsInfo) Log() { func (s *StatsInfo) Log() {
if s.ci.UseJSONLog { if s.ci.UseJSONLog {
out, _ := s.RemoteStats() out, _ := s.RemoteStats()
fs.LogLevelPrintf(s.ci.StatsLogLevel, nil, "%v%v\n", s, fs.LogValue("stats", out)) fs.LogLevelPrintf(s.ci.StatsLogLevel, nil, "%v%v\n", s, fs.LogValueHide("stats", out))
} else { } else {
fs.LogLevelPrintf(s.ci.StatsLogLevel, nil, "%v\n", s) fs.LogLevelPrintf(s.ci.StatsLogLevel, nil, "%v\n", s)
} }

View file

@ -77,8 +77,9 @@ var LogPrint = func(level LogLevel, text string) {
// LogValueItem describes keyed item for a JSON log entry // LogValueItem describes keyed item for a JSON log entry
type LogValueItem struct { type LogValueItem struct {
key string key string
value interface{} value interface{}
render bool
} }
// LogValue should be used as an argument to any logging calls to // LogValue should be used as an argument to any logging calls to
@ -86,14 +87,31 @@ type LogValueItem struct {
// //
// key is the dictionary parameter used to store value. // key is the dictionary parameter used to store value.
func LogValue(key string, value interface{}) LogValueItem { func LogValue(key string, value interface{}) LogValueItem {
return LogValueItem{key: key, value: value} return LogValueItem{key: key, value: value, render: true}
} }
// String returns an empty string so LogValueItem entries won't show // LogValueHide should be used as an argument to any logging calls to
// in the textual representation of logs. They need to be put in so // augment the JSON output with more structured information.
// the number of parameters of the log call matches. //
// key is the dictionary parameter used to store value.
//
// String() will return a blank string - this is useful to put items
// in which don't print into the log.
func LogValueHide(key string, value interface{}) LogValueItem {
return LogValueItem{key: key, value: value, render: false}
}
// String returns the representation of value. If render is fals this
// is an empty string so LogValueItem entries won't show in the
// textual representation of logs.
func (j LogValueItem) String() string { func (j LogValueItem) String() string {
return "" if !j.render {
return ""
}
if do, ok := j.value.(fmt.Stringer); ok {
return do.String()
}
return fmt.Sprint(j.value)
} }
// LogPrintf produces a log string from the arguments passed in // LogPrintf produces a log string from the arguments passed in

View file

@ -1,6 +1,28 @@
package fs package fs
import "github.com/spf13/pflag" import (
"fmt"
"testing"
"github.com/spf13/pflag"
"github.com/stretchr/testify/assert"
)
// Check it satisfies the interface // Check it satisfies the interface
var _ pflag.Value = (*LogLevel)(nil) var _ pflag.Value = (*LogLevel)(nil)
var _ fmt.Stringer = LogValueItem{}
type withString struct{}
func (withString) String() string {
return "hello"
}
func TestLogValue(t *testing.T) {
x := LogValue("x", 1)
assert.Equal(t, "1", x.String())
x = LogValue("x", withString{})
assert.Equal(t, "hello", x.String())
x = LogValueHide("x", withString{})
assert.Equal(t, "", x.String())
}