mirror of
https://github.com/yusing/godoxy.git
synced 2026-02-24 03:14:50 +01:00
This is a large-scale refactoring across the codebase that replaces the custom `gperr.Error` type with Go's standard `error` interface. The changes include: - Replacing `gperr.Error` return types with `error` in function signatures - Using `errors.New()` and `fmt.Errorf()` instead of `gperr.New()` and `gperr.Errorf()` - Using `%w` format verb for error wrapping instead of `.With()` method - Replacing `gperr.Subject()` calls with `gperr.PrependSubject()` - Converting error logging from `gperr.Log*()` functions to zerolog's `.Err().Msg()` pattern - Update NewLogger to handle multiline error message - Updating `goutils` submodule to latest commit This refactoring aligns with Go idioms and removes the dependency on custom error handling abstractions in favor of standard library patterns.
140 lines
3.4 KiB
Go
140 lines
3.4 KiB
Go
package accesslog
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/yusing/godoxy/internal/serialization"
|
|
)
|
|
|
|
type (
|
|
ConfigBase struct {
|
|
Path string `json:"path,omitempty"`
|
|
Stdout bool `json:"stdout"`
|
|
Retention *Retention `json:"retention" aliases:"keep"`
|
|
RotateInterval time.Duration `json:"rotate_interval,omitempty" swaggertype:"primitive,integer"`
|
|
} // @name AccessLoggerConfigBase
|
|
ACLLoggerConfig struct {
|
|
ConfigBase
|
|
LogAllowed bool `json:"log_allowed"`
|
|
} // @name ACLLoggerConfig
|
|
RequestLoggerConfig struct {
|
|
ConfigBase
|
|
Format Format `json:"format" validate:"oneof=common combined json"`
|
|
Filters Filters `json:"filters"`
|
|
Fields Fields `json:"fields"`
|
|
} // @name RequestLoggerConfig
|
|
Config struct {
|
|
ConfigBase
|
|
acl *ACLLoggerConfig
|
|
req *RequestLoggerConfig
|
|
}
|
|
AnyConfig interface {
|
|
ToConfig() *Config
|
|
Writers() ([]File, error)
|
|
}
|
|
|
|
Format string
|
|
Filters struct {
|
|
StatusCodes LogFilter[*StatusCodeRange] `json:"status_codes,omitzero"`
|
|
Method LogFilter[HTTPMethod] `json:"method,omitzero"`
|
|
Host LogFilter[Host] `json:"host,omitzero"`
|
|
Headers LogFilter[*HTTPHeader] `json:"headers,omitzero"` // header exists or header == value
|
|
CIDR LogFilter[*CIDR] `json:"cidr,omitzero"`
|
|
}
|
|
Fields struct {
|
|
Headers FieldConfig `json:"headers,omitzero" aliases:"header"`
|
|
Query FieldConfig `json:"query,omitzero" aliases:"queries"`
|
|
Cookies FieldConfig `json:"cookies,omitzero" aliases:"cookie"`
|
|
}
|
|
)
|
|
|
|
var (
|
|
FormatCommon Format = "common"
|
|
FormatCombined Format = "combined"
|
|
FormatJSON Format = "json"
|
|
|
|
ReqLoggerFormats = []Format{FormatCommon, FormatCombined, FormatJSON}
|
|
)
|
|
|
|
func (cfg *ConfigBase) Validate() error {
|
|
if cfg.Path == "" && !cfg.Stdout {
|
|
return errors.New("path or stdout is required")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Writers returns a list of writers for the config.
|
|
func (cfg *ConfigBase) Writers() ([]File, error) {
|
|
writers := make([]File, 0, 2)
|
|
if cfg.Path != "" {
|
|
f, err := OpenFile(cfg.Path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
writers = append(writers, f)
|
|
}
|
|
if cfg.Stdout {
|
|
writers = append(writers, stdout)
|
|
}
|
|
return writers, nil
|
|
}
|
|
|
|
func (cfg *ACLLoggerConfig) ToConfig() *Config {
|
|
return &Config{
|
|
ConfigBase: cfg.ConfigBase,
|
|
acl: cfg,
|
|
}
|
|
}
|
|
|
|
func (cfg *RequestLoggerConfig) ToConfig() *Config {
|
|
return &Config{
|
|
ConfigBase: cfg.ConfigBase,
|
|
req: cfg,
|
|
}
|
|
}
|
|
|
|
func (cfg *Config) ShouldLogRequest(req *http.Request, res *http.Response) bool {
|
|
if cfg.req == nil {
|
|
return true
|
|
}
|
|
return cfg.req.Filters.StatusCodes.CheckKeep(req, res) &&
|
|
cfg.req.Filters.Method.CheckKeep(req, res) &&
|
|
cfg.req.Filters.Headers.CheckKeep(req, res) &&
|
|
cfg.req.Filters.CIDR.CheckKeep(req, res)
|
|
}
|
|
|
|
func DefaultRequestLoggerConfig() *RequestLoggerConfig {
|
|
return &RequestLoggerConfig{
|
|
ConfigBase: ConfigBase{
|
|
Retention: &Retention{Days: 30},
|
|
},
|
|
Format: FormatCombined,
|
|
Fields: Fields{
|
|
Headers: FieldConfig{
|
|
Default: FieldModeDrop,
|
|
},
|
|
Query: FieldConfig{
|
|
Default: FieldModeKeep,
|
|
},
|
|
Cookies: FieldConfig{
|
|
Default: FieldModeDrop,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func DefaultACLLoggerConfig() *ACLLoggerConfig {
|
|
return &ACLLoggerConfig{
|
|
ConfigBase: ConfigBase{
|
|
Retention: &Retention{Days: 30},
|
|
},
|
|
}
|
|
}
|
|
|
|
func init() {
|
|
serialization.RegisterDefaultValueFactory(DefaultRequestLoggerConfig)
|
|
serialization.RegisterDefaultValueFactory(DefaultACLLoggerConfig)
|
|
}
|