mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 14:02:25 -05:00 
			
		
		
		
	
		
			
	
	
		
			641 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			641 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...) | ||
|  | } |