Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

otelzap: Basic implementation of Core.Write #5539

Merged
merged 25 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
6e38ddd
Implement functionality of Core
khushijain21 May 9, 2024
ac3cd9d
write tests for with and write
khushijain21 May 9, 2024
72110a2
remove comments
khushijain21 May 9, 2024
1f2b21d
Merge branch 'main' into zapcore2
khushijain21 May 9, 2024
444be44
Update bridges/otelzap/core.go
khushijain21 May 13, 2024
e3900ce
addressed requested changes
khushijain21 May 13, 2024
16e183e
addressed requested changes
khushijain21 May 13, 2024
e51ae34
changes
khushijain21 May 13, 2024
7dee762
Merge branch 'main' into zapcore2
khushijain21 May 13, 2024
262196d
add check method
khushijain21 May 13, 2024
2ef1105
Merge branch 'zapcore2' of https://github.com/khushijain21/openteleme…
khushijain21 May 13, 2024
80a541b
minor changes
khushijain21 May 13, 2024
f78d702
Update bridges/otelzap/core.go
khushijain21 May 15, 2024
5059a86
Update bridges/otelzap/core.go
khushijain21 May 15, 2024
4571a02
Merge branch 'main' into zapcore2
khushijain21 May 15, 2024
a3c6c83
accomdodate feedback
khushijain21 May 15, 2024
9d820df
Merge branch 'zapcore2' of https://github.com/khushijain21/openteleme…
khushijain21 May 15, 2024
02489df
Update core_test.go
pellared May 15, 2024
b10604a
format
pellared May 15, 2024
d3e6ee4
Update core_test.go
pellared May 15, 2024
1d91526
Update core.go
pellared May 15, 2024
fbf0ddd
Update core.go
pellared May 15, 2024
baa33cb
Update bridges/otelzap/core.go
khushijain21 May 15, 2024
accb80c
Update bridges/otelzap/core_test.go
khushijain21 May 15, 2024
2db5b6b
Merge branch 'main' into zapcore2
pellared May 15, 2024
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
63 changes: 59 additions & 4 deletions bridges/otelzap/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
package otelzap // import "go.opentelemetry.io/contrib/bridges/otelzap"

import (
"context"
"fmt"
"slices"

"go.uber.org/zap/zapcore"

"go.opentelemetry.io/otel/log"
Expand Down Expand Up @@ -92,6 +96,7 @@
// Core is a [zapcore.Core] that sends logging records to OpenTelemetry.
type Core struct {
logger log.Logger
attr []log.KeyValue
}

// Compile-time check *Core implements zapcore.Core.
Expand All @@ -105,16 +110,22 @@
}
}

// TODO
// LevelEnabler decides whether a given logging level is enabled when logging a message.
func (o *Core) Enabled(level zapcore.Level) bool {
return true
r := log.Record{}
r.SetSeverity(getOTelLevel(level))
return o.logger.Enabled(context.Background(), r)
}

// TODO
// With adds structured context to the Core.
func (o *Core) With(fields []zapcore.Field) zapcore.Core {
return o
clone := o.clone()
if len(fields) > 0 {
// TODO convert zap fields to otel attributes
fmt.Println("TODO")
}
return clone
}

// TODO
Expand All @@ -123,14 +134,58 @@
return nil
}

// TODO
// Check determines whether the supplied Entry should be logged using core.Enabled method.
khushijain21 marked this conversation as resolved.
Show resolved Hide resolved
func (o *Core) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
if o.Enabled(ent.Level) {
pellared marked this conversation as resolved.
Show resolved Hide resolved
return ce.AddCore(ent, o)

Check warning on line 140 in bridges/otelzap/core.go

View check run for this annotation

Codecov / codecov/patch

bridges/otelzap/core.go#L139-L140

Added lines #L139 - L140 were not covered by tests
}
return ce
}

// TODO
khushijain21 marked this conversation as resolved.
Show resolved Hide resolved
// Write method encodes zap fields to OTel logs and emits them.
func (o *Core) Write(ent zapcore.Entry, fields []zapcore.Field) error {
r := log.Record{}
r.SetTimestamp(ent.Time)
r.SetBody(log.StringValue(ent.Message))
r.SetSeverity(getOTelLevel(ent.Level))

if len(fields) > 0 {
// TODO map zap field to otel attributes
fmt.Println("TODO")
} else {
r.AddAttributes(o.attr...)

Check warning on line 157 in bridges/otelzap/core.go

View check run for this annotation

Codecov / codecov/patch

bridges/otelzap/core.go#L157

Added line #L157 was not covered by tests
}
khushijain21 marked this conversation as resolved.
Show resolved Hide resolved

o.logger.Emit(context.Background(), r)
return nil
}

