logger.go 2.5 KB

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