log_writer.go 1.6 KB

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