Skip to content

Commit ca5ff48

Browse files
committed
add unit tests
1 parent 24d5e13 commit ca5ff48

File tree

7 files changed

+1719
-0
lines changed

7 files changed

+1719
-0
lines changed

logger_test.go

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
package gotel
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"log/slog"
7+
"net/http/httptest"
8+
"strings"
9+
"testing"
10+
"time"
11+
12+
"github.com/hasura/gotel/otelutils"
13+
"go.opentelemetry.io/otel/trace"
14+
)
15+
16+
func TestLogHandler_Enabled(t *testing.T) {
17+
var buf bytes.Buffer
18+
stdHandler := slog.NewJSONHandler(&buf, &slog.HandlerOptions{
19+
Level: slog.LevelInfo,
20+
})
21+
22+
handler := createLogHandler("test-service", slog.New(stdHandler), nil)
23+
24+
t.Run("respects log level", func(t *testing.T) {
25+
ctx := context.Background()
26+
27+
if !handler.Enabled(ctx, slog.LevelInfo) {
28+
t.Error("expected Info level to be enabled")
29+
}
30+
31+
if !handler.Enabled(ctx, slog.LevelError) {
32+
t.Error("expected Error level to be enabled")
33+
}
34+
35+
if handler.Enabled(ctx, slog.LevelDebug) {
36+
t.Error("expected Debug level to be disabled")
37+
}
38+
})
39+
}
40+
41+
func TestLogHandler_Handle(t *testing.T) {
42+
var buf bytes.Buffer
43+
stdHandler := slog.NewJSONHandler(&buf, &slog.HandlerOptions{
44+
Level: slog.LevelInfo,
45+
})
46+
47+
handler := createLogHandler("test-service", slog.New(stdHandler), nil)
48+
49+
t.Run("handles log records", func(t *testing.T) {
50+
ctx := context.Background()
51+
record := slog.NewRecord(time.Now(), slog.LevelInfo, "test message", 0)
52+
record.AddAttrs(slog.String("key", "value"))
53+
54+
err := handler.Handle(ctx, record)
55+
if err != nil {
56+
t.Fatalf("unexpected error: %v", err)
57+
}
58+
59+
// Check that the log was written to the buffer
60+
logOutput := buf.String()
61+
if !strings.Contains(logOutput, "test message") {
62+
t.Errorf("expected log output to contain 'test message', got: %s", logOutput)
63+
}
64+
65+
if !strings.Contains(logOutput, "key") {
66+
t.Errorf("expected log output to contain 'key', got: %s", logOutput)
67+
}
68+
})
69+
}
70+
71+
func TestLogHandler_WithAttrs(t *testing.T) {
72+
var buf bytes.Buffer
73+
stdHandler := slog.NewJSONHandler(&buf, &slog.HandlerOptions{
74+
Level: slog.LevelInfo,
75+
})
76+
77+
handler := createLogHandler("test-service", slog.New(stdHandler), nil)
78+
79+
t.Run("returns handler with attributes", func(t *testing.T) {
80+
attrs := []slog.Attr{
81+
slog.String("service", "test"),
82+
slog.Int("version", 1),
83+
}
84+
85+
newHandler := handler.WithAttrs(attrs)
86+
if newHandler == nil {
87+
t.Fatal("expected non-nil handler")
88+
}
89+
90+
// Verify it's a LogHandler
91+
if _, ok := newHandler.(LogHandler); !ok {
92+
t.Error("expected handler to be of type LogHandler")
93+
}
94+
})
95+
}
96+
97+
func TestLogHandler_WithGroup(t *testing.T) {
98+
var buf bytes.Buffer
99+
stdHandler := slog.NewJSONHandler(&buf, &slog.HandlerOptions{
100+
Level: slog.LevelInfo,
101+
})
102+
103+
handler := createLogHandler("test-service", slog.New(stdHandler), nil)
104+
105+
t.Run("returns handler with group", func(t *testing.T) {
106+
newHandler := handler.WithGroup("request")
107+
if newHandler == nil {
108+
t.Fatal("expected non-nil handler")
109+
}
110+
111+
// Verify it's a LogHandler
112+
if _, ok := newHandler.(LogHandler); !ok {
113+
t.Error("expected handler to be of type LogHandler")
114+
}
115+
})
116+
}
117+
118+
func TestGetLogger(t *testing.T) {
119+
t.Run("returns logger from context", func(t *testing.T) {
120+
var buf bytes.Buffer
121+
expectedLogger := slog.New(slog.NewJSONHandler(&buf, nil))
122+
ctx := otelutils.NewContextWithLogger(context.Background(), expectedLogger)
123+
124+
logger := GetLogger(ctx)
125+
if logger == nil {
126+
t.Fatal("expected non-nil logger")
127+
}
128+
129+
// The logger should be the same instance
130+
if logger != expectedLogger {
131+
t.Error("expected logger to be the same instance from context")
132+
}
133+
})
134+
135+
t.Run("returns default logger when not in context", func(t *testing.T) {
136+
ctx := context.Background()
137+
138+
logger := GetLogger(ctx)
139+
if logger == nil {
140+
t.Fatal("expected non-nil logger")
141+
}
142+
})
143+
}
144+
145+
func TestGetRequestLogger(t *testing.T) {
146+
t.Run("returns logger from request context", func(t *testing.T) {
147+
var buf bytes.Buffer
148+
expectedLogger := slog.New(slog.NewJSONHandler(&buf, nil))
149+
ctx := otelutils.NewContextWithLogger(context.Background(), expectedLogger)
150+
req := httptest.NewRequest("GET", "/test", nil).WithContext(ctx)
151+
152+
logger := GetRequestLogger(req)
153+
if logger == nil {
154+
t.Fatal("expected non-nil logger")
155+
}
156+
157+
if logger != expectedLogger {
158+
t.Error("expected logger to be the same instance from context")
159+
}
160+
})
161+
162+
t.Run("returns logger with request ID when not in context", func(t *testing.T) {
163+
req := httptest.NewRequest("GET", "/test", nil)
164+
req.Header.Set("x-request-id", "test-request-id")
165+
166+
logger := GetRequestLogger(req)
167+
if logger == nil {
168+
t.Fatal("expected non-nil logger")
169+
}
170+
171+
// We can't easily verify the request_id attribute without capturing logs,
172+
// but we can verify the logger is not nil
173+
})
174+
175+
t.Run("uses trace ID as request ID when header missing", func(t *testing.T) {
176+
req := httptest.NewRequest("GET", "/test", nil)
177+
ctx := trace.ContextWithSpanContext(req.Context(), trace.NewSpanContext(trace.SpanContextConfig{
178+
TraceID: trace.TraceID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
179+
SpanID: trace.SpanID{1, 2, 3, 4, 5, 6, 7, 8},
180+
}))
181+
req = req.WithContext(ctx)
182+
183+
logger := GetRequestLogger(req)
184+
if logger == nil {
185+
t.Fatal("expected non-nil logger")
186+
}
187+
})
188+
}

0 commit comments

Comments
 (0)