// Forks and re-runs your program to add panic monitoring. This function does // not return on one process, instead listening on stderr of the other process, // which returns nil. // // Related: https://godoc.org/github.com/bugsnag/panicwrap#BasicMonitor func defaultPanicHandler() { defer defaultNotifier.dontPanic() err := panicwrap.BasicMonitor(func(output string) { toNotify, err := errors.ParsePanic(output) if err != nil { defaultNotifier.Config.logf("bugsnag.handleUncaughtPanic: %v", err) } Notify(toNotify, SeverityError, Configuration{Synchronous: true}) }) if err != nil { defaultNotifier.Config.logf("bugsnag.handleUncaughtPanic: %v", err) } }
func main() { dir := flag.String("d", ".", "directory containing stack traces") flag.Parse() files, err := filepath.Glob(*dir + "/*") if err != nil { log.Fatalf("error globbing: %v\n", err) } var errs []*berrors.Error var fnames []string for _, f := range files { r, err := ioutil.ReadFile(f) if err != nil { log.Printf("error reading %s: %v\n", f, err) continue } e, err := berrors.ParsePanic(string(r)) if err != nil { log.Printf("error parsing panic %s: %v\n", f, err) continue } errs = append(errs, e) fnames = append(fnames, f) } // TODO(dgryski): I made up these numbers. They "should" be computed // from a human tagged corpus via algorithm 6 in // http://research.microsoft.com/en-us/groups/sa/rebucket-icse2012.pdf groups := rebucket.ClusterErrors(errs, 1, 1, 1) fmt.Printf("groups=%v\n", groups) for i, g := range groups { fmt.Println("cluster", i) for _, idx := range g.Idx { fmt.Println("\t", fnames[idx]) } fmt.Println() } }