yoake/server/webroot/log.go
2022-11-07 05:45:02 -05:00

134 lines
3.4 KiB
Go

package webroot
import (
"fmt"
"log"
"path"
"regexp"
"strconv"
"github.com/eternal-flame-AD/yoake/internal/auth"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
type logEntry struct {
middleware.RequestLoggerValues
Categories []string
CleanPath string
Auth auth.RequestAuth
}
func processLoggerValues(c echo.Context, values middleware.RequestLoggerValues) logEntry {
status := values.Status
statusString := []byte(strconv.Itoa(status))
for i := len(statusString) - 1; i >= 0; i-- {
logSetRequestCategory(c, fmt.Sprintf("status_%s", statusString))
statusString[i] = 'x'
}
return logEntry{
RequestLoggerValues: values,
Categories: logGetCategories(c),
CleanPath: path.Clean(c.Request().URL.Path),
Auth: auth.GetRequestAuth(c),
}
}
type logCompiledFilter struct {
Negate bool
Pattern *regexp.Regexp
}
func logGetCategories(c echo.Context) []string {
if existingCates, err := c.Get("log_request_categories").([]string); err {
return existingCates
} else {
return []string{}
}
}
func logCompileFilters(filters []string) []logCompiledFilter {
var compiledFilters []logCompiledFilter
for _, filter := range filters {
negate := false
if filter[0] == '!' {
negate = true
filter = filter[1:]
}
log.Printf("Compiling filter: %s negate=%v", filter, negate)
compiledFilters = append(compiledFilters, logCompiledFilter{negate, regexp.MustCompile(filter)})
}
return compiledFilters
}
func logFilterCategories(c echo.Context, filters []logCompiledFilter) bool {
if filters == nil {
return true
}
for _, category := range logGetCategories(c) {
for _, filter := range filters {
matches := filter.Pattern.MatchString(category)
negate := filter.Negate
// log.Printf("Checking category %s against filter %s negate=%v matches=%v", category, filter.Pattern, negate, matches)
if matches {
return !negate
}
}
}
return true
}
func logSetRequestCategory(c echo.Context, category string) {
if existingCates, ok := c.Get("log_request_categories").([]string); !ok {
c.Set("log_request_categories", []string{category})
} else {
c.Set("log_request_categories", append(existingCates, category))
}
}
func logRemoveRequestCategory(c echo.Context, category string) {
if existingCates, ok := c.Get("log_request_categories").([]string); ok {
for i, existingCate := range existingCates {
if existingCate == category {
c.Set("log_request_categories", append(existingCates[:i], existingCates[i+1:]...))
return
}
}
}
}
func logMiddleware(category string, backend echo.MiddlewareFunc) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
logSetRequestCategory(c, category)
wrappedNext := func(c echo.Context) error {
logRemoveRequestCategory(c, category)
return next(c)
}
return backend(wrappedNext)(c)
}
}
}
var (
loggerConfig = middleware.RequestLoggerConfig{
LogLatency: true,
LogProtocol: true,
LogRemoteIP: true,
LogHost: true,
LogMethod: true,
LogURI: true,
LogURIPath: true,
LogRoutePath: true,
LogRequestID: true,
LogReferer: true,
LogUserAgent: true,
LogStatus: true,
LogError: true,
LogContentLength: true,
LogResponseSize: true,
LogHeaders: []string{},
LogQueryParams: []string{},
LogFormValues: []string{},
}
)