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.
kratos/pkg/log/pattern.go

165 lines
3.2 KiB

6 years ago
package log
import (
"fmt"
"io"
"path"
6 years ago
"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,
6 years ago
"M": message,
}
// newPatternRender new pattern render
func newPatternRender(format string) Render {
p := &pattern{
bufPool: sync.Pool{New: func() interface{} { return &strings.Builder{} }},
6 years ago
}
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 implemet Formater
func (p *pattern) Render(w io.Writer, d map[string]interface{}) error {
builder := p.bufPool.Get().(*strings.Builder)
6 years ago
defer func() {
builder.Reset()
p.bufPool.Put(builder)
6 years ago
}()
for _, f := range p.funcs {
builder.WriteString(f(d))
6 years ago
}
_, err := w.Write([]byte(builder.String()))
6 years ago
return err
}
// Render implemet Formater as string
func (p *pattern) RenderString(d map[string]interface{}) string {
builder := p.bufPool.Get().(*strings.Builder)
6 years ago
defer func() {
builder.Reset()
p.bufPool.Put(builder)
6 years ago
}()
for _, f := range p.funcs {
builder.WriteString(f(d))
6 years ago
}
return builder.String()
6 years ago
}
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"
}
6 years ago
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, " ")
}