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: Add skeleton and config options #5449

Merged
merged 19 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,15 @@ updates:
schedule:
interval: weekly
day: sunday
- package-ecosystem: gomod
directory: /bridges/otelzap
labels:
- dependencies
- go
- Skip Changelog
schedule:
interval: weekly
day: sunday
- package-ecosystem: gomod
directory: /bridges/prometheus
labels:
Expand Down
82 changes: 82 additions & 0 deletions bridges/otelzap/config.go
pellared marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package otelzap // import "otelzap"
khushijain21 marked this conversation as resolved.
Show resolved Hide resolved

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

type config struct {
provider log.LoggerProvider
scope instrumentation.Scope
}

func newConfig(options []Option) config {
var c config
for _, opt := range options {
c = opt.apply(c)
}

var emptyScope instrumentation.Scope
if c.scope == emptyScope {
c.scope = instrumentation.Scope{
Name: bridgeName,
Version: version,
}
}

if c.provider == nil {
c.provider = global.GetLoggerProvider()
}

return c
}

func (c config) logger() log.Logger {
var opts []log.LoggerOption
if c.scope.Version != "" {
opts = append(opts, log.WithInstrumentationVersion(c.scope.Version))
}
if c.scope.SchemaURL != "" {
opts = append(opts, log.WithSchemaURL(c.scope.SchemaURL))
}
return c.provider.Logger(c.scope.Name, opts...)
}

// Option configures a [zapcore].
khushijain21 marked this conversation as resolved.
Show resolved Hide resolved
type Option interface {
apply(config) config
}

type optFunc func(config) config

func (f optFunc) apply(c config) config { return f(c) }

// WithInstrumentationScope returns an [Option] that configures the scope of
// the [log.Logger] used by a [zapcore].
khushijain21 marked this conversation as resolved.
Show resolved Hide resolved
//
// By default if this Option is not provided, the zapcore will use a default
khushijain21 marked this conversation as resolved.
Show resolved Hide resolved
// instrumentation scope describing this bridge package. It is recommended to
// provide this so log data can be associated with its source package or
// module.
func WithInstrumentationScope(scope instrumentation.Scope) Option {
return optFunc(func(c config) config {
c.scope = scope
return c
})
}

// WithLoggerProvider returns an [Option] that configures [log.LoggerProvider]
// used by a [Core] to create its [log.Logger].
//
// By default if this Option is not provided, the Handler will use the global
// LoggerProvider.
func WithLoggerProvider(provider log.LoggerProvider) Option {
return optFunc(func(c config) config {
c.provider = provider
return c
})
}
62 changes: 62 additions & 0 deletions bridges/otelzap/core.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

// Package otelzap provides a bridge between the [go.uber.org/zap] and
// OpenTelemetry logging.
package otelzap // import "otelzap"

import (
"go.uber.org/zap/zapcore"

"go.opentelemetry.io/otel/log"
)

const (
bridgeName = "go.opentelemetry.io/contrib/bridges/otelzap"
)

// Core is a [zapcore.Core] that sends logging records to OpenTelemetry.
type Core struct {
logger log.Logger
}

// Compile-time check *Core implements zapcore.Core.
var _ zapcore.Core = (*Core)(nil)

// NewOTelZapCore creates a new [zapcore.Core] that can be used with zap.New()
// this instance will translate zap logs to opentelemetry logs and export them.
khushijain21 marked this conversation as resolved.
Show resolved Hide resolved
func NewCore(opts ...Option) *Core {
cfg := newConfig(opts)
return &Core{
logger: cfg.logger(),
}
}

// TODO
// LevelEnabler decides whether a given logging level is enabled when logging a message.
func (o *Core) Enabled(level zapcore.Level) bool {
return true

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

View check run for this annotation

Codecov / codecov/patch

bridges/otelzap/core.go#L37-L38

Added lines #L37 - L38 were not covered by tests
}

// TODO
// With adds structured context to the Core.
func (o *Core) With(fields []zapcore.Field) zapcore.Core {
return o

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

View check run for this annotation

Codecov / codecov/patch

bridges/otelzap/core.go#L43-L44

Added lines #L43 - L44 were not covered by tests
}

// Sync flushes buffered logs (if any).
khushijain21 marked this conversation as resolved.
Show resolved Hide resolved
func (o *Core) Sync() error {
return nil

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

View check run for this annotation

Codecov / codecov/patch

bridges/otelzap/core.go#L48-L49

Added lines #L48 - L49 were not covered by tests
}

