pattlog.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // Copyright (C) 2010, Kyle Lemons <kyle@kylelemons.net>. All rights reserved.
  2. package log4go
  3. import (
  4. "bytes"
  5. "fmt"
  6. "io"
  7. "strings"
  8. "sync"
  9. )
  10. const (
  11. FORMAT_DEFAULT = "[%D %T] [%L] (%S) %M"
  12. FORMAT_SHORT = "[%t %d] [%L] %M"
  13. FORMAT_ABBREV = "[%L] %M"
  14. )
  15. type formatCacheType struct {
  16. LastUpdateSeconds int64
  17. shortTime, shortDate string
  18. longTime, longDate string
  19. }
  20. var formatCache = &formatCacheType{}
  21. var muFormatCache = sync.Mutex{}
  22. func setFormatCache(f *formatCacheType) {
  23. muFormatCache.Lock()
  24. defer muFormatCache.Unlock()
  25. formatCache = f
  26. }
  27. func getFormatCache() *formatCacheType {
  28. muFormatCache.Lock()
  29. defer muFormatCache.Unlock()
  30. return formatCache
  31. }
  32. // Known format codes:
  33. // %T - Time (15:04:05 MST)
  34. // %t - Time (15:04)
  35. // %D - Date (2006/01/02)
  36. // %d - Date (01/02/06)
  37. // %L - Level (FNST, FINE, DEBG, TRAC, WARN, EROR, CRIT)
  38. // %S - Source
  39. // %M - Message
  40. // Ignores unknown formats
  41. // Recommended: "[%D %T] [%L] (%S) %M"
  42. func FormatLogRecord(format string, rec *LogRecord) string {
  43. if rec == nil {
  44. return "<nil>"
  45. }
  46. if len(format) == 0 {
  47. return ""
  48. }
  49. out := bytes.NewBuffer(make([]byte, 0, 64))
  50. secs := rec.Created.UnixNano() / 1e9
  51. cache := getFormatCache()
  52. if cache.LastUpdateSeconds != secs {
  53. month, day, year := rec.Created.Month(), rec.Created.Day(), rec.Created.Year()
  54. hour, minute, second := rec.Created.Hour(), rec.Created.Minute(), rec.Created.Second()
  55. zone, _ := rec.Created.Zone()
  56. updated := &formatCacheType{
  57. LastUpdateSeconds: secs,
  58. shortTime: fmt.Sprintf("%02d:%02d", hour, minute),
  59. shortDate: fmt.Sprintf("%02d/%02d/%02d", day, month, year%100),
  60. longTime: fmt.Sprintf("%02d:%02d:%02d %s", hour, minute, second, zone),
  61. longDate: fmt.Sprintf("%04d/%02d/%02d", year, month, day),
  62. }
  63. cache = updated
  64. setFormatCache(updated)
  65. }
  66. // Split the string into pieces by % signs
  67. pieces := bytes.Split([]byte(format), []byte{'%'})
  68. // Iterate over the pieces, replacing known formats
  69. for i, piece := range pieces {
  70. if i > 0 && len(piece) > 0 {
  71. switch piece[0] {
  72. case 'T':
  73. out.WriteString(cache.longTime)
  74. case 't':
  75. out.WriteString(cache.shortTime)
  76. case 'D':
  77. out.WriteString(cache.longDate)
  78. case 'd':
  79. out.WriteString(cache.shortDate)
  80. case 'L':
  81. out.WriteString(levelStrings[rec.Level])
  82. case 'S':
  83. out.WriteString(rec.Source)
  84. case 's':
  85. slice := strings.Split(rec.Source, "/")
  86. out.WriteString(slice[len(slice)-1])
  87. case 'M':
  88. out.WriteString(rec.Message)
  89. }
  90. if len(piece) > 1 {
  91. out.Write(piece[1:])
  92. }
  93. } else if len(piece) > 0 {
  94. out.Write(piece)
  95. }
  96. }
  97. out.WriteByte('\n')
  98. return out.String()
  99. }
  100. // This is the standard writer that prints to standard output.
  101. type FormatLogWriter chan *LogRecord
  102. // This creates a new FormatLogWriter
  103. func NewFormatLogWriter(out io.Writer, format string) FormatLogWriter {
  104. records := make(FormatLogWriter, LogBufferLength)
  105. go records.run(out, format)
  106. return records
  107. }
  108. func (w FormatLogWriter) run(out io.Writer, format string) {
  109. for rec := range w {
  110. fmt.Fprint(out, FormatLogRecord(format, rec))
  111. }
  112. }
  113. // This is the FormatLogWriter's output method. This will block if the output
  114. // buffer is full.
  115. func (w FormatLogWriter) LogWrite(rec *LogRecord) {
  116. w <- rec
  117. }
  118. // Close stops the logger from sending messages to standard output. Attempts to
  119. // send log messages to this logger after a Close have undefined behavior.
  120. func (w FormatLogWriter) Close() {
  121. close(w)
  122. }