X-Git-Url: http://git.osdn.net/view?p=bytom%2Fvapor.git;a=blobdiff_plain;f=toolbar%2Fmeasure%2Fmethod.go;fp=toolbar%2Fmeasure%2Fmethod.go;h=dbb3b63d3b62b296c78e0ddef4311665654a22c5;hp=0000000000000000000000000000000000000000;hb=36ed0fa1af1b068729a5bd88f663fedee5854295;hpb=f0a522057a65acf27966e5bbc48b5d6a7392587e diff --git a/toolbar/measure/method.go b/toolbar/measure/method.go new file mode 100644 index 00000000..dbb3b63d --- /dev/null +++ b/toolbar/measure/method.go @@ -0,0 +1,83 @@ +package measure + +import ( + "fmt" + "runtime/debug" + "strings" + "sync" + + log "github.com/sirupsen/logrus" +) + +const ( + logModule = "measure" +) + +var store sync.Map + +// Start trigger record of stack trace run time record as a graph view +func Start() { + routineID, stacks, err := traceStacks() + if err != nil { + log.WithFields(log.Fields{"module": logModule, "err": err}).Error("fail on measure get stacks") + return + } + + data, ok := store.Load(routineID) + if !ok { + store.Store(routineID, NewTimer(stacks[0])) + return + } + + if err := data.(*Timer).StartTimer(stacks); err != nil { + log.WithFields(log.Fields{"module": logModule, "err": err, "routine": routineID, "stack": stacks}).Error("fail on start timer") + } +} + +// End end the stack trace run time +func End() { + routineID, stacks, err := traceStacks() + if err != nil { + log.WithFields(log.Fields{"module": logModule, "err": err}).Error("fail on measure get stacks") + return + } + + data, ok := store.Load(routineID) + if !ok { + log.WithFields(log.Fields{"module": logModule, "err": err}).Error("fail on measure timer by routine ID") + return + } + + rootTimer := data.(*Timer) + if err := rootTimer.EndTimer(stacks); err != nil { + log.WithFields(log.Fields{"module": logModule, "err": err, "routine": routineID, "stack": stacks}).Error("fail on end timer") + } + + if rootTimer.IsEnd() { + log.WithField("module", logModule).Info(rootTimer.String()) + store.Delete(routineID) + } +} + +func traceStacks() (string, []string, error) { + stacks := []string{} + for _, stack := range strings.Split(string(debug.Stack()), "\n") { + // skip the file path stack + if strings.HasPrefix(stack, " ") { + continue + } + + // delete the func memory address stuff + if subPos := strings.LastIndexAny(stack, "("); subPos > 0 { + stacks = append(stacks, stack[:subPos]) + } else { + stacks = append(stacks, stack) + } + } + + if len(stacks) < 4 { + return "", nil, fmt.Errorf("fail to decode stack") + } + + return stacks[0], stacks[4:], nil +}