aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Hanley <felix@userspace.com.au>2017-11-28 04:05:50 +0000
committerFelix Hanley <felix@userspace.com.au>2017-11-28 04:06:25 +0000
commitaeaf184905c94143dacfc7d9e3b08f179121ba4d (patch)
tree3adf5667b87d8083b3cacde3ef40c8607332726e
parentbe3cf83fff7b64eb04146f9195de6abe71bbe5db (diff)
downloadlogger-aeaf184905c94143dacfc7d9e3b08f179121ba4d.tar.gz
logger-aeaf184905c94143dacfc7d9e3b08f179121ba4d.tar.bz2
Update output to be more uniform, adding support for map arguments
-rw-r--r--default.go3
-rw-r--r--level.go14
-rw-r--r--log.go70
-rw-r--r--logger.go1
-rw-r--r--logger_test.go18
-rw-r--r--outputs/json/json.go9
-rw-r--r--outputs/json/json_test.go16
-rw-r--r--outputs/keyvalue/keyvalue.go21
-rw-r--r--outputs/keyvalue/keyvalue_test.go16
9 files changed, 103 insertions, 65 deletions
diff --git a/default.go b/default.go
index 7a66003..c87ff2d 100644
--- a/default.go
+++ b/default.go
@@ -20,8 +20,7 @@ func (dw DefaultWriter) Write(w io.Writer, m Message) {
io.WriteString(w, prefix)
if m.Name != "" {
- io.WriteString(w, " ")
- io.WriteString(w, m.Name)
+ io.WriteString(w, fmt.Sprintf(" %s:", m.Name))
}
for _, f := range m.Fields {
diff --git a/level.go b/level.go
index 1d8e2b5..3d2aee4 100644
--- a/level.go
+++ b/level.go
@@ -1,13 +1,19 @@
package logger
+// Level defines the logger output level
type Level int
const (
+ // NoLevel is prior to being defined
NoLevel Level = 0
- Debug Level = 1
- Info Level = 2
- Warn Level = 3
- Error Level = 4
+ // Debug is for development
+ Debug Level = 1
+ // Info are for interesting runtime events
+ Info Level = 2
+ // Warn is for almost errors
+ Warn Level = 3
+ // Error is a runtime problem
+ Error Level = 4
)
func (lvl Level) String() string {
diff --git a/log.go b/log.go
index 1034192..4183cbe 100644
--- a/log.go
+++ b/log.go
@@ -17,6 +17,7 @@ type logger struct {
out *bufio.Writer
}
+// New creates a new logger
func New(opts *Options) Logger {
if opts == nil {
opts = &Options{}
@@ -53,6 +54,7 @@ func New(opts *Options) Logger {
return &l
}
+// Log is a generic logger function
func (l logger) Log(lvl Level, args ...interface{}) {
if lvl < l.level {
return
@@ -70,13 +72,27 @@ func (l logger) Log(lvl Level, args ...interface{}) {
Fields: make([]interface{}, 0),
}
- offset := 0
- if len(args)%2 != 0 {
- msg.Fields = append(msg.Fields, "message", args[0])
- offset = 1
- }
- for i := offset; i < len(args); i = i + 2 {
- msg.Fields = append(msg.Fields, ToString(args[i]), args[i+1])
+ for _, f := range args {
+ switch c := f.(type) {
+ case map[string]string:
+ for k, v := range c {
+ msg.Fields = append(msg.Fields, k, v)
+ }
+ case map[string]int:
+ for k, v := range c {
+ msg.Fields = append(msg.Fields, k, v)
+ }
+ case map[int]string:
+ for k, v := range c {
+ msg.Fields = append(msg.Fields, k, v)
+ }
+ case map[string]interface{}:
+ for k, v := range c {
+ msg.Fields = append(msg.Fields, k, v)
+ }
+ default:
+ msg.Fields = append(msg.Fields, c)
+ }
}
l.formatter.Write(l.out, msg)
@@ -84,39 +100,29 @@ func (l logger) Log(lvl Level, args ...interface{}) {
l.out.Flush()
}
-func (l logger) Debug(args ...interface{}) {
- l.Log(Debug, args...)
-}
-
-func (l logger) Warn(args ...interface{}) {
- l.Log(Warn, args...)
-}
-
-func (l logger) Error(args ...interface{}) {
- l.Log(Error, args...)
-}
-
-func (l logger) Info(args ...interface{}) {
- l.Log(Info, args...)
-}
-
-func (l logger) IsLevel(lvl Level) bool {
- return l.level <= lvl
-}
+// Convenience functions for logging at levels
+func (l logger) Debug(args ...interface{}) { l.Log(Debug, args...) }
+func (l logger) Warn(args ...interface{}) { l.Log(Warn, args...) }
+func (l logger) Error(args ...interface{}) { l.Log(Error, args...) }
+func (l logger) Info(args ...interface{}) { l.Log(Info, args...) }
-func (l *logger) IsDebug() bool { return l.IsLevel(Debug) }
-func (l *logger) IsInfo() bool { return l.IsLevel(Info) }
-func (l *logger) IsWarn() bool { return l.IsLevel(Warn) }
-func (l *logger) IsError() bool { return l.IsLevel(Error) }
+// Test for current logging level
+func (l logger) IsLevel(lvl Level) bool { return l.level <= lvl }
+func (l *logger) IsDebug() bool { return l.IsLevel(Debug) }
+func (l *logger) IsInfo() bool { return l.IsLevel(Info) }
+func (l *logger) IsWarn() bool { return l.IsLevel(Warn) }
+func (l *logger) IsError() bool { return l.IsLevel(Error) }
+// WithFields sets the default fields for a new logger
func (l *logger) WithFields(args ...interface{}) Logger {
- var nl logger = *l
+ var nl = *l
nl.fields = append(nl.fields, args...)
return &nl
}
+// Named sets the name for a new logger
func (l *logger) Named(name string) Logger {
- var nl logger = *l
+ var nl = *l
if nl.name != "" {
nl.name = nl.name + "." + name
} else {
diff --git a/logger.go b/logger.go
index bea82be..b68dd36 100644
--- a/logger.go
+++ b/logger.go
@@ -1,5 +1,6 @@
package logger
+// Logger defines our methods
type Logger interface {
Log(level Level, args ...interface{})
Info(args ...interface{})
diff --git a/logger_test.go b/logger_test.go
index cd51b8e..ec9b78c 100644
--- a/logger_test.go
+++ b/logger_test.go
@@ -12,23 +12,27 @@ func TestDefaultWriter(t *testing.T) {
out string
}{
{
- in: []interface{}{"test message"},
- out: "[INFO ] test message test message",
+ in: []interface{}{"one"},
+ out: "[INFO ] testlog: one",
},
{
- in: []interface{}{"test message", "name", "me"},
- out: "[INFO ] test message test message name me",
+ in: []interface{}{"one", "two", "2"},
+ out: "[INFO ] testlog: one two 2",
},
{
- in: []interface{}{"test message", "name", "me", "number", 2},
- out: "[INFO ] test message test message name me number 2",
+ in: []interface{}{"one", "two", "2", "three", 3},
+ out: "[INFO ] testlog: one two 2 three 3",
+ },
+ {
+ in: []interface{}{"one", map[string]string{"two": "2", "three": "3"}},
+ out: "[INFO ] testlog: one two 2 three 3",
},
}
for _, tt := range tests {
var buf bytes.Buffer
logger := New(&Options{
- Name: "test",
+ Name: "testlog",
Output: &buf,
})
diff --git a/outputs/json/json.go b/outputs/json/json.go
index b170c2b..d7924ad 100644
--- a/outputs/json/json.go
+++ b/outputs/json/json.go
@@ -22,8 +22,13 @@ func (w Writer) Write(lw io.Writer, m logger.Message) {
"@time": m.Time,
}
- for i := 0; i < len(m.Fields); i = i + 2 {
- vals[m.Fields[i].(string)] = m.Fields[i+1]
+ offset := len(m.Fields) % 2
+ if offset != 0 {
+ vals["message"] = logger.ToString(m.Fields[0])
+ }
+
+ for i := offset; i < len(m.Fields); i = i + 2 {
+ vals[logger.ToString(m.Fields[i])] = m.Fields[i+1]
}
err := json.NewEncoder(lw).Encode(vals)
diff --git a/outputs/json/json_test.go b/outputs/json/json_test.go
index d5f436e..8142fa9 100644
--- a/outputs/json/json_test.go
+++ b/outputs/json/json_test.go
@@ -14,16 +14,20 @@ func TestWriter(t *testing.T) {
out map[string]interface{}
}{
{
- in: []interface{}{"test message"},
- out: map[string]interface{}{"@level": "info", "@name": "test", "message": "test message"},
+ in: []interface{}{"one"},
+ out: map[string]interface{}{"@level": "info", "@name": "test", "message": "one"},
},
{
- in: []interface{}{"test message", "name", "me"},
- out: map[string]interface{}{"@level": "info", "@name": "test", "message": "test message", "name": "me"},
+ in: []interface{}{"one", "two", "2"},
+ out: map[string]interface{}{"@level": "info", "@name": "test", "message": "one", "two": "2"},
},
{
- in: []interface{}{"test message", "name", "me", "number", 2},
- out: map[string]interface{}{"@level": "info", "@name": "test", "message": "test message", "name": "me", "number": float64(2)},
+ in: []interface{}{"one", "two", "2", "three", 3},
+ out: map[string]interface{}{"@level": "info", "@name": "test", "message": "one", "two": "2", "three": float64(3)},
+ },
+ {
+ in: []interface{}{"one", "two", "2", "three", 3, "fo ur", "# 4"},
+ out: map[string]interface{}{"@level": "info", "@name": "test", "message": "one", "two": "2", "three": float64(3), "fo ur": "# 4"},
},
}
diff --git a/outputs/keyvalue/keyvalue.go b/outputs/keyvalue/keyvalue.go
index 5649f5e..234f29b 100644
--- a/outputs/keyvalue/keyvalue.go
+++ b/outputs/keyvalue/keyvalue.go
@@ -25,15 +25,24 @@ func (kv Writer) Write(w io.Writer, m logger.Message) {
io.WriteString(w, ":")
}
- for i := 0; i < len(m.Fields); i = i + 2 {
- io.WriteString(w, " ")
- io.WriteString(w, maybeQuote(logger.ToString(m.Fields[i])))
- io.WriteString(w, "=")
- s := logger.ToString(m.Fields[i+1])
- io.WriteString(w, maybeQuote(s))
+ offset := len(m.Fields) % 2
+ if offset != 0 {
+ io.WriteString(w, writeKV("message", m.Fields[0]))
+ }
+
+ for i := offset; i < len(m.Fields); i = i + 2 {
+ io.WriteString(w, writeKV(m.Fields[i], m.Fields[i+1]))
}
}
+func writeKV(k, v interface{}) string {
+ return fmt.Sprintf(
+ " %s=%s",
+ maybeQuote(logger.ToString(k)),
+ maybeQuote(logger.ToString(v)),
+ )
+}
+
func maybeQuote(s string) string {
if strings.ContainsAny(s, " \t\n\r") {
return fmt.Sprintf("%q", s)
diff --git a/outputs/keyvalue/keyvalue_test.go b/outputs/keyvalue/keyvalue_test.go
index 4ce6d90..7abe81e 100644
--- a/outputs/keyvalue/keyvalue_test.go
+++ b/outputs/keyvalue/keyvalue_test.go
@@ -13,16 +13,20 @@ func TestKeyValueWriter(t *testing.T) {
out string
}{
{
- in: []interface{}{"test message"},
- out: "[INFO ] test: message=\"test message\"",
+ in: []interface{}{"one"},
+ out: "[INFO ] test: message=one",
},
{
- in: []interface{}{"test message", "name", "me"},
- out: "[INFO ] test: message=\"test message\" name=me",
+ in: []interface{}{"one", "two", "2"},
+ out: "[INFO ] test: message=one two=2",
},
{
- in: []interface{}{"test message", "name", "me", "number", 2},
- out: "[INFO ] test: message=\"test message\" name=me number=2",
+ in: []interface{}{"one", "two", "2", "three", 3},
+ out: "[INFO ] test: message=one two=2 three=3",
+ },
+ {
+ in: []interface{}{"one", "two", "2", "three", 3, "fo ur", "# 4"},
+ out: "[INFO ] test: message=one two=2 three=3 \"fo ur\"=\"# 4\"",
},
}