sing-box/log/format.go

175 lines
4.6 KiB
Go
Raw Normal View History

2022-07-12 07:17:29 +00:00
package log
import (
"context"
"strconv"
"strings"
"time"
F "github.com/sagernet/sing/common/format"
"github.com/logrusorgru/aurora"
)
type Formatter struct {
BaseTime time.Time
DisableColors bool
DisableTimestamp bool
FullTimestamp bool
TimestampFormat string
2023-07-02 08:45:30 +00:00
DisableLineBreak bool
2022-07-12 07:17:29 +00:00
}
func (f Formatter) Format(ctx context.Context, level Level, tag string, message string, timestamp time.Time) string {
levelString := strings.ToUpper(FormatLevel(level))
if !f.DisableColors {
switch level {
case LevelDebug, LevelTrace:
levelString = aurora.White(levelString).String()
case LevelInfo:
levelString = aurora.Cyan(levelString).String()
case LevelWarn:
levelString = aurora.Yellow(levelString).String()
case LevelError, LevelFatal, LevelPanic:
levelString = aurora.Red(levelString).String()
}
}
if tag != "" {
message = tag + ": " + message
}
2023-03-29 05:07:08 +00:00
var id ID
2022-07-12 07:17:29 +00:00
var hasId bool
if ctx != nil {
id, hasId = IDFromContext(ctx)
}
if hasId {
2023-03-29 05:07:08 +00:00
activeDuration := formatDuration(time.Since(id.CreatedAt))
if !f.DisableColors {
var color aurora.Color
2023-03-29 05:07:08 +00:00
color = aurora.Color(uint8(id.ID))
color %= 215
row := uint(color / 36)
column := uint(color % 36)
2022-07-12 07:17:29 +00:00
var r, g, b float32
r = float32(row * 51)
g = float32(column / 6 * 51)
b = float32((column % 6) * 51)
luma := 0.2126*r + 0.7152*g + 0.0722*b
if luma < 60 {
row = 5 - row
column = 35 - column
color = aurora.Color(row*36 + column)
}
color += 16
color = color << 16
color |= 1 << 14
2023-03-29 05:07:08 +00:00
message = F.ToString("[", aurora.Colorize(id.ID, color).String(), " ", activeDuration, "] ", message)
} else {
2023-03-29 05:07:08 +00:00
message = F.ToString("[", id.ID, " ", activeDuration, "] ", message)
2022-07-12 07:17:29 +00:00
}
}
switch {
case f.DisableTimestamp:
message = levelString + " " + message
case f.FullTimestamp:
2022-08-31 15:35:43 +00:00
message = timestamp.Format(f.TimestampFormat) + " " + levelString + " " + message
2022-07-12 07:17:29 +00:00
default:
message = levelString + "[" + xd(int(timestamp.Sub(f.BaseTime)/time.Second), 4) + "] " + message
}
2023-07-02 08:45:30 +00:00
if f.DisableLineBreak {
2023-07-09 04:24:43 +00:00
if message[len(message)-1] == '\n' {
2023-07-02 08:45:30 +00:00
message = message[:len(message)-1]
}
} else {
if message[len(message)-1] != '\n' {
message += "\n"
}
2022-07-22 06:28:29 +00:00
}
return message
2022-07-12 07:17:29 +00:00
}
2022-07-19 14:16:49 +00:00
func (f Formatter) FormatWithSimple(ctx context.Context, level Level, tag string, message string, timestamp time.Time) (string, string) {
levelString := strings.ToUpper(FormatLevel(level))
if !f.DisableColors {
switch level {
case LevelDebug, LevelTrace:
levelString = aurora.White(levelString).String()
case LevelInfo:
levelString = aurora.Cyan(levelString).String()
case LevelWarn:
levelString = aurora.Yellow(levelString).String()
case LevelError, LevelFatal, LevelPanic:
levelString = aurora.Red(levelString).String()
}
}
if tag != "" {
message = tag + ": " + message
}
messageSimple := message
2023-03-29 05:07:08 +00:00
var id ID
2022-07-19 14:16:49 +00:00
var hasId bool
if ctx != nil {
id, hasId = IDFromContext(ctx)
}
if hasId {
2023-03-29 05:07:08 +00:00
activeDuration := formatDuration(time.Since(id.CreatedAt))
2022-07-19 14:16:49 +00:00
if !f.DisableColors {
var color aurora.Color
2023-03-29 05:07:08 +00:00
color = aurora.Color(uint8(id.ID))
2022-07-19 14:16:49 +00:00
color %= 215
row := uint(color / 36)
column := uint(color % 36)
var r, g, b float32
r = float32(row * 51)
g = float32(column / 6 * 51)
b = float32((column % 6) * 51)
luma := 0.2126*r + 0.7152*g + 0.0722*b
if luma < 60 {
row = 5 - row
column = 35 - column
color = aurora.Color(row*36 + column)
}
color += 16
color = color << 16
color |= 1 << 14
2023-03-29 05:07:08 +00:00
message = F.ToString("[", aurora.Colorize(id.ID, color).String(), " ", activeDuration, "] ", message)
2022-07-19 14:16:49 +00:00
} else {
2023-03-29 05:07:08 +00:00
message = F.ToString("[", id.ID, " ", activeDuration, "] ", message)
2022-07-19 14:16:49 +00:00
}
2023-03-29 05:07:08 +00:00
messageSimple = F.ToString("[", id.ID, " ", activeDuration, "] ", messageSimple)
2022-07-20 01:41:44 +00:00
2022-07-19 14:16:49 +00:00
}
switch {
case f.DisableTimestamp:
message = levelString + " " + message
case f.FullTimestamp:
2022-08-31 15:35:43 +00:00
message = timestamp.Format(f.TimestampFormat) + " " + levelString + " " + message
2022-07-19 14:16:49 +00:00
default:
message = levelString + "[" + xd(int(timestamp.Sub(f.BaseTime)/time.Second), 4) + "] " + message
}
2022-07-22 06:28:29 +00:00
if message[len(message)-1] != '\n' {
message += "\n"
}
return message, messageSimple
2022-07-19 14:16:49 +00:00
}
2022-07-12 07:17:29 +00:00
func xd(value int, x int) string {
message := strconv.Itoa(value)
for len(message) < x {
message = "0" + message
}
return message
}
2023-03-29 05:07:08 +00:00
func formatDuration(duration time.Duration) string {
if duration < time.Second {
return F.ToString(duration.Milliseconds(), "ms")
} else if duration < time.Minute {
return F.ToString(int64(duration.Seconds()), ".", int64(duration.Seconds()*100)%100, "s")
} else {
return F.ToString(int64(duration.Minutes()), "m", int64(duration.Seconds())%60, "s")
}
}