Add slog attributes at pool, worker, and connection levels.
This commit is contained in:
@@ -4,6 +4,8 @@ import (
|
||||
"bytes"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"io"
|
||||
"log/slog"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -29,6 +31,12 @@ type MockOutgoingData struct {
|
||||
Data []byte
|
||||
}
|
||||
|
||||
type ExpectedLog struct {
|
||||
Level slog.Level
|
||||
Msg string
|
||||
Attrs map[string]any
|
||||
}
|
||||
|
||||
// Setup
|
||||
|
||||
func SetupTestSocket(t *testing.T) (
|
||||
@@ -117,3 +125,109 @@ func Never(t *testing.T, condition func() bool, msg string) {
|
||||
t.Helper()
|
||||
assert.Never(t, condition, NegativeTestTimeout, TestTick, msg)
|
||||
}
|
||||
|
||||
// Logging Helpers
|
||||
|
||||
func AssertLogSequence(t *testing.T, records []slog.Record, expected []ExpectedLog) {
|
||||
t.Helper()
|
||||
|
||||
recIndex := 0
|
||||
for expIndex, exp := range expected {
|
||||
found := false
|
||||
|
||||
for recIndex < len(records) {
|
||||
rec := records[recIndex]
|
||||
|
||||
if rec.Level == exp.Level && strings.Contains(rec.Message, exp.Msg) {
|
||||
allAttrsMatch := true
|
||||
for key, expectedValue := range exp.Attrs {
|
||||
if !AssertAttributePresent(t, rec, key, expectedValue) {
|
||||
allAttrsMatch = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if allAttrsMatch {
|
||||
found = true
|
||||
recIndex++
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
recIndex++
|
||||
}
|
||||
|
||||
if !found {
|
||||
t.Fatalf(
|
||||
"expected log not found: index=%d level=%v msg=%q attrs=%v",
|
||||
expIndex, exp.Level, exp.Msg, exp.Attrs,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func FindLogRecord(records []slog.Record, level slog.Level, msgSnippet string) *slog.Record {
|
||||
for i := range records {
|
||||
if records[i].Level == level && strings.Contains(records[i].Message, msgSnippet) {
|
||||
return &records[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func AssertAttributePresent(t *testing.T, record slog.Record, key string, expectedValue any) bool {
|
||||
t.Helper()
|
||||
|
||||
var found bool
|
||||
var actualValue any
|
||||
|
||||
record.Attrs(func(attr slog.Attr) bool {
|
||||
if attr.Key == key {
|
||||
found = true
|
||||
actualValue = attr.Value.Any()
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
if !found {
|
||||
t.Fatalf("attribute %q not found in log record", key)
|
||||
return false
|
||||
}
|
||||
|
||||
if !logValuesEqual(actualValue, expectedValue) {
|
||||
t.Errorf("attribute %q: expected=%v actual=%v", key, expectedValue, actualValue)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func logValuesEqual(a, b any) bool {
|
||||
if a == b {
|
||||
return true
|
||||
}
|
||||
aInt, aOk := toInt64(a)
|
||||
bInt, bOk := toInt64(b)
|
||||
if aOk && bOk {
|
||||
return aInt == bInt
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func toInt64(v any) (int64, bool) {
|
||||
switch val := v.(type) {
|
||||
case int:
|
||||
return int64(val), true
|
||||
case int64:
|
||||
return val, true
|
||||
case int32:
|
||||
return int64(val), true
|
||||
case int16:
|
||||
return int64(val), true
|
||||
case int8:
|
||||
return int64(val), true
|
||||
default:
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user