slog_handler_test.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. package logger
  2. import (
  3. "context"
  4. "log/slog"
  5. "testing"
  6. "time"
  7. "go.uber.org/zap"
  8. "go.uber.org/zap/zapcore"
  9. )
  10. type captureState struct {
  11. writes []capturedWrite
  12. }
  13. type capturedWrite struct {
  14. fields []zapcore.Field
  15. }
  16. type captureCore struct {
  17. state *captureState
  18. withFields []zapcore.Field
  19. }
  20. func newCaptureCore() *captureCore {
  21. return &captureCore{state: &captureState{}}
  22. }
  23. func (c *captureCore) Enabled(zapcore.Level) bool {
  24. return true
  25. }
  26. func (c *captureCore) With(fields []zapcore.Field) zapcore.Core {
  27. nextFields := make([]zapcore.Field, 0, len(c.withFields)+len(fields))
  28. nextFields = append(nextFields, c.withFields...)
  29. nextFields = append(nextFields, fields...)
  30. return &captureCore{
  31. state: c.state,
  32. withFields: nextFields,
  33. }
  34. }
  35. func (c *captureCore) Check(entry zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
  36. return ce.AddCore(entry, c)
  37. }
  38. func (c *captureCore) Write(entry zapcore.Entry, fields []zapcore.Field) error {
  39. allFields := make([]zapcore.Field, 0, len(c.withFields)+len(fields))
  40. allFields = append(allFields, c.withFields...)
  41. allFields = append(allFields, fields...)
  42. c.state.writes = append(c.state.writes, capturedWrite{
  43. fields: allFields,
  44. })
  45. return nil
  46. }
  47. func (c *captureCore) Sync() error {
  48. return nil
  49. }
  50. func TestSlogZapHandler_Handle_DoesNotAppendTimeField(t *testing.T) {
  51. core := newCaptureCore()
  52. handler := newSlogZapHandler(zap.New(core))
  53. record := slog.NewRecord(time.Date(2026, 1, 1, 12, 0, 0, 0, time.UTC), slog.LevelInfo, "hello", 0)
  54. record.AddAttrs(slog.String("component", "http.access"))
  55. if err := handler.Handle(context.Background(), record); err != nil {
  56. t.Fatalf("handle slog record: %v", err)
  57. }
  58. if len(core.state.writes) != 1 {
  59. t.Fatalf("write calls = %d, want 1", len(core.state.writes))
  60. }
  61. var hasComponent bool
  62. for _, field := range core.state.writes[0].fields {
  63. if field.Key == "time" {
  64. t.Fatalf("unexpected duplicate time field in slog adapter output")
  65. }
  66. if field.Key == "component" {
  67. hasComponent = true
  68. }
  69. }
  70. if !hasComponent {
  71. t.Fatalf("component field should be preserved")
  72. }
  73. }