From 2482c8ffc33e39cae2ce057865cc82669bd3ce3b Mon Sep 17 00:00:00 2001 From: Jean Mertz Date: Wed, 13 May 2020 09:26:37 +0200 Subject: [PATCH] prevent duplicate labels fields --- core.go | 2 +- core_test.go | 22 ++++++++++++++++++++++ label.go | 23 +++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/core.go b/core.go index bcb7660..4408de8 100644 --- a/core.go +++ b/core.go @@ -121,7 +121,7 @@ func (c *core) Write(ent zapcore.Entry, fields []zapcore.Field) error { c.tempLabels.mutex.Unlock() lbls.mutex.RUnlock() - fields = append(fields, labelsField(c.allLabels())) + fields = mergeLabelFields(fields, c.allLabels()) fields = c.withSourceLocation(ent, fields) if c.config.ServiceName != "" { fields = c.withServiceContext(c.config.ServiceName, fields) diff --git a/core_test.go b/core_test.go index 85d8c3a..9485300 100644 --- a/core_test.go +++ b/core_test.go @@ -180,6 +180,28 @@ func TestWrite(t *testing.T) { assert.NotNil(t, logs.All()[0].ContextMap()[labelsKey]) } +// ref: https://github.com/blendle/zapdriver/issues/29 +func TestWriteDuplicateLabels(t *testing.T) { + debugcore, logs := observer.New(zapcore.DebugLevel) + core := &core{ + Core: debugcore, + permLabels: newLabels(), + tempLabels: newLabels(), + } + + fields := []zap.Field{ + Labels( + Label("hello", "world"), + Label("hi", "universe"), + ), + } + + err := core.Write(zapcore.Entry{}, fields) + require.NoError(t, err) + + assert.Len(t, logs.All()[0].Context, 1) +} + func TestWriteConcurrent(t *testing.T) { temp := newLabels() temp.store = map[string]string{"one": "1", "two": "2"} diff --git a/label.go b/label.go index 7238642..2512b9b 100644 --- a/label.go +++ b/label.go @@ -45,6 +45,29 @@ func labelsField(l *labels) zap.Field { return zap.Object(labelsKey, l) } +func mergeLabelFields(fields []zap.Field, newLabels *labels) []zap.Field { + for i := range fields { + lbls, ok := fields[i].Interface.(*labels) + if !ok { + continue + } + + newLabels.mutex.RLock() + defer newLabels.mutex.RUnlock() + + lbls.mutex.Lock() + defer lbls.mutex.Unlock() + + for k, v := range newLabels.store { + lbls.store[k] = v + } + + return fields + } + + return append(fields, labelsField(newLabels)) +} + type labels struct { store map[string]string mutex *sync.RWMutex