logger.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. package logger
  2. import (
  3. "fmt"
  4. "net/http"
  5. "os"
  6. "time"
  7. "golang-fave/consts"
  8. "golang-fave/utils"
  9. )
  10. type logMsg struct {
  11. host string
  12. message string
  13. isError bool
  14. }
  15. type Logger struct {
  16. wwwDir string
  17. cdata chan logMsg
  18. cclose chan bool
  19. }
  20. func (this *Logger) console(msg *logMsg) {
  21. if consts.ParamDebug {
  22. if !msg.isError {
  23. if consts.IS_WIN {
  24. fmt.Fprintln(os.Stdout, "[ACCESS] "+msg.message)
  25. } else {
  26. fmt.Fprintln(os.Stdout, "\033[0;32m[ACCESS] "+msg.message+"\033[0m")
  27. }
  28. } else {
  29. if consts.IS_WIN {
  30. fmt.Fprintln(os.Stdout, "[ERROR] "+msg.message)
  31. } else {
  32. fmt.Fprintln(os.Stdout, "\033[0;31m[ERROR] "+msg.message+"\033[0m")
  33. }
  34. }
  35. return
  36. }
  37. if !msg.isError {
  38. fmt.Fprintln(os.Stdout, msg.message)
  39. } else {
  40. fmt.Fprintln(os.Stderr, msg.message)
  41. }
  42. }
  43. func (this *Logger) write(msg *logMsg) {
  44. // Ignore file if debug
  45. if consts.ParamDebug {
  46. this.console(msg)
  47. return
  48. }
  49. // Ignore file if host not set
  50. if msg.host == "" {
  51. this.console(msg)
  52. return
  53. }
  54. // Ignore file if www dir is not exists
  55. if !utils.IsDirExists(this.wwwDir) {
  56. this.console(msg)
  57. return
  58. }
  59. // Extract host
  60. host, _ := utils.ExtractHostPort(msg.host, false)
  61. logs_dir := this.wwwDir + string(os.PathSeparator) + host + string(os.PathSeparator) + "logs"
  62. // Ignore file if logs dir is not exists
  63. if !utils.IsDirExists(logs_dir) {
  64. this.console(msg)
  65. return
  66. }
  67. // Detect which log file
  68. log_file := logs_dir + string(os.PathSeparator) + "access.log"
  69. if msg.isError {
  70. log_file = logs_dir + string(os.PathSeparator) + "error.log"
  71. }
  72. // Try write to file
  73. f, err := os.OpenFile(log_file, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
  74. if err == nil {
  75. defer f.Close()
  76. fmt.Fprintln(f, msg.message)
  77. return
  78. }
  79. // By default
  80. this.console(msg)
  81. }
  82. func New() *Logger {
  83. // Logs channel
  84. cdata := make(chan logMsg)
  85. // Close channel
  86. cclose := make(chan bool)
  87. // Init logger pointer
  88. lg := Logger{cdata: cdata, cclose: cclose}
  89. // Write log string in background
  90. go func() {
  91. for {
  92. select {
  93. case msg := <-cdata:
  94. lg.write(&msg)
  95. case <-cclose:
  96. cclose <- true
  97. return
  98. }
  99. }
  100. }()
  101. return &lg
  102. }
  103. func (this *Logger) Log(msg string, r *http.Request, isError bool) {
  104. var host string = ""
  105. if r != nil {
  106. host = r.Host
  107. }
  108. // Do not wait
  109. go func() {
  110. select {
  111. case this.cdata <- logMsg{host, msg, isError}:
  112. return
  113. case <-time.After(1 * time.Second):
  114. fmt.Println("Logger error, log channel is overflowed (1)")
  115. return
  116. }
  117. }()
  118. }
  119. func (this *Logger) SetWwwDir(dir string) {
  120. this.wwwDir = dir
  121. }
  122. func (this *Logger) Handler(h http.Handler) http.Handler {
  123. return handler{
  124. h: h,
  125. w: os.Stdout,
  126. c: this.cdata,
  127. }
  128. }
  129. func (this *Logger) Close() {
  130. this.cclose <- true
  131. <-this.cclose
  132. }