Merge pull request #6003 from cpuguy83/add_otel_log_hook

Add open telemetry logging hook for logrus
This commit is contained in:
Derek McGowan 2021-09-24 17:21:46 -07:00 committed by GitHub
commit 22beecb7d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 75 additions and 4 deletions

View File

@ -301,6 +301,8 @@ func applyFlags(context *cli.Context, config *srvconfig.Config) error {
if err := setLogFormat(config); err != nil { if err := setLogFormat(config); err != nil {
return err return err
} }
setLogHooks()
for _, v := range []struct { for _, v := range []struct {
name string name string
d *string d *string
@ -366,6 +368,10 @@ func setLogFormat(config *srvconfig.Config) error {
return nil return nil
} }
func setLogHooks() {
logrus.StandardLogger().AddHook(tracing.NewLogrusHook())
}
func dumpStacks(writeToFile bool) { func dumpStacks(writeToFile bool) {
var ( var (
buf []byte buf []byte

View File

@ -52,7 +52,8 @@ const (
// WithLogger returns a new context with the provided logger. Use in // WithLogger returns a new context with the provided logger. Use in
// combination with logger.WithField(s) for great effect. // combination with logger.WithField(s) for great effect.
func WithLogger(ctx context.Context, logger *logrus.Entry) context.Context { func WithLogger(ctx context.Context, logger *logrus.Entry) context.Context {
return context.WithValue(ctx, loggerKey{}, logger) e := logger.WithContext(ctx)
return context.WithValue(ctx, loggerKey{}, e)
} }
// GetLogger retrieves the current logger from the context. If no logger is // GetLogger retrieves the current logger from the context. If no logger is
@ -61,7 +62,7 @@ func GetLogger(ctx context.Context) *logrus.Entry {
logger := ctx.Value(loggerKey{}) logger := ctx.Value(loggerKey{})
if logger == nil { if logger == nil {
return L return L.WithContext(ctx)
} }
return logger.(*logrus.Entry) return logger.(*logrus.Entry)

View File

@ -25,8 +25,6 @@ import (
func TestLoggerContext(t *testing.T) { func TestLoggerContext(t *testing.T) {
ctx := context.Background() ctx := context.Background()
assert.Equal(t, GetLogger(ctx), L) // should be same as L variable
assert.Equal(t, G(ctx), GetLogger(ctx)) // these should be the same.
ctx = WithLogger(ctx, G(ctx).WithField("test", "one")) ctx = WithLogger(ctx, G(ctx).WithField("test", "one"))
assert.Equal(t, GetLogger(ctx).Data["test"], "one") assert.Equal(t, GetLogger(ctx).Data["test"], "one")

66
tracing/log.go Normal file
View File

@ -0,0 +1,66 @@
/*
Copyright The containerd 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 tracing
import (
"github.com/sirupsen/logrus"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)
// NewLogrusHook creates a new logrus hook
func NewLogrusHook() *LogrusHook {
return &LogrusHook{}
}
// LogrusHook is a logrus hook which adds logrus events to active spans.
// If the span is not recording or the span context is invalid, the hook is a no-op.
type LogrusHook struct{}
// Levels returns the logrus levels that this hook is interested in.
func (h *LogrusHook) Levels() []logrus.Level {
return logrus.AllLevels
}
// Fire is called when a log event occurs.
func (h *LogrusHook) Fire(entry *logrus.Entry) error {
span := trace.SpanFromContext(entry.Context)
if span == nil {
return nil
}
if !span.SpanContext().IsValid() || !span.IsRecording() {
return nil
}
span.AddEvent(
entry.Message,
trace.WithAttributes(logrusDataToAttrs(entry.Data)...),
trace.WithAttributes(attribute.String("level", entry.Level.String())),
trace.WithTimestamp(entry.Time),
)
return nil
}
func logrusDataToAttrs(data logrus.Fields) []attribute.KeyValue {
attrs := make([]attribute.KeyValue, 0, len(data))
for k, v := range data {
attrs = append(attrs, attribute.Any(k, v))
}
return attrs
}