Skip to content

Commit

Permalink
feature: ability to set context for log, output can use context to ga…
Browse files Browse the repository at this point in the history
…ther extra context info
  • Loading branch information
Ak-Army committed Sep 2, 2024
1 parent 55ad774 commit 24494b2
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 5 deletions.
4 changes: 4 additions & 0 deletions nop.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package xlog

import "context"

type nop struct{}

// NopLogger is an no-op implementation of xlog.Logger
Expand Down Expand Up @@ -43,3 +45,5 @@ func (n nop) Write(p []byte) (int, error) { return len(p), nil }
func (n nop) Output(calldepth int, s string) error {
return nil
}

func (n nop) SetContext(ctx context.Context) {}
6 changes: 3 additions & 3 deletions output.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ func (o consoleOutput) write(fields map[string]interface{}) error {
keys := []string{}
for k := range fields {
switch k {
case KeyLevel, KeyMessage, KeyTime, KeyError:
case KeyLevel, KeyMessage, KeyTime, KeyError, KeyContext:
continue
}
keys = append(keys, k)
Expand Down Expand Up @@ -337,7 +337,7 @@ func (o consoleOutput) writeWithColor(fields map[string]interface{}) error {
keys := []string{}
for k := range fields {
switch k {
case KeyLevel, KeyMessage, KeyTime, KeyError:
case KeyLevel, KeyMessage, KeyTime, KeyError, KeyContext:
continue
}
keys = append(keys, k)
Expand Down Expand Up @@ -377,7 +377,7 @@ func (o logfmtOutput) Write(fields map[string]interface{}) error {
keys := []string{}
for k := range fields {
switch k {
case KeyLevel, KeyMessage, KeyTime, KeyError:
case KeyLevel, KeyMessage, KeyTime, KeyError, KeyContext:
continue
}
keys = append(keys, k)
Expand Down
1 change: 1 addition & 0 deletions output_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func newTestOutputErr(err error) *testOutput {
}

func (o *testOutput) Write(fields map[string]interface{}) (err error) {
delete(fields, KeyContext)
o.w <- fields
return o.err
}
Expand Down
18 changes: 16 additions & 2 deletions xlog.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
package xlog // import "github.com/Ak-Army/xlog"

import (
"context"
"fmt"
"io"
"log"
Expand All @@ -38,6 +39,9 @@ type Logger interface {
// Implements io.Writer so it can be set a output of log.Logger
io.Writer

// SetContext set the context for logging. All future messages on this logger
// will have this context set.
SetContext(ctx context.Context)
// SetField sets a field on the logger's context. All future messages on this logger
// will have this field set.
SetField(name string, value interface{})
Expand Down Expand Up @@ -115,6 +119,7 @@ type logger struct {
level Level
output Output
fields F
ctx context.Context
disablePooling bool
disableCallerInfo bool
}
Expand All @@ -126,6 +131,7 @@ var (
KeyLevel = "level"
KeyFile = "file"
KeyError = "error"
KeyContext = "context"
)

var now = time.Now
Expand All @@ -152,6 +158,7 @@ func New(c Config) Logger {
}
l.level = c.Level
l.output = c.Output
l.ctx = context.Background()
if l.output == nil {
l.output = NewOutputChannel(NewConsoleOutput())
}
Expand All @@ -177,6 +184,7 @@ func (l *logger) Copy() Logger {
output: l.output,
fields: map[string]interface{}{},
disablePooling: l.disablePooling,
ctx: l.ctx,
}
for k, v := range l.fields {
l2.fields[k] = v
Expand All @@ -202,6 +210,7 @@ func (l *logger) send(level Level, calldepth int, msg string, fields map[string]
data[KeyTime] = now()
data[KeyLevel] = level.String()
data[KeyMessage] = msg
data[KeyContext] = l.ctx
if err != nil {
data[KeyError] = err
}
Expand Down Expand Up @@ -247,6 +256,11 @@ func extractFields(v *[]interface{}) (map[string]interface{}, error) {
return f, e
}

// SetContext implements Logger interface
func (l *logger) SetContext(ctx context.Context) {
l.ctx = ctx
}

// SetField implements Logger interface
func (l *logger) SetField(name string, value interface{}) {
if l.fields == nil {
Expand All @@ -255,7 +269,7 @@ func (l *logger) SetField(name string, value interface{}) {
l.fields[name] = value
}

// SetFields
// SetFields implements Logger interface
func (l *logger) SetFields(fields F) {
if l.fields == nil {
l.fields = map[string]interface{}{}
Expand All @@ -270,7 +284,7 @@ func (l *logger) GetFields() F {
return l.fields
}

// Output implements Logger interface
// OutputF implements Logger interface
func (l *logger) OutputF(level Level, calldepth int, msg string, fields map[string]interface{}, err error) {
l.send(level, calldepth+1, msg, fields, err)
}
Expand Down
37 changes: 37 additions & 0 deletions xlog_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package xlog

import (
"context"
"errors"
"io"
"log"
Expand Down Expand Up @@ -342,3 +343,39 @@ func TestOutput(t *testing.T) {
delete(last, "file")
assert.Equal(t, map[string]interface{}{"time": fakeNow, "level": "info", "message": "test"}, last)
}

func TestOutput2(t *testing.T) {
o := newTestOutput()
l := New(Config{Output: o}).(*logger)
done := make(chan struct{})
end := make(chan struct{})
go func() {
defer close(end)
for {
select {
case <-done:
return
default:
l.Output(2, "test")
last := <-o.w
assert.Contains(t, last["file"], "log_test.go:")
delete(last, "file")
assert.Equal(t, map[string]interface{}{"time": fakeNow, "level": "info", "message": "test"}, last)
}
}
}()
go func() {
for {
select {
case <-done:
return
default:
ll := l.Copy()
ll.SetContext(context.Background())
}
}
}()
time.Sleep(time.Second)
close(done)
<-end
}

0 comments on commit 24494b2

Please sign in to comment.