Merge pull request #6003 from cpuguy83/add_otel_log_hook
Add open telemetry logging hook for logrus
This commit is contained in:
		@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
									
								
							
							
						
						
									
										66
									
								
								tracing/log.go
									
									
									
									
									
										Normal 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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user