mirror of
https://github.com/yusing/godoxy.git
synced 2026-03-31 14:13:09 +02:00
v0.26.0
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
package accesslog
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/yusing/godoxy/internal/serialization"
|
||||
gperr "github.com/yusing/goutils/errs"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -58,9 +58,9 @@ var (
|
||||
ReqLoggerFormats = []Format{FormatCommon, FormatCombined, FormatJSON}
|
||||
)
|
||||
|
||||
func (cfg *ConfigBase) Validate() gperr.Error {
|
||||
func (cfg *ConfigBase) Validate() error {
|
||||
if cfg.Path == "" && !cfg.Stdout {
|
||||
return gperr.New("path or stdout is required")
|
||||
return errors.New("path or stdout is required")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -59,8 +59,8 @@ func (l *ConsoleLogger) LogError(req *http.Request, err error) {
|
||||
l.formatter.LogRequestZeroLog(&log, req, internalErrorResponse)
|
||||
}
|
||||
|
||||
func (l *ConsoleLogger) LogACL(info *maxmind.IPInfo, blocked bool) {
|
||||
ConsoleACLFormatter{}.LogACLZeroLog(stdoutLogger, info, blocked)
|
||||
func (l *ConsoleLogger) LogACL(info *maxmind.IPInfo, blocked bool, reason string) {
|
||||
ConsoleACLFormatter{}.LogACLZeroLog(stdoutLogger, info, blocked, reason)
|
||||
}
|
||||
|
||||
func (l *ConsoleLogger) Flush() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package accesslog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"sync"
|
||||
@@ -11,7 +12,6 @@ import (
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
maxmind "github.com/yusing/godoxy/internal/maxmind/types"
|
||||
gperr "github.com/yusing/goutils/errs"
|
||||
ioutils "github.com/yusing/goutils/io"
|
||||
strutils "github.com/yusing/goutils/strings"
|
||||
"github.com/yusing/goutils/synk"
|
||||
@@ -131,7 +131,7 @@ func (l *fileAccessLogger) LogError(req *http.Request, err error) {
|
||||
l.LogRequest(req, internalErrorResponse)
|
||||
}
|
||||
|
||||
func (l *fileAccessLogger) LogACL(info *maxmind.IPInfo, blocked bool) {
|
||||
func (l *fileAccessLogger) LogACL(info *maxmind.IPInfo, blocked bool, reason string) {
|
||||
line := bytesPool.GetBuffer()
|
||||
defer bytesPool.PutBuffer(line)
|
||||
l.AppendACLLog(line, info, blocked)
|
||||
@@ -161,9 +161,9 @@ func (l *fileAccessLogger) Rotate(result *RotateResult) (rotated bool, err error
|
||||
|
||||
func (l *fileAccessLogger) handleErr(err error) {
|
||||
if l.errRateLimiter.Allow() {
|
||||
gperr.LogError("failed to write access log", err, &l.logger)
|
||||
l.logger.Err(err).Msg("failed to write access log")
|
||||
} else {
|
||||
gperr.LogError("too many errors, stopping access log", err, &l.logger)
|
||||
l.logger.Err(err).Msg("too many errors, stopping access log")
|
||||
l.task.Finish(err)
|
||||
}
|
||||
}
|
||||
@@ -234,7 +234,7 @@ func (l *fileAccessLogger) write(data []byte) {
|
||||
if err != nil {
|
||||
l.handleErr(err)
|
||||
} else if n < len(data) {
|
||||
l.handleErr(gperr.Errorf("%w, writing %d bytes, only %d written", io.ErrShortWrite, len(data), n))
|
||||
l.handleErr(fmt.Errorf("%w, writing %d bytes, only %d written", io.ErrShortWrite, len(data), n))
|
||||
}
|
||||
atomic.AddInt64(&l.writeCount, int64(n))
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package accesslog
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
nettypes "github.com/yusing/godoxy/internal/net/types"
|
||||
gperr "github.com/yusing/goutils/errs"
|
||||
strutils "github.com/yusing/goutils/strings"
|
||||
)
|
||||
|
||||
@@ -29,7 +30,7 @@ type (
|
||||
} // @name CIDR
|
||||
)
|
||||
|
||||
var ErrInvalidHTTPHeaderFilter = gperr.New("invalid http header filter")
|
||||
var ErrInvalidHTTPHeaderFilter = errors.New("invalid http header filter")
|
||||
|
||||
func (f *LogFilter[T]) CheckKeep(req *http.Request, res *http.Response) bool {
|
||||
if len(f.Values) == 0 {
|
||||
@@ -59,7 +60,7 @@ func (k *HTTPHeader) Parse(v string) error {
|
||||
split = append(split, "")
|
||||
case 2:
|
||||
default:
|
||||
return ErrInvalidHTTPHeaderFilter.Subject(v)
|
||||
return fmt.Errorf("%w: %s", ErrInvalidHTTPHeaderFilter, v)
|
||||
}
|
||||
k.Key = split[0]
|
||||
k.Value = split[1]
|
||||
|
||||
@@ -171,7 +171,7 @@ func (f ACLLogFormatter) LogACLZeroLog(logger *zerolog.Logger, info *maxmind.IPI
|
||||
event.Send()
|
||||
}
|
||||
|
||||
func (f ConsoleACLFormatter) LogACLZeroLog(logger *zerolog.Logger, info *maxmind.IPInfo, blocked bool) {
|
||||
func (f ConsoleACLFormatter) LogACLZeroLog(logger *zerolog.Logger, info *maxmind.IPInfo, blocked bool, reason string) {
|
||||
event := logger.Info()
|
||||
if info.City != nil {
|
||||
if isoCode := info.City.Country.IsoCode; isoCode != "" {
|
||||
@@ -186,6 +186,10 @@ func (f ConsoleACLFormatter) LogACLZeroLog(logger *zerolog.Logger, info *maxmind
|
||||
action = "denied"
|
||||
}
|
||||
|
||||
if reason != "" {
|
||||
event.Str("reason", reason)
|
||||
}
|
||||
|
||||
// NOTE: zerolog will append a newline to the buffer
|
||||
event.Msgf("request %s from %s", action, info.Str)
|
||||
}
|
||||
|
||||
@@ -50,9 +50,9 @@ func (m *MultiAccessLogger) LogError(req *http.Request, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MultiAccessLogger) LogACL(info *maxmind.IPInfo, blocked bool) {
|
||||
func (m *MultiAccessLogger) LogACL(info *maxmind.IPInfo, blocked bool, reason string) {
|
||||
for _, accessLogger := range m.accessLoggers {
|
||||
accessLogger.LogACL(info, blocked)
|
||||
accessLogger.LogACL(info, blocked, reason)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ func TestMultiAccessLoggerLogACL(t *testing.T) {
|
||||
Str: "192.168.1.1",
|
||||
}
|
||||
|
||||
logger.LogACL(info, false)
|
||||
logger.LogACL(info, false, "test reason")
|
||||
logger.Flush()
|
||||
|
||||
expect.Equal(t, writer1.NumLines(), 1)
|
||||
@@ -252,7 +252,7 @@ func TestMultiAccessLoggerMixedOperations(t *testing.T) {
|
||||
cfg2 := DefaultACLLoggerConfig()
|
||||
cfg2.LogAllowed = true
|
||||
aclLogger := NewMultiAccessLogger(testTask, cfg2, writers)
|
||||
aclLogger.LogACL(info, false)
|
||||
aclLogger.LogACL(info, false, "test reason")
|
||||
|
||||
logger.Flush()
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package accesslog
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
gperr "github.com/yusing/goutils/errs"
|
||||
strutils "github.com/yusing/goutils/strings"
|
||||
)
|
||||
|
||||
@@ -15,8 +15,8 @@ type Retention struct {
|
||||
} // @name LogRetention
|
||||
|
||||
var (
|
||||
ErrInvalidSyntax = gperr.New("invalid syntax")
|
||||
ErrZeroValue = gperr.New("zero value")
|
||||
ErrInvalidSyntax = errors.New("invalid syntax")
|
||||
ErrZeroValue = errors.New("zero value")
|
||||
)
|
||||
|
||||
// see back_scanner_test.go#L210 for benchmarks
|
||||
@@ -34,7 +34,7 @@ var defaultChunkSize = 32 * kilobyte
|
||||
func (r *Retention) Parse(v string) (err error) {
|
||||
split := strutils.SplitSpace(v)
|
||||
if len(split) != 2 {
|
||||
return ErrInvalidSyntax.Subject(v)
|
||||
return fmt.Errorf("%w: %s", ErrInvalidSyntax, v)
|
||||
}
|
||||
switch split[0] {
|
||||
case "last":
|
||||
@@ -64,7 +64,7 @@ func (r *Retention) Parse(v string) (err error) {
|
||||
case "GB":
|
||||
r.KeepSize = n * gigabyte
|
||||
default:
|
||||
return ErrInvalidSyntax.Subject("unit " + split[1])
|
||||
return fmt.Errorf("%w: unit %s", ErrInvalidSyntax, split[1])
|
||||
}
|
||||
}
|
||||
if !r.IsValid() {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package accesslog
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
gperr "github.com/yusing/goutils/errs"
|
||||
@@ -12,7 +14,7 @@ type StatusCodeRange struct {
|
||||
End int
|
||||
} // @name StatusCodeRange
|
||||
|
||||
var ErrInvalidStatusCodeRange = gperr.New("invalid status code range")
|
||||
var ErrInvalidStatusCodeRange = errors.New("invalid status code range")
|
||||
|
||||
func (r *StatusCodeRange) Includes(code int) bool {
|
||||
return r.Start <= code && code <= r.End
|
||||
@@ -25,7 +27,7 @@ func (r *StatusCodeRange) Parse(v string) error {
|
||||
case 1:
|
||||
start, err := strconv.Atoi(split[0])
|
||||
if err != nil {
|
||||
return gperr.Wrap(err)
|
||||
return err
|
||||
}
|
||||
r.Start = start
|
||||
r.End = start
|
||||
@@ -40,7 +42,7 @@ func (r *StatusCodeRange) Parse(v string) error {
|
||||
r.End = end
|
||||
return nil
|
||||
default:
|
||||
return ErrInvalidStatusCodeRange.Subject(v)
|
||||
return fmt.Errorf("%w: %s", ErrInvalidStatusCodeRange, v)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ type (
|
||||
AccessLogger interface {
|
||||
LogRequest(req *http.Request, res *http.Response)
|
||||
LogError(req *http.Request, err error)
|
||||
LogACL(info *maxmind.IPInfo, blocked bool)
|
||||
LogACL(info *maxmind.IPInfo, blocked bool, reason string)
|
||||
|
||||
Config() *Config
|
||||
|
||||
@@ -35,9 +35,9 @@ type (
|
||||
}
|
||||
ACLFormatter interface {
|
||||
// AppendACLLog appends a log line to line with or without a trailing newline
|
||||
AppendACLLog(line *bytes.Buffer, info *maxmind.IPInfo, blocked bool)
|
||||
AppendACLLog(line *bytes.Buffer, info *maxmind.IPInfo, blocked bool, reason string)
|
||||
// LogACLZeroLog logs an ACL log to the logger
|
||||
LogACLZeroLog(logger *zerolog.Logger, info *maxmind.IPInfo, blocked bool)
|
||||
LogACLZeroLog(logger *zerolog.Logger, info *maxmind.IPInfo, blocked bool, reason string)
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -87,8 +87,28 @@ func multiWriter(out ...io.Writer) io.Writer {
|
||||
|
||||
func NewLogger(out ...io.Writer) zerolog.Logger {
|
||||
writer := zerolog.NewConsoleWriter(func(w *zerolog.ConsoleWriter) {
|
||||
w.Out = diodeMultiWriter(out...)
|
||||
if !common.IsTest {
|
||||
w.Out = diodeMultiWriter(out...)
|
||||
} else {
|
||||
w.Out = multiWriter(out...)
|
||||
}
|
||||
w.TimeFormat = timeFmt
|
||||
w.FormatPrepare = func(evt map[string]any) error {
|
||||
// move error field to join message if it's multiline
|
||||
if err, ok := evt[zerolog.ErrorFieldName].(string); ok {
|
||||
if strings.Count(err, "\n") == 0 {
|
||||
return nil
|
||||
}
|
||||
msg, ok := evt[zerolog.MessageFieldName].(string)
|
||||
if ok && msg != "" {
|
||||
evt[zerolog.MessageFieldName] = msg + "\n" + err
|
||||
} else {
|
||||
evt[zerolog.MessageFieldName] = err
|
||||
}
|
||||
delete(evt, zerolog.ErrorFieldName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
w.FormatMessage = func(msgI any) string { // pad spaces for each line
|
||||
if msgI == nil {
|
||||
return ""
|
||||
|
||||
Reference in New Issue
Block a user