// Check determines whether the supplied Entry should be logged using core.Enabled method.
func (o *Core) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {

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

View check run for this annotation

Codecov / codecov/patch

bridges/otelzap/core.go#L53

Added line #L53 was not covered by tests
// TODO
return ce

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

View check run for this annotation

Codecov / codecov/patch

bridges/otelzap/core.go#L55

Added line #L55 was not covered by tests
}

// TODO
// Write method encodes zap fields to OTel logs and emits them.
func (o *Core) Write(ent zapcore.Entry, fields []zapcore.Field) error {
return nil

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

View check run for this annotation

Codecov / codecov/patch

bridges/otelzap/core.go#L60-L61

Added lines #L60 - L61 were not covered by tests
}
51 changes: 51 additions & 0 deletions bridges/otelzap/core_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

// Copyright (c) 2016-2017 Uber Technologies, Inc.
khushijain21 marked this conversation as resolved.
Show resolved Hide resolved
package otelzap

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

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

func TestNewCoreConfiguration(t *testing.T) {
t.Run("Default", func(t *testing.T) {
r := logtest.NewRecorder()
global.SetLoggerProvider(r)
khushijain21 marked this conversation as resolved.
Show resolved Hide resolved

var h *Core
assert.NotPanics(t, func() { h = NewCore() })
assert.NotNil(t, h.logger)
require.IsType(t, &logtest.Recorder{}, h.logger)

l := h.logger.(*logtest.Recorder)
want := &logtest.ScopeRecords{Name: bridgeName, Version: version}
assert.Equal(t, want, l.Result()[0])
khushijain21 marked this conversation as resolved.
Show resolved Hide resolved
})

t.Run("Options", func(t *testing.T) {
r := logtest.NewRecorder()
scope := instrumentation.Scope{Name: "name", Version: "ver", SchemaURL: "url"}
var h *Core
assert.NotPanics(t, func() {
khushijain21 marked this conversation as resolved.
Show resolved Hide resolved
h = NewCore(
WithLoggerProvider(r),
WithInstrumentationScope(scope),
)
})
assert.NotNil(t, h.logger)
khushijain21 marked this conversation as resolved.
Show resolved Hide resolved
require.IsType(t, &logtest.Recorder{}, h.logger)

l := h.logger.(*logtest.Recorder)
assert.Equal(t, scope.Name, l.Result()[0].Name)
assert.Equal(t, scope.Version, l.Result()[0].Version)
assert.Equal(t, scope.SchemaURL, l.Result()[0].SchemaURL)
khushijain21 marked this conversation as resolved.
Show resolved Hide resolved
})
}
22 changes: 22 additions & 0 deletions bridges/otelzap/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module otelzap

go 1.21

require (
github.com/stretchr/testify v1.9.0
go.opentelemetry.io/otel/log v0.2.0-alpha
go.opentelemetry.io/otel/sdk v1.26.0
go.uber.org/zap v1.27.0
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.opentelemetry.io/otel v1.26.0 // indirect
go.opentelemetry.io/otel/metric v1.26.0 // indirect
go.opentelemetry.io/otel/trace v1.26.0 // indirect
go.uber.org/multierr v1.10.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
33 changes: 33 additions & 0 deletions bridges/otelzap/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs=
go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4=
go.opentelemetry.io/otel/log v0.2.0-alpha h1:ixOPvMzserpqA07SENHvRzkZOsnG0XbPr74hv1AQ+n0=
go.opentelemetry.io/otel/log v0.2.0-alpha/go.mod h1:vbFZc65yq4c4ssvXY43y/nIqkNJLxORrqw0L85P59LA=
go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30=
go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4=
go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8=
go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs=
go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA=
go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
7 changes: 7 additions & 0 deletions bridges/otelzap/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package otelzap // import "otelzap"

// Version is the current release version of otelzap in use.
const version = "0.1.0"
1 change: 1 addition & 0 deletions versions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,4 @@ excluded-modules:
- go.opentelemetry.io/contrib/instrgen
- go.opentelemetry.io/contrib/instrgen/driver
- go.opentelemetry.io/contrib/instrgen/testdata/interface
- go.opentelemetry.io/contrib/bridges/otelzap
khushijain21 marked this conversation as resolved.
Show resolved Hide resolved