package blammo import ( "bytes" "io" "strconv" "strings" "sync" "time" ) // LineWriter is an EventWriter that writes one event per line. Event that have // multiline messages will have the newlines in their messages replaced with \n // sequences. This is the default EventWriter and is designed to be reasonably // safe and practical for most users. type LineWriter struct { pool sync.Pool out struct { sync.Mutex io.Writer } } func NewLineWriter(w io.Writer) *LineWriter { lw := new(LineWriter) lw.pool = sync.Pool{ New: func() interface{} { return new(bytes.Buffer) }, } lw.out.Writer = w return lw } func (l *LineWriter) WriteEvent(e *Event) { buf := l.pool.Get().(*bytes.Buffer) buf.Reset() buf.WriteString(e.Time.Format(time.RFC3339)) buf.WriteRune(' ') switch e.Level { case Debug: buf.WriteString("d ") case Info: buf.WriteString("i ") case Error: buf.WriteString("e ") default: buf.WriteString("? ") } buf.WriteRune('[') if e.Path != nil { buf.WriteString(e.Path.String()) } buf.WriteRune(']') buf.WriteRune(' ') if e.Tags == nil { buf.WriteString("[]") } else { buf.WriteRune('[') writeTags(buf, e.Tags) buf.WriteRune(']') } if e.Text != "" { buf.WriteRune(' ') buf.WriteString(strings.ReplaceAll(e.Text, string('\n'), "\n")) buf.WriteRune('\n') } l.out.Lock() l.out.Write(buf.Bytes()) l.out.Unlock() l.pool.Put(buf) } // writeTags is a helper for LineWriter's WriteEvent method. writeTags writes // tags in the order in which they were added to the list of tags; the oldest // tag is always written first. func writeTags(buf *bytes.Buffer, tags *Tags) { if tags.parent != nil { writeTags(buf, tags.parent) buf.WriteRune('+') } buf.WriteString(tags.key) if tags.value != nil { buf.WriteRune('=') switch v := tags.value.(type) { case int: buf.WriteString(strconv.Itoa(v)) case string: buf.WriteString(MakeSafeName(v)) case float64: buf.WriteString(strconv.FormatFloat(v, 'f', -1, 64)) default: buf.WriteString("???") } } }