Add example for custom fast Accesslog Formatter

This commit is contained in:
Gerasimos (Makis) Maropoulos 2020-09-14 02:35:01 +03:00
parent 7113165cb8
commit 54a095c23f
No known key found for this signature in database
GPG Key ID: 5DBE766BD26A54E7
3 changed files with 138 additions and 8 deletions

View File

@ -71,16 +71,17 @@
* [API Versioning](routing/versioning/main.go)
* [Sitemap](routing/sitemap/main.go)
* Logging
* [Request Logger](logging/request-logger/main.go)
* [AccessLog: simple example](logging/request-logger/accesslog-simple/main.go)
* [AccessLog: log request & response and more](logging/request-logger/accesslog)
* [AccessLog: custom fields and template](logging/request-logger/accesslog-template/main.go)
* [AccessLog: CSV Format](logging/request-logger/accesslog-csv/main.go)
* [AccessLog: listen to logs and render them](logging/request-logger/accesslog-broker/main.go)
* [Log Requests to a JSON File](logging/request-logger/request-logger-file-json/main.go)
* [Application File Logger](logging/file-logger/main.go)
* [Application JSON Logger](logging/json-logger/main.go)
* [Rollbar](logging/rollbar/main.go)
* AccessLog
* [Log Requests to a JSON File](logging/request-logger/accesslog-simple/main.go)
* [Using Log Rotation and more](logging/request-logger/accesslog)
* [Custom Fields and Template](logging/request-logger/accesslog-template/main.go)
* [Listen and render Logs to a Client](logging/request-logger/accesslog-broker/main.go)
* [The CSV Formatter](logging/request-logger/accesslog-csv/main.go)
* [Create your own Formatter](logging/request-logger/accesslog-formatter/main.go)
<!-- * [Log Requests to a JSON File](logging/request-logger/request-logger-file-json/main.go) -->
* API Documentation
* [Yaag](apidoc/yaag/main.go)
* [Swagger](https://github.com/iris-contrib/swagger/tree/master/example)

View File

@ -0,0 +1,129 @@
// Package main shows to create a quite fast custom Log Formatter.
// Note that, this example requires a little more knowledge about Go.
package main
import (
"bytes"
"fmt"
"io"
"strconv"
"sync"
"time"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/middleware/accesslog"
"github.com/kataras/iris/v12/middleware/requestid"
)
func logFields(ctx iris.Context, fields *accesslog.Fields) {
fields.Set("reqid", ctx.GetID())
}
func main() {
app := iris.New()
ac := accesslog.File("./access.log").
AddFields(logFields).
SetFormatter(newCustomFormatter(' ', "-\t\t\t\t\t"))
ac.RequestBody = false
ac.BytesReceivedBody = false
ac.BytesSentBody = false
defer ac.Close()
app.UseRouter(ac.Handler)
app.UseRouter(requestid.New())
app.OnErrorCode(iris.StatusNotFound, notFound)
app.Get("/", index)
app.Listen(":8080")
}
func notFound(ctx iris.Context) {
ctx.WriteString("The page you're looking for does not exist!")
}
func index(ctx iris.Context) {
ctx.WriteString("OK Index")
}
type customFormatter struct {
w io.Writer
bufPool *sync.Pool
delim byte
blank string
}
var _ accesslog.Formatter = (*customFormatter)(nil)
func newCustomFormatter(delim byte, blank string) *customFormatter {
return &customFormatter{delim: delim, blank: blank}
}
func (f *customFormatter) SetOutput(dest io.Writer) {
f.w = dest
f.bufPool = &sync.Pool{
New: func() interface{} {
return new(bytes.Buffer)
},
}
if f.delim == 0 {
f.delim = ' '
}
}
const newLine = '\n'
func (f *customFormatter) Format(log *accesslog.Log) (bool, error) {
buf := f.bufPool.Get().(*bytes.Buffer)
buf.WriteString(log.Now.Format(log.TimeFormat))
buf.WriteByte(f.delim)
reqid := log.Fields.GetString("reqid")
f.writeTextOrBlank(buf, reqid)
buf.WriteString(uniformDuration(log.Latency))
buf.WriteByte(f.delim)
buf.WriteString(log.IP)
buf.WriteByte(f.delim)
buf.WriteString(strconv.Itoa(log.Code))
buf.WriteByte(f.delim)
buf.WriteString(log.Method)
buf.WriteByte(f.delim)
buf.WriteString(log.Path)
buf.WriteByte(newLine)
// _, err := buf.WriteTo(f.w)
// or (to make sure that it resets on errors too):
_, err := f.w.Write(buf.Bytes())
buf.Reset()
f.bufPool.Put(buf)
return true, err
}
func (f *customFormatter) writeTextOrBlank(buf *bytes.Buffer, s string) {
if len(s) == 0 {
if len(f.blank) == 0 {
return
}
buf.WriteString(f.blank)
} else {
buf.WriteString(s)
}
buf.WriteByte(f.delim)
}
func uniformDuration(t time.Duration) string {
return fmt.Sprintf("%*s", 12, t.String())
}

View File

@ -631,7 +631,7 @@ func (ac *AccessLog) after(ctx *context.Context, lat time.Duration, method, path
requestData, err := ctx.GetBody()
requestBodyLength := len(requestData)
if ac.BytesReceivedBody {
bytesReceived = requestBodyLength // store it, if the total is enabled then this will be overriden.
bytesReceived = requestBodyLength // store it, if the total is enabled then this will be overridden.
}
if err != nil && ac.RequestBody {
requestBody = ac.getErrorText(err)