logger.go 2.2 KB

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