@@ -0,0 +1,83 @@ | |||
// Copyright 2019 The Gitea Authors. All rights reserved. | |||
// Use of this source code is governed by a MIT-style | |||
// license that can be found in the LICENSE file. | |||
package log | |||
import ( | |||
"time" | |||
) | |||
var statusToColor = map[int][]byte{ | |||
100: ColorBytes(Bold), | |||
200: ColorBytes(FgGreen), | |||
300: ColorBytes(FgYellow), | |||
304: ColorBytes(FgCyan), | |||
400: ColorBytes(Bold, FgRed), | |||
401: ColorBytes(Bold, FgMagenta), | |||
403: ColorBytes(Bold, FgMagenta), | |||
500: ColorBytes(Bold, BgRed), | |||
} | |||
// ColoredStatus addes colors for HTTP status | |||
func ColoredStatus(status int, s ...string) *ColoredValue { | |||
color, ok := statusToColor[status] | |||
if !ok { | |||
color, ok = statusToColor[(status/100)*100] | |||
} | |||
if !ok { | |||
color = fgBoldBytes | |||
} | |||
if len(s) > 0 { | |||
return NewColoredValueBytes(s[0], &color) | |||
} | |||
return NewColoredValueBytes(status, &color) | |||
} | |||
var methodToColor = map[string][]byte{ | |||
"GET": ColorBytes(FgBlue), | |||
"POST": ColorBytes(FgGreen), | |||
"DELETE": ColorBytes(FgRed), | |||
"PATCH": ColorBytes(FgCyan), | |||
"PUT": ColorBytes(FgYellow, Faint), | |||
"HEAD": ColorBytes(FgBlue, Faint), | |||
} | |||
// ColoredMethod addes colors for HtTP methos on log | |||
func ColoredMethod(method string) *ColoredValue { | |||
color, ok := methodToColor[method] | |||
if !ok { | |||
return NewColoredValueBytes(method, &fgBoldBytes) | |||
} | |||
return NewColoredValueBytes(method, &color) | |||
} | |||
var ( | |||
durations = []time.Duration{ | |||
10 * time.Millisecond, | |||
100 * time.Millisecond, | |||
1 * time.Second, | |||
5 * time.Second, | |||
10 * time.Second, | |||
} | |||
durationColors = [][]byte{ | |||
ColorBytes(FgGreen), | |||
ColorBytes(Bold), | |||
ColorBytes(FgYellow), | |||
ColorBytes(FgRed, Bold), | |||
ColorBytes(BgRed), | |||
} | |||
wayTooLong = ColorBytes(BgMagenta) | |||
) | |||
// ColoredTime addes colors for time on log | |||
func ColoredTime(duration time.Duration) *ColoredValue { | |||
for i, k := range durations { | |||
if duration < k { | |||
return NewColoredValueBytes(duration, &durationColors[i]) | |||
} | |||
} | |||
return NewColoredValueBytes(duration, &wayTooLong) | |||
} |
@@ -1,103 +0,0 @@ | |||
// Copyright 2019 The Gitea Authors. All rights reserved. | |||
// Use of this source code is governed by a MIT-style | |||
// license that can be found in the LICENSE file. | |||
package log | |||
import ( | |||
"net/http" | |||
"time" | |||
macaron "gopkg.in/macaron.v1" | |||
) | |||
var statusToColor = map[int][]byte{ | |||
100: ColorBytes(Bold), | |||
200: ColorBytes(FgGreen), | |||
300: ColorBytes(FgYellow), | |||
304: ColorBytes(FgCyan), | |||
400: ColorBytes(Bold, FgRed), | |||
401: ColorBytes(Bold, FgMagenta), | |||
403: ColorBytes(Bold, FgMagenta), | |||
500: ColorBytes(Bold, BgRed), | |||
} | |||
func coloredStatus(status int, s ...string) *ColoredValue { | |||
color, ok := statusToColor[status] | |||
if !ok { | |||
color, ok = statusToColor[(status/100)*100] | |||
} | |||
if !ok { | |||
color = fgBoldBytes | |||
} | |||
if len(s) > 0 { | |||
return NewColoredValueBytes(s[0], &color) | |||
} | |||
return NewColoredValueBytes(status, &color) | |||
} | |||
var methodToColor = map[string][]byte{ | |||
"GET": ColorBytes(FgBlue), | |||
"POST": ColorBytes(FgGreen), | |||
"DELETE": ColorBytes(FgRed), | |||
"PATCH": ColorBytes(FgCyan), | |||
"PUT": ColorBytes(FgYellow, Faint), | |||
"HEAD": ColorBytes(FgBlue, Faint), | |||
} | |||
func coloredMethod(method string) *ColoredValue { | |||
color, ok := methodToColor[method] | |||
if !ok { | |||
return NewColoredValueBytes(method, &fgBoldBytes) | |||
} | |||
return NewColoredValueBytes(method, &color) | |||
} | |||
var durations = []time.Duration{ | |||
10 * time.Millisecond, | |||
100 * time.Millisecond, | |||
1 * time.Second, | |||
5 * time.Second, | |||
10 * time.Second, | |||
} | |||
var durationColors = [][]byte{ | |||
ColorBytes(FgGreen), | |||
ColorBytes(Bold), | |||
ColorBytes(FgYellow), | |||
ColorBytes(FgRed, Bold), | |||
ColorBytes(BgRed), | |||
} | |||
var wayTooLong = ColorBytes(BgMagenta) | |||
func coloredTime(duration time.Duration) *ColoredValue { | |||
for i, k := range durations { | |||
if duration < k { | |||
return NewColoredValueBytes(duration, &durationColors[i]) | |||
} | |||
} | |||
return NewColoredValueBytes(duration, &wayTooLong) | |||
} | |||
// SetupRouterLogger will setup macaron to routing to the main gitea log | |||
func SetupRouterLogger(m *macaron.Macaron, level Level) { | |||
if GetLevel() <= level { | |||
m.Use(RouterHandler(level)) | |||
} | |||
} | |||
// RouterHandler is a macaron handler that will log the routing to the default gitea log | |||
func RouterHandler(level Level) func(ctx *macaron.Context) { | |||
return func(ctx *macaron.Context) { | |||
start := time.Now() | |||
GetLogger("router").Log(0, level, "Started %s %s for %s", coloredMethod(ctx.Req.Method), ctx.Req.RequestURI, ctx.RemoteAddr()) | |||
rw := ctx.Resp.(macaron.ResponseWriter) | |||
ctx.Next() | |||
status := rw.Status() | |||
GetLogger("router").Log(0, level, "Completed %s %s %v %s in %v", coloredMethod(ctx.Req.Method), ctx.Req.RequestURI, coloredStatus(status), coloredStatus(status, http.StatusText(rw.Status())), coloredTime(time.Since(start))) | |||
} | |||
} |
@@ -94,6 +94,21 @@ func setupAccessLogger(m *macaron.Macaron) { | |||
}) | |||
} | |||
// RouterHandler is a macaron handler that will log the routing to the default gitea log | |||
func RouterHandler(level log.Level) func(ctx *macaron.Context) { | |||
return func(ctx *macaron.Context) { | |||
start := time.Now() | |||
log.GetLogger("router").Log(0, level, "Started %s %s for %s", log.ColoredMethod(ctx.Req.Method), ctx.Req.RequestURI, ctx.RemoteAddr()) | |||
rw := ctx.Resp.(macaron.ResponseWriter) | |||
ctx.Next() | |||
status := rw.Status() | |||
log.GetLogger("router").Log(0, level, "Completed %s %s %v %s in %v", log.ColoredMethod(ctx.Req.Method), ctx.Req.RequestURI, log.ColoredStatus(status), log.ColoredStatus(status, http.StatusText(rw.Status())), log.ColoredTime(time.Since(start))) | |||
} | |||
} | |||
// NewMacaron initializes Macaron instance. | |||
func NewMacaron() *macaron.Macaron { | |||
gob.Register(&u2f.Challenge{}) | |||
@@ -102,7 +117,9 @@ func NewMacaron() *macaron.Macaron { | |||
loggerAsWriter := log.NewLoggerAsWriter("INFO", log.GetLogger("macaron")) | |||
m = macaron.NewWithLogger(loggerAsWriter) | |||
if !setting.DisableRouterLog && setting.RouterLogLevel != log.NONE { | |||
log.SetupRouterLogger(m, setting.RouterLogLevel) | |||
if log.GetLogger("router").GetLevel() <= setting.RouterLogLevel { | |||
m.Use(RouterHandler(setting.RouterLogLevel)) | |||
} | |||
} | |||
} else { | |||
m = macaron.New() |