github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/system/trace/trace.go (about) 1 package trace 2 3 import ( 4 "fmt" 5 "time" 6 ) 7 8 type IElapsedTimeInfos interface { 9 AddInfo(key string, info string) 10 Dump(logger interface{}) 11 SetElapsedTime(elapsedTime int64) 12 GetElapsedTime() int64 13 } 14 15 func SetInfoObject(e IElapsedTimeInfos) { 16 if e != nil { 17 elapsedInfo = e 18 } 19 } 20 21 var elapsedInfo IElapsedTimeInfos = &EmptyTimeInfo{} 22 23 func GetElapsedInfo() IElapsedTimeInfos { 24 return elapsedInfo 25 } 26 27 type Tracer struct { 28 name string 29 startTime time.Time 30 lastPin string 31 lastPinStartTime time.Time 32 pins []string 33 intervals []time.Duration 34 elapsedTime time.Duration 35 36 pinMap map[string]time.Duration 37 enableSummary bool 38 39 wls *WorkloadStatistic 40 } 41 42 func NewTracer(name string) *Tracer { 43 t := &Tracer{ 44 startTime: time.Now(), 45 name: name, 46 pinMap: make(map[string]time.Duration), 47 } 48 return t 49 } 50 51 func (t *Tracer) EnableSummary() { 52 t.enableSummary = true 53 } 54 55 func (t *Tracer) SetWorkloadStatistic(wls *WorkloadStatistic) { 56 t.wls = wls 57 } 58 59 func (t *Tracer) Pin(format string, args ...interface{}) { 60 t.pinByFormat(fmt.Sprintf(format, args...)) 61 } 62 63 func (t *Tracer) pinByFormat(tag string) { 64 if len(tag) == 0 { 65 //panic("invalid tag") 66 return 67 } 68 69 if len(t.pins) > 100 { 70 // 100 pins limitation 71 return 72 } 73 74 now := time.Now() 75 76 if len(t.lastPin) > 0 { 77 t.pins = append(t.pins, t.lastPin) 78 duration := now.Sub(t.lastPinStartTime) 79 t.intervals = append(t.intervals, duration) 80 if t.enableSummary { 81 insertElapse(t.lastPin, duration.Milliseconds()) 82 } 83 84 if t.wls != nil { 85 t.wls.Add(t.lastPin, now, duration) 86 } 87 } 88 t.lastPinStartTime = now 89 t.lastPin = tag 90 } 91 92 func (t *Tracer) Format() string { 93 if len(t.pins) == 0 { 94 now := time.Now() 95 t.elapsedTime = now.Sub(t.startTime) 96 return fmt.Sprintf("%dms", t.elapsedTime.Milliseconds()) 97 } 98 99 t.Pin("_") 100 101 now := time.Now() 102 t.elapsedTime = now.Sub(t.startTime) 103 info := fmt.Sprintf("%s<%dms>", 104 t.name, 105 t.elapsedTime.Milliseconds(), 106 ) 107 108 for i := range t.pins { 109 info += fmt.Sprintf(", %s<%dms>", t.pins[i], t.intervals[i].Milliseconds()) 110 } 111 return info 112 } 113 114 func (t *Tracer) RepeatingPin(format string, args ...interface{}) { 115 if len(args) == 0 { 116 t.repeatingPinByFormat(format) 117 } else { 118 t.repeatingPinByFormat(fmt.Sprintf(format, args...)) 119 } 120 } 121 122 func (t *Tracer) repeatingPinByFormat(tag string) { 123 if len(tag) == 0 { 124 //panic("invalid tag") 125 return 126 } 127 128 if len(t.pinMap) > 100 { 129 // 100 pins limitation 130 return 131 } 132 133 now := time.Now() 134 135 if len(t.lastPin) > 0 { 136 t.pinMap[t.lastPin] += now.Sub(t.lastPinStartTime) 137 } 138 t.lastPinStartTime = now 139 t.lastPin = tag 140 } 141 142 func (t *Tracer) FormatRepeatingPins(ignoredTags string) string { 143 var info, comma string 144 145 if len(t.pinMap) == 0 { 146 return info 147 } 148 149 t.RepeatingPin("_") 150 151 for tag, interval := range t.pinMap { 152 if tag == ignoredTags { 153 continue 154 } 155 info += fmt.Sprintf("%s%s<%dms>", comma, tag, interval.Milliseconds()) 156 comma = ", " 157 } 158 return info 159 } 160 161 func (t *Tracer) GetElapsedTime() int64 { 162 return t.elapsedTime.Milliseconds() 163 } 164 165 func (t *Tracer) Reset() { 166 t.startTime = time.Now() 167 t.lastPin = "" 168 t.lastPinStartTime = time.Date(2018, 1, 1, 1, 1, 1, 1, time.Local) 169 t.pins = nil 170 t.intervals = nil 171 t.pinMap = make(map[string]time.Duration) 172 } 173 174 type EmptyTimeInfo struct { 175 } 176 177 func (e *EmptyTimeInfo) AddInfo(key string, info string) { 178 } 179 180 func (e *EmptyTimeInfo) Dump(logger interface{}) { 181 } 182 183 func (e *EmptyTimeInfo) SetElapsedTime(elapsedTime int64) { 184 } 185 186 func (e *EmptyTimeInfo) GetElapsedTime() int64 { 187 return 0 188 }