format.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. package formatter
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io"
  6. "text/template"
  7. "time"
  8. "github.com/mgutz/ansi"
  9. "gopkg.in/mcuadros/go-syslog.v2/format"
  10. "gopkg.in/mgo.v2/bson"
  11. )
  12. // Formatter is an interface, so that multiple implementations can exist
  13. type Formatter func(format.LogParts) string
  14. var tmplFuncs template.FuncMap
  15. var syslogTmpl *template.Template
  16. func init() {
  17. tmplFuncs := template.FuncMap{
  18. "dateFormat": func(dt time.Time, fmt string) string {
  19. return dt.Format(fmt)
  20. },
  21. "rfc822": func(dt time.Time) string {
  22. return dt.Format(time.RFC822)
  23. },
  24. "sevName": func(s int) string {
  25. names := []string{"emerg ", "alert ", "crit ", "err ", "warn ", "notice", "info ", "dbg "}
  26. switch {
  27. case s < 2: // emerg..alert
  28. return ansi.Color(names[s], "red+b")
  29. case s < 4: // emerg..err
  30. return ansi.Color(names[s], "red")
  31. case s < 6: // warn..notice
  32. return ansi.Color(names[s], "white+b")
  33. case s >= len(names):
  34. return "???"
  35. default:
  36. return names[s]
  37. }
  38. },
  39. "color": func(color, text string) string {
  40. return ansi.Color(text, color) // slow; should use colorfunc
  41. },
  42. "red": ansi.ColorFunc("red+b"),
  43. }
  44. syslogTmpl = template.Must(template.New("syslog").Funcs(tmplFuncs).Parse(
  45. "{{color \"yellow\" (rfc822 (index . \"timestamp\")) }} {{index . \"hostname\"}} " +
  46. "{{index . \"app_name\"}}" +
  47. "{{ if (ne (index . \"proc_id\") \"-\")}}[{{index . \"proc_id\"}}]{{end}}: " +
  48. "{{ sevName (index . \"severity\") }} " +
  49. "{{index . \"message\"}}",
  50. ))
  51. }
  52. type Format int
  53. func (rf *Format) Set(v string) error {
  54. newvalue, err := parseFormat(v)
  55. if err != nil {
  56. return err
  57. }
  58. *rf = newvalue
  59. return nil
  60. }
  61. func (rf Format) String() string {
  62. switch rf {
  63. case FormatJSON:
  64. return "json"
  65. case FormatSyslog:
  66. return "syslog"
  67. case FormatBSON:
  68. return "bson"
  69. }
  70. return ""
  71. }
  72. func (rf Format) WriteFormatted(w io.Writer, msg format.LogParts) error {
  73. return WriteFormatted(w, rf, msg)
  74. }
  75. func parseFormat(s string) (Format, error) {
  76. switch s {
  77. case "json":
  78. return FormatJSON, nil
  79. case "syslog":
  80. return FormatSyslog, nil
  81. case "bson":
  82. return FormatBSON, nil
  83. default:
  84. return 0, fmt.Errorf("Undefined format `%s`", s)
  85. }
  86. }
  87. const (
  88. FormatSyslog = iota // 0
  89. FormatJSON = iota
  90. FormatBSON = iota
  91. )
  92. func WriteFormatted(w io.Writer, f Format, msg format.LogParts) error {
  93. switch f {
  94. case FormatSyslog:
  95. return syslogTmpl.Execute(w, msg)
  96. case FormatJSON:
  97. enc := json.NewEncoder(w)
  98. enc.SetIndent("", " ")
  99. return enc.Encode(msg)
  100. case FormatBSON:
  101. enc, err := bson.Marshal(msg)
  102. if err != nil {
  103. return err
  104. }
  105. _, err = w.Write(enc)
  106. return err
  107. }
  108. return nil
  109. }