logger.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. package log
  2. import (
  3. "io"
  4. "log"
  5. "os"
  6. "time"
  7. "v2ray.com/core/common/platform"
  8. "v2ray.com/core/common/signal"
  9. )
  10. type LogWriter interface {
  11. io.WriteCloser
  12. }
  13. type LogWriterCreator func() LogWriter
  14. type generalLogger struct {
  15. creator LogWriterCreator
  16. buffer chan Message
  17. access *signal.Semaphore
  18. }
  19. // NewLogger returns a generic log handler that can handle all type of messages.
  20. func NewLogger(logWriterCreator LogWriterCreator) Handler {
  21. return &generalLogger{
  22. creator: logWriterCreator,
  23. buffer: make(chan Message, 16),
  24. access: signal.NewSemaphore(1),
  25. }
  26. }
  27. func (l *generalLogger) run() {
  28. defer l.access.Signal()
  29. dataWritten := false
  30. ticker := time.NewTicker(time.Minute)
  31. defer ticker.Stop()
  32. logger := l.creator()
  33. if logger == nil {
  34. return
  35. }
  36. defer logger.Close()
  37. ls := []byte(platform.LineSeparator())
  38. for {
  39. select {
  40. case msg := <-l.buffer:
  41. logger.Write([]byte(msg.String()))
  42. logger.Write(ls)
  43. dataWritten = true
  44. case <-ticker.C:
  45. if !dataWritten {
  46. return
  47. }
  48. dataWritten = false
  49. }
  50. }
  51. }
  52. func (l *generalLogger) Handle(msg Message) {
  53. select {
  54. case l.buffer <- msg:
  55. default:
  56. }
  57. select {
  58. case <-l.access.Wait():
  59. go l.run()
  60. default:
  61. }
  62. }
  63. type consoleLogWriter struct {
  64. logger *log.Logger
  65. }
  66. func (w *consoleLogWriter) Write(b []byte) (int, error) {
  67. w.logger.Print(string(b))
  68. return len(b), nil
  69. }
  70. func (w *consoleLogWriter) Close() error {
  71. return nil
  72. }
  73. type fileLogWriter struct {
  74. file *os.File
  75. logger *log.Logger
  76. }
  77. func (w *fileLogWriter) Write(b []byte) (int, error) {
  78. w.logger.Print(string(b))
  79. return len(b), nil
  80. }
  81. func (w *fileLogWriter) Close() error {
  82. return w.file.Close()
  83. }
  84. func CreateStdoutLogWriter() LogWriterCreator {
  85. return func() LogWriter {
  86. return &consoleLogWriter{
  87. logger: log.New(os.Stdout, "", log.Ldate|log.Ltime),
  88. }
  89. }
  90. }
  91. func CreateFileLogWriter(path string) (LogWriterCreator, error) {
  92. file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
  93. if err != nil {
  94. return nil, err
  95. }
  96. file.Close()
  97. return func() LogWriter {
  98. file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
  99. if err != nil {
  100. return nil
  101. }
  102. return &fileLogWriter{
  103. file: file,
  104. logger: log.New(file, "", log.Ldate|log.Ltime),
  105. }
  106. }, nil
  107. }
  108. func init() {
  109. RegisterHandler(NewLogger(CreateStdoutLogWriter()))
  110. }