2021-11-03 17:17:58 +00:00
|
|
|
package ksrv
|
|
|
|
|
|
|
|
import (
|
2021-11-05 13:19:45 +00:00
|
|
|
"fmt"
|
|
|
|
"io"
|
2021-11-03 17:17:58 +00:00
|
|
|
"net/http"
|
|
|
|
|
2021-11-03 19:08:05 +00:00
|
|
|
"kumoly.io/lib/klog"
|
2021-11-03 17:17:58 +00:00
|
|
|
)
|
|
|
|
|
2021-11-03 19:08:05 +00:00
|
|
|
func (k *kserver) SetLogger(l *klog.Logger) {
|
2021-11-03 17:17:58 +00:00
|
|
|
k.l = l
|
|
|
|
}
|
|
|
|
|
2021-11-03 19:08:05 +00:00
|
|
|
func (k *kserver) GetLogger() *klog.Logger {
|
2021-11-03 17:17:58 +00:00
|
|
|
return k.l
|
|
|
|
}
|
|
|
|
|
|
|
|
// New returns a extended http.Server
|
|
|
|
func New() *kserver {
|
2021-11-03 19:08:05 +00:00
|
|
|
l := klog.Sub("KSRV")
|
2021-11-05 13:19:45 +00:00
|
|
|
l.SetPrinter(func(w io.Writer, d *klog.Ldata, l2 *klog.Logger) {
|
2021-11-11 06:46:16 +00:00
|
|
|
status, ok := d.Fields["Status"].(int)
|
2021-11-11 06:46:59 +00:00
|
|
|
msg := d.Message
|
|
|
|
if msg != "" {
|
|
|
|
msg = l.M(msg, klog.FgRed)
|
|
|
|
}
|
|
|
|
stack := d.Stack
|
|
|
|
if stack != "" {
|
|
|
|
stack = l.M(stack, klog.FgRed)
|
|
|
|
}
|
2021-11-11 06:46:16 +00:00
|
|
|
if !ok {
|
|
|
|
status = 500
|
|
|
|
}
|
2021-11-05 13:19:45 +00:00
|
|
|
fmt.Fprintf(w, "[%s] %s |%s| %15s %s %s %s\n%s",
|
2021-11-05 15:31:55 +00:00
|
|
|
l.M("KSRV ", klog.FgHiCyan),
|
2021-11-05 13:19:45 +00:00
|
|
|
d.Time.Format("2006/01/02 15:04:05"),
|
2021-11-11 06:46:16 +00:00
|
|
|
StatusColor(status, l),
|
2021-11-05 13:19:45 +00:00
|
|
|
d.Fields["IP"],
|
|
|
|
MethodColor(d.Fields["Method"], l),
|
2021-11-11 06:46:59 +00:00
|
|
|
d.Fields["URL"], msg, stack,
|
2021-11-05 13:19:45 +00:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
2021-11-03 18:09:00 +00:00
|
|
|
k := &kserver{
|
|
|
|
l: l,
|
2021-11-03 18:15:45 +00:00
|
|
|
nolog: func(r *http.Request) bool { return false },
|
2021-11-03 18:09:00 +00:00
|
|
|
}
|
2021-11-03 17:17:58 +00:00
|
|
|
return k
|
|
|
|
}
|
|
|
|
|
|
|
|
func (k *kserver) Middleware(next http.Handler) http.Handler {
|
|
|
|
return http.HandlerFunc(
|
|
|
|
func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
rw := &responseWriter{w, 0, ""}
|
|
|
|
defer k.catch(rw, r)
|
|
|
|
next.ServeHTTP(rw, r)
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-11-05 13:19:45 +00:00
|
|
|
func (k *kserver) SetNoLogCondition(nolog func(r *http.Request) bool) *kserver {
|
2021-11-03 18:09:00 +00:00
|
|
|
k.nolog = nolog
|
2021-11-05 13:19:45 +00:00
|
|
|
return k
|
2021-11-03 18:09:00 +00:00
|
|
|
}
|
|
|
|
|
2021-11-03 17:17:58 +00:00
|
|
|
func (k *kserver) catch(rw *responseWriter, r *http.Request) {
|
|
|
|
ex := recover()
|
|
|
|
if ex != nil {
|
|
|
|
Abort(rw, ex)
|
2021-11-03 19:08:05 +00:00
|
|
|
k.l.ErrorF(klog.H{"Status": rw.StatueCode, "IP": GetIP(r), "Method": r.Method, "URL": r.URL.Path, "Agent": r.Header.Get("User-Agent")}, ex)
|
2021-11-03 17:17:58 +00:00
|
|
|
} else if rw.StatueCode >= 500 {
|
2021-11-03 19:08:05 +00:00
|
|
|
k.l.ErrorF(klog.H{"Status": rw.StatueCode, "IP": GetIP(r), "Method": r.Method, "URL": r.URL.Path, "Agent": r.Header.Get("User-Agent")}, rw.err)
|
2021-11-03 18:15:45 +00:00
|
|
|
} else if k.nolog == nil || !k.nolog(r) {
|
2021-11-03 19:08:05 +00:00
|
|
|
k.l.InfoF(klog.H{"Status": rw.StatueCode, "IP": GetIP(r), "Method": r.Method, "URL": r.URL.Path, "Agent": r.Header.Get("User-Agent")})
|
2021-11-03 17:17:58 +00:00
|
|
|
}
|
|
|
|
}
|
2021-11-05 13:19:45 +00:00
|
|
|
|
|
|
|
func MethodColor(method interface{}, l *klog.Logger) string {
|
|
|
|
show := fmt.Sprintf(" %-7s", method)
|
|
|
|
switch method {
|
|
|
|
case http.MethodGet:
|
|
|
|
return l.M(show, 97, 44)
|
|
|
|
case http.MethodPost:
|
|
|
|
return l.M(show, 97, 46)
|
|
|
|
case http.MethodPut:
|
|
|
|
return l.M(show, 90, 43)
|
|
|
|
case http.MethodDelete:
|
|
|
|
return l.M(show, 97, 41)
|
|
|
|
case http.MethodPatch:
|
|
|
|
return l.M(show, 97, 42)
|
|
|
|
case http.MethodHead:
|
|
|
|
return l.M(show, 97, 45)
|
|
|
|
case http.MethodOptions:
|
|
|
|
return l.M(show, 90, 47)
|
|
|
|
default:
|
|
|
|
return l.M(show, 0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func StatusColor(code int, l *klog.Logger) string {
|
|
|
|
s := fmt.Sprintf(" %d ", code)
|
|
|
|
switch {
|
|
|
|
case code >= http.StatusOK && code < http.StatusMultipleChoices:
|
|
|
|
return l.M(s, 97, 42)
|
|
|
|
case code >= http.StatusMultipleChoices && code < http.StatusBadRequest:
|
|
|
|
return l.M(s, 90, 47)
|
|
|
|
case code >= http.StatusBadRequest && code < http.StatusInternalServerError:
|
|
|
|
return l.M(s, 90, 43)
|
|
|
|
default:
|
|
|
|
return l.M(s, 97, 41)
|
|
|
|
}
|
|
|
|
}
|