123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- // Package logger provides request logging via middleware. See _examples/http_request/request-logger
- package logger
- import (
- "fmt"
- "strconv"
- "time"
- "github.com/kataras/iris/context"
- "github.com/ryanuber/columnize"
- )
- type requestLoggerMiddleware struct {
- config Config
- }
- // New creates and returns a new request logger middleware.
- // Do not confuse it with the framework's Logger.
- // This is for the http requests.
- //
- // Receives an optional configuation.
- func New(cfg ...Config) context.Handler {
- c := DefaultConfig()
- if len(cfg) > 0 {
- c = cfg[0]
- }
- c.buildSkipper()
- l := &requestLoggerMiddleware{config: c}
- return l.ServeHTTP
- }
- // Serve serves the middleware
- func (l *requestLoggerMiddleware) ServeHTTP(ctx context.Context) {
- // skip logs and serve the main request immediately
- if l.config.skip != nil {
- if l.config.skip(ctx) {
- ctx.Next()
- return
- }
- }
- //all except latency to string
- var status, ip, method, path string
- var latency time.Duration
- var startTime, endTime time.Time
- startTime = time.Now()
- ctx.Next()
- //no time.Since in order to format it well after
- endTime = time.Now()
- latency = endTime.Sub(startTime)
- if l.config.Status {
- status = strconv.Itoa(ctx.GetStatusCode())
- }
- if l.config.IP {
- ip = ctx.RemoteAddr()
- }
- if l.config.Method {
- method = ctx.Method()
- }
- if l.config.Path {
- if l.config.Query {
- path = ctx.Request().URL.RequestURI()
- } else {
- path = ctx.Path()
- }
- }
- var message interface{}
- if ctxKeys := l.config.MessageContextKeys; len(ctxKeys) > 0 {
- for _, key := range ctxKeys {
- msg := ctx.Values().Get(key)
- if message == nil {
- message = msg
- } else {
- message = fmt.Sprintf(" %v %v", message, msg)
- }
- }
- }
- var headerMessage interface{}
- if headerKeys := l.config.MessageHeaderKeys; len(headerKeys) > 0 {
- for _, key := range headerKeys {
- msg := ctx.GetHeader(key)
- if headerMessage == nil {
- headerMessage = msg
- } else {
- headerMessage = fmt.Sprintf(" %v %v", headerMessage, msg)
- }
- }
- }
- // print the logs
- if logFunc := l.config.LogFunc; logFunc != nil {
- logFunc(endTime, latency, status, ip, method, path, message, headerMessage)
- return
- }
- if l.config.Columns {
- endTimeFormatted := endTime.Format("2006/01/02 - 15:04:05")
- output := Columnize(endTimeFormatted, latency, status, ip, method, path, message, headerMessage)
- ctx.Application().Logger().Printer.Output.Write([]byte(output))
- return
- }
- // no new line, the framework's logger is responsible how to render each log.
- line := fmt.Sprintf("%v %4v %s %s %s", status, latency, ip, method, path)
- if message != nil {
- line += fmt.Sprintf(" %v", message)
- }
- if headerMessage != nil {
- line += fmt.Sprintf(" %v", headerMessage)
- }
- ctx.Application().Logger().Info(line)
- }
- // Columnize formats the given arguments as columns and returns the formatted output,
- // note that it appends a new line to the end.
- func Columnize(nowFormatted string, latency time.Duration, status, ip, method, path string, message interface{}, headerMessage interface{}) string {
- titles := "Time | Status | Latency | IP | Method | Path"
- line := fmt.Sprintf("%s | %v | %4v | %s | %s | %s", nowFormatted, status, latency, ip, method, path)
- if message != nil {
- titles += " | Message"
- line += fmt.Sprintf(" | %v", message)
- }
- if headerMessage != nil {
- titles += " | HeaderMessage"
- line += fmt.Sprintf(" | %v", headerMessage)
- }
- outputC := []string{
- titles,
- line,
- }
- output := columnize.SimpleFormat(outputC) + "\n"
- return output
- }
|