log_writer.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package internal
  2. import (
  3. "log"
  4. "os"
  5. "time"
  6. "v2ray.com/core/common/platform"
  7. "v2ray.com/core/common/signal"
  8. )
  9. type LogWriter interface {
  10. Log(LogEntry)
  11. Close()
  12. }
  13. type NoOpLogWriter struct {
  14. }
  15. func (v *NoOpLogWriter) Log(entry LogEntry) {
  16. entry.Release()
  17. }
  18. func (v *NoOpLogWriter) Close() {
  19. }
  20. type StdOutLogWriter struct {
  21. logger *log.Logger
  22. cancel *signal.CancelSignal
  23. }
  24. func NewStdOutLogWriter() LogWriter {
  25. return &StdOutLogWriter{
  26. logger: log.New(os.Stdout, "", log.Ldate|log.Ltime),
  27. cancel: signal.NewCloseSignal(),
  28. }
  29. }
  30. func (v *StdOutLogWriter) Log(log LogEntry) {
  31. v.logger.Print(log.String() + platform.LineSeparator())
  32. log.Release()
  33. }
  34. func (v *StdOutLogWriter) Close() {
  35. time.Sleep(500 * time.Millisecond)
  36. }
  37. type FileLogWriter struct {
  38. queue chan string
  39. logger *log.Logger
  40. file *os.File
  41. cancel *signal.CancelSignal
  42. }
  43. func (v *FileLogWriter) Log(log LogEntry) {
  44. select {
  45. case v.queue <- log.String():
  46. default:
  47. // We don't expect this to happen, but don't want to block main thread as well.
  48. }
  49. log.Release()
  50. }
  51. func (v *FileLogWriter) run() {
  52. v.cancel.WaitThread()
  53. defer v.cancel.FinishThread()
  54. for {
  55. entry, open := <-v.queue
  56. if !open {
  57. break
  58. }
  59. v.logger.Print(entry + platform.LineSeparator())
  60. }
  61. }
  62. func (v *FileLogWriter) Close() {
  63. close(v.queue)
  64. v.cancel.WaitForDone()
  65. v.file.Close()
  66. }
  67. func NewFileLogWriter(path string) (*FileLogWriter, error) {
  68. file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
  69. if err != nil {
  70. return nil, err
  71. }
  72. logger := &FileLogWriter{
  73. queue: make(chan string, 16),
  74. logger: log.New(file, "", log.Ldate|log.Ltime),
  75. file: file,
  76. cancel: signal.NewCloseSignal(),
  77. }
  78. go logger.run()
  79. return logger, nil
  80. }