Files
sing-box-extended-mirror/log/format.go
T

189 lines
4.7 KiB
Go
Raw Normal View History

2022-07-12 15:17:29 +08:00
package log
import (
"context"
"strconv"
"strings"
"time"
"github.com/logrusorgru/aurora"
)
type Formatter struct {
BaseTime time.Time
DisableColors bool
DisableTimestamp bool
FullTimestamp bool
TimestampFormat string
2023-07-02 16:45:30 +08:00
DisableLineBreak bool
2022-07-12 15:17:29 +08:00
}
2026-09-01 22:39:35 +08:00
var (
levelLabels [LevelTrace + 1]string
coloredLevelLabels [LevelTrace + 1]string
)
func init() {
for level := LevelPanic; level <= LevelTrace; level++ {
label := strings.ToUpper(FormatLevel(level))
levelLabels[level] = label
2022-07-12 15:17:29 +08:00
switch level {
case LevelDebug, LevelTrace:
2026-09-01 22:39:35 +08:00
coloredLevelLabels[level] = aurora.White(label).String()
2022-07-12 15:17:29 +08:00
case LevelInfo:
2026-09-01 22:39:35 +08:00
coloredLevelLabels[level] = aurora.Cyan(label).String()
2022-07-12 15:17:29 +08:00
case LevelWarn:
2026-09-01 22:39:35 +08:00
coloredLevelLabels[level] = aurora.Yellow(label).String()
2022-07-12 15:17:29 +08:00
case LevelError, LevelFatal, LevelPanic:
2026-09-01 22:39:35 +08:00
coloredLevelLabels[level] = aurora.Red(label).String()
2022-07-12 15:17:29 +08:00
}
}
2026-09-01 22:39:35 +08:00
}
func (f Formatter) Format(ctx context.Context, level Level, tag string, message string, timestamp time.Time) string {
2023-03-29 13:07:08 +08:00
var id ID
2022-07-12 15:17:29 +08:00
var hasId bool
if ctx != nil {
id, hasId = IDFromContext(ctx)
}
2026-09-01 22:39:35 +08:00
var builder strings.Builder
builder.Grow(len(tag) + len(message) + 64)
f.writePrefix(&builder, level, timestamp)
2022-07-12 15:17:29 +08:00
if hasId {
2026-09-01 22:39:35 +08:00
f.writeIdPrefix(&builder, id)
2022-07-12 15:17:29 +08:00
}
2026-09-01 22:39:35 +08:00
if tag != "" {
builder.WriteString(tag)
builder.WriteString(": ")
2022-07-12 15:17:29 +08:00
}
2023-07-02 16:45:30 +08:00
if f.DisableLineBreak {
2026-09-01 22:39:35 +08:00
builder.WriteString(strings.TrimSuffix(message, "\n"))
2023-07-02 16:45:30 +08:00
} else {
2026-09-01 22:39:35 +08:00
builder.WriteString(message)
if !strings.HasSuffix(message, "\n") {
builder.WriteByte('\n')
2023-07-02 16:45:30 +08:00
}
2022-07-22 14:28:29 +08:00
}
2026-09-01 22:39:35 +08:00
return builder.String()
2022-07-12 15:17:29 +08:00
}
2026-09-01 22:39:35 +08:00
func (f Formatter) FormatSimple(ctx context.Context, tag string, message string) string {
2023-03-29 13:07:08 +08:00
var id ID
2022-07-19 22:16:49 +08:00
var hasId bool
if ctx != nil {
id, hasId = IDFromContext(ctx)
}
2026-09-01 22:39:35 +08:00
if !hasId && tag == "" {
return message
}
var builder strings.Builder
builder.Grow(len(tag) + len(message) + 32)
2022-07-19 22:16:49 +08:00
if hasId {
2026-09-01 22:39:35 +08:00
builder.WriteByte('[')
writeUint(&builder, uint64(id.ID))
builder.WriteByte(' ')
writeDuration(&builder, time.Since(id.CreatedAt))
builder.WriteString("] ")
}
if tag != "" {
builder.WriteString(tag)
builder.WriteString(": ")
}
builder.WriteString(message)
return builder.String()
}
2022-07-20 09:41:44 +08:00
2026-09-01 22:39:35 +08:00
func (f Formatter) writePrefix(builder *strings.Builder, level Level, timestamp time.Time) {
var levelString string
if int(level) >= len(levelLabels) {
levelString = "UNKNOWN"
} else if f.DisableColors {
levelString = levelLabels[level]
} else {
levelString = coloredLevelLabels[level]
2022-07-19 22:16:49 +08:00
}
switch {
case f.DisableTimestamp:
2026-09-01 22:39:35 +08:00
builder.WriteString(levelString)
builder.WriteByte(' ')
2022-07-19 22:16:49 +08:00
case f.FullTimestamp:
2026-09-01 22:39:35 +08:00
var timeBuffer [64]byte
builder.Write(timestamp.AppendFormat(timeBuffer[:0], f.TimestampFormat))
builder.WriteByte(' ')
builder.WriteString(levelString)
builder.WriteByte(' ')
2022-07-19 22:16:49 +08:00
default:
2026-09-01 22:39:35 +08:00
builder.WriteString(levelString)
builder.WriteByte('[')
seconds := strconv.AppendInt(make([]byte, 0, 20), int64(timestamp.Sub(f.BaseTime)/time.Second), 10)
for pad := 4 - len(seconds); pad > 0; pad-- {
builder.WriteByte('0')
}
builder.Write(seconds)
builder.WriteString("] ")
2022-07-19 22:16:49 +08:00
}
2026-09-01 22:39:35 +08:00
}
func (f Formatter) writeIdPrefix(builder *strings.Builder, id ID) {
builder.WriteByte('[')
if f.DisableColors {
writeUint(builder, uint64(id.ID))
} else {
builder.WriteString("\x1b[38;5;")
writeUint(builder, uint64(colorForID(id.ID)))
builder.WriteByte('m')
writeUint(builder, uint64(id.ID))
builder.WriteString("\x1b[0m")
2022-07-22 14:28:29 +08:00
}
2026-09-01 22:39:35 +08:00
builder.WriteByte(' ')
writeDuration(builder, time.Since(id.CreatedAt))
builder.WriteString("] ")
2022-07-19 22:16:49 +08:00
}
2026-09-01 22:39:35 +08:00
func colorForID(value uint32) uint8 {
color := uint8(value) % 215
row := uint(color / 36)
column := uint(color % 36)
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 = uint8(row*36 + column)
2022-07-12 15:17:29 +08:00
}
2026-09-01 22:39:35 +08:00
return color + 16
2022-07-12 15:17:29 +08:00
}
2023-03-29 13:07:08 +08:00
2026-09-01 22:39:35 +08:00
func writeUint(builder *strings.Builder, value uint64) {
builder.Write(strconv.AppendUint(make([]byte, 0, 20), value, 10))
}
func writeInt(builder *strings.Builder, value int64) {
builder.Write(strconv.AppendInt(make([]byte, 0, 20), value, 10))
}
func writeDuration(builder *strings.Builder, duration time.Duration) {
2023-03-29 13:07:08 +08:00
if duration < time.Second {
2026-09-01 22:39:35 +08:00
writeInt(builder, duration.Milliseconds())
builder.WriteString("ms")
2023-03-29 13:07:08 +08:00
} else if duration < time.Minute {
2026-09-01 22:39:35 +08:00
writeInt(builder, int64(duration.Seconds()))
builder.WriteByte('.')
writeInt(builder, int64(duration.Seconds()*100)%100)
builder.WriteByte('s')
2023-03-29 13:07:08 +08:00
} else {
2026-09-01 22:39:35 +08:00
writeInt(builder, int64(duration.Minutes()))
builder.WriteByte('m')
writeInt(builder, int64(duration.Seconds())%60)
builder.WriteByte('s')
2023-03-29 13:07:08 +08:00
}
}
2026-09-01 22:39:35 +08:00
func FormatDuration(duration time.Duration) string {
var builder strings.Builder
writeDuration(&builder, duration)
return builder.String()
}