diff --git a/entity.go b/entity.go index df284c7..019fde8 100644 --- a/entity.go +++ b/entity.go @@ -65,6 +65,12 @@ type Summary interface { // Size returns the log content size. Size() int + + // Clone returns a copy of the current log summary (excluding context). + Clone() Summary + + // CloneWithContext returns a copy of the current log summary and sets its context to the given value. + CloneWithContext(context.Context) Summary } // The logEntity type is a built-in implementation of the Entity interface. @@ -141,6 +147,43 @@ func (o *logEntity) Size() int { return o.buffer.Len() } +// Clone returns a copy of the current log summary (excluding context). +func (o *logEntity) Clone() Summary { + return o.CloneWithContext(nil) +} + +// CloneWithContext returns a copy of the current log summary and sets its context to the given value. +func (o *logEntity) CloneWithContext(ctx context.Context) Summary { + var buffer *bytes.Buffer + if bs := o.buffer.Bytes(); len(bs) > 0 { + cp := make([]byte, len(bs)) + copy(cp, bs) + buffer = bytes.NewBuffer(cp) + } else { + buffer = new(bytes.Buffer) + } + + var fields map[string]interface{} + if n := len(o.fields); n > 0 { + fields = make(map[string]interface{}, n) + for k, v := range o.fields { + fields[k] = v + } + } + + return &logEntity{ + name: o.name, + time: o.time, + timeFormat: o.timeFormat, + level: o.level, + message: o.message, + fields: fields, + ctx: ctx, + buffer: *buffer, + caller: o.caller, + } +} + // Read is the implementation of io.Reader interface. func (o *logEntity) Read(p []byte) (int, error) { return o.buffer.Read(p) diff --git a/entity_test.go b/entity_test.go index 22240b1..808fc81 100644 --- a/entity_test.go +++ b/entity_test.go @@ -16,6 +16,7 @@ package logger import ( "bytes" + "context" "fmt" "io/ioutil" "testing" @@ -69,6 +70,14 @@ func TestLogEntityAndSummary(t *testing.T) { if got := o.Size(); got != 4 { t.Fatalf("Summary.Size(): %d", got) } + + if o.Clone() == nil { + t.Fatalf("Summary.Clone(): nil") + } + if o.CloneWithContext(context.Background()) == nil { + t.Fatalf("Summary.CloneWithContext(): nil") + } + if got, err := ioutil.ReadAll(o); err == nil { if !bytes.Equal(got, []byte("test")) { t.Fatalf("Summary.Read(): %s", string(got)) @@ -76,4 +85,12 @@ func TestLogEntityAndSummary(t *testing.T) { } else { t.Fatalf("Summary.Read(): %s", err) } + // empty buffer + if o.Clone() == nil { + t.Fatalf("Summary.Clone(): nil") + } + // empty buffer + if o.CloneWithContext(context.Background()) == nil { + t.Fatalf("Summary.CloneWithContext(): nil") + } }