log_writer.go 1.6 KB

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