logger.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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. // Writer is the interface for writing logs.
  11. type Writer interface {
  12. Write(string) error
  13. io.Closer
  14. }
  15. // WriterCreator is a function to create LogWriters.
  16. type WriterCreator func() Writer
  17. type generalLogger struct {
  18. creator WriterCreator
  19. buffer chan Message
  20. access *signal.Semaphore
  21. done *signal.Done
  22. }
  23. // NewLogger returns a generic log handler that can handle all type of messages.
  24. func NewLogger(logWriterCreator WriterCreator) Handler {
  25. return &generalLogger{
  26. creator: logWriterCreator,
  27. buffer: make(chan Message, 16),
  28. access: signal.NewSemaphore(1),
  29. done: signal.NewDone(),
  30. }
  31. }
  32. func (l *generalLogger) run() {
  33. defer l.access.Signal()
  34. dataWritten := false
  35. ticker := time.NewTicker(time.Minute)
  36. defer ticker.Stop()
  37. logger := l.creator()
  38. if logger == nil {
  39. return
  40. }
  41. defer logger.Close()
  42. for {
  43. select {
  44. case <-l.done.C():
  45. return
  46. case msg := <-l.buffer:
  47. logger.Write(msg.String() + platform.LineSeparator())
  48. dataWritten = true
  49. case <-ticker.C:
  50. if !dataWritten {
  51. return
  52. }
  53. dataWritten = false
  54. }
  55. }
  56. }
  57. func (l *generalLogger) Handle(msg Message) {
  58. select {
  59. case l.buffer <- msg:
  60. default:
  61. }
  62. select {
  63. case <-l.access.Wait():
  64. go l.run()
  65. default:
  66. }
  67. }
  68. func (l *generalLogger) Close() error {
  69. return l.done.Close()
  70. }
  71. type consoleLogWriter struct {
  72. logger *log.Logger
  73. }
  74. func (w *consoleLogWriter) Write(s string) error {
  75. w.logger.Print(s)
  76. return nil
  77. }
  78. func (w *consoleLogWriter) Close() error {
  79. return nil
  80. }
  81. type fileLogWriter struct {
  82. file *os.File
  83. logger *log.Logger
  84. }
  85. func (w *fileLogWriter) Write(s string) error {
  86. w.logger.Print(s)
  87. return nil
  88. }
  89. func (w *fileLogWriter) Close() error {
  90. return w.file.Close()
  91. }
  92. // CreateStdoutLogWriter returns a LogWriterCreator that creates LogWriter for stdout.
  93. func CreateStdoutLogWriter() WriterCreator {
  94. return func() Writer {
  95. return &consoleLogWriter{
  96. logger: log.New(os.Stdout, "", log.Ldate|log.Ltime),
  97. }
  98. }
  99. }
  100. // CreateFileLogWriter returns a LogWriterCreator that creates LogWriter for the given file.
  101. func CreateFileLogWriter(path string) (WriterCreator, error) {
  102. file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
  103. if err != nil {
  104. return nil, err
  105. }
  106. file.Close()
  107. return func() Writer {
  108. file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
  109. if err != nil {
  110. return nil
  111. }
  112. return &fileLogWriter{
  113. file: file,
  114. logger: log.New(file, "", log.Ldate|log.Ltime),
  115. }
  116. }, nil
  117. }
  118. func init() {
  119. RegisterHandler(NewLogger(CreateStdoutLogWriter()))
  120. }