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

Enhance internal logging #3900

Merged
merged 13 commits into from
Mar 21, 2023
2 changes: 2 additions & 0 deletions CHANGELOG.md
unicod3 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- The new `Exemplar` type is added to `go.opentelemetry.io/otel/sdk/metric/metricdata`.
Both the `DataPoint` and `HistogramDataPoint` types from that package have a new field of `Exemplars` containing the sampled exemplars for their timeseries. (#3849)
- Configuration for each metric instrument in `go.opentelemetry.io/otel/sdk/metric/instrument`. (#3895)
- The internal logging introduces a warning level verbosity equal to `V(1)`. (#3900)

### Changed

Expand All @@ -29,6 +30,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- `NewNoopMeter` is replaced with `noop.NewMeterProvider().Meter("")`
- Rename `Int64ObserverOption` to `Int64ObservableOption` in `go.opentelemetry.io/otel/metric/instrument`. (#3895)
- Rename `Float64ObserverOption` to `Float64ObservableOption` in `go.opentelemetry.io/otel/metric/instrument`. (#3895)
- The internal logging changes the verbosity level of info to `V(4)`, the verbosity level of debug to `V(8)`. (#3900)

### Removed

Expand Down
19 changes: 13 additions & 6 deletions internal/global/internal_logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
"github.com/go-logr/stdr"
)

// globalLogger is the logging interface used within the otel api and sdk provide deatails of the internals.
// globalLogger is the logging interface used within the otel api and sdk provide details of the internals.
//
// The default logger uses stdr which is backed by the standard `log.Logger`
// interface. This logger will only show messages at the Error Level.
Expand All @@ -36,8 +36,9 @@ func init() {

// SetLogger overrides the globalLogger with l.
//
// To see Info messages use a logger with `l.V(1).Enabled() == true`
// To see Debug messages use a logger with `l.V(5).Enabled() == true`.
// To see Warn messages use a logger with `l.V(1).Enabled() == true`
// To see Info messages use a logger with `l.V(4).Enabled() == true`
// To see Debug messages use a logger with `l.V(8).Enabled() == true`.
func SetLogger(l logr.Logger) {
atomic.StorePointer(&globalLogger, unsafe.Pointer(&l))
}
Expand All @@ -47,9 +48,9 @@ func getLogger() logr.Logger {
}

// Info prints messages about the general state of the API or SDK.
// This should usually be less then 5 messages a minute.
// This should usually be less than 5 messages a minute.
func Info(msg string, keysAndValues ...interface{}) {
getLogger().V(1).Info(msg, keysAndValues...)
getLogger().V(4).Info(msg, keysAndValues...)
}

// Error prints messages about exceptional states of the API or SDK.
Expand All @@ -59,5 +60,11 @@ func Error(err error, msg string, keysAndValues ...interface{}) {

// Debug prints messages about all internal changes in the API or SDK.
func Debug(msg string, keysAndValues ...interface{}) {
getLogger().V(5).Info(msg, keysAndValues...)
getLogger().V(8).Info(msg, keysAndValues...)
}

// Warn prints messages about warnings in the API or SDK.
// Not an error but is likely more important than an informational event.
func Warn(msg string, keysAndValues ...interface{}) {
getLogger().V(1).Info(msg, keysAndValues...)
}
68 changes: 68 additions & 0 deletions internal/global/internal_logging_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,82 @@
package global

import (
"bytes"
"errors"
"log"
"os"
"testing"

"github.com/go-logr/logr"

"github.com/stretchr/testify/assert"

"github.com/go-logr/logr/funcr"
"github.com/go-logr/stdr"
)

func TestRace(t *testing.T) {
go SetLogger(stdr.New(log.New(os.Stderr, "", 0)))
go Info("")
}

func TestLogLevel(t *testing.T) {
tests := []struct {
name string
verbosity int
logF func()
want string
}{
{
name: "Verbosity 0 should log errors.",
verbosity: 0,
want: `"msg"="foobar" "error"="foobar"`,
logF: func() {
Error(errors.New("foobar"), "foobar")
},
},
{
name: "Verbosity 1 should log warnings",
verbosity: 1,
want: `"level"=1 "msg"="foo"`,
logF: func() {
Warn("foo")
},
},
{
name: "Verbosity 4 should log info",
verbosity: 4,
want: `"level"=4 "msg"="bar"`,
logF: func() {
Info("bar")
},
},
{
name: "Verbosity 8 should log debug",
verbosity: 8,
want: `"level"=8 "msg"="baz"`,
logF: func() {
Debug("baz")
},
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
var buf bytes.Buffer
SetLogger(newBuffLogger(&buf, test.verbosity))

test.logF()

assert.Equal(t, test.want, buf.String())
})
}
}

func newBuffLogger(buf *bytes.Buffer, verbosity int) logr.Logger {
return funcr.New(func(prefix, args string) {
_, _ = buf.Write([]byte(args))
}, funcr.Options{
Verbosity: verbosity,
})
}