log_writer.go 1.6 KB

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