diff --git a/core/logx/writer.go b/core/logx/writer.go index e494df60..70182a70 100644 --- a/core/logx/writer.go +++ b/core/logx/writer.go @@ -241,7 +241,6 @@ func output(writer io.Writer, level string, val interface{}, fields ...LogField) switch atomic.LoadUint32(&encoding) { case plainEncodingType: - level = wrapLevelWithColor(level) writePlainAny(writer, level, val, buildFields(fields...)...) default: entry := make(logEntryWithFields) @@ -290,6 +289,8 @@ func writeJson(writer io.Writer, info interface{}) { } func writePlainAny(writer io.Writer, level string, val interface{}, fields ...string) { + level = wrapLevelWithColor(level) + switch v := val.(type) { case string: writePlainText(writer, level, v, fields...) diff --git a/core/logx/writer_test.go b/core/logx/writer_test.go index 6d96808c..edc4ff98 100644 --- a/core/logx/writer_test.go +++ b/core/logx/writer_test.go @@ -124,18 +124,27 @@ func TestWritePlainAny(t *testing.T) { assert.Contains(t, buf.String(), "foo") buf.Reset() - writePlainAny(nil, levelInfo, make(chan int)) + writePlainAny(nil, levelError, make(chan int)) assert.Contains(t, buf.String(), "unsupported type") - writePlainAny(nil, levelInfo, 100) + writePlainAny(nil, levelSlow, 100) assert.Contains(t, buf.String(), "100") buf.Reset() - writePlainAny(hardToWriteWriter{}, levelInfo, 100) + writePlainAny(hardToWriteWriter{}, levelStat, 100) assert.Contains(t, buf.String(), "write error") buf.Reset() - writePlainAny(hardToWriteWriter{}, levelInfo, "foo") + writePlainAny(hardToWriteWriter{}, levelSevere, "foo") assert.Contains(t, buf.String(), "write error") + + buf.Reset() + writePlainAny(hardToWriteWriter{}, levelAlert, "foo") + assert.Contains(t, buf.String(), "write error") + + buf.Reset() + writePlainAny(hardToWriteWriter{}, levelFatal, "foo") + assert.Contains(t, buf.String(), "write error") + } type mockedEntry struct { diff --git a/rest/handler/loghandler_test.go b/rest/handler/loghandler_test.go index aa96d5a4..25019dbf 100644 --- a/rest/handler/loghandler_test.go +++ b/rest/handler/loghandler_test.go @@ -1,6 +1,8 @@ package handler import ( + "bytes" + "io" "io/ioutil" "log" "net/http" @@ -44,6 +46,33 @@ func TestLogHandler(t *testing.T) { } } +func TestLogHandlerVeryLong(t *testing.T) { + var buf bytes.Buffer + for i := 0; i < limitBodyBytes<<1; i++ { + buf.WriteByte('a') + } + + req := httptest.NewRequest(http.MethodPost, "http://localhost", &buf) + handler := LogHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r.Context().Value(internal.LogContext).(*internal.LogCollector).Append("anything") + io.Copy(ioutil.Discard, r.Body) + w.Header().Set("X-Test", "test") + w.WriteHeader(http.StatusServiceUnavailable) + _, err := w.Write([]byte("content")) + assert.Nil(t, err) + + flusher, ok := w.(http.Flusher) + assert.True(t, ok) + flusher.Flush() + })) + + resp := httptest.NewRecorder() + handler.ServeHTTP(resp, req) + assert.Equal(t, http.StatusServiceUnavailable, resp.Code) + assert.Equal(t, "test", resp.Header().Get("X-Test")) + assert.Equal(t, "content", resp.Body.String()) +} + func TestLogHandlerSlow(t *testing.T) { handlers := []func(handler http.Handler) http.Handler{ LogHandler, @@ -106,6 +135,28 @@ func TestSetSlowThreshold(t *testing.T) { assert.Equal(t, time.Second, slowThreshold.Load()) } +func TestWrapMethodWithColor(t *testing.T) { + // no tty + assert.Equal(t, http.MethodGet, wrapMethod(http.MethodGet)) + assert.Equal(t, http.MethodPost, wrapMethod(http.MethodPost)) + assert.Equal(t, http.MethodPut, wrapMethod(http.MethodPut)) + assert.Equal(t, http.MethodDelete, wrapMethod(http.MethodDelete)) + assert.Equal(t, http.MethodPatch, wrapMethod(http.MethodPatch)) + assert.Equal(t, http.MethodHead, wrapMethod(http.MethodHead)) + assert.Equal(t, http.MethodOptions, wrapMethod(http.MethodOptions)) + assert.Equal(t, http.MethodConnect, wrapMethod(http.MethodConnect)) + assert.Equal(t, http.MethodTrace, wrapMethod(http.MethodTrace)) +} + +func TestWrapStatusCodeWithColor(t *testing.T) { + // no tty + assert.Equal(t, "200", wrapStatusCode(http.StatusOK)) + assert.Equal(t, "302", wrapStatusCode(http.StatusFound)) + assert.Equal(t, "404", wrapStatusCode(http.StatusNotFound)) + assert.Equal(t, "500", wrapStatusCode(http.StatusInternalServerError)) + assert.Equal(t, "503", wrapStatusCode(http.StatusServiceUnavailable)) +} + func BenchmarkLogHandler(b *testing.B) { b.ReportAllocs()