mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 11:52:24 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			640 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			640 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package logger
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"reflect"
 | |
| 	"strconv"
 | |
| 	"time"
 | |
| 
 | |
| 	"codeberg.org/gruf/go-bytes"
 | |
| )
 | |
| 
 | |
| // Check our types impl LogFormat
 | |
| var _ LogFormat = &TextFormat{}
 | |
| 
 | |
| // LogFormat defines a method of formatting log entries
 | |
| type LogFormat interface {
 | |
| 	AppendLevel(buf *bytes.Buffer, lvl LEVEL)
 | |
| 	AppendTimestamp(buf *bytes.Buffer, fmtNow string)
 | |
| 	AppendField(buf *bytes.Buffer, key string, value interface{})
 | |
| 	AppendFields(buf *bytes.Buffer, fields map[string]interface{})
 | |
| 	AppendByteField(buf *bytes.Buffer, key string, value byte)
 | |
| 	AppendBytesField(buf *bytes.Buffer, key string, value []byte)
 | |
| 	AppendStringField(buf *bytes.Buffer, key string, value string)
 | |
| 	AppendStringsField(buf *bytes.Buffer, key string, value []string)
 | |
| 	AppendBoolField(buf *bytes.Buffer, key string, value bool)
 | |
| 	AppendBoolsField(buf *bytes.Buffer, key string, value []bool)
 | |
| 	AppendIntField(buf *bytes.Buffer, key string, value int)
 | |
| 	AppendIntsField(buf *bytes.Buffer, key string, value []int)
 | |
| 	AppendUintField(buf *bytes.Buffer, key string, value uint)
 | |
| 	AppendUintsField(buf *bytes.Buffer, key string, value []uint)
 | |
| 	AppendFloatField(buf *bytes.Buffer, key string, value float64)
 | |
| 	AppendFloatsField(buf *bytes.Buffer, key string, value []float64)
 | |
| 	AppendTimeField(buf *bytes.Buffer, key string, value time.Time)
 | |
| 	AppendTimesField(buf *bytes.Buffer, key string, value []time.Time)
 | |
| 	AppendDurationField(buf *bytes.Buffer, key string, value time.Duration)
 | |
| 	AppendDurationsField(buf *bytes.Buffer, key string, value []time.Duration)
 | |
| 	AppendMsg(buf *bytes.Buffer, a ...interface{})
 | |
| 	AppendMsgf(buf *bytes.Buffer, s string, a ...interface{})
 | |
| }
 | |
| 
 | |
| // TextFormat is the default LogFormat implementation, with very similar formatting to logfmt
 | |
| type TextFormat struct {
 | |
| 	// Strict defines whether to use strict key-value pair formatting,
 | |
| 	// i.e. should the level, timestamp and msg be formatted as key-value pairs
 | |
| 	// or simply be printed as-is
 | |
| 	Strict bool
 | |
| 
 | |
| 	// Levels defines the map of log LEVELs to level strings this LogFormat will use
 | |
| 	Levels Levels
 | |
| }
 | |
| 
 | |
| // NewLogFmt returns a newly set LogFmt object, with DefaultLevels() set
 | |
