type TextHandler … // NewTextHandler creates a [TextHandler] that writes to w, // using the given options. // If opts is nil, the default options are used. func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler { … } // Enabled reports whether the handler handles records at the given level. // The handler ignores records whose level is lower. func (h *TextHandler) Enabled(_ context.Context, level Level) bool { … } // WithAttrs returns a new [TextHandler] whose attributes consists // of h's attributes followed by attrs. func (h *TextHandler) WithAttrs(attrs []Attr) Handler { … } func (h *TextHandler) WithGroup(name string) Handler { … } // Handle formats its argument [Record] as a single line of space-separated // key=value items. // // If the Record's time is zero, the time is omitted. // Otherwise, the key is "time" // and the value is output in RFC3339 format with millisecond precision. // // If the Record's level is zero, the level is omitted. // Otherwise, the key is "level" // and the value of [Level.String] is output. // // If the AddSource option is set and source information is available, // the key is "source" and the value is output as FILE:LINE. // // The message's key is "msg". // // To modify these or other attributes, or remove them from the output, use // [HandlerOptions.ReplaceAttr]. // // If a value implements [encoding.TextMarshaler], the result of MarshalText is // written. Otherwise, the result of [fmt.Sprint] is written. // // Keys and values are quoted with [strconv.Quote] if they contain Unicode space // characters, non-printing characters, '"' or '='. // // Keys inside groups consist of components (keys or group names) separated by // dots. No further escaping is performed. // Thus there is no way to determine from the key "a.b.c" whether there // are two groups "a" and "b" and a key "c", or a single group "a.b" and a key "c", // or single group "a" and a key "b.c". // If it is necessary to reconstruct the group structure of a key // even in the presence of dots inside components, use // [HandlerOptions.ReplaceAttr] to encode that information in the key. // // Each call to Handle results in a single serialized call to // io.Writer.Write. func (h *TextHandler) Handle(_ context.Context, r Record) error { … } func appendTextValue(s *handleState, v Value) error { … } // byteSlice returns its argument as a []byte if the argument's // underlying type is []byte, along with a second return value of true. // Otherwise it returns nil, false. func byteSlice(a any) ([]byte, bool) { … } func needsQuoting(s string) bool { … }