logger.go 2.5 KB

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