| func NewLogFmt(strict bool) *TextFormat {
 | |
| 	return &TextFormat{
 | |
| 		Strict: strict,
 | |
| 		Levels: DefaultLevels(),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // appendReflectValue will safely append a reflected value
 | |
| func appendReflectValue(buf *bytes.Buffer, v reflect.Value, isKey bool) {
 | |
| 	switch v.Kind() {
 | |
| 	case reflect.Slice:
 | |
| 		appendSliceType(buf, v)
 | |
| 	case reflect.Map:
 | |
| 		appendMapType(buf, v)
 | |
| 	case reflect.Struct:
 | |
| 		appendStructType(buf, v)
 | |
| 	case reflect.Ptr:
 | |
| 		if v.IsNil() {
 | |
| 			appendNil(buf)
 | |
| 		} else {
 | |
| 			appendIface(buf, v.Elem().Interface(), isKey)
 | |
| 		}
 | |
| 	default:
 | |
| 		// Just print reflect string
 | |
| 		appendString(buf, v.String())
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // appendKey should only be used in the case of directly setting key-value pairs,
 | |
| // not in the case of appendMapType, appendStructType
 | |
| func appendKey(buf *bytes.Buffer, key string) {
 | |
| 	if len(key) > 0 {
 | |
| 		// Only write key if here
 | |
| 		appendStringUnquoted(buf, key)
 | |
| 		buf.WriteByte('=')
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // appendSlice performs provided fn and writes square brackets [] around it
 | |
| func appendSlice(buf *bytes.Buffer, fn func()) {
 | |
| 	buf.WriteByte('[')
 | |
| 	fn()
 | |
| 	buf.WriteByte(']')
 | |
| }
 | |
| 
 | |
| // appendMap performs provided fn and writes curly braces {} around it
 | |
| func appendMap(buf *bytes.Buffer, fn func()) {
 | |
| 	buf.WriteByte('{')
 | |
| 	fn()
 | |
| 	buf.WriteByte('}')
 | |
| }
 | |
| 
 | |
| // appendStruct performs provided fn and writes curly braces {} around it
 | |
| func appendStruct(buf *bytes.Buffer, fn func()) {
 | |
| 	buf.WriteByte('{')
 | |
| 	fn()
 | |
| 	buf.WriteByte('}')
 | |
| }
 | |
| 
 | |
| // appendNil writes a nil value placeholder to buf
 | |
| func appendNil(buf *bytes.Buffer) {
 | |
| 	buf.WriteString(`<nil>`)
 | |
| }
 | |
| 
 | |
| // appendByte writes a single byte to buf
 | |
| func appendByte(buf *bytes.Buffer, b byte) {
 | |
| 	buf.WriteByte(b)
 | |
| }
 | |
| 
 | |
| // appendBytes writes a quoted byte slice to buf
 | |
| func appendBytes(buf *bytes.Buffer, b []byte) {
 | |
| 	buf.WriteByte('"')
 | |
| 	buf.Write(b)
 | |
| 	buf.WriteByte('"')
 | |
| }
 | |
| 
 | |
| // appendBytesUnquoted writes a byte slice to buf as-is
 | |
| func appendBytesUnquoted(buf *bytes.Buffer, b []byte) {
 | |
| 	buf.Write(b)
 | |
| }
 | |
| 
 | |
| // appendString writes a quoted string to buf
 | |
| func appendString(buf *bytes.Buffer, s string) {
 | |
| 	buf.WriteByte('"')
 | |
| 	buf.WriteString(s)
 | |
| 	buf.WriteByte('"')
 | |
| }
 | |
| 
 | |
| // appendStringUnquoted writes a string as-is to buf
 | |
| func appendStringUnquoted(buf *bytes.Buffer, s string) {
 | |
| 	buf.WriteString(s)
 | |
| }
 | |
| 
 | |
| // appendStringSlice writes a slice of strings to buf
 | |
| func appendStringSlice(buf *bytes.Buffer, s []string) {
 | |
| 	appendSlice(buf, func() {
 | |
| 		for _, s := range s {
 | |
| 			appendString(buf, s)
 | |
| 			buf.WriteByte(',')
 | |
| 		}
 | |
| 		if len(s) > 0 {
 | |
| 			buf.Truncate(1)
 | |
| 		}
 | |
| 	})
 | |
| }
 | |
| 
 | |
| // appendBool writes a formatted bool to buf
 | |
| func appendBool(buf *bytes.Buffer, b bool) {
 | |
| 	buf.B = strconv.AppendBool(buf.B, b)
 | |
| }
 | |
| 
 | |
| // appendBool writes a slice of formatted bools to buf
 | |
| func appendBoolSlice(buf *bytes.Buffer, b []bool) {
 | |
| 	appendSlice(buf, func() {
 | |
| 		// Write elements
 | |
| 		for _, b := range b {
 | |
| 			appendBool(buf, b)
 | |
| 			buf.WriteByte(',')
 | |
| 		}
 | |
| 
 | |
| 		// Drop last comma
 | |
| 		if len(b) > 0 {
 | |
| 			buf.Truncate(1)
 | |
| 		}
 | |
| 	})
 | |
| }
 | |
| 
 | |
| // appendInt writes a formatted int to buf
 | |
| func appendInt(buf *bytes.Buffer, i int64) {
 | |
| 	buf.B = strconv.AppendInt(buf.B, i, 10)
 | |
| }
 | |
| 
 | |
| // appendIntSlice writes a slice of formatted int to buf
 | |
| func appendIntSlice(buf *bytes.Buffer, i []int) {
 | |
| 	appendSlice(buf, func() {
 | |
| 		// Write elements
 | |
| 		for _, i := range i {
 | |
| 			appendInt(buf, int64(i))
 | |
| 			buf.WriteByte(',')
 | |
| 		}
 | |
| 
 | |
| 		// Drop last comma
 | |
| 		if len(i) > 0 {
 | |
| 			buf.Truncate(1)
 | |
| 		}
 | |
| 	})
 | |
| }
 | |
| 
 | |
| // appendUint writes a formatted uint to buf
 | |
| func appendUint(buf *bytes.Buffer, u uint64) {
 | |
| 	buf.B = strconv.AppendUint(buf.B, u, 10)
 | |
| }
 | |
| 
 | |
| // appendUintSlice writes a slice of formatted uint to buf
 | |
| func appendUintSlice(buf *bytes.Buffer, u []uint) {
 | |
| 	appendSlice(buf, func() {
 | |
| 		// Write elements
 | |
| 		for _, u := range u {
 | |
| 			appendUint(buf, uint64(u))
 | |
| 			buf.WriteByte(',')
 | |
| 		}
 | |
| 
 | |
| 		// Drop last comma
 | |
| 		if len(u) > 0 {
 | |
| 			buf.Truncate(1)
 | |
| 		}
 | |
| 	})
 | |
| }
 | |
| 
 | |
| // appendFloat writes a formatted float to buf
 | |
| func appendFloat(buf *bytes.Buffer, f float64) {
 | |
| 	buf.B = strconv.AppendFloat(buf.B, f, 'G', -1, 64)
 | |
| }
 | |
| 
 | |
| // appendFloatSlice writes a slice formatted floats to buf
 | |
| func appendFloatSlice(buf *bytes.Buffer, f []float64) {
 | |
| 	appendSlice(buf, func() {
 | |
| 		// Write elements
 | |
| 		for _, f := range f {
 | |
| 			appendFloat(buf, f)
 | |
| 			buf.WriteByte(',')
 | |
| 		}
 | |
| 
 | |
| 		// Drop last comma
 | |
| 		if len(f) > 0 {
 | |
| 			buf.Truncate(1)
 | |
| 		}
 | |
| 	})
 | |
| }
 | |
| 
 | |
| // appendTime writes a formatted, quoted time string to buf
 | |
| func appendTime(buf *bytes.Buffer, t time.Time) {
 | |
| 	buf.WriteByte('"')
 | |
| 	buf.B = t.AppendFormat(buf.B, time.RFC1123)
 | |
| 	buf.WriteByte('"')
 | |
| }
 | |
| 
 | |
| // appendTimeUnquoted writes a formatted time string to buf as-is
 | |
| func appendTimeUnquoted(buf *bytes.Buffer, t time.Time) {
 | |
| 	buf.B = t.AppendFormat(buf.B, time.RFC1123)
 | |
| }
 | |
| 
 | |
| // appendTimeSlice writes a slice of formatted time strings to buf
 | |
| func appendTimeSlice(buf *bytes.Buffer, t []time.Time) {
 | |
| 	appendSlice(buf, func() {
 | |
| 		// Write elements
 | |
| 		for _, t := range t {
 | |
| 			appendTime(buf, t)
 | |
| 			buf.WriteByte(',')
 | |
| 		}
 | |
| 
 | |
| 		// Drop last comma
 | |
| 		if len(t) > 0 {
 | |
| 			buf.Truncate(1)
 | |
| 		}
 | |
| 	})
 | |
| }
 | |
| 
 | |
| // appendDuration writes a formatted, quoted duration string to buf
 | |
| func appendDuration(buf *bytes.Buffer, d time.Duration) {
 | |
| 	appendString(buf, d.String())
 | |
| }
 | |
| 
 | |
| // appendDurationUnquoted writes a formatted duration string to buf as-is
 | |
| func appendDurationUnquoted(buf *bytes.Buffer, d time.Duration) {
 | |
| 	appendStringUnquoted(buf, d.String())
 | |
| }
 | |
| 
 | |
| // appendDurationSlice writes a slice of formatted, quoted duration strings to buf
 | |
| func appendDurationSlice(buf *bytes.Buffer, d []time.Duration) {
 | |
| 	appendSlice(buf, func() {
 | |
| 		// Write elements
 | |
| 		for _, d := range d {
 | |
| 			appendString(buf, d.String())
 | |
| 			buf.WriteByte(',')
 | |
| 		}
 | |
| 
 | |
| 		// Drop last comma
 | |
| 		if len(d) > 0 {
 | |
| 			buf.Truncate(1)
 | |
| 		}
 | |
| 	})
 | |
| }
 | |
| 
 | |
| // appendIface parses and writes a formatted interface value to buf
 | |
| func appendIface(buf *bytes.Buffer, i interface{}, isKey bool) {
 | |
| 	switch i := i.(type) {
 | |
| 	case nil:
 | |
| 		appendNil(buf)
 | |
| 	case byte:
 | |
| 		appendByte(buf, i)
 | |
| 	case []byte:
 | |
| 		if isKey {
 | |
| 			// Keys don't get quoted
 | |
| 			appendBytesUnquoted(buf, i)
 | |
| 		} else {
 | |
| 			appendBytes(buf, i)
 | |
| 		}
 | |
| 	case string:
 | |
| 		if isKey {
 | |
| 			// Keys don't get quoted
 | |
| 			appendStringUnquoted(buf, i)
 | |
| 		} else {
 | |
| 			appendString(buf, i)
 | |
| 		}
 | |
| 	case []string:
 | |
| 		appendStringSlice(buf, i)
 | |
| 	case int:
 | |
| 		appendInt(buf, int64(i))
 | |
| 	case int8:
 | |
| 		appendInt(buf, int64(i))
 | |
| 	case int16:
 | |
| 		appendInt(buf, int64(i))
 | |
| 	case int32:
 | |
| 		appendInt(buf, int64(i))
 | |
| 	case int64:
 | |
| 		appendInt(buf, i)
 | |
| 	case []int:
 | |
| 		appendIntSlice(buf, i)
 | |
| 	case uint:
 | |
| 		appendUint(buf, uint64(i))
 | |
| 	case uint16:
 | |
| 		appendUint(buf, uint64(i))
 | |
| 	case uint32:
 | |
| 		appendUint(buf, uint64(i))
 | |
| 	case uint64:
 | |
| 		appendUint(buf, i)
 | |
| 	case []uint:
 | |
| 		appendUintSlice(buf, i)
 | |
| 	case float32:
 | |
| 		appendFloat(buf, float64(i))
 | |
| 	case float64:
 | |
| 		appendFloat(buf, i)
 | |
| 	case []float64:
 | |
| 		appendFloatSlice(buf, i)
 | |
| 	case bool:
 | |
| 		appendBool(buf, i)
 | |
| 	case []bool:
 | |
| 		appendBoolSlice(buf, i)
 | |
| 	case time.Time:
 | |
| 		if isKey {
 | |
| 			// Keys don't get quoted
 | |
| 			appendTimeUnquoted(buf, i)
 | |
| 		} else {
 | |
| 			appendTime(buf, i)
 | |
| 		}
 | |
| 	case *time.Time:
 | |
| 		if isKey {
 | |
| 			// Keys don't get quoted
 | |
| 			appendTimeUnquoted(buf, *i)
 | |
| 		} else {
 | |
| 			appendTime(buf, *i)
 | |
| 		}
 | |
| 	case []time.Time:
 | |
| 		appendTimeSlice(buf, i)
 | |
| 	case time.Duration:
 | |
| 		if isKey {
 | |
| 			// Keys dont get quoted
 | |
| 			appendDurationUnquoted(buf, i)
 | |
| 		} else {
 | |
| 			appendDuration(buf, i)
 | |
| 		}
 | |
| 	case []time.Duration:
 | |
| 		appendDurationSlice(buf, i)
 | |
| 	case map[string]interface{}:
 | |
| 		appendIfaceMap(buf, i)
 | |
| 	case error:
 | |
| 		if isKey {
 | |
| 			// Keys don't get quoted
 | |
| 			appendStringUnquoted(buf, i.Error())
 | |
| 		} else {
 | |
| 			appendString(buf, i.Error())
 | |
| 		}
 | |
| 	case fmt.Stringer:
 | |
| 		if isKey {
 | |
| 			// Keys don't get quoted
 | |
| 			appendStringUnquoted(buf, i.String())
 | |
| 		} else {
 | |
| 			appendString(buf, i.String())
 | |
| 		}
 | |
| 	default:
 | |
| 		// If we reached here, we need reflection.
 | |
| 		appendReflectValue(buf, reflect.ValueOf(i), isKey)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // appendIfaceMap writes a map of key-value pairs (as a set of fields) to buf
 | |
| func appendIfaceMap(buf *bytes.Buffer, v map[string]interface{}) {
 | |
| 	appendMap(buf, func() {
 | |
| 		// Write map pairs!
 | |
| 		for key, value := range v {
 | |
| 			appendStringUnquoted(buf, key)
 | |
| 			buf.WriteByte('=')
 | |
| 			appendIface(buf, value, false)
 | |
| 			buf.WriteByte(' ')
 | |
| 		}
 | |
| 
 | |
| 		// Drop last space
 | |
| 		if len(v) > 0 {
 | |
| 			buf.Truncate(1)
 | |
| 		}
 | |
| 	})
 | |
| }
 | |
| 
 | |
| // appendSliceType writes a slice of unknown type (parsed by reflection) to buf
 | |
| func appendSliceType(buf *bytes.Buffer, v reflect.Value) {
 | |
| 	n := v.Len()
 | |
| 	appendSlice(buf, func() {
 | |
| 		for i := 0; i < n; i++ {
 | |
| 			appendIface(buf, v.Index(i).Interface(), false)
 | |
| 			buf.WriteByte(',')
 | |
| 		}
 | |
| 
 | |
| 		// Drop last comma
 | |
| 		if n > 0 {
 | |
| 			buf.Truncate(1)
 | |
| 		}
 | |
| 	})
 | |
| }
 | |
| 
 | |
| // appendMapType writes a map of unknown types (parsed by reflection) to buf
 | |
| func appendMapType(buf *bytes.Buffer, v reflect.Value) {
 | |
| 	// Get a map iterator
 | |
| 	r := v.MapRange()
 | |
| 	n := v.Len()
 | |
| 
 | |
| 	// Now begin creating the map!
 | |
| 	appendMap(buf, func() {
 | |
| 		// Iterate pairs
 | |
| 		for r.Next() {
 | |
| 			appendIface(buf, r.Key().Interface(), true)
 | |
| 			buf.WriteByte('=')
 | |
| 			appendIface(buf, r.Value().Interface(), false)
 | |
| 			buf.WriteByte(' ')
 | |
| 		}
 | |
| 
 | |
| 		// Drop last space
 | |
| 		if n > 0 {
 | |
| 			buf.Truncate(1)
 | |
| 		}
 | |
| 	})
 | |
| }
 | |
| 
 | |
| // appendStructType writes a struct (as a set of key-value fields) to buf
 | |
| func appendStructType(buf *bytes.Buffer, v reflect.Value) {
 | |
| 	// Get value type & no. fields
 | |
| 	t := v.Type()
 | |
| 	n := v.NumField()
 | |
| 	w := 0
 | |
| 
 | |
| 	// Iter and write struct fields
 | |
| 	appendStruct(buf, func() {
 | |
| 		for i := 0; i < n; i++ {
 | |
| 			vfield := v.Field(i)
 | |
| 
 | |
| 			// Check for unexported fields
 | |
| 			if !vfield.CanInterface() {
 | |
| 				continue
 | |
| 			}
 | |
| 
 | |
| 			// Append the struct member as field key-value
 | |
| 			appendStringUnquoted(buf, t.Field(i).Name)
 | |
| 			buf.WriteByte('=')
 | |
| 			appendIface(buf, vfield.Interface(), false)
 | |
| 			buf.WriteByte(' ')
 | |
| 
 | |
| 			// Iter written count
 | |
| 			w++
 | |
| 		}
 | |
| 
 | |
| 		// Drop last space
 | |
| 		if w > 0 {
 | |
| 			buf.Truncate(1)
 | |
| 		}
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendLevel(buf *bytes.Buffer, lvl LEVEL) {
 | |
| 	if f.Strict {
 | |
| 		// Strict format, append level key
 | |
| 		buf.WriteString(`level=`)
 | |
| 		buf.WriteString(f.Levels.LevelString(lvl))
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// Write level string
 | |
| 	buf.WriteByte('[')
 | |
| 	buf.WriteString(f.Levels.LevelString(lvl))
 | |
| 	buf.WriteByte(']')
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendTimestamp(buf *bytes.Buffer, now string) {
 | |
| 	if f.Strict {
 | |
| 		// Strict format, use key and quote
 | |
| 		appendStringUnquoted(buf, `time`)
 | |
| 		buf.WriteByte('=')
 | |
| 		appendString(buf, now)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// Write time as-is
 | |
| 	appendStringUnquoted(buf, now)
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendField(buf *bytes.Buffer, key string, value interface{}) {
 | |
| 	appendKey(buf, key)
 | |
| 	appendIface(buf, value, false)
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendFields(buf *bytes.Buffer, fields map[string]interface{}) {
 | |
| 	// Append individual fields
 | |
| 	for key, value := range fields {
 | |
| 		appendKey(buf, key)
 | |
| 		appendIface(buf, value, false)
 | |
| 		buf.WriteByte(' ')
 | |
| 	}
 | |
| 
 | |
| 	// Drop last space
 | |
| 	if len(fields) > 0 {
 | |
| 		buf.Truncate(1)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendByteField(buf *bytes.Buffer, key string, value byte) {
 | |
| 	appendKey(buf, key)
 | |
| 	appendByte(buf, value)
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendBytesField(buf *bytes.Buffer, key string, value []byte) {
 | |
| 	appendKey(buf, key)
 | |
| 	appendBytes(buf, value)
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendStringField(buf *bytes.Buffer, key string, value string) {
 | |
| 	appendKey(buf, key)
 | |
| 	appendString(buf, value)
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendStringsField(buf *bytes.Buffer, key string, value []string) {
 | |
| 	appendKey(buf, key)
 | |
| 	appendStringSlice(buf, value)
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendBoolField(buf *bytes.Buffer, key string, value bool) {
 | |
| 	appendKey(buf, key)
 | |
| 	appendBool(buf, value)
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendBoolsField(buf *bytes.Buffer, key string, value []bool) {
 | |
| 	appendKey(buf, key)
 | |
| 	appendBoolSlice(buf, value)
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendIntField(buf *bytes.Buffer, key string, value int) {
 | |
| 	appendKey(buf, key)
 | |
| 	appendInt(buf, int64(value))
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendIntsField(buf *bytes.Buffer, key string, value []int) {
 | |
| 	appendKey(buf, key)
 | |
| 	appendIntSlice(buf, value)
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendUintField(buf *bytes.Buffer, key string, value uint) {
 | |
| 	appendKey(buf, key)
 | |
| 	appendUint(buf, uint64(value))
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendUintsField(buf *bytes.Buffer, key string, value []uint) {
 | |
| 	appendKey(buf, key)
 | |
| 	appendUintSlice(buf, value)
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendFloatField(buf *bytes.Buffer, key string, value float64) {
 | |
| 	appendKey(buf, key)
 | |
| 	appendFloat(buf, value)
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendFloatsField(buf *bytes.Buffer, key string, value []float64) {
 | |
| 	appendKey(buf, key)
 | |
| 	appendFloatSlice(buf, value)
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendTimeField(buf *bytes.Buffer, key string, value time.Time) {
 | |
| 	appendKey(buf, key)
 | |
| 	appendTime(buf, value)
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendTimesField(buf *bytes.Buffer, key string, value []time.Time) {
 | |
| 	appendKey(buf, key)
 | |
| 	appendTimeSlice(buf, value)
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendDurationField(buf *bytes.Buffer, key string, value time.Duration) {
 | |
| 	appendKey(buf, key)
 | |
| 	appendDuration(buf, value)
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendDurationsField(buf *bytes.Buffer, key string, value []time.Duration) {
 | |
| 	appendKey(buf, key)
 | |
| 	appendDurationSlice(buf, value)
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendMsg(buf *bytes.Buffer, a ...interface{}) {
 | |
| 	if f.Strict {
 | |
| 		// Strict format, use key and quote
 | |
| 		buf.WriteString(`msg="`)
 | |
| 		fmt.Fprint(buf, a...)
 | |
| 		buf.WriteByte('"')
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// Write message as-is
 | |
| 	fmt.Fprint(buf, a...)
 | |
| }
 | |
| 
 | |
| func (f *TextFormat) AppendMsgf(buf *bytes.Buffer, s string, a ...interface{}) {
 | |
| 	if f.Strict {
 | |
| 		// Strict format, use key and quote
 | |
| 		buf.WriteString(`msg="`)
 | |
| 		fmt.Fprintf(buf, s, a...)
 | |
| 		buf.WriteByte('"')
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// Write message as-is
 | |
| 	fmt.Fprintf(buf, s, a...)
 | |
| }
 |