You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
164 lines
3.2 KiB
164 lines
3.2 KiB
package log
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"path"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
var patternMap = map[string]func(map[string]interface{}) string{
|
|
"T": longTime,
|
|
"t": shortTime,
|
|
"D": longDate,
|
|
"d": shortDate,
|
|
"L": keyFactory(_level),
|
|
"f": keyFactory(_source),
|
|
"i": keyFactory(_instanceID),
|
|
"e": keyFactory(_deplyEnv),
|
|
"z": keyFactory(_zone),
|
|
"S": longSource,
|
|
"s": shortSource,
|
|
"M": message,
|
|
}
|
|
|
|
// newPatternRender new pattern render
|
|
func newPatternRender(format string) Render {
|
|
p := &pattern{
|
|
bufPool: sync.Pool{New: func() interface{} { return &strings.Builder{} }},
|
|
}
|
|
b := make([]byte, 0, len(format))
|
|
for i := 0; i < len(format); i++ {
|
|
if format[i] != '%' {
|
|
b = append(b, format[i])
|
|
continue
|
|
}
|
|
if i+1 >= len(format) {
|
|
b = append(b, format[i])
|
|
continue
|
|
}
|
|
f, ok := patternMap[string(format[i+1])]
|
|
if !ok {
|
|
b = append(b, format[i])
|
|
continue
|
|
}
|
|
if len(b) != 0 {
|
|
p.funcs = append(p.funcs, textFactory(string(b)))
|
|
b = b[:0]
|
|
}
|
|
p.funcs = append(p.funcs, f)
|
|
i++
|
|
}
|
|
if len(b) != 0 {
|
|
p.funcs = append(p.funcs, textFactory(string(b)))
|
|
}
|
|
return p
|
|
}
|
|
|
|
type pattern struct {
|
|
funcs []func(map[string]interface{}) string
|
|
bufPool sync.Pool
|
|
}
|
|
|
|
// Render implements Formater
|
|
func (p *pattern) Render(w io.Writer, d map[string]interface{}) error {
|
|
builder := p.bufPool.Get().(*strings.Builder)
|
|
defer func() {
|
|
builder.Reset()
|
|
p.bufPool.Put(builder)
|
|
}()
|
|
for _, f := range p.funcs {
|
|
builder.WriteString(f(d))
|
|
}
|
|
|
|
_, err := w.Write([]byte(builder.String()))
|
|
return err
|
|
}
|
|
|
|
// Render implements Formater as string
|
|
func (p *pattern) RenderString(d map[string]interface{}) string {
|
|
builder := p.bufPool.Get().(*strings.Builder)
|
|
defer func() {
|
|
builder.Reset()
|
|
p.bufPool.Put(builder)
|
|
}()
|
|
for _, f := range p.funcs {
|
|
builder.WriteString(f(d))
|
|
}
|
|
|
|
return builder.String()
|
|
}
|
|
|
|
func textFactory(text string) func(map[string]interface{}) string {
|
|
return func(map[string]interface{}) string {
|
|
return text
|
|
}
|
|
}
|
|
func keyFactory(key string) func(map[string]interface{}) string {
|
|
return func(d map[string]interface{}) string {
|
|
if v, ok := d[key]; ok {
|
|
if s, ok := v.(string); ok {
|
|
return s
|
|
}
|
|
return fmt.Sprint(v)
|
|
}
|
|
return ""
|
|
}
|
|
}
|
|
|
|
func longSource(d map[string]interface{}) string {
|
|
if fn, ok := d[_source].(string); ok {
|
|
return fn
|
|
}
|
|
return "unknown:0"
|
|
}
|
|
|
|
func shortSource(d map[string]interface{}) string {
|
|
if fn, ok := d[_source].(string); ok {
|
|
return path.Base(fn)
|
|
}
|
|
return "unknown:0"
|
|
}
|
|
|
|
func longTime(map[string]interface{}) string {
|
|
return time.Now().Format("15:04:05.000")
|
|
}
|
|
|
|
func shortTime(map[string]interface{}) string {
|
|
return time.Now().Format("15:04")
|
|
}
|
|
|
|
func longDate(map[string]interface{}) string {
|
|
return time.Now().Format("2006/01/02")
|
|
}
|
|
|
|
func shortDate(map[string]interface{}) string {
|
|
return time.Now().Format("01/02")
|
|
}
|
|
|
|
func isInternalKey(k string) bool {
|
|
switch k {
|
|
case _level, _levelValue, _time, _source, _instanceID, _appID, _deplyEnv, _zone:
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func message(d map[string]interface{}) string {
|
|
var m string
|
|
var s []string
|
|
for k, v := range d {
|
|
if k == _log {
|
|
m = fmt.Sprint(v)
|
|
continue
|
|
}
|
|
if isInternalKey(k) {
|
|
continue
|
|
}
|
|
s = append(s, fmt.Sprintf("%s=%v", k, v))
|
|
}
|
|
s = append(s, m)
|
|
return strings.Join(s, " ")
|
|
}
|
|
|