|
5 | 5 | "context" |
6 | 6 | "encoding/json" |
7 | 7 | "errors" |
| 8 | + stdlog "log" |
8 | 9 | "testing" |
9 | 10 | "time" |
10 | 11 |
|
@@ -40,26 +41,103 @@ func TestGormWarningLogger(t *testing.T) { |
40 | 41 | SlowThreshold: 200 * time.Millisecond, |
41 | 42 | LogLevel: gormlogger.Warn, |
42 | 43 | }).LogMode(test.logLevel) |
| 44 | + formatted := false |
43 | 45 | queryLogger.Trace(context.Background(), time.Now().Add(-test.elapsed), func() (string, int64) { |
| 46 | + formatted = true |
44 | 47 | return "SELECT 1", 1 |
45 | 48 | }, test.err) |
46 | 49 |
|
47 | | - if test.want == "" { |
48 | | - require.Empty(t, output.String()) |
49 | | - return |
50 | | - } |
51 | | - var record struct { |
52 | | - Level string `json:"level"` |
53 | | - Error string `json:"error"` |
54 | | - } |
55 | | - require.NoError(t, json.Unmarshal(output.Bytes(), &record)) |
56 | | - require.Equal(t, test.want, record.Level) |
57 | | - require.Contains(t, record.Error, "SELECT 1") |
58 | | - if test.err != nil { |
59 | | - require.Contains(t, record.Error, test.err.Error()) |
60 | | - } else { |
61 | | - require.Contains(t, record.Error, "SLOW SQL") |
62 | | - } |
| 50 | + require.Equal(t, test.want != "", formatted) |
| 51 | + assertGormQueryLog(t, output.Bytes(), test.want, test.err) |
63 | 52 | }) |
64 | 53 | } |
65 | 54 | } |
| 55 | + |
| 56 | +func assertGormQueryLog(t *testing.T, output []byte, wantLevel string, err error) { |
| 57 | + t.Helper() |
| 58 | + if wantLevel == "" { |
| 59 | + require.Empty(t, output) |
| 60 | + return |
| 61 | + } |
| 62 | + var record struct { |
| 63 | + Level string `json:"level"` |
| 64 | + Error string `json:"error"` |
| 65 | + } |
| 66 | + require.NoError(t, json.Unmarshal(output, &record)) |
| 67 | + require.Equal(t, wantLevel, record.Level) |
| 68 | + require.Contains(t, record.Error, "SELECT 1") |
| 69 | + if err != nil { |
| 70 | + require.Contains(t, record.Error, err.Error()) |
| 71 | + return |
| 72 | + } |
| 73 | + require.Contains(t, record.Error, "SLOW SQL") |
| 74 | +} |
| 75 | + |
| 76 | +func TestGormSpanLoggerPreservesDelegate(t *testing.T) { |
| 77 | + tests := []struct { |
| 78 | + name string |
| 79 | + elapsed time.Duration |
| 80 | + err error |
| 81 | + level gormlogger.LogLevel |
| 82 | + message string |
| 83 | + spans []string |
| 84 | + }{ |
| 85 | + {name: "fast query", elapsed: time.Millisecond, level: gormlogger.Warn}, |
| 86 | + {name: "slow query", elapsed: time.Second, level: gormlogger.Warn, message: "SLOW SQL", spans: []string{"test"}}, |
| 87 | + {name: "query error", err: errors.New("original query error"), level: gormlogger.Warn, message: "original query error", spans: []string{"test"}}, |
| 88 | + {name: "info query", elapsed: time.Millisecond, level: gormlogger.Info, message: "SELECT 1"}, |
| 89 | + {name: "silent error", err: errors.New("query error"), level: gormlogger.Silent}, |
| 90 | + } |
| 91 | + for _, spec := range tests { |
| 92 | + t.Run(spec.name, func(t *testing.T) { |
| 93 | + test := newSamplingTestSpan(t, false) |
| 94 | + queryLogger, output := newDelegatedGormLogger(test) |
| 95 | + formatted := false |
| 96 | + queryLogger.LogMode(spec.level).Trace(test.ctx, time.Now().Add(-spec.elapsed), func() (string, int64) { |
| 97 | + formatted = true |
| 98 | + return "SELECT 1", 1 |
| 99 | + }, spec.err) |
| 100 | + |
| 101 | + test.finish(t, spec.spans...) |
| 102 | + require.Equal(t, spec.message != "", formatted) |
| 103 | + assertDelegatedGormOutput(t, output.String(), spec.message) |
| 104 | + }) |
| 105 | + } |
| 106 | +} |
| 107 | + |
| 108 | +func TestGormSpanLoggerDirectWarningsAndErrors(t *testing.T) { |
| 109 | + logs := map[string]func(gormlogger.Interface, context.Context){ |
| 110 | + "warning": func(logger gormlogger.Interface, ctx context.Context) { |
| 111 | + logger.Warn(ctx, "original %s", "message") |
| 112 | + }, |
| 113 | + "error": func(logger gormlogger.Interface, ctx context.Context) { |
| 114 | + logger.Error(ctx, "original %s", "message") |
| 115 | + }, |
| 116 | + } |
| 117 | + for name, log := range logs { |
| 118 | + t.Run(name, func(t *testing.T) { |
| 119 | + test := newSamplingTestSpan(t, false) |
| 120 | + logger, output := newDelegatedGormLogger(test) |
| 121 | + log(logger, test.ctx) |
| 122 | + test.finish(t, "test") |
| 123 | + require.Contains(t, output.String(), "original message") |
| 124 | + }) |
| 125 | + } |
| 126 | +} |
| 127 | + |
| 128 | +func newDelegatedGormLogger(test *samplingTestSpan) (gormlogger.Interface, *bytes.Buffer) { |
| 129 | + output := &bytes.Buffer{} |
| 130 | + config := gormlogger.Config{SlowThreshold: 200 * time.Millisecond, LogLevel: gormlogger.Warn} |
| 131 | + delegate := gormlogger.New(stdlog.New(output, "", 0), config) |
| 132 | + return NewGormSpanLogger(test.tracer, delegate, config), output |
| 133 | +} |
| 134 | + |
| 135 | +func assertDelegatedGormOutput(t *testing.T, output string, message string) { |
| 136 | + t.Helper() |
| 137 | + if message == "" { |
| 138 | + require.Empty(t, output) |
| 139 | + return |
| 140 | + } |
| 141 | + require.Contains(t, output, message) |
| 142 | + require.Contains(t, output, "SELECT 1") |
| 143 | +} |
0 commit comments