package logrus_sentry import ( "net/http" "github.com/getsentry/raven-go" "github.com/sirupsen/logrus" ) const ( fieldEventID = "event_id" fieldFingerprint = "fingerprint" fieldLogger = "logger" fieldServerName = "server_name" fieldTags = "tags" fieldHTTPRequest = "http_request" fieldUser = "user" ) type dataField struct { data logrus.Fields omitList map[string]struct{} } func newDataField(data logrus.Fields) *dataField { return &dataField{ data: data, omitList: make(map[string]struct{}), } } func (d *dataField) len() int { return len(d.data) } func (d *dataField) isOmit(key string) bool { _, ok := d.omitList[key] return ok } func (d *dataField) getLogger() (string, bool) { if logger, ok := d.data[fieldLogger].(string); ok { d.omitList[fieldLogger] = struct{}{} return logger, true } return "", false } func (d *dataField) getServerName() (string, bool) { if serverName, ok := d.data[fieldServerName].(string); ok { d.omitList[fieldServerName] = struct{}{} return serverName, true } return "", false } func (d *dataField) getTags() (raven.Tags, bool) { if tags, ok := d.data[fieldTags].(raven.Tags); ok { d.omitList[fieldTags] = struct{}{} return tags, true } return nil, false } func (d *dataField) getFingerprint() ([]string, bool) { if fingerprint, ok := d.data[fieldFingerprint].([]string); ok { d.omitList[fieldFingerprint] = struct{}{} return fingerprint, true } return nil, false } func (d *dataField) getError() (error, bool) { if err, ok := d.data[logrus.ErrorKey].(error); ok { d.omitList[logrus.ErrorKey] = struct{}{} return err, true } return nil, false } func (d *dataField) getHTTPRequest() (*raven.Http, bool) { if req, ok := d.data[fieldHTTPRequest].(*http.Request); ok { d.omitList[fieldHTTPRequest] = struct{}{} return raven.NewHttp(req), true } if req, ok := d.data[fieldHTTPRequest].(*raven.Http); ok { d.omitList[fieldHTTPRequest] = struct{}{} return req, true } return nil, false } func (d *dataField) getEventID() (string, bool) { eventID, ok := d.data[fieldEventID].(string) if !ok { return "", false } //verify eventID is 32 characters hexadecimal string (UUID4) uuid := parseUUID(eventID) if uuid == nil { return "", false } d.omitList[fieldEventID] = struct{}{} return uuid.noDashString(), true } func (d *dataField) getUser() (*raven.User, bool) { data := d.data if v, ok := data[fieldUser]; ok { switch val := v.(type) { case *raven.User: d.omitList[fieldUser] = struct{}{} return val, true case raven.User: d.omitList[fieldUser] = struct{}{} return &val, true } } username, _ := data["user_name"].(string) email, _ := data["user_email"].(string) id, _ := data["user_id"].(string) ip, _ := data["user_ip"].(string) if username == "" && email == "" && id == "" && ip == "" { return nil, false } return &raven.User{ ID: id, Username: username, Email: email, IP: ip, }, true }