Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

## [Unreleased]

### Fixed

- Fix data race when writing log entries with `context.Context` fields in `go.opentelemetry.io/contrib/bridges/otelzap`. (#7368)

<!-- Released section -->
<!-- Don't change this section unless doing release -->

Expand Down
5 changes: 3 additions & 2 deletions bridges/otelzap/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,11 @@ func (o *Core) Write(ent zapcore.Entry, fields []zapcore.Field) error {
if ent.Stack != "" {
r.AddAttributes(log.String(string(semconv.CodeStacktraceKey), ent.Stack))
}
emitCtx := o.ctx
if len(fields) > 0 {
ctx, attrbuf := convertField(fields)
if ctx != nil {
o.ctx = ctx
emitCtx = ctx
}
r.AddAttributes(attrbuf...)
}
Expand All @@ -235,7 +236,7 @@ func (o *Core) Write(ent zapcore.Entry, fields []zapcore.Field) error {
if ent.LoggerName != "" {
logger = o.provider.Logger(ent.LoggerName, o.opts...)
}
logger.Emit(o.ctx, r)
logger.Emit(emitCtx, r)
return nil
}

Expand Down
33 changes: 33 additions & 0 deletions bridges/otelzap/core_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package otelzap

import (
"context"
"sync"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -144,6 +145,38 @@ func TestCore(t *testing.T) {
})
}

func TestCoreConcurrentSafe(t *testing.T) {
rec := logtest.NewRecorder()
zc := NewCore(loggerName, WithLoggerProvider(rec))
logger := zap.New(zc)

t.Run("Write", func(t *testing.T) {
var wg sync.WaitGroup
const n = 2
wg.Add(n)
ctx := context.Background()
for i := 0; i < n; i++ {
go func() {
defer wg.Done()
logger.Info(testMessage, zap.String(testKey, testValue), zap.Any("ctx", ctx))
}()
}
wg.Wait()

result := rec.Result()
require.Len(t, result, 1)
require.Len(t, result[logtest.Scope{Name: "name"}], 2)
got := result[logtest.Scope{Name: "name"}][0]

assert.Equal(t, testMessage, got.Body.AsString())
assert.Equal(t, log.SeverityInfo, got.Severity)
assert.Equal(t, zap.InfoLevel.String(), got.SeverityText)
assert.Equal(t, []log.KeyValue{
log.String(testKey, testValue),
}, got.Attributes)
Comment thread
pellared marked this conversation as resolved.
})
}

func TestCoreEnabled(t *testing.T) {
enabledFunc := func(c context.Context, param log.EnabledParameters) bool {
return param.Severity >= log.SeverityInfo
Expand Down