file.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package writer
  2. import (
  3. "errors"
  4. "fmt"
  5. "log"
  6. "os"
  7. "path/filepath"
  8. "strings"
  9. "time"
  10. )
  11. // timeFormat 时间格式
  12. // 用于文件名称格式
  13. const timeFormat = "2006-01-02"
  14. // FileWriter 文件写入结构体
  15. type FileWriter struct {
  16. file *os.File
  17. FilenameFunc func(*FileWriter) string
  18. num uint
  19. opts Options
  20. input chan []byte
  21. }
  22. // NewFileWriter 实例化FileWriter, 支持大文件分割
  23. func NewFileWriter(opts ...Option) (*FileWriter, error) {
  24. p := &FileWriter{
  25. opts: setDefault(),
  26. }
  27. for _, o := range opts {
  28. o(&p.opts)
  29. }
  30. var filename string
  31. var err error
  32. for {
  33. filename = p.getFilename()
  34. _, err := os.Stat(filename)
  35. if err != nil {
  36. if os.IsNotExist(err) {
  37. if p.num > 0 {
  38. p.num--
  39. filename = p.getFilename()
  40. }
  41. //文件不存在
  42. break
  43. }
  44. //存在,但是报错了
  45. return nil, err
  46. }
  47. p.num++
  48. if p.opts.cap == 0 {
  49. break
  50. }
  51. }
  52. p.file, err = os.OpenFile(filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_SYNC, 0600)
  53. if err != nil {
  54. return nil, err
  55. }
  56. p.input = make(chan []byte, 100)
  57. go p.write()
  58. return p, nil
  59. }
  60. func (p *FileWriter) write() {
  61. for {
  62. select {
  63. case d := <-p.input:
  64. _, err := p.file.Write(d)
  65. if err != nil {
  66. log.Printf("write file failed, %s\n", err.Error())
  67. }
  68. p.checkFile()
  69. }
  70. }
  71. }
  72. func (p *FileWriter) checkFile() {
  73. info, _ := p.file.Stat()
  74. if strings.Index(p.file.Name(), time.Now().Format(timeFormat)) < 0 ||
  75. (p.opts.cap > 0 && uint(info.Size()) > p.opts.cap) {
  76. //生成新文件
  77. if uint(info.Size()) > p.opts.cap {
  78. p.num++
  79. } else {
  80. p.num = 0
  81. }
  82. filename := p.getFilename()
  83. _ = p.file.Close()
  84. p.file, _ = os.OpenFile(filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_SYNC, 0600)
  85. }
  86. }
  87. // Write 写入方法
  88. func (p *FileWriter) Write(data []byte) (n int, err error) {
  89. if p == nil {
  90. return 0, errors.New("logFileWriter is nil")
  91. }
  92. if p.file == nil {
  93. return 0, errors.New("file not opened")
  94. }
  95. n = len(data)
  96. go func() {
  97. p.input <- data
  98. }()
  99. return n, nil
  100. }
  101. // getFilename 获取log文件名
  102. // 目前为:以日期格式命名,eg:2006-01-02.log or 2006-01-02.log
  103. func (p *FileWriter) getFilename() string {
  104. if p.FilenameFunc != nil {
  105. return p.FilenameFunc(p)
  106. }
  107. if p.opts.cap == 0 {
  108. return filepath.Join(p.opts.path,
  109. fmt.Sprintf("%s.%s",
  110. time.Now().Format(timeFormat),
  111. p.opts.suffix))
  112. }
  113. return filepath.Join(p.opts.path,
  114. fmt.Sprintf("%s-[%d].%s",
  115. time.Now().Format(timeFormat),
  116. p.num,
  117. p.opts.suffix))
  118. }