utils.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. package utils
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. "strings"
  7. "sync"
  8. "time"
  9. "github.com/wecisecode/util/logger"
  10. )
  11. var (
  12. dataStats = make(map[string]*DataStat) // <title-name>:DataStat
  13. dataStatsMu sync.Mutex
  14. )
  15. func CheckWritePermission(fp string) (err error) {
  16. var file *os.File
  17. if file, err = ioutil.TempFile(fp, ".toe.perm_check"); err == nil {
  18. errMsgs := make([]string, 0, 3)
  19. var e error
  20. if _, e = file.WriteString("ok"); e != nil {
  21. errMsgs = append(errMsgs, "can't write to test file")
  22. }
  23. if e = file.Close(); e != nil {
  24. errMsgs = append(errMsgs, "can't close test file")
  25. }
  26. if e = os.Remove(file.Name()); e != nil {
  27. errMsgs = append(errMsgs, "can't remove test file")
  28. }
  29. if len(errMsgs) > 0 {
  30. err = fmt.Errorf("errors: %s", strings.Join(errMsgs, ", "))
  31. }
  32. }
  33. return
  34. }
  35. type DataStat struct {
  36. statChan chan int
  37. running bool
  38. title string
  39. name string
  40. Interval int `json:"interval"`
  41. Success int64 `json:"success"`
  42. Fail int64 `json:"fail"`
  43. Ignore int64 `json:"ignore"`
  44. TotalSuccess int64 `json:"total_success"`
  45. TotalFail int64 `json:"total_fail"`
  46. TotalIgnore int64 `json:"total_ignore"`
  47. StartTime int64 `json:"start_time"`
  48. LastTime int64 `json:"last_time"`
  49. StatTime int64 `json:"stat_time"`
  50. }
  51. func NewDataStat(title, name string, interval int, chanSize int) *DataStat {
  52. dataStatsMu.Lock()
  53. defer dataStatsMu.Unlock()
  54. key := title + "-" + name
  55. if ds, ok := dataStats[key]; ok {
  56. if ds.statChan != nil {
  57. close(ds.statChan)
  58. }
  59. delete(dataStats, key)
  60. }
  61. ds := &DataStat{
  62. title: title,
  63. name: name,
  64. statChan: make(chan int, chanSize),
  65. Interval: interval,
  66. Success: 0,
  67. Fail: 0,
  68. TotalSuccess: 0,
  69. TotalFail: 0,
  70. }
  71. dataStats[key] = ds
  72. return ds
  73. }
  74. func GetDataStats() []*DataStat {
  75. dataStatsMu.Lock()
  76. defer dataStatsMu.Unlock()
  77. var list []*DataStat
  78. for _, ds := range dataStats {
  79. list = append(list, ds)
  80. }
  81. return list
  82. }
  83. func GetDataStat(key string) *DataStat {
  84. dataStatsMu.Lock()
  85. defer dataStatsMu.Unlock()
  86. return dataStats[key]
  87. }
  88. func (ds *DataStat) Close() {
  89. if ds.statChan != nil && ds.running {
  90. close(ds.statChan)
  91. }
  92. ds.statChan = nil
  93. }
  94. func (ds *DataStat) Start() {
  95. tc := time.NewTicker(time.Duration(ds.Interval) * time.Second)
  96. startTime := time.Now()
  97. ds.StartTime = startTime.UnixNano() / int64(time.Millisecond)
  98. ds.running = true
  99. defer func() {
  100. ds.running = false
  101. }()
  102. L:
  103. for {
  104. select {
  105. case <-tc.C:
  106. now := time.Now()
  107. speed := float64(ds.Success+ds.Fail+ds.Ignore) / now.Sub(startTime).Seconds()
  108. startTime = now
  109. logger.Infof("Stat %s %s: success:%d fail:%d ignore:%d within %ds, total success:%d total fail:%d total ignore:%d speed:%.1f/s.\n", ds.title, ds.name, ds.Success, ds.Fail, ds.Ignore, ds.Interval, ds.TotalSuccess, ds.TotalFail, ds.TotalIgnore, speed)
  110. ds.StatTime = now.UnixNano() / int64(time.Millisecond)
  111. ds.Success = 0
  112. ds.Fail = 0
  113. ds.Ignore = 0
  114. case n, ok := <-ds.statChan:
  115. if !ok {
  116. break L
  117. }
  118. ds.LastTime = time.Now().UnixNano() / int64(time.Millisecond)
  119. switch n {
  120. case 0:
  121. ds.Success++
  122. ds.TotalSuccess++
  123. case 1:
  124. ds.Fail++
  125. ds.TotalFail++
  126. case 2:
  127. ds.Ignore++
  128. ds.TotalIgnore++
  129. }
  130. }
  131. }
  132. }
  133. func (ds *DataStat) Send(status int) {
  134. if ds.statChan != nil && ds.running {
  135. ds.statChan <- status
  136. }
  137. }
  138. func (ds *DataStat) GetTitle() string {
  139. return ds.title
  140. }
  141. func (ds *DataStat) GetName() string {
  142. return ds.name
  143. }
  144. //func Stats(title, name string, interval int, statChan chan int) {
  145. // var totalSuccess, success, fail, totalFail int64
  146. // tc := time.NewTicker(time.Duration(interval) * time.Second)
  147. // lastTime := time.Now()
  148. //L:
  149. // for {
  150. // select {
  151. // case <-tc.C:
  152. // now := time.Now()
  153. // speed := float64(success + fail) / now.Sub(lastTime).Seconds()
  154. // lastTime = now
  155. // logger.Infof("Stats %s %s: success:%d fail:%d within %ds, total success:%d total fail:%d speed:%.1f/s.\n", title, name, success, fail, interval, totalSuccess, totalFail, speed)
  156. // success = 0
  157. // fail = 0
  158. // //ignore = 0
  159. // case n, ok := <-statChan:
  160. // if !ok {
  161. // break L
  162. // }
  163. // switch n {
  164. // case 0:
  165. // success++
  166. // totalSuccess++
  167. // case 1:
  168. // fail++
  169. // totalFail++
  170. // //case 2:
  171. // // ignore ++
  172. // // totalIgnore ++
  173. // }
  174. // }
  175. // }
  176. //}