github.com/oinume/lekcije@v0.0.0-20231017100347-5b4c5eb6ab24/backend/infrastructure/rollbar/repository.go (about) 1 package rollbar 2 3 import ( 4 "context" 5 "runtime" 6 7 pkg_errors "github.com/pkg/errors" 8 "github.com/rollbar/rollbar-go" 9 10 "github.com/oinume/lekcije/backend/domain/repository" 11 "github.com/oinume/lekcije/backend/errors" 12 ) 13 14 type errorRecorderRepository struct { 15 client Client 16 } 17 18 func NewErrorRecorderRepository(client Client) repository.ErrorRecorder { 19 client.SetStackTracer(StackTracer) 20 return &errorRecorderRepository{ 21 client: client, 22 } 23 } 24 25 func (r *errorRecorderRepository) Record(ctx context.Context, err error, userID string) { 26 if userID != "" { 27 ctx = rollbar.NewPersonContext(ctx, &rollbar.Person{ 28 Id: userID, 29 }) 30 } 31 r.client.ErrorWithStackSkipWithExtrasAndContext(ctx, "error", err, 0, nil) 32 } 33 34 func StackTracer(err error) ([]runtime.Frame, bool) { 35 switch e := err.(type) { 36 case *errors.AnnotatedError: 37 if !e.OutputStackTrace() { 38 return nil, false 39 } 40 return toFrames(e.StackTrace()), true 41 case errors.StackTracer: 42 return toFrames(e.StackTrace()), true 43 default: 44 return nil, false 45 } 46 } 47 48 func toFrames(st pkg_errors.StackTrace) []runtime.Frame { 49 frames := make([]runtime.Frame, 0, len(st)) 50 for _, f := range st { 51 pc := uintptr(f) 52 fn := runtime.FuncForPC(pc) 53 file, line := fn.FileLine(pc) 54 frame := runtime.Frame{ 55 PC: pc, 56 Func: fn, 57 Function: fn.Name(), 58 File: file, 59 Line: line, 60 } 61 frames = append(frames, frame) 62 } 63 return frames 64 }