(db *sql.DB, w http.ResponseWriter, r *http.Request)
| 22 | } |
| 23 | |
| 24 | func handleExceptionsGrouped(db *sql.DB, w http.ResponseWriter, r *http.Request) { |
| 25 | limit, offset := pagination(r, 50) |
| 26 | q := r.URL.Query() |
| 27 | |
| 28 | query := `SELECT |
| 29 | g.fingerprint, |
| 30 | se.exception_type, |
| 31 | se.exception_value, |
| 32 | g.count, |
| 33 | g.first_seen, |
| 34 | g.last_seen, |
| 35 | g.level, |
| 36 | g.handled, |
| 37 | g.sample_event_id |
| 38 | FROM ( |
| 39 | SELECT |
| 40 | e.fingerprint, |
| 41 | COUNT(*) as count, |
| 42 | MIN(e.received_at) as first_seen, |
| 43 | MAX(e.received_at) as last_seen, |
| 44 | MAX(e.level) as level, |
| 45 | MIN(e.handled) as handled, |
| 46 | MAX(e.event_id) as sample_event_id |
| 47 | FROM sentry_error_events e` |
| 48 | |
| 49 | countQuery := `SELECT COUNT(DISTINCT e.fingerprint) FROM sentry_error_events e` |
| 50 | |
| 51 | var conditions []string |
| 52 | var args []any |
| 53 | |
| 54 | if v := q.Get("level"); v != "" { |
| 55 | conditions = append(conditions, "e.level = ?") |
| 56 | args = append(args, v) |
| 57 | } |
| 58 | if v := q.Get("handled"); v != "" { |
| 59 | if v == "true" { |
| 60 | conditions = append(conditions, "e.handled = 1") |
| 61 | } else { |
| 62 | conditions = append(conditions, "e.handled = 0") |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | where := "" |
| 67 | if len(conditions) > 0 { |
| 68 | where = " WHERE " + strings.Join(conditions, " AND ") |
| 69 | } |
| 70 | |
| 71 | query += where + ` GROUP BY e.fingerprint |
| 72 | ) g |
| 73 | LEFT JOIN sentry_error_events sample_e ON sample_e.event_id = g.sample_event_id |
| 74 | LEFT JOIN sentry_exceptions se ON se.error_event_id = sample_e.id AND se.position = 0 |
| 75 | ORDER BY g.count DESC LIMIT ? OFFSET ?` |
| 76 | countQuery += where |
| 77 | |
| 78 | // Get total. |
| 79 | var total int |
| 80 | db.QueryRow(countQuery, args...).Scan(&total) |
| 81 |
no test coverage detected