func newEvent(err *errors.Error, rawData []interface{}, notifier *Notifier) (*Event, *Configuration) { config := notifier.Config event := &Event{ Error: err, RawData: append(notifier.RawData, rawData...), ErrorClass: err.TypeName(), Message: err.Error(), Stacktrace: make([]stackFrame, len(err.StackFrames())), Severity: SeverityWarning, MetaData: make(MetaData), } for _, datum := range event.RawData { switch datum := datum.(type) { case severity: event.Severity = datum case Context: event.Context = datum.String case Configuration: config = config.merge(&datum) case MetaData: event.MetaData.Update(datum) case User: event.User = &datum case ErrorClass: event.ErrorClass = datum.Name } } for i, frame := range err.StackFrames() { file := frame.File inProject := config.isProjectPackage(frame.Package) // remove $GOROOT and $GOHOME from other frames if idx := strings.Index(file, frame.Package); idx > -1 { file = file[idx:] } if inProject { file = config.stripProjectPackages(file) } event.Stacktrace[i] = stackFrame{ Method: frame.Name, File: file, LineNumber: frame.LineNumber, InProject: inProject, } } return event, config }
func distance(e1, e2 *errors.Error, c, o float64) float64 { c1 := e1.StackFrames() c2 := e2.StackFrames() if len(c1) == 0 { return 1 } if len(c2) == 0 { return 1 } M := make([][]float64, len(c1)+1) for i := range M { M[i] = make([]float64, len(c2)+1) } for i := 1; i <= len(c1); i++ { for j := 1; j <= len(c2); j++ { var x float64 // TODO(dgryski): better 'equality' comparison here if c1[i-1].Name == c2[j-1].Name { x = math.Exp(-c*fmin(i-1, j-1)) * math.Exp(-o*fabs(i-j)) } M[i][j] = fmax3(M[i-1][j-1]+x, M[i-1][j], M[i][j-1]) } } var sig float64 for i := 0; i < min(len(c1), len(c2)); i++ { sig += math.Exp(-c * float64(i)) } res := M[len(c1)][len(c2)] / sig return 1 - res }