gitee.com/h79/goutils@v1.22.10/perf/perf.go (about) 1 package perf 2 3 import ( 4 "context" 5 "fmt" 6 "gitee.com/h79/goutils/alarm" 7 "gitee.com/h79/goutils/common/random" 8 "gitee.com/h79/goutils/common/result" 9 "gitee.com/h79/goutils/common/timer" 10 "go.uber.org/zap" 11 "path/filepath" 12 "runtime" 13 "time" 14 ) 15 16 type Config struct { 17 DisableLog bool `json:"disableLog" yaml:"disableLog"` 18 DisableWarn bool `json:"disableWarn" yaml:"disableWarn"` 19 } 20 21 type RunTime struct { 22 warn int64 23 start int64 24 } 25 26 func Begin(warn int64) *RunTime { 27 if warn == 0 { 28 warn = 3000 29 } 30 return &RunTime{start: timer.CurrentMS(), warn: warn} 31 } 32 33 func (t *RunTime) Start() int64 { 34 return t.start 35 } 36 37 func (t *RunTime) End() int64 { 38 end := timer.CurrentMS() 39 diff := end - t.start 40 if diff >= t.warn { 41 return diff 42 } 43 return 0 44 } 45 46 type Perf struct { 47 Config 48 id string 49 model string 50 funName string 51 file string 52 line int 53 warn int64 54 start int64 55 mid int64 56 } 57 58 func (p *Perf) EnableLog(enable bool) *Perf { 59 p.DisableLog = !enable 60 return p 61 } 62 63 func (p *Perf) EnableWarn(enable bool) *Perf { 64 p.DisableWarn = !enable 65 return p 66 } 67 68 func (p *Perf) WithModel(model string) *Perf { 69 p.model = model 70 return p 71 } 72 73 func (p *Perf) WithWarn(t int64) *Perf { 74 p.warn = t 75 return p 76 } 77 78 func (p *Perf) WithPerfId(id string) *Perf { 79 p.id = id 80 return p 81 } 82 83 func (p *Perf) Start() *Perf { 84 p.start = timer.CurrentMS() 85 p.mid = p.start 86 return p 87 } 88 89 func (p *Perf) End() { 90 end := timer.CurrentMS() 91 dif := end - p.start 92 p.mid = end 93 p.waring(end, dif, "end") 94 } 95 96 func (p *Perf) Out(detail string) { 97 end := timer.CurrentMS() 98 dif := end - p.mid 99 p.mid = end 100 p.waring(end, dif, detail) 101 } 102 103 func (p *Perf) log(end, dif int64, detail string) { 104 zap.L().WithOptions(zap.AddCallerSkip(2)).Debug("Perf", 105 zap.String("perfId", p.id), 106 zap.String("model", p.model), 107 zap.String("detail", detail), 108 zap.Int64("start", p.start), 109 zap.Int64("end", end), 110 zap.Duration("dif", time.Duration(dif)*time.Millisecond), 111 zap.String("func", p.funName), 112 zap.String("file", p.file), 113 zap.Int("line", p.line)) 114 } 115 116 func (p *Perf) waring(end, dif int64, detail string) { 117 //执行时间太长,告警 118 wa := p.warn 119 if wa <= 0 { 120 wa = 2000 121 } 122 if p.DisableWarn { 123 if !p.DisableLog { 124 p.log(end, dif, detail) 125 } 126 return 127 } 128 if dif >= p.warn+1000 { 129 p.log(end, dif, detail) 130 alarm.Tight(context.Background(), result.ErrTimeout, 131 "perf", "", 132 fmt.Sprintf("%s, detail=> '%s', run time too long=> %dms, start=> %d,end=> %d", p.info(), detail, dif, p.start, end), nil) 133 } else if dif >= p.warn { 134 p.log(end, dif, detail) 135 alarm.Important(context.Background(), result.ErrTimeout, 136 "perf", "", 137 fmt.Sprintf("%s, detail=> '%s', run time too long=> %dms,start=> %d,end=> %d", p.info(), detail, dif, p.start, end), nil) 138 } 139 } 140 141 func (p *Perf) info() string { 142 return fmt.Sprintf("perfId: '%s', model: '%s',funcName: '%s', fileName: '%s', line: %d", 143 p.id, p.model, p.funName, p.file, p.line) 144 } 145 146 // T OWNER 147 func T() *Perf { 148 pc, file, line, _ := runtime.Caller(1) 149 return &Perf{ 150 id: random.GenerateNumString(16), 151 model: "", 152 warn: 2000, 153 funName: filepath.Base(runtime.FuncForPC(pc).Name()), 154 file: filepath.Base(file), 155 line: line, 156 } 157 } 158 159 // C caller 160 func C() *Perf { 161 pc, file, line, _ := runtime.Caller(2) 162 return &Perf{ 163 id: random.GenerateNumString(16), 164 model: "", 165 warn: 2000, 166 funName: filepath.Base(runtime.FuncForPC(pc).Name()), 167 file: filepath.Base(file), 168 line: line, 169 } 170 }