feat: adding filters

This commit is contained in:
Samuel Berthe
2023-09-15 04:55:51 +02:00
parent 6e969abe5d
commit 8fc05e396a
3 changed files with 400 additions and 0 deletions
+40
View File
@@ -78,6 +78,46 @@ router.Run(":1234")
// time=2023-04-10T14:00:0.000000Z level=INFO msg="Incoming request" status=200 method=GET path=/pong ip=127.0.0.1 latency=25.5µs user-agent=curl/7.77.0 time=2023-04-10T14:00:00.000Z // time=2023-04-10T14:00:0.000000Z level=INFO msg="Incoming request" status=200 method=GET path=/pong ip=127.0.0.1 latency=25.5µs user-agent=curl/7.77.0 time=2023-04-10T14:00:00.000Z
``` ```
### Filters
```go
import (
"github.com/gin-gonic/gin"
sloggin "github.com/samber/slog-gin"
"log/slog"
)
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
router := gin.New()
router.Use(
sloggin.NewWithFilters(
logger,
sloggin.Accept(func (c *gin.Context) bool {
return xxx
}),
sloggin.IgnoreStatus(401, 404),
),
)
```
Available filters:
- Accept / Ignore
- AcceptMethod / IgnoreMethod
- AcceptStatus / IgnoreStatus
- AcceptStatusGreaterThan / IgnoreStatusLessThan
- AcceptStatusGreaterThanOrEqual / IgnoreStatusLessThanOrEqual
- AcceptPath / IgnorePath
- AcceptPathContains / IgnorePathContains
- AcceptPathPrefix / IgnorePathPrefix
- AcceptPathSuffix / IgnorePathSuffix
- AcceptPathMatch / IgnorePathMatch
- AcceptHost / IgnoreHost
- AcceptHostContains / IgnoreHostContains
- AcceptHostPrefix / IgnoreHostPrefix
- AcceptHostSuffix / IgnoreHostSuffix
- AcceptHostMatch / IgnoreHostMatch
### Using custom time formatters ### Using custom time formatters
```go ```go
+334
View File
@@ -0,0 +1,334 @@
package sloggin
import (
"regexp"
"strings"
"github.com/gin-gonic/gin"
)
type Filter func(ctx *gin.Context) bool
// Basic
func Accept(filter Filter) Filter { return filter }
func Ignore(filter Filter) Filter { return filter }
// Method
func AcceptMethod(methods ...string) Filter {
return func(c *gin.Context) bool {
reqMethod := strings.ToLower(c.Request.Method)
for _, method := range methods {
if strings.ToLower(method) == reqMethod {
return true
}
}
return false
}
}
func IgnoreMethod(methods ...string) Filter {
return func(c *gin.Context) bool {
reqMethod := strings.ToLower(c.Request.Method)
for _, method := range methods {
if strings.ToLower(method) == reqMethod {
return false
}
}
return true
}
}
// Status
func AcceptStatus(statuses ...int) Filter {
return func(c *gin.Context) bool {
for _, status := range statuses {
if status == c.Writer.Status() {
return true
}
}
return false
}
}
func IgnoreStatus(statuses ...int) Filter {
return func(c *gin.Context) bool {
for _, status := range statuses {
if status == c.Writer.Status() {
return false
}
}
return true
}
}
func AcceptStatusGreaterThan(status int) Filter {
return func(c *gin.Context) bool {
return c.Writer.Status() > status
}
}
func IgnoreStatusLessThan(status int) Filter {
return func(c *gin.Context) bool {
return c.Writer.Status() < status
}
}
func AcceptStatusGreaterThanOrEqual(status int) Filter {
return func(c *gin.Context) bool {
return c.Writer.Status() >= status
}
}
func IgnoreStatusLessThanOrEqual(status int) Filter {
return func(c *gin.Context) bool {
return c.Writer.Status() <= status
}
}
// Path
func AcceptPath(urls ...string) Filter {
return func(c *gin.Context) bool {
for _, url := range urls {
if c.Request.URL.Path == url {
return true
}
}
return false
}
}
func IgnorePath(urls ...string) Filter {
return func(c *gin.Context) bool {
for _, url := range urls {
if c.Request.URL.Path == url {
return false
}
}
return true
}
}
func AcceptPathContains(parts ...string) Filter {
return func(c *gin.Context) bool {
for _, part := range parts {
if strings.Contains(c.Request.URL.Path, part) {
return true
}
}
return false
}
}
func IgnorePathContains(parts ...string) Filter {
return func(c *gin.Context) bool {
for _, part := range parts {
if strings.Contains(c.Request.URL.Path, part) {
return false
}
}
return true
}
}
func AcceptPathPrefix(prefixs ...string) Filter {
return func(c *gin.Context) bool {
for _, prefix := range prefixs {
if strings.HasPrefix(c.Request.URL.Path, prefix) {
return true
}
}
return false
}
}
func IgnorePathPrefix(prefixs ...string) Filter {
return func(c *gin.Context) bool {
for _, prefix := range prefixs {
if strings.HasPrefix(c.Request.URL.Path, prefix) {
return false
}
}
return true
}
}
func AcceptPathSuffix(prefixs ...string) Filter {
return func(c *gin.Context) bool {
for _, prefix := range prefixs {
if strings.HasPrefix(c.Request.URL.Path, prefix) {
return true
}
}
return false
}
}
func IgnorePathSuffix(suffixs ...string) Filter {
return func(c *gin.Context) bool {
for _, suffix := range suffixs {
if strings.HasSuffix(c.Request.URL.Path, suffix) {
return false
}
}
return true
}
}
func AcceptPathMatch(regs ...regexp.Regexp) Filter {
return func(c *gin.Context) bool {
for _, reg := range regs {
if reg.Match([]byte(c.Request.URL.Path)) {
return true
}
}
return false
}
}
func IgnorePathMatch(regs ...regexp.Regexp) Filter {
return func(c *gin.Context) bool {
for _, reg := range regs {
if reg.Match([]byte(c.Request.URL.Path)) {
return false
}
}
return true
}
}
// Host
func AcceptHost(hosts ...string) Filter {
return func(c *gin.Context) bool {
for _, host := range hosts {
if c.Request.URL.Host == host {
return true
}
}
return false
}
}
func IgnoreHost(hosts ...string) Filter {
return func(c *gin.Context) bool {
for _, host := range hosts {
if c.Request.URL.Host == host {
return false
}
}
return true
}
}
func AcceptHostContains(parts ...string) Filter {
return func(c *gin.Context) bool {
for _, part := range parts {
if strings.Contains(c.Request.URL.Host, part) {
return true
}
}
return false
}
}
func IgnoreHostContains(parts ...string) Filter {
return func(c *gin.Context) bool {
for _, part := range parts {
if strings.Contains(c.Request.URL.Host, part) {
return false
}
}
return true
}
}
func AcceptHostPrefix(prefixs ...string) Filter {
return func(c *gin.Context) bool {
for _, prefix := range prefixs {
if strings.HasPrefix(c.Request.URL.Host, prefix) {
return true
}
}
return false
}
}
func IgnoreHostPrefix(prefixs ...string) Filter {
return func(c *gin.Context) bool {
for _, prefix := range prefixs {
if strings.HasPrefix(c.Request.URL.Host, prefix) {
return false
}
}
return true
}
}
func AcceptHostSuffix(prefixs ...string) Filter {
return func(c *gin.Context) bool {
for _, prefix := range prefixs {
if strings.HasPrefix(c.Request.URL.Host, prefix) {
return true
}
}
return false
}
}
func IgnoreHostSuffix(suffixs ...string) Filter {
return func(c *gin.Context) bool {
for _, suffix := range suffixs {
if strings.HasSuffix(c.Request.URL.Host, suffix) {
return false
}
}
return true
}
}
func AcceptHostMatch(regs ...regexp.Regexp) Filter {
return func(c *gin.Context) bool {
for _, reg := range regs {
if reg.Match([]byte(c.Request.URL.Host)) {
return true
}
}
return false
}
}
func IgnoreHostMatch(regs ...regexp.Regexp) Filter {
return func(c *gin.Context) bool {
for _, reg := range regs {
if reg.Match([]byte(c.Request.URL.Host)) {
return false
}
}
return true
}
}
+26
View File
@@ -19,6 +19,8 @@ type Config struct {
ServerErrorLevel slog.Level ServerErrorLevel slog.Level
WithRequestID bool WithRequestID bool
Filters []Filter
} }
// New returns a gin.HandlerFunc (middleware) that logs requests using slog. // New returns a gin.HandlerFunc (middleware) that logs requests using slog.
@@ -32,6 +34,24 @@ func New(logger *slog.Logger) gin.HandlerFunc {
ServerErrorLevel: slog.LevelError, ServerErrorLevel: slog.LevelError,
WithRequestID: true, WithRequestID: true,
Filters: []Filter{},
})
}
// NewWithFilters returns a gin.HandlerFunc (middleware) that logs requests using slog.
//
// Requests with errors are logged using slog.Error().
// Requests without errors are logged using slog.Info().
func NewWithFilters(logger *slog.Logger, filters ...Filter) gin.HandlerFunc {
return NewWithConfig(logger, Config{
DefaultLevel: slog.LevelInfo,
ClientErrorLevel: slog.LevelWarn,
ServerErrorLevel: slog.LevelError,
WithRequestID: true,
Filters: filters,
}) })
} }
@@ -66,6 +86,12 @@ func NewWithConfig(logger *slog.Logger, config Config) gin.HandlerFunc {
attributes = append(attributes, slog.String("request-id", requestID)) attributes = append(attributes, slog.String("request-id", requestID))
} }
for _, filter := range config.Filters {
if !filter(c) {
return
}
}
switch { switch {
case c.Writer.Status() >= http.StatusBadRequest && c.Writer.Status() < http.StatusInternalServerError: case c.Writer.Status() >= http.StatusBadRequest && c.Writer.Status() < http.StatusInternalServerError:
logger.LogAttrs(context.Background(), config.ClientErrorLevel, c.Errors.String(), attributes...) logger.LogAttrs(context.Background(), config.ClientErrorLevel, c.Errors.String(), attributes...)