log.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package log
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. "strings"
  7. "sync"
  8. "go-common/app/tool/bgr/log/color"
  9. "golang.org/x/crypto/ssh/terminal"
  10. )
  11. // FDWriter interface extends io.Writer with file descriptor function
  12. type FDWriter interface {
  13. io.Writer
  14. Fd() uintptr
  15. }
  16. // Logger struct definition
  17. type Logger struct {
  18. mu sync.RWMutex
  19. out FDWriter
  20. color bool
  21. debug bool
  22. buf strings.Builder
  23. }
  24. type prefix struct {
  25. Plain string
  26. Color string
  27. }
  28. const (
  29. _plainError = "[ ERROR ] "
  30. _plainWarn = "[ WARN ] "
  31. _plainInfo = "[ INFO ] "
  32. _plainDebug = "[ DEBUG ] "
  33. _plainFatal = "[ FATAL ] "
  34. )
  35. var (
  36. _prefixError = prefix{
  37. Plain: _plainError,
  38. Color: colorful.Red(_plainError),
  39. }
  40. _prefixWarn = prefix{
  41. Plain: _plainWarn,
  42. Color: colorful.Orange(_plainWarn),
  43. }
  44. _prefixInfo = prefix{
  45. Plain: _plainInfo,
  46. Color: colorful.Green(_plainInfo),
  47. }
  48. _prefixDebug = prefix{
  49. Plain: _plainDebug,
  50. Color: colorful.Purple(_plainDebug),
  51. }
  52. _prefixFatal = prefix{
  53. Plain: _plainFatal,
  54. Color: colorful.Gray(_plainFatal),
  55. }
  56. )
  57. // New returns new Logger instance with predefined writer output and
  58. // automatically detect terminal coloring support
  59. func New(out FDWriter, debug bool) *Logger {
  60. return &Logger{
  61. color: terminal.IsTerminal(int(out.Fd())),
  62. out: out,
  63. debug: debug,
  64. buf: strings.Builder{},
  65. }
  66. }
  67. func (l *Logger) output(prefix prefix, data string) (err error) {
  68. l.mu.Lock()
  69. defer l.mu.Unlock()
  70. l.buf.Reset()
  71. if l.color {
  72. if _, err = l.buf.WriteString(prefix.Color); err != nil {
  73. return
  74. }
  75. } else {
  76. if _, err = l.buf.WriteString(prefix.Plain); err != nil {
  77. return
  78. }
  79. }
  80. if _, err = l.buf.WriteString(data); err != nil {
  81. return
  82. }
  83. if data[len(data)-1] != '\n' {
  84. l.buf.WriteString("\n")
  85. }
  86. _, err = l.out.Write([]byte(l.buf.String()))
  87. return
  88. }
  89. // Error print error message to output
  90. func (l *Logger) Error(v ...interface{}) {
  91. l.output(_prefixError, fmt.Sprintln(v...))
  92. }
  93. // Errorf print formatted error message to output
  94. func (l *Logger) Errorf(format string, v ...interface{}) {
  95. l.output(_prefixError, fmt.Sprintf(format, v...))
  96. }
  97. // Warn print warning message to output
  98. func (l *Logger) Warn(v ...interface{}) {
  99. l.output(_prefixWarn, fmt.Sprintln(v...))
  100. }
  101. // Warnf print formatted warning message to output
  102. func (l *Logger) Warnf(format string, v ...interface{}) {
  103. l.output(_prefixWarn, fmt.Sprintf(format, v...))
  104. }
  105. // Info print informational message to output
  106. func (l *Logger) Info(v ...interface{}) {
  107. l.output(_prefixInfo, fmt.Sprintln(v...))
  108. }
  109. // Infof print formatted informational message to output
  110. func (l *Logger) Infof(format string, v ...interface{}) {
  111. l.output(_prefixInfo, fmt.Sprintf(format, v...))
  112. }
  113. // Debug print debug message to output if debug output enabled
  114. func (l *Logger) Debug(v ...interface{}) {
  115. if l.debug {
  116. l.output(_prefixDebug, fmt.Sprintln(v...))
  117. }
  118. }
  119. // Debugf print formatted debug message to output if debug output enabled
  120. func (l *Logger) Debugf(format string, v ...interface{}) {
  121. if l.debug {
  122. l.output(_prefixDebug, fmt.Sprintf(format, v...))
  123. }
  124. }
  125. // Fatal print fatal message to output and then exit(1)
  126. func (l *Logger) Fatal(v ...interface{}) {
  127. l.output(_prefixFatal, fmt.Sprintln(v...))
  128. os.Exit(1)
  129. }
  130. // Fatalf print formatted fatal message to output and then exit(1)
  131. func (l *Logger) Fatalf(format string, v ...interface{}) {
  132. l.output(_prefixFatal, fmt.Sprintf(format, v...))
  133. os.Exit(1)
  134. }