169 lines
4.8 KiB
Go
169 lines
4.8 KiB
Go
package log
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"apigo.cc/go/cast"
|
|
"apigo.cc/go/shell"
|
|
)
|
|
|
|
var errorLineMatcher = regexp.MustCompile(`(\w+\.go:\d+)`)
|
|
var codeFileMatcher = regexp.MustCompile(`(\w+?\.)(go|js)`)
|
|
|
|
func Viewable(line string) string {
|
|
b := ParseBaseLog(line)
|
|
if b == nil {
|
|
// 高亮错误代码
|
|
if strings.Contains(line, ".go:") {
|
|
if strings.Contains(line, "/ssgo/") || strings.Contains(line, "/ssdo/") || strings.Contains(line, "/gojs/") {
|
|
line = errorLineMatcher.ReplaceAllString(line, shell.BYellow("$1"))
|
|
} else if !strings.Contains(line, "/apigo.cc/") {
|
|
line = errorLineMatcher.ReplaceAllString(line, shell.BMagenta("$1"))
|
|
} else if !strings.Contains(line, "/go/src/") {
|
|
line = errorLineMatcher.ReplaceAllString(line, shell.BRed("$1"))
|
|
}
|
|
}
|
|
return line
|
|
}
|
|
|
|
logTime := time.Unix(0, b.LogTime)
|
|
|
|
var builder strings.Builder
|
|
builder.WriteString(shell.White(shell.Bold, logTime.Format("01-02 15:04:05.000")))
|
|
builder.WriteString(" ")
|
|
builder.WriteString(shell.Style(shell.TextWhite, shell.Dim, shell.Underline, b.TraceId))
|
|
|
|
level := ""
|
|
for _, k := range []string{"info", "warning", "error", "debug"} {
|
|
if b.Extra[k] != nil {
|
|
level = k
|
|
break
|
|
}
|
|
}
|
|
|
|
if b.LogType == LogTypeRequest {
|
|
method := cast.String(b.Extra["method"])
|
|
path := cast.String(b.Extra["path"])
|
|
code := cast.Int(b.Extra["responsecode"])
|
|
used := float32(cast.Float64(b.Extra["usedtime"]))
|
|
|
|
builder.WriteString(" ")
|
|
builder.WriteString(shell.Cyan(shell.Bold, "REQUEST"))
|
|
builder.WriteString(" ")
|
|
builder.WriteString(shell.Cyan(method))
|
|
builder.WriteString(" ")
|
|
builder.WriteString(path)
|
|
builder.WriteString(" ")
|
|
if code >= 500 {
|
|
builder.WriteString(shell.BRed(cast.String(code)))
|
|
} else if code >= 400 {
|
|
builder.WriteString(shell.BYellow(cast.String(code)))
|
|
} else {
|
|
builder.WriteString(shell.BGreen(cast.String(code)))
|
|
}
|
|
builder.WriteString(" ")
|
|
builder.WriteString(shell.Style(shell.Dim, fmt.Sprintf("%.2fms", used)))
|
|
|
|
for _, k := range []string{"method", "path", "responsecode", "usedtime", "host", "scheme", "proto", "clientip", "serverid", "app", "node", "fromapp", "fromnode", "userid", "deviceid", "clientappname", "clientappversion", "sessionid", "requestid", "authlevel", "priority", "requestheaders", "requestdata", "responseheaders", "responsedatalength", "responsedata", "logname", "logtype", "logtime", "traceid", "imagename", "imagetag", "servername", "serverip"} {
|
|
delete(b.Extra, k)
|
|
}
|
|
} else if b.LogType == LogTypeStatistic {
|
|
builder.WriteString(" ")
|
|
builder.WriteString(shell.Cyan(shell.Bold, "STATISTIC"))
|
|
} else if b.LogType == LogTypeTask {
|
|
builder.WriteString(" ")
|
|
builder.WriteString(shell.Cyan(shell.Bold, "TASK"))
|
|
} else {
|
|
if level != "" {
|
|
msg := cast.String(b.Extra[level])
|
|
delete(b.Extra, level)
|
|
builder.WriteString(" ")
|
|
switch level {
|
|
case "info":
|
|
builder.WriteString(shell.Cyan(msg))
|
|
case "warning":
|
|
builder.WriteString(shell.Yellow(msg))
|
|
case "error":
|
|
builder.WriteString(shell.Red(msg))
|
|
case "debug":
|
|
builder.WriteString(msg)
|
|
}
|
|
} else if b.LogType == "undefined" {
|
|
builder.WriteString(" ")
|
|
builder.WriteString(shell.Style(shell.Dim, "-"))
|
|
} else {
|
|
builder.WriteString(" ")
|
|
builder.WriteString(shell.Cyan(shell.Bold, b.LogType))
|
|
}
|
|
}
|
|
|
|
callStacks := b.Extra["callstacks"]
|
|
delete(b.Extra, "callstacks")
|
|
|
|
if b.Extra != nil {
|
|
for k, v := range b.Extra {
|
|
vStr := ""
|
|
if v == nil {
|
|
continue
|
|
}
|
|
switch v.(type) {
|
|
case map[string]any, []any:
|
|
vStr, _ = cast.ToJSON(v)
|
|
default:
|
|
vStr = cast.String(v)
|
|
}
|
|
|
|
if k == "extra" && len(vStr) > 0 && vStr[0] == '{' {
|
|
extra, err := cast.ToMap[string, any](vStr)
|
|
if err == nil {
|
|
for k2, v2 := range extra {
|
|
builder.WriteString(" ")
|
|
builder.WriteString(shell.Style(shell.TextWhite, shell.Dim, shell.Italic, k2+":"))
|
|
builder.WriteString(cast.String(v2))
|
|
}
|
|
}
|
|
} else {
|
|
builder.WriteString(" ")
|
|
builder.WriteString(shell.Style(shell.TextWhite, shell.Dim, shell.Italic, k+":"))
|
|
builder.WriteString(vStr)
|
|
}
|
|
}
|
|
}
|
|
|
|
if callStacks != nil {
|
|
var callStacksList []any
|
|
switch cs := callStacks.(type) {
|
|
case string:
|
|
if len(cs) > 2 && cs[0] == '[' {
|
|
_ = json.Unmarshal([]byte(cs), &callStacksList)
|
|
}
|
|
case []any:
|
|
callStacksList = cs
|
|
}
|
|
|
|
if len(callStacksList) > 0 {
|
|
builder.WriteString("\n")
|
|
for _, vi := range callStacksList {
|
|
v := cast.String(vi)
|
|
postfix := ""
|
|
if pos := strings.LastIndexByte(v, '/'); pos != -1 {
|
|
postfix = v[pos+1:]
|
|
v = v[:pos+1]
|
|
} else {
|
|
postfix = v
|
|
v = ""
|
|
}
|
|
builder.WriteString(" ")
|
|
builder.WriteString(shell.Style(shell.Dim, v))
|
|
builder.WriteString(shell.Style(shell.TextWhite, postfix))
|
|
builder.WriteString("\n")
|
|
}
|
|
}
|
|
}
|
|
return builder.String()
|
|
}
|