func (o *Core) clone() *Core {
return &Core{
logger: o.logger,
attr: slices.Clone(o.attr),
}
}

// converts zap level to OTel log level.
func getOTelLevel(level zapcore.Level) log.Severity {
khushijain21 marked this conversation as resolved.
Show resolved Hide resolved
switch level {
case zapcore.DebugLevel:
return log.SeverityDebug
case zapcore.InfoLevel:
return log.SeverityInfo
case zapcore.WarnLevel:
return log.SeverityWarn
case zapcore.ErrorLevel:
return log.SeverityError
case zapcore.DPanicLevel:
return log.SeverityFatal1
case zapcore.PanicLevel:
return log.SeverityFatal2
case zapcore.FatalLevel:
return log.SeverityFatal3
default:
return log.SeverityUndefined
}
}
82 changes: 82 additions & 0 deletions bridges/otelzap/core_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,30 @@
package otelzap

import (
"context"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"

"go.opentelemetry.io/otel/log"
"go.opentelemetry.io/otel/log/global"
"go.opentelemetry.io/otel/log/logtest"
"go.opentelemetry.io/otel/sdk/instrumentation"
)

var (
testBodyString = "log message"
testSeverity = log.SeverityInfo
entry = zapcore.Entry{
Level: zapcore.InfoLevel,
Message: testBodyString,
}
field = zap.String("key", "testValue")
)

func TestNewCoreConfiguration(t *testing.T) {
t.Run("Default", func(t *testing.T) {
r := logtest.NewRecorder()
Expand Down Expand Up @@ -53,3 +67,71 @@ func TestNewCoreConfiguration(t *testing.T) {
assert.Equal(t, want, got)
dmathieu marked this conversation as resolved.
Show resolved Hide resolved
})
}

func TestCoreEnabled(t *testing.T) {
enabledFunc := func(c context.Context, r log.Record) bool {
return r.Severity() >= log.SeverityInfo
}

r := logtest.NewRecorder(logtest.WithEnabledFunc(enabledFunc))
zc := NewCore(WithLoggerProvider(r))

assert.False(t, zc.Enabled(zap.DebugLevel), "level conversion: permissive")
assert.True(t, zc.Enabled(zap.InfoLevel), "level conversion: restrictive")
}

// Test conversion of Zap Level to OTel level.
func TestGetOTelLevel(t *testing.T) {
tests := []struct {
level zapcore.Level
expectedSev log.Severity
}{
{zapcore.DebugLevel, log.SeverityDebug},
{zapcore.InfoLevel, log.SeverityInfo},
{zapcore.WarnLevel, log.SeverityWarn},
{zapcore.ErrorLevel, log.SeverityError},
{zapcore.DPanicLevel, log.SeverityFatal1},
{zapcore.PanicLevel, log.SeverityFatal2},
{zapcore.FatalLevel, log.SeverityFatal3},
{zapcore.InvalidLevel, log.SeverityUndefined},
}

for _, test := range tests {
result := getOTelLevel(test.level)
if result != test.expectedSev {
t.Errorf("For level %v, expected %v but got %v", test.level, test.expectedSev, result)
}
}
}

// Tests [Core] write method.
func TestCore(t *testing.T) {
rec := logtest.NewRecorder()
zc := NewCore(WithLoggerProvider(rec))

t.Run("test Write method of Core", func(t *testing.T) {
err := zc.Write(entry, []zap.Field{field})
pellared marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
t.Errorf("Error occurred: %v", err)
}

// why is index 1 populated with results and not 0?
got := rec.Result()[1].Records[0]
assert.Equal(t, testBodyString, got.Body().AsString())
assert.Equal(t, testSeverity, got.Severity())
pellared marked this conversation as resolved.
Show resolved Hide resolved

// TODO test record attributes

rec.Reset()
pellared marked this conversation as resolved.
Show resolved Hide resolved
})

t.Run("test With method of Core", func(t *testing.T) {
childCore := zc.With([]zap.Field{field})
assert.Equal(t, childCore, zc)

// TODO test record attributes

rec.Reset()
})

}
Loading