refactor(accesslog): replace JSON log entry struct with zerolog for improved logging efficiency, updated test

This commit is contained in:
yusing 2025-04-17 15:06:21 +08:00
parent 9d85a41bc5
commit 85c9ea34aa
2 changed files with 52 additions and 51 deletions

View file

@ -23,7 +23,7 @@ const (
referer = "https://www.google.com/" referer = "https://www.google.com/"
proto = "HTTP/1.1" proto = "HTTP/1.1"
ua = "Go-http-client/1.1" ua = "Go-http-client/1.1"
status = http.StatusOK status = http.StatusNotFound
contentLength = 100 contentLength = 100
method = http.MethodGet method = http.MethodGet
) )
@ -99,6 +99,25 @@ func TestAccessLoggerRedactQuery(t *testing.T) {
) )
} }
type JSONLogEntry struct {
Time string `json:"time"`
IP string `json:"ip"`
Method string `json:"method"`
Scheme string `json:"scheme"`
Host string `json:"host"`
URI string `json:"uri"`
Protocol string `json:"protocol"`
Status int `json:"status"`
Error string `json:"error,omitempty"`
ContentType string `json:"type"`
Size int64 `json:"size"`
Referer string `json:"referer"`
UserAgent string `json:"useragent"`
Query map[string][]string `json:"query,omitempty"`
Headers map[string][]string `json:"headers,omitempty"`
Cookies map[string]string `json:"cookies,omitempty"`
}
func getJSONEntry(t *testing.T, config *Config) JSONLogEntry { func getJSONEntry(t *testing.T, config *Config) JSONLogEntry {
t.Helper() t.Helper()
config.Format = FormatJSON config.Format = FormatJSON
@ -125,4 +144,7 @@ func TestAccessLoggerJSON(t *testing.T) {
ExpectEqual(t, entry.UserAgent, ua) ExpectEqual(t, entry.UserAgent, ua)
ExpectEqual(t, len(entry.Headers), 0) ExpectEqual(t, len(entry.Headers), 0)
ExpectEqual(t, len(entry.Cookies), 0) ExpectEqual(t, len(entry.Cookies), 0)
if status >= 400 {
ExpectEqual(t, entry.Error, http.StatusText(status))
}
} }

View file

@ -8,9 +8,8 @@ import (
"strconv" "strconv"
"time" "time"
"github.com/rs/zerolog"
"github.com/yusing/go-proxy/pkg/json" "github.com/yusing/go-proxy/pkg/json"
"github.com/yusing/go-proxy/internal/logging"
) )
type ( type (
@ -20,25 +19,6 @@ type (
} }
CombinedFormatter struct{ CommonFormatter } CombinedFormatter struct{ CommonFormatter }
JSONFormatter struct{ CommonFormatter } JSONFormatter struct{ CommonFormatter }
JSONLogEntry struct {
Time string `json:"time"`
IP string `json:"ip"`
Method string `json:"method"`
Scheme string `json:"scheme"`
Host string `json:"host"`
URI string `json:"uri"`
Protocol string `json:"protocol"`
Status int `json:"status"`
Error string `json:"error,omitempty"`
ContentType string `json:"type"`
Size int64 `json:"size"`
Referer string `json:"referer"`
UserAgent string `json:"useragent"`
Query map[string][]string `json:"query,omitempty"`
Headers map[string][]string `json:"headers,omitempty"`
Cookies map[string]string `json:"cookies,omitempty"`
}
) )
const LogTimeFormat = "02/Jan/2006:15:04:05 -0700" const LogTimeFormat = "02/Jan/2006:15:04:05 -0700"
@ -109,37 +89,36 @@ func (f *JSONFormatter) Format(line *bytes.Buffer, req *http.Request, res *http.
headers := f.cfg.Headers.ProcessHeaders(req.Header) headers := f.cfg.Headers.ProcessHeaders(req.Header)
headers.Del("Cookie") headers.Del("Cookie")
cookies := f.cfg.Cookies.ProcessCookies(req.Cookies()) cookies := f.cfg.Cookies.ProcessCookies(req.Cookies())
contentType := res.Header.Get("Content-Type")
entry := JSONLogEntry{ queryBytes, _ := json.Marshal(query)
Time: f.GetTimeNow().Format(LogTimeFormat), headersBytes, _ := json.Marshal(headers)
IP: clientIP(req), cookiesBytes, _ := json.Marshal(cookies)
Method: req.Method,
Scheme: scheme(req), logger := zerolog.New(line).With().Logger()
Host: req.Host, event := logger.Info().
URI: requestURI(req.URL, query), Str("time", f.GetTimeNow().Format(LogTimeFormat)).
Protocol: req.Proto, Str("ip", clientIP(req)).
Status: res.StatusCode, Str("method", req.Method).
ContentType: res.Header.Get("Content-Type"), Str("scheme", scheme(req)).
Size: res.ContentLength, Str("host", req.Host).
Referer: req.Referer(), Str("uri", requestURI(req.URL, query)).
UserAgent: req.UserAgent(), Str("protocol", req.Proto).
Query: query, Int("status", res.StatusCode).
Headers: headers, Str("type", contentType).
Cookies: cookies, Int64("size", res.ContentLength).
} Str("referer", req.Referer()).
Str("useragent", req.UserAgent()).
RawJSON("query", queryBytes).
RawJSON("headers", headersBytes).
RawJSON("cookies", cookiesBytes)
if res.StatusCode >= 400 { if res.StatusCode >= 400 {
entry.Error = res.Status if res.Status != "" {
} event.Str("error", res.Status)
} else {
if entry.ContentType == "" { event.Str("error", http.StatusText(res.StatusCode))
// try to get content type from request
entry.ContentType = req.Header.Get("Content-Type")
}
marshaller := json.NewEncoder(line)
err := marshaller.Encode(entry)
if err != nil {
logging.Err(err).Msg("failed to marshal json log")
} }
} }
event.Send()
}