Recently, golang was used to write a server. The stress testing process found that the response was slow, but because the intermediate operations were serial, it was impossible to know which operation took a lot of time.
At first, we thought of logging. However, a single request is very fast, so I thought of the following solution:
When calling each function, calculate the time consumption of the function, and then use the channel to send the same function call to the same place, and use map for accumulative statistics (here we can take a closer step, for example, you can count the status of each worker or even each service, including the longest request time, shortest request time, and average consumption. If Runtime is added, other running information can be recorded ).
At first, I was thinking about whether there was a static variable similar to C ++. Fortunately, the closure of golang supports stateful behavior, and it is more advanced than static, each call to the closure can get a new local variable entity. Therefore, different results can be obtained for different calls at different points of time.
Directly add the code.
func preReportStatus(funcName string) func(reportType int, input chan<- *RequestProf) {var startTime = time.Now()var reportFunc = funcNamea := func(reportType int, input chan<- *RequestProf) {consumeTime := int64(time.Now().Sub(startTime) / 1000)requestProf := &RequestProf{apiName: reportFunc,consumeTime: consumeTime,invokeTimes: 1,successCount: 0,errorCount: 0,}if reportType == kSuccess {requestProf.successCount = 1} else {requestProf.errorCount = 1}input <- requestProf}return a}var requestProfChan = make(chan *RequestProf,500)var requestProfMap = make(map[string]*RequestProf)func funcA() error {report := preReportStatus("funcA")err := funcB()if err != nil {report(kFail, requestProfChan)return errors.New("funcA error.")}report(kSuccess, requestProfChan)return nil}
A Preliminary Study on golang performance monitoring