Improve interface for custom logger func (#2225)

* - logger: fix custom tag
- use real bytebufferpool dependency instead of the internal

* - logger: fix custom tag
- use real bytebufferpool dependency instead of the internal

* - logger: fix custom tag
- use real bytebufferpool dependency instead of the internal

* - logger: fix custom tag
- use real bytebufferpool dependency instead of the internal
pull/2227/head
RW 2022-11-18 15:32:56 +01:00 committed by GitHub
parent 92ce4aac77
commit e4b3b5c708
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 114 additions and 390 deletions

2
ctx.go
View File

@ -24,10 +24,10 @@ import (
"text/template"
"time"
"github.com/gofiber/fiber/v2/internal/bytebufferpool"
"github.com/gofiber/fiber/v2/internal/dictpool"
"github.com/gofiber/fiber/v2/internal/schema"
"github.com/gofiber/fiber/v2/utils"
"github.com/valyala/bytebufferpool"
"github.com/valyala/fasthttp"
)

View File

@ -29,9 +29,9 @@ import (
"text/template"
"time"
"github.com/gofiber/fiber/v2/internal/bytebufferpool"
"github.com/gofiber/fiber/v2/internal/storage/memory"
"github.com/gofiber/fiber/v2/utils"
"github.com/valyala/bytebufferpool"
"github.com/valyala/fasthttp"
)

2
go.mod
View File

@ -6,6 +6,7 @@ require (
github.com/mattn/go-colorable v0.1.13
github.com/mattn/go-isatty v0.0.16
github.com/mattn/go-runewidth v0.0.14
github.com/valyala/bytebufferpool v1.0.0
github.com/valyala/fasthttp v1.41.0
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab
)
@ -14,6 +15,5 @@ require (
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/klauspost/compress v1.15.9 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
)

View File

@ -19,8 +19,8 @@ import (
"time"
"unsafe"
"github.com/gofiber/fiber/v2/internal/bytebufferpool"
"github.com/gofiber/fiber/v2/utils"
"github.com/valyala/bytebufferpool"
"github.com/valyala/fasthttp"
)

View File

@ -6,8 +6,8 @@ import (
"testing"
"time"
"github.com/gofiber/fiber/v2/internal/bytebufferpool"
"github.com/gofiber/fiber/v2/utils"
"github.com/valyala/bytebufferpool"
)
var testSimpleHandler = func(c *Ctx) error {

View File

@ -1,22 +0,0 @@
The MIT License (MIT)
Copyright (c) 2016 Aliaksandr Valialkin, VertaMedia
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,111 +0,0 @@
package bytebufferpool
import "io"
// ByteBuffer provides byte buffer, which can be used for minimizing
// memory allocations.
//
// ByteBuffer may be used with functions appending data to the given []byte
// slice. See example code for details.
//
// Use Get for obtaining an empty byte buffer.
type ByteBuffer struct {
// B is a byte buffer to use in append-like workloads.
// See example code for details.
B []byte
}
// Len returns the size of the byte buffer.
func (b *ByteBuffer) Len() int {
return len(b.B)
}
// ReadFrom implements io.ReaderFrom.
//
// The function appends all the data read from r to b.
func (b *ByteBuffer) ReadFrom(r io.Reader) (int64, error) {
p := b.B
nStart := int64(len(p))
nMax := int64(cap(p))
n := nStart
if nMax == 0 {
nMax = 64
p = make([]byte, nMax)
} else {
p = p[:nMax]
}
for {
if n == nMax {
nMax *= 2
bNew := make([]byte, nMax)
copy(bNew, p)
p = bNew
}
nn, err := r.Read(p[n:])
n += int64(nn)
if err != nil {
b.B = p[:n]
n -= nStart
if err == io.EOF {
return n, nil
}
return n, err
}
}
}
// WriteTo implements io.WriterTo.
func (b *ByteBuffer) WriteTo(w io.Writer) (int64, error) {
n, err := w.Write(b.B)
return int64(n), err
}
// Bytes returns b.B, i.e. all the bytes accumulated in the buffer.
//
// The purpose of this function is bytes.Buffer compatibility.
func (b *ByteBuffer) Bytes() []byte {
return b.B
}
// Write implements io.Writer - it appends p to ByteBuffer.B
func (b *ByteBuffer) Write(p []byte) (int, error) {
b.B = append(b.B, p...)
return len(p), nil
}
// WriteByte appends the byte c to the buffer.
//
// The purpose of this function is bytes.Buffer compatibility.
//
// The function always returns nil.
func (b *ByteBuffer) WriteByte(c byte) error {
b.B = append(b.B, c)
return nil
}
// WriteString appends s to ByteBuffer.B.
func (b *ByteBuffer) WriteString(s string) (int, error) {
b.B = append(b.B, s...)
return len(s), nil
}
// Set sets ByteBuffer.B to p.
func (b *ByteBuffer) Set(p []byte) {
b.B = append(b.B[:0], p...)
}
// SetString sets ByteBuffer.B to s.
func (b *ByteBuffer) SetString(s string) {
b.B = append(b.B[:0], s...)
}
// String returns string representation of ByteBuffer.B.
func (b *ByteBuffer) String() string {
return string(b.B)
}
// Reset makes ByteBuffer.B empty.
func (b *ByteBuffer) Reset() {
b.B = b.B[:0]
}

View File

@ -1,151 +0,0 @@
package bytebufferpool
import (
"sort"
"sync"
"sync/atomic"
)
const (
minBitSize = 6 // 2**6=64 is a CPU cache line size
steps = 20
minSize = 1 << minBitSize
maxSize = 1 << (minBitSize + steps - 1)
calibrateCallsThreshold = 42000
maxPercentile = 0.95
)
// Pool represents byte buffer pool.
//
// Distinct pools may be used for distinct types of byte buffers.
// Properly determined byte buffer types with their own pools may help reducing
// memory waste.
type Pool struct {
calls [steps]uint64
calibrating uint64
defaultSize uint64
maxSize uint64
pool sync.Pool
}
var defaultPool Pool
// Get returns an empty byte buffer from the pool.
//
// Got byte buffer may be returned to the pool via Put call.
// This reduces the number of memory allocations required for byte buffer
// management.
func Get() *ByteBuffer { return defaultPool.Get() }
// Get returns new byte buffer with zero length.
//
// The byte buffer may be returned to the pool via Put after the use
// in order to minimize GC overhead.
func (p *Pool) Get() *ByteBuffer {
v := p.pool.Get()
if v != nil {
return v.(*ByteBuffer)
}
return &ByteBuffer{
B: make([]byte, 0, atomic.LoadUint64(&p.defaultSize)),
}
}
// Put returns byte buffer to the pool.
//
// ByteBuffer.B mustn't be touched after returning it to the pool.
// Otherwise data races will occur.
func Put(b *ByteBuffer) { defaultPool.Put(b) }
// Put releases byte buffer obtained via Get to the pool.
//
// The buffer mustn't be accessed after returning to the pool.
func (p *Pool) Put(b *ByteBuffer) {
idx := index(len(b.B))
if atomic.AddUint64(&p.calls[idx], 1) > calibrateCallsThreshold {
p.calibrate()
}
maxSize := int(atomic.LoadUint64(&p.maxSize))
if maxSize == 0 || cap(b.B) <= maxSize {
b.Reset()
p.pool.Put(b)
}
}
func (p *Pool) calibrate() {
if !atomic.CompareAndSwapUint64(&p.calibrating, 0, 1) {
return
}
a := make(callSizes, 0, steps)
var callsSum uint64
for i := uint64(0); i < steps; i++ {
calls := atomic.SwapUint64(&p.calls[i], 0)
callsSum += calls
a = append(a, callSize{
calls: calls,
size: minSize << i,
})
}
sort.Sort(a)
defaultSize := a[0].size
maxSize := defaultSize
maxSum := uint64(float64(callsSum) * maxPercentile)
callsSum = 0
for i := 0; i < steps; i++ {
if callsSum > maxSum {
break
}
callsSum += a[i].calls
size := a[i].size
if size > maxSize {
maxSize = size
}
}
atomic.StoreUint64(&p.defaultSize, defaultSize)
atomic.StoreUint64(&p.maxSize, maxSize)
atomic.StoreUint64(&p.calibrating, 0)
}
type callSize struct {
calls uint64
size uint64
}
type callSizes []callSize
func (ci callSizes) Len() int {
return len(ci)
}
func (ci callSizes) Less(i, j int) bool {
return ci[i].calls > ci[j].calls
}
func (ci callSizes) Swap(i, j int) {
ci[i], ci[j] = ci[j], ci[i]
}
func index(n int) int {
n--
n >>= minBitSize
idx := 0
for n > 0 {
n >>= 1
idx++
}
if idx >= steps {
idx = steps - 1
}
return idx
}

View File

@ -5,7 +5,7 @@ import (
"hash/crc32"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/internal/bytebufferpool"
"github.com/valyala/bytebufferpool"
)
var (

View File

@ -40,7 +40,7 @@ app.Use(logger.New())
```go
app.Use(logger.New(logger.Config{
Format: "[${ip}]:${port} ${status} - ${method} ${path}\n",
Format: "[${ip}]:${port} ${status} - ${method} ${path}\n",
}))
```
@ -80,8 +80,8 @@ app.Use(logger.New(logger.Config{
```go
app.Use(logger.New(logger.Config{
CustomTags: map[string]logger.LogFunc{
"custom_tag": func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString("it is a custom tag")
"custom_tag": func(output logger.Buffer, c *fiber.Ctx, data *logger.Data, extraParam string) (int, error) {
return output.WriteString("it is a custom tag")
},
},
}))
@ -145,11 +145,9 @@ type Config struct {
//
// Default: os.Stdout
Output io.Writer
enableColors bool
enableLatency bool
timeZoneLocation *time.Location
}
type LogFunc func(buf logger.Buffer, c *fiber.Ctx, data *logger.Data, extraParam string) (int, error)
```
## Default Config

View File

@ -7,7 +7,6 @@ import (
"time"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/internal/bytebufferpool"
)
// Config defines the config for middleware.
@ -64,7 +63,20 @@ const (
paramSeparator = ":"
)
type LogFunc func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error)
type Buffer interface {
Len() int
ReadFrom(r io.Reader) (int64, error)
WriteTo(w io.Writer) (int64, error)
Bytes() []byte
Write(p []byte) (int, error)
WriteByte(c byte) error
WriteString(s string) (int, error)
Set(p []byte)
SetString(s string)
String() string
}
type LogFunc func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error)
// ConfigDefault is the default config
var ConfigDefault = Config{

View File

@ -13,9 +13,8 @@ import (
"github.com/gofiber/fiber/v2/utils"
"github.com/mattn/go-colorable"
"github.com/mattn/go-isatty"
"github.com/valyala/bytebufferpool"
"github.com/valyala/fasthttp"
"github.com/gofiber/fiber/v2/internal/bytebufferpool"
)
// New creates a new middleware handler
@ -207,8 +206,8 @@ func New(config ...Config) fiber.Handler {
}
}
func appendInt(buf *bytebufferpool.ByteBuffer, v int) (int, error) {
old := len(buf.B)
buf.B = fasthttp.AppendUint(buf.B, v)
return len(buf.B) - old, nil
func appendInt(output Buffer, v int) (int, error) {
old := output.Len()
output.Set(fasthttp.AppendUint(output.Bytes(), v))
return output.Len() - old, nil
}

View File

@ -11,10 +11,10 @@ import (
"sync"
"testing"
"github.com/valyala/bytebufferpool"
"github.com/valyala/fasthttp"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/internal/bytebufferpool"
"github.com/gofiber/fiber/v2/middleware/requestid"
"github.com/gofiber/fiber/v2/utils"
)
@ -424,8 +424,8 @@ func Test_CustomTags(t *testing.T) {
app.Use(New(Config{
Format: "${custom_tag}",
CustomTags: map[string]LogFunc{
"custom_tag": func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(customTag)
"custom_tag": func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(customTag)
},
},
Output: buf,

View File

@ -6,7 +6,6 @@ import (
"time"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/internal/bytebufferpool"
)
// Logger variables
@ -56,145 +55,145 @@ const (
func createTagMap(cfg *Config) map[string]LogFunc {
// Set default tags
tagFunctions := map[string]LogFunc{
TagReferer: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.Get(fiber.HeaderReferer))
TagReferer: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.Get(fiber.HeaderReferer))
},
TagProtocol: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.Protocol())
TagProtocol: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.Protocol())
},
TagPort: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.Port())
TagPort: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.Port())
},
TagIP: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.IP())
TagIP: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.IP())
},
TagIPs: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.Get(fiber.HeaderXForwardedFor))
TagIPs: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.Get(fiber.HeaderXForwardedFor))
},
TagHost: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.Hostname())
TagHost: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.Hostname())
},
TagPath: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.Path())
TagPath: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.Path())
},
TagURL: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.OriginalURL())
TagURL: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.OriginalURL())
},
TagUA: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.Get(fiber.HeaderUserAgent))
TagUA: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.Get(fiber.HeaderUserAgent))
},
TagBody: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.Write(c.Body())
TagBody: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.Write(c.Body())
},
TagBytesReceived: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return appendInt(buf, len(c.Request().Body()))
TagBytesReceived: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return appendInt(output, len(c.Request().Body()))
},
TagBytesSent: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return appendInt(buf, len(c.Response().Body()))
TagBytesSent: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return appendInt(output, len(c.Response().Body()))
},
TagRoute: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.Route().Path)
TagRoute: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.Route().Path)
},
TagResBody: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.Write(c.Response().Body())
TagResBody: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.Write(c.Response().Body())
},
TagReqHeaders: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
TagReqHeaders: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
reqHeaders := make([]string, 0)
for k, v := range c.GetReqHeaders() {
reqHeaders = append(reqHeaders, k+"="+v)
}
return buf.Write([]byte(strings.Join(reqHeaders, "&")))
return output.Write([]byte(strings.Join(reqHeaders, "&")))
},
TagQueryStringParams: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.Request().URI().QueryArgs().String())
TagQueryStringParams: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.Request().URI().QueryArgs().String())
},
TagBlack: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.App().Config().ColorScheme.Black)
TagBlack: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.App().Config().ColorScheme.Black)
},
TagRed: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.App().Config().ColorScheme.Red)
TagRed: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.App().Config().ColorScheme.Red)
},
TagGreen: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.App().Config().ColorScheme.Green)
TagGreen: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.App().Config().ColorScheme.Green)
},
TagYellow: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.App().Config().ColorScheme.Yellow)
TagYellow: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.App().Config().ColorScheme.Yellow)
},
TagBlue: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.App().Config().ColorScheme.Blue)
TagBlue: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.App().Config().ColorScheme.Blue)
},
TagMagenta: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.App().Config().ColorScheme.Magenta)
TagMagenta: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.App().Config().ColorScheme.Magenta)
},
TagCyan: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.App().Config().ColorScheme.Cyan)
TagCyan: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.App().Config().ColorScheme.Cyan)
},
TagWhite: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.App().Config().ColorScheme.White)
TagWhite: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.App().Config().ColorScheme.White)
},
TagReset: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.App().Config().ColorScheme.Reset)
TagReset: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.App().Config().ColorScheme.Reset)
},
TagError: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
TagError: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
if data.ChainErr != nil {
return buf.WriteString(data.ChainErr.Error())
return output.WriteString(data.ChainErr.Error())
}
return buf.WriteString("-")
return output.WriteString("-")
},
TagReqHeader: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.Get(extraParam))
TagReqHeader: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.Get(extraParam))
},
TagHeader: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.Get(extraParam))
TagHeader: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.Get(extraParam))
},
TagRespHeader: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.GetRespHeader(extraParam))
TagRespHeader: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.GetRespHeader(extraParam))
},
TagQuery: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.Query(extraParam))
TagQuery: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.Query(extraParam))
},
TagForm: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.FormValue(extraParam))
TagForm: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.FormValue(extraParam))
},
TagCookie: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(c.Cookies(extraParam))
TagCookie: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(c.Cookies(extraParam))
},
TagLocals: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
TagLocals: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
switch v := c.Locals(extraParam).(type) {
case []byte:
return buf.Write(v)
return output.Write(v)
case string:
return buf.WriteString(v)
return output.WriteString(v)
case nil:
return 0, nil
default:
return buf.WriteString(fmt.Sprintf("%v", v))
return output.WriteString(fmt.Sprintf("%v", v))
}
},
TagStatus: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
TagStatus: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
if cfg.enableColors {
colors := c.App().Config().ColorScheme
return buf.WriteString(fmt.Sprintf("%s %3d %s", statusColor(c.Response().StatusCode(), colors), c.Response().StatusCode(), colors.Reset))
return output.WriteString(fmt.Sprintf("%s %3d %s", statusColor(c.Response().StatusCode(), colors), c.Response().StatusCode(), colors.Reset))
}
return appendInt(buf, c.Response().StatusCode())
return appendInt(output, c.Response().StatusCode())
},
TagMethod: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
TagMethod: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
if cfg.enableColors {
colors := c.App().Config().ColorScheme
return buf.WriteString(fmt.Sprintf("%s %-7s %s", methodColor(c.Method(), colors), c.Method(), colors.Reset))
return output.WriteString(fmt.Sprintf("%s %-7s %s", methodColor(c.Method(), colors), c.Method(), colors.Reset))
}
return buf.WriteString(c.Method())
return output.WriteString(c.Method())
},
TagPid: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(data.Pid)
TagPid: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(data.Pid)
},
TagLatency: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
TagLatency: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
latency := data.Stop.Sub(data.Start).Round(time.Millisecond)
return buf.WriteString(fmt.Sprintf("%7v", latency))
return output.WriteString(fmt.Sprintf("%7v", latency))
},
TagTime: func(buf *bytebufferpool.ByteBuffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return buf.WriteString(data.Timestamp.Load().(string))
TagTime: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) {
return output.WriteString(data.Timestamp.Load().(string))
},
}
// merge with custom tags from user