Skip to content

Commit ac6d80e

Browse files
committed
otel: avoid span lookup for entries without context
Logrus entries are not required to have a context, so return early when one is not set instead of performing an unnecessary OpenTelemetry span lookup. Also reuse the span context when validating it and extracting the trace ID, and update the test to exercise the hook through Logrus' normal logging path, including entries with a nil context. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
1 parent 47f9d38 commit ac6d80e

2 files changed

Lines changed: 34 additions & 22 deletions

File tree

otel/log.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,17 +72,18 @@ func (h *LogrusHook) Levels() []log.Level {
7272

7373
// Fire is called when a log event occurs.
7474
func (h *LogrusHook) Fire(entry *log.Entry) error {
75-
span := trace.SpanFromContext(entry.Context)
76-
if span == nil {
75+
if entry.Context == nil {
7776
return nil
7877
}
7978

80-
if !span.SpanContext().IsValid() {
79+
span := trace.SpanFromContext(entry.Context)
80+
spanCtx := span.SpanContext()
81+
if !spanCtx.IsValid() {
8182
return nil
8283
}
8384

8485
if h.enableTraceIDField {
85-
entry.Data["trace_id"] = span.SpanContext().TraceID().String()
86+
entry.Data["trace_id"] = spanCtx.TraceID().String()
8687
}
8788

8889
if !span.IsRecording() {

otel/log_test.go

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ package otel_test
1818

1919
import (
2020
"context"
21+
"io"
2122
"testing"
2223

23-
"github.com/containerd/log"
2424
"github.com/containerd/log/otel"
25+
"github.com/sirupsen/logrus"
26+
"github.com/sirupsen/logrus/hooks/test"
2527
"go.opentelemetry.io/otel/trace"
2628
)
2729

@@ -36,6 +38,7 @@ func TestLogrusHookTraceID(t *testing.T) {
3638
tests := []struct {
3739
name string
3840
enableOpt bool
41+
nilContext bool
3942
withSpan bool
4043
expectedTID string
4144
}{
@@ -55,30 +58,38 @@ func TestLogrusHookTraceID(t *testing.T) {
5558
enableOpt: true,
5659
withSpan: false,
5760
},
61+
{
62+
name: "TraceIDNotInjected_NoContext",
63+
enableOpt: true,
64+
nilContext: true,
65+
},
5866
}
5967

6068
for _, tc := range tests {
6169
t.Run(tc.name, func(t *testing.T) {
62-
ctx := context.Background()
63-
if tc.withSpan {
64-
ctx = trace.ContextWithSpanContext(
65-
ctx,
66-
trace.NewSpanContext(trace.SpanContextConfig{
67-
TraceID: testTraceID,
68-
SpanID: testSpanID,
69-
}),
70-
)
71-
}
70+
logger := logrus.New()
71+
logger.SetOutput(io.Discard)
72+
logger.AddHook(otel.NewLogrusHook(otel.WithTraceIDField(tc.enableOpt)))
73+
testHook := test.NewLocal(logger)
74+
75+
switch {
76+
case tc.withSpan:
77+
ctx := trace.ContextWithSpanContext(context.Background(), trace.NewSpanContext(trace.SpanContextConfig{
78+
TraceID: testTraceID,
79+
SpanID: testSpanID,
80+
}))
81+
logger.WithContext(ctx).Info("test")
82+
83+
case tc.nilContext:
84+
logger.Info("test")
7285

73-
hook := otel.NewLogrusHook(otel.WithTraceIDField(tc.enableOpt))
74-
entry := &log.Entry{
75-
Context: ctx,
76-
Data: make(log.Fields),
86+
default:
87+
logger.WithContext(context.Background()).Info("test")
7788
}
7889

79-
err := hook.Fire(entry)
80-
if err != nil {
81-
t.Fatal(err)
90+
entry := testHook.LastEntry()
91+
if entry == nil {
92+
t.Fatal("expected log entry")
8293
}
8394

8495
traceID, ok := entry.Data["trace_id"]

0 commit comments

Comments
 (0)