merge: access log rotation and enhancements

This commit is contained in:
yusing
2025-04-24 15:29:18 +08:00
parent d668b03175
commit 31812430f1
29 changed files with 1600 additions and 581 deletions

View File

@@ -1,7 +1,6 @@
package accesslog_test
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
@@ -11,7 +10,7 @@ import (
. "github.com/yusing/go-proxy/internal/net/gphttp/accesslog"
"github.com/yusing/go-proxy/internal/task"
. "github.com/yusing/go-proxy/internal/utils/testing"
expect "github.com/yusing/go-proxy/internal/utils/testing"
)
const (
@@ -22,14 +21,14 @@ const (
referer = "https://www.google.com/"
proto = "HTTP/1.1"
ua = "Go-http-client/1.1"
status = http.StatusOK
status = http.StatusNotFound
contentLength = 100
method = http.MethodGet
)
var (
testTask = task.RootTask("test", false)
testURL = Must(url.Parse("http://" + host + uri))
testURL = expect.Must(url.Parse("http://" + host + uri))
req = &http.Request{
RemoteAddr: remote,
Method: method,
@@ -53,22 +52,20 @@ var (
)
func fmtLog(cfg *Config) (ts string, line string) {
var buf bytes.Buffer
buf := make([]byte, 0, 1024)
t := time.Now()
logger := NewAccessLogger(testTask, nil, cfg)
logger.Formatter.SetGetTimeNow(func() time.Time {
return t
})
logger.Format(&buf, req, resp)
return t.Format(LogTimeFormat), buf.String()
logger := NewMockAccessLogger(testTask, cfg)
MockTimeNow(t)
buf = logger.AppendLog(buf, req, resp)
return t.Format(LogTimeFormat), string(buf)
}
func TestAccessLoggerCommon(t *testing.T) {
config := DefaultConfig()
config.Format = FormatCommon
ts, log := fmtLog(config)
ExpectEqual(t, log,
expect.Equal(t, log,
fmt.Sprintf("%s %s - - [%s] \"%s %s %s\" %d %d",
host, remote, ts, method, uri, proto, status, contentLength,
),
@@ -79,7 +76,7 @@ func TestAccessLoggerCombined(t *testing.T) {
config := DefaultConfig()
config.Format = FormatCombined
ts, log := fmtLog(config)
ExpectEqual(t, log,
expect.Equal(t, log,
fmt.Sprintf("%s %s - - [%s] \"%s %s %s\" %d %d \"%s\" \"%s\"",
host, remote, ts, method, uri, proto, status, contentLength, referer, ua,
),
@@ -91,37 +88,79 @@ func TestAccessLoggerRedactQuery(t *testing.T) {
config.Format = FormatCommon
config.Fields.Query.Default = FieldModeRedact
ts, log := fmtLog(config)
ExpectEqual(t, log,
expect.Equal(t, log,
fmt.Sprintf("%s %s - - [%s] \"%s %s %s\" %d %d",
host, remote, ts, method, uriRedacted, proto, status, contentLength,
),
)
}
type JSONLogEntry struct {
Time string `json:"time"`
IP string `json:"ip"`
Method string `json:"method"`
Scheme string `json:"scheme"`
Host string `json:"host"`
Path string `json:"path"`
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 {
t.Helper()
config.Format = FormatJSON
var entry JSONLogEntry
_, log := fmtLog(config)
err := json.Unmarshal([]byte(log), &entry)
ExpectNoError(t, err)
expect.NoError(t, err)
return entry
}
func TestAccessLoggerJSON(t *testing.T) {
config := DefaultConfig()
entry := getJSONEntry(t, config)
ExpectEqual(t, entry.IP, remote)
ExpectEqual(t, entry.Method, method)
ExpectEqual(t, entry.Scheme, "http")
ExpectEqual(t, entry.Host, testURL.Host)
ExpectEqual(t, entry.URI, testURL.RequestURI())
ExpectEqual(t, entry.Protocol, proto)
ExpectEqual(t, entry.Status, status)
ExpectEqual(t, entry.ContentType, "text/plain")
ExpectEqual(t, entry.Size, contentLength)
ExpectEqual(t, entry.Referer, referer)
ExpectEqual(t, entry.UserAgent, ua)
ExpectEqual(t, len(entry.Headers), 0)
ExpectEqual(t, len(entry.Cookies), 0)
expect.Equal(t, entry.IP, remote)
expect.Equal(t, entry.Method, method)
expect.Equal(t, entry.Scheme, "http")
expect.Equal(t, entry.Host, testURL.Host)
expect.Equal(t, entry.Path, testURL.Path)
expect.Equal(t, entry.Protocol, proto)
expect.Equal(t, entry.Status, status)
expect.Equal(t, entry.ContentType, "text/plain")
expect.Equal(t, entry.Size, contentLength)
expect.Equal(t, entry.Referer, referer)
expect.Equal(t, entry.UserAgent, ua)
expect.Equal(t, len(entry.Headers), 0)
expect.Equal(t, len(entry.Cookies), 0)
if status >= 400 {
expect.Equal(t, entry.Error, http.StatusText(status))
}
}
func BenchmarkAccessLoggerJSON(b *testing.B) {
config := DefaultConfig()
config.Format = FormatJSON
logger := NewMockAccessLogger(testTask, config)
b.ResetTimer()
for b.Loop() {
logger.Log(req, resp)
}
}
func BenchmarkAccessLoggerCombined(b *testing.B) {
config := DefaultConfig()
config.Format = FormatCombined
logger := NewMockAccessLogger(testTask, config)
b.ResetTimer()
for b.Loop() {
logger.Log(req, resp)
}
}