diff --git a/internal/middleware/accesslog/accesslog.go b/internal/middleware/accesslog/accesslog.go index 7c0abbf..aec3449 100644 --- a/internal/middleware/accesslog/accesslog.go +++ b/internal/middleware/accesslog/accesslog.go @@ -50,12 +50,14 @@ type AccessLog struct { // - *AccessLog: 访问日志中间件实例 func New(cfg *config.LoggingConfig) *AccessLog { sampleRate := cfg.Access.SampleRate - if sampleRate <= 0.0 || sampleRate > 1.0 { + // sampleRate=0 明确表示禁用访问日志 + // sampleRate<0 或 >1 修正为 1.0(全量记录) + if sampleRate < 0.0 || sampleRate > 1.0 { sampleRate = 1.0 } var sampleInterval uint64 = 1 - if sampleRate < 1.0 { + if sampleRate > 0.0 && sampleRate < 1.0 { // 使用 1000 作为基数以提高精度,例如 0.123 -> 间隔约 8 sampleInterval = uint64((1.0 / sampleRate) + 0.5) if sampleInterval < 1 { @@ -81,17 +83,21 @@ func (a *AccessLog) Name() string { // shouldLog 判断当前请求是否应记录访问日志。 // // 规则: +// - 5xx 服务器错误始终记录(便于排查错误) +// - sampleRate=0 时不记录 2xx/3xx/4xx // - 采样率为 1.0 时始终记录 -// - 非 2xx 响应始终记录(便于排查错误) -// - 2xx 响应按采样率决定是否记录 +// - 其他情况按 sampleRate 采样 // // 使用原子计数器实现无锁、零分配采样。 func (a *AccessLog) shouldLog(status int) bool { - if a.sampleRate >= 1.0 { + // 5xx 服务器错误始终记录 + if status >= 500 { return true } - // 非成功响应始终记录 - if status < 200 || status >= 300 { + if a.sampleRate == 0.0 { + return false + } + if a.sampleRate >= 1.0 { return true } // 确定性采样:每 sampleInterval 个请求记录一个 diff --git a/internal/middleware/accesslog/accesslog_test.go b/internal/middleware/accesslog/accesslog_test.go index c1fb849..d8f50ec 100644 --- a/internal/middleware/accesslog/accesslog_test.go +++ b/internal/middleware/accesslog/accesslog_test.go @@ -91,17 +91,24 @@ func TestAccessLog_SampleRateAlwaysRecordErrors(t *testing.T) { al := New(&config.LoggingConfig{ Access: config.AccessLogConfig{ Format: "json", - SampleRate: 0.0, // 理论上不采样成功请求,但错误始终记录 + SampleRate: 0.0, // 理论上不采样成功请求,但 5xx 始终记录 }, }) - // 非 2xx 请求应始终记录 - for _, status := range []int{199, 300, 400, 500} { + // 5xx 请求应始终记录 + for _, status := range []int{500, 502, 503, 504} { if !al.shouldLog(status) { t.Errorf("status %d should always be logged regardless of sample rate", status) } } + // 2xx/3xx/4xx 请求按采样率(0% 不记录) + for _, status := range []int{200, 301, 404} { + if al.shouldLog(status) { + t.Errorf("status %d should not be logged with sample_rate=0", status) + } + } + _ = al.Close() }