Skip to content

Commit

Permalink
Add the log/noop package (#4943)
Browse files Browse the repository at this point in the history
* Add the `log/noop` package

* Add implementation tests

---------

Co-authored-by: Robert Pająk <[email protected]>
  • Loading branch information
MrAlias and pellared authored Feb 20, 2024
1 parent 3fe7401 commit dd3b00f
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 0 deletions.
56 changes: 56 additions & 0 deletions log/noop/noop.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package noop provides an implementation of the OpenTelemetry Logs Bridge API
// that produces no telemetry and minimizes used computation resources.
//
// Using this package to implement the OpenTelemetry Logs Bridge API will
// effectively disable OpenTelemetry.
//
// This implementation can be embedded in other implementations of the
// OpenTelemetry Logs Bridge API. Doing so will mean the implementation
// defaults to no operation for methods it does not implement.
package noop // import "go.opentelemetry.io/otel/log/noop"

import (
"context"

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

var (
// Compile-time check this implements the OpenTelemetry API.
_ log.LoggerProvider = LoggerProvider{}
_ log.Logger = Logger{}
)

// LoggerProvider is an OpenTelemetry No-Op LoggerProvider.
type LoggerProvider struct{ embedded.LoggerProvider }

// NewLoggerProvider returns a LoggerProvider that does not record any telemetry.
func NewLoggerProvider() LoggerProvider {
return LoggerProvider{}
}

// Logger returns an OpenTelemetry Logger that does not record any telemetry.
func (LoggerProvider) Logger(string, ...log.LoggerOption) log.Logger {
return Logger{}
}

// Logger is an OpenTelemetry No-Op Logger.
type Logger struct{ embedded.Logger }

// Emit does nothing.
func (Logger) Emit(context.Context, log.Record) {}
81 changes: 81 additions & 0 deletions log/noop/noop_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package noop // import "go.opentelemetry.io/otel/log/noop"

import (
"context"
"reflect"
"testing"

"github.com/stretchr/testify/assert"

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

func TestImplementationNoPanics(t *testing.T) {
// Check that if type has an embedded interface and that interface has
// methods added to it than the No-Op implementation implements them.
t.Run("LoggerProvider", assertAllExportedMethodNoPanic(
reflect.ValueOf(LoggerProvider{}),
reflect.TypeOf((*log.LoggerProvider)(nil)).Elem(),
))
t.Run("Logger", assertAllExportedMethodNoPanic(
reflect.ValueOf(Logger{}),
reflect.TypeOf((*log.Logger)(nil)).Elem(),
))
}

func assertAllExportedMethodNoPanic(rVal reflect.Value, rType reflect.Type) func(*testing.T) {
return func(t *testing.T) {
for n := 0; n < rType.NumMethod(); n++ {
mType := rType.Method(n)
if !mType.IsExported() {
t.Logf("ignoring unexported %s", mType.Name)
continue
}
m := rVal.MethodByName(mType.Name)
if !m.IsValid() {
t.Errorf("unknown method for %s: %s", rVal.Type().Name(), mType.Name)
}

numIn := mType.Type.NumIn()
if mType.Type.IsVariadic() {
numIn--
}
args := make([]reflect.Value, numIn)
ctx := context.Background()
for i := range args {
aType := mType.Type.In(i)
if aType.Name() == "Context" {
// Do not panic on a nil context.
args[i] = reflect.ValueOf(ctx)
} else {
args[i] = reflect.New(aType).Elem()
}
}

assert.NotPanicsf(t, func() {
_ = m.Call(args)
}, "%s.%s", rVal.Type().Name(), mType.Name)
}
}
}

func TestNewTracerProvider(t *testing.T) {
provider := NewLoggerProvider()
assert.Equal(t, provider, LoggerProvider{})
logger := provider.Logger("")
assert.Equal(t, logger, Logger{})
}

0 comments on commit dd3b00f

Please sign in to comment.