Skip to content

Commit

Permalink
Formatter (#12)
Browse files Browse the repository at this point in the history
* WIP: add template formatter

* partial compatibility with prev version

* handle braces, add docs about templating

* more explicit levels brace replacement

* add TRACE level

* handle valid template with invalid var in
  • Loading branch information
umputun committed Mar 30, 2019
1 parent 0b5e20c commit eadc464
Show file tree
Hide file tree
Showing 5 changed files with 299 additions and 137 deletions.
30 changes: 26 additions & 4 deletions README.md
Expand Up @@ -33,19 +33,41 @@ _Without `lgr.Caller*` it will drop `{caller}` part_
`lgr.New` call accepts functional options:

- `lgr.Debug` - turn debug mode on to allow messages with "DEBUG" level (filtered overwise)
- `lgr.Out(io.Writer)` - sets the output writer, default `os.Stdout`
- `lgr.Err(io.Writer)` - sets the error writer, default `os.Stderr`
- `lgr.CallerFile` - adds the caller file info
- `lgr.CallerFunc` - adds the caller function info
- `lgr.CallerPkg` - adds the caller package
- `lgr.LevelBraces` - wraps levels with "[" and "]"
- `lgr.Msec` - adds milliseconds to timestamp
- `lgr.Out(io.Writer)` - sets the output writer, default `os.Stdout`
- `lgr.Err(io.Writer)` - sets the error writer, default `os.Stderr`
- `lgr.Format` - sets custom template, overwrite all other formatting modifiers.

#### formatting templates:

Several predefined templates provided and can be passed directly to `lgr.Format`, i.e. `lgr.Format(lgr.WithMsec)`

```
Short = `{{.DT.Format "2006/01/02 15:04:05"}} {{.Level}} {{.Message}}`
WithMsec = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} {{.Message}}`
WithPkg = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerPkg}}) {{.Message}}`
ShortDebug = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerFile}}:{{.CallerLine}}) {{.Message}}`
FuncDebug = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerFunc}}) {{.Message}}`
FullDebug = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerFile}}:{{.CallerLine}} {{.CallerFunc}}) {{.Message}}`
```

User can make a custom template and pass it directly to `lgr.Format`. For example:

```go
lgr.Format(`{{.Level}} - {{.DT.Format "2006-01-02T15:04:05Z07:00") - {{.CallerPkg}} - {{.Message}}`)
```
)

### levels

`lgr.Logf` recognizes prefixes like "INFO" or "[INFO]" as levels. The full list of supported levels - "DEBUG", "INFO", "WARN", "ERROR", "PANIC" and "FATAL"
`lgr.Logf` recognizes prefixes like "INFO" or "[INFO]" as levels. The full list of supported levels - "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "PANIC" and "FATAL"

- `DEBUG` will be filtered unless `lgr.Debug` option defined
- `TRACE` will be filtered unless `lgr.Trace` option defined
- `DEBUG` will be filtered unless `lgr.Debug` or `lgr.Trace` options defined
- `INFO` and `WARN` don't have any special behavior attached
- `ERROR` sends messages to both out and err writers
- `PANIC` and `FATAL` send messages to both out and err writers. In addition sends dump of callers and runtime info to err only, and calls `os.Exit(1)`.
Expand Down
10 changes: 5 additions & 5 deletions adaptor_test.go
Expand Up @@ -11,14 +11,14 @@ import (

func TestAdaptor_ToWriter(t *testing.T) {
rout, rerr := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{})
l := New(Out(rout), Err(rerr), Msec, LevelBraces)
l := New(Out(rout), Err(rerr), Format(WithMsec))
l.now = func() time.Time { return time.Date(2018, 1, 7, 13, 2, 34, 0, time.Local) }

wr := ToWriter(l, "WARN")
sz, err := wr.Write([]byte("something blah 123"))
require.NoError(t, err)
assert.Equal(t, 18, sz)
assert.Equal(t, "2018/01/07 13:02:34.000 [WARN] something blah 123\n", rout.String())
assert.Equal(t, "2018/01/07 13:02:34.000 WARN something blah 123\n", rout.String())
}

func TestAdaptor_ToWriterNoLevel(t *testing.T) {
Expand All @@ -41,15 +41,15 @@ func TestAdaptor_ToWriterNoLevel(t *testing.T) {

func TestAdaptor_ToStdLogger(t *testing.T) {
rout, rerr := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{})
l := New(Out(rout), Err(rerr), Msec, LevelBraces)
l := New(Out(rout), Err(rerr), Format(WithMsec))
l.now = func() time.Time { return time.Date(2018, 1, 7, 13, 2, 34, 0, time.Local) }

wr := ToStdLogger(l, "WARN")
wr.Print("something")
assert.Equal(t, "2018/01/07 13:02:34.000 [WARN] something\n", rout.String())
assert.Equal(t, "2018/01/07 13:02:34.000 WARN something\n", rout.String())

rout.Reset()
rerr.Reset()
wr.Printf("xxx %s", "yyy")
assert.Equal(t, "2018/01/07 13:02:34.000 [WARN] xxx yyy\n", rout.String())
assert.Equal(t, "2018/01/07 13:02:34.000 WARN xxx yyy\n", rout.String())
}
12 changes: 7 additions & 5 deletions interface_test.go
Expand Up @@ -67,16 +67,18 @@ func TestDefault(t *testing.T) {

func TestDefaultWithSetup(t *testing.T) {
buff := bytes.NewBuffer([]byte{})
Setup(Out(buff), Debug, CallerFile, CallerFunc, Msec, LevelBraces)
Setup(Out(buff), Debug, Format(FullDebug))
def.now = func() time.Time { return time.Date(2018, 1, 7, 13, 2, 34, 0, time.Local) }
Printf("[INFO] something 123 %s", "xyz")
assert.Equal(t, "2018/01/07 13:02:34.000 [INFO] {lgr/interface_test.go:72 lgr.TestDefaultWithSetup} something 123 xyz\n", buff.String())
Printf("[DEBUG] something 123 %s", "xyz")
assert.Equal(t, "2018/01/07 13:02:34.000 DEBUG (lgr/interface_test.go:72 lgr.TestDefaultWithSetup) something 123 xyz\n",
buff.String())
}

func TestDefaultFuncWithSetup(t *testing.T) {
buff := bytes.NewBuffer([]byte{})
Setup(Out(buff), Debug, CallerFile, CallerFunc, Msec, LevelBraces)
Setup(Out(buff), Debug, Format(FullDebug))
def.now = func() time.Time { return time.Date(2018, 1, 7, 13, 2, 34, 0, time.Local) }
Default().Logf("[INFO] something 123 %s", "xyz")
assert.Equal(t, "2018/01/07 13:02:34.000 [INFO] {lgr/interface_test.go:80 lgr.TestDefaultFuncWithSetup} something 123 xyz\n", buff.String())
assert.Equal(t, "2018/01/07 13:02:34.000 INFO (lgr/interface_test.go:81 lgr."+
"TestDefaultFuncWithSetup) something 123 xyz\n", buff.String())
}

0 comments on commit eadc464

Please sign in to comment.