forked from boyska/circolog
boyska
b11c2edfc0
JSON is actually unfit to send structured log messages, because date/time is not well supported. So we are using BSON, which supports those. BSON is, among the dozen serializers available, really a random choice and might be changed in the future.
100 lines
1.9 KiB
Go
100 lines
1.9 KiB
Go
package formatter
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"text/template"
|
|
"time"
|
|
|
|
"gopkg.in/mcuadros/go-syslog.v2/format"
|
|
"gopkg.in/mgo.v2/bson"
|
|
)
|
|
|
|
// Formatter is an interface, so that multiple implementations can exist
|
|
type Formatter func(format.LogParts) string
|
|
|
|
var tmplFuncs template.FuncMap
|
|
var syslogTmpl *template.Template
|
|
|
|
func init() {
|
|
tmplFuncs := template.FuncMap{
|
|
"dateFormat": func(dt time.Time, fmt string) string {
|
|
return dt.Format(fmt)
|
|
},
|
|
"rfc822": func(dt time.Time) string {
|
|
return dt.Format(time.RFC822)
|
|
},
|
|
}
|
|
syslogTmpl = template.Must(template.New("syslog").Funcs(tmplFuncs).Parse(
|
|
"{{rfc822 (index . \"timestamp\")}} {{index . \"hostname\"}} " +
|
|
"{{index . \"app_name\"}}" +
|
|
"{{ if (ne (index . \"proc_id\") \"-\")}}[{{index . \"proc_id\"}}]{{end}}: " +
|
|
"{{index . \"message\"}}",
|
|
))
|
|
}
|
|
|
|
type Format int
|
|
|
|
func (rf *Format) Set(v string) error {
|
|
newvalue, err := parseFormat(v)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*rf = newvalue
|
|
return nil
|
|
}
|
|
|
|
func (rf Format) String() string {
|
|
switch rf {
|
|
case FormatJSON:
|
|
return "json"
|
|
case FormatSyslog:
|
|
return "syslog"
|
|
case FormatBSON:
|
|
return "bson"
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func (rf Format) WriteFormatted(w io.Writer, msg format.LogParts) error {
|
|
return WriteFormatted(w, rf, msg)
|
|
}
|
|
|
|
func parseFormat(s string) (Format, error) {
|
|
switch s {
|
|
case "json":
|
|
return FormatJSON, nil
|
|
case "syslog":
|
|
return FormatSyslog, nil
|
|
case "bson":
|
|
return FormatBSON, nil
|
|
default:
|
|
return 0, fmt.Errorf("Undefined format `%s`", s)
|
|
}
|
|
}
|
|
|
|
const (
|
|
FormatSyslog = iota // 0
|
|
FormatJSON = iota
|
|
FormatBSON = iota
|
|
)
|
|
|
|
func WriteFormatted(w io.Writer, f Format, msg format.LogParts) error {
|
|
switch f {
|
|
case FormatSyslog:
|
|
return syslogTmpl.Execute(w, msg)
|
|
case FormatJSON:
|
|
enc := json.NewEncoder(w)
|
|
enc.SetIndent("", " ")
|
|
return enc.Encode(msg)
|
|
case FormatBSON:
|
|
enc, err := bson.Marshal(msg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = w.Write(enc)
|
|
return err
|
|
}
|
|
return nil
|
|
}
|