(db *sql.DB)
| 7 | ) |
| 8 | |
| 9 | func handleServiceMap(db *sql.DB) http.HandlerFunc { |
| 10 | return func(w http.ResponseWriter, r *http.Request) { |
| 11 | windowMinutes := 60 |
| 12 | if v := r.URL.Query().Get("window"); v != "" { |
| 13 | if n, err := strconv.Atoi(v); err == nil && n > 0 && n <= 10080 { |
| 14 | windowMinutes = n |
| 15 | } |
| 16 | } |
| 17 | |
| 18 | // Build edges from spans with peer_address. |
| 19 | edgeRows, err := db.Query( |
| 20 | `SELECT |
| 21 | COALESCE(service_name, 'unknown') as source, |
| 22 | peer_address as target, |
| 23 | peer_type as op_type, |
| 24 | COUNT(*) as request_count, |
| 25 | SUM(CASE WHEN is_error = 1 THEN 1 ELSE 0 END) as error_count, |
| 26 | CAST(AVG(duration_ms) AS INTEGER) as avg_duration_ms |
| 27 | FROM sentry_spans |
| 28 | WHERE peer_address IS NOT NULL |
| 29 | AND start_ts >= datetime('now', ? || ' minutes') |
| 30 | GROUP BY source, target, op_type |
| 31 | ORDER BY request_count DESC`, |
| 32 | strconv.Itoa(-windowMinutes), |
| 33 | ) |
| 34 | if err != nil { |
| 35 | apiError(w, err.Error(), http.StatusInternalServerError) |
| 36 | return |
| 37 | } |
| 38 | defer edgeRows.Close() |
| 39 | |
| 40 | nodeMap := make(map[string]*serviceNode) |
| 41 | var edges []map[string]any |
| 42 | |
| 43 | for edgeRows.Next() { |
| 44 | var ( |
| 45 | source, target, opType string |
| 46 | requestCount, errorCount int |
| 47 | avgDuration sql.NullInt64 |
| 48 | ) |
| 49 | if err := edgeRows.Scan(&source, &target, &opType, &requestCount, &errorCount, &avgDuration); err != nil { |
| 50 | continue |
| 51 | } |
| 52 | |
| 53 | edges = append(edges, map[string]any{ |
| 54 | "source": source, |
| 55 | "target": target, |
| 56 | "op_type": opType, |
| 57 | "request_count": requestCount, |
| 58 | "error_count": errorCount, |
| 59 | "avg_duration_ms": scanNullInt(avgDuration), |
| 60 | }) |
| 61 | |
| 62 | // Accumulate node stats. |
| 63 | if _, ok := nodeMap[source]; !ok { |
| 64 | nodeMap[source] = &serviceNode{ID: source, Label: source} |
| 65 | } |
| 66 | nodeMap[source].RequestCount += requestCount |
no test coverage detected