diff --git a/handlers/dashboard.go b/handlers/dashboard.go index a4a2a69c01..2a192ce325 100644 --- a/handlers/dashboard.go +++ b/handlers/dashboard.go @@ -35,7 +35,7 @@ func handleValidatorsQuery(w http.ResponseWriter, r *http.Request, checkValidato q := r.URL.Query() validatorLimit := getUserPremium(r).MaxValidators - fieldMap := map[string]interface{}{"route": r.URL.String()} + errFieldMap := map[string]interface{}{"route": r.URL.String()} // Parse all the validator indices and pubkeys from the query string queryValidatorIndices, queryValidatorPubkeys, err := parseValidatorsFromQueryString(q.Get("validators"), validatorLimit) @@ -48,7 +48,7 @@ func handleValidatorsQuery(w http.ResponseWriter, r *http.Request, checkValidato // Check whether pubkeys can be converted to indices and redirect if necessary redirect, err := updateValidatorsQueryString(w, r, queryValidatorIndices, queryValidatorPubkeys) if err != nil { - utils.LogError(err, fmt.Errorf("error finding validators in database for dashboard query update"), 0, fieldMap) + utils.LogError(err, fmt.Errorf("error finding validators in database for dashboard query update"), 0, errFieldMap) http.Error(w, "Not found", http.StatusNotFound) return nil, nil, false, err } @@ -243,15 +243,17 @@ func Heatmap(w http.ResponseWriter, r *http.Request) { } heatmapData.Epochs = epochs + errFieldMap := map[string]interface{}{"route": r.URL.String()} + start := time.Now() if len(validators) == 0 { - logger.WithError(err).WithField("route", r.URL.String()).Error("error no validators provided") + utils.LogError(err, "error no validators provided", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } incomeData, err := db.BigtableClient.GetValidatorIncomeDetailsHistory(validators, endEpoch-100, endEpoch) if err != nil { - logger.WithError(err).WithField("route", r.URL.String()).Error("error loading validator income history data") + utils.LogError(err, "error loading validator income history data", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } @@ -462,6 +464,7 @@ func DashboardDataBalanceCombined(w http.ResponseWriter, r *http.Request) { } currency := GetCurrency(r) + errFieldMap := map[string]interface{}{"route": r.URL.String()} w.Header().Set("Content-Type", "application/json") @@ -480,17 +483,23 @@ func DashboardDataBalanceCombined(w http.ResponseWriter, r *http.Request) { var executionChartData []*types.ChartDataPoint g.Go(func() error { incomeHistoryChartData, err = db.GetValidatorIncomeHistoryChart(queryValidatorIndices, currency, services.LatestFinalizedEpoch(), lowerBoundDay) - return err + if err != nil { + return fmt.Errorf("error in GetValidatorIncomeHistoryChart: %w", err) + } + return nil }) g.Go(func() error { executionChartData, err = getExecutionChartData(queryValidatorIndices, currency, lowerBoundDay) - return err + if err != nil { + return fmt.Errorf("error in getExecutionChartData: %w", err) + } + return nil }) err = g.Wait() if err != nil { - logger.Errorf("combined balance chart %v", err) + utils.LogError(err, "error while combining balance chart", 0, errFieldMap) sendErrorResponse(w, r.URL.String(), err.Error()) return } @@ -504,7 +513,7 @@ func DashboardDataBalanceCombined(w http.ResponseWriter, r *http.Request) { err = json.NewEncoder(w).Encode(response) if err != nil { - logger.WithError(err).WithField("route", r.URL.String()).Error("error enconding json response") + utils.LogError(err, "error enconding json response", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } @@ -513,6 +522,7 @@ func DashboardDataBalanceCombined(w http.ResponseWriter, r *http.Request) { // DashboardDataBalance retrieves the income history of a set of validators func DashboardDataBalance(w http.ResponseWriter, r *http.Request) { currency := GetCurrency(r) + errFieldMap := map[string]interface{}{"route": r.URL.String()} w.Header().Set("Content-Type", "application/json") @@ -520,7 +530,7 @@ func DashboardDataBalance(w http.ResponseWriter, r *http.Request) { validatorLimit := getUserPremium(r).MaxValidators queryValidatorIndices, queryValidatorPubkeys, err := parseValidatorsFromQueryString(q.Get("validators"), validatorLimit) if err != nil || len(queryValidatorPubkeys) > 0 { - utils.LogError(err, fmt.Errorf("error parsing validators from query string"), 0) + utils.LogError(err, "error parsing validators from query string", 0, errFieldMap) http.Error(w, "Invalid query", http.StatusBadRequest) return } @@ -531,14 +541,14 @@ func DashboardDataBalance(w http.ResponseWriter, r *http.Request) { incomeHistoryChartData, err := db.GetValidatorIncomeHistoryChart(queryValidatorIndices, currency, services.LatestFinalizedEpoch(), 0) if err != nil { - logger.Errorf("failed to genereate income history chart data for dashboard view: %v", err) + utils.LogError(err, "failed to genereate income history chart data for dashboard view", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusInternalServerError) return } err = json.NewEncoder(w).Encode(incomeHistoryChartData) if err != nil { - logger.WithError(err).WithField("route", r.URL.String()).Error("error enconding json response") + utils.LogError(err, "error enconding json response", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } @@ -559,13 +569,15 @@ func DashboardDataProposals(w http.ResponseWriter, r *http.Request) { Status uint64 }{} + errFieldMap := map[string]interface{}{"route": r.URL.String()} + err = db.ReaderDb.Select(&proposals, ` SELECT slot, status FROM blocks WHERE proposer = ANY($1) ORDER BY slot`, filter) if err != nil { - logger.WithError(err).WithField("route", r.URL.String()).Error("error retrieving block-proposals") + utils.LogError(err, "error retrieving block-proposals", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } @@ -580,7 +592,7 @@ func DashboardDataProposals(w http.ResponseWriter, r *http.Request) { err = json.NewEncoder(w).Encode(proposalsResult) if err != nil { - logger.WithError(err).WithField("route", r.URL.String()).Error("error enconding json response") + utils.LogError(err, "error enconding json response", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } @@ -629,16 +641,18 @@ func DashboardDataWithdrawals(w http.ResponseWriter, r *http.Request) { length := uint64(10) + errFieldMap := map[string]interface{}{"route": r.URL.String()} + withdrawalCount, err := db.GetTotalWithdrawalsCount(validatorIndices) if err != nil { - utils.LogError(err, fmt.Errorf("error retrieving dashboard validator withdrawals count: %v", err), 0) + utils.LogError(err, "error retrieving dashboard validator withdrawals count", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusInternalServerError) return } withdrawals, err := db.GetDashboardWithdrawals(validatorIndices, length, start, orderBy, orderDir) if err != nil { - utils.LogError(err, fmt.Errorf("error retrieving validator withdrawals: %v", err), 0) + utils.LogError(err, "error retrieving validator withdrawals", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -648,7 +662,7 @@ func DashboardDataWithdrawals(w http.ResponseWriter, r *http.Request) { // check if there is a NextWithdrawal and append NextWithdrawalRow, err := getNextWithdrawalRow(validatorIndices) if err != nil { - logger.WithError(err).WithField("route", r.URL.String()).Error("error calculating next withdrawal row") + utils.LogError(err, "error calculating next withdrawal row", 0, errFieldMap) tableData = make([][]interface{}, 0, len(withdrawals)) } else { if NextWithdrawalRow == nil { @@ -680,7 +694,7 @@ func DashboardDataWithdrawals(w http.ResponseWriter, r *http.Request) { err = json.NewEncoder(w).Encode(data) if err != nil { - utils.LogError(err, fmt.Errorf("error enconding json response for %v route: %v", r.URL.String(), err), 0) + utils.LogError(err, "error enconding json response", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -696,6 +710,8 @@ func DashboardDataValidators(w http.ResponseWriter, r *http.Request) { return } + errFieldMap := map[string]interface{}{"route": r.URL.String()} + filter := pq.Array(validatorIndexArr) validatorLimit := getUserPremium(r).MaxValidators @@ -721,7 +737,7 @@ func DashboardDataValidators(w http.ResponseWriter, r *http.Request) { LIMIT $2`, filter, validatorLimit) if err != nil { - logger.WithError(err).WithField("route", r.URL.String()).Errorf("error retrieving validator data") + utils.LogError(err, "error retrieving validator data", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } @@ -743,7 +759,7 @@ func DashboardDataValidators(w http.ResponseWriter, r *http.Request) { FROM eth1_deposits WHERE publickey = ANY($1)`, pubkeyFilter) if err != nil { - logger.WithError(err).WithField("route", r.URL.String()).Errorf("error retrieving validator deposists") + utils.LogError(err, "error retrieving validator deposists", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } @@ -765,7 +781,7 @@ func DashboardDataValidators(w http.ResponseWriter, r *http.Request) { if len(validatorIndexArr) > 0 { balances, err := db.BigtableClient.GetValidatorBalanceHistory(validatorIndexArr, latestEpoch, latestEpoch) if err != nil { - logger.WithError(err).WithField("route", r.URL.String()).Errorf("error retrieving validator balance data") + utils.LogError(err, "error retrieving validator balance data", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } @@ -784,7 +800,7 @@ func DashboardDataValidators(w http.ResponseWriter, r *http.Request) { lastAttestationSlots, err := db.BigtableClient.GetLastAttestationSlots(validatorIndexArr) if err != nil { - logger.WithError(err).WithField("route", r.URL.String()).Errorf("error retrieving validator last attestation slot data") + utils.LogError(err, "error retrieving validator last attestation slot data", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } @@ -822,7 +838,7 @@ func DashboardDataValidators(w http.ResponseWriter, r *http.Request) { if v.ActivationEpoch > 100_000_000 { queueAhead, err = db.GetQueueAheadOfValidator(v.ValidatorIndex) if err != nil { - logger.WithError(err).Errorf("failed to retrieve queue ahead of validator %v for dashboard", v.ValidatorIndex) + utils.LogError(err, fmt.Sprintf("failed to retrieve queue ahead of validator %v for dashboard", v.ValidatorIndex), 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } @@ -916,7 +932,7 @@ func DashboardDataValidators(w http.ResponseWriter, r *http.Request) { err = json.NewEncoder(w).Encode(data) if err != nil { - logger.WithError(err).WithField("route", r.URL.String()).Errorf("error enconding json response") + utils.LogError(err, "error enconding json response", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } @@ -925,6 +941,8 @@ func DashboardDataValidators(w http.ResponseWriter, r *http.Request) { func DashboardDataEarnings(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") + errFieldMap := map[string]interface{}{"route": r.URL.String()} + queryValidatorIndices, _, redirect, err := handleValidatorsQuery(w, r, true) if err != nil || redirect { return @@ -932,7 +950,7 @@ func DashboardDataEarnings(w http.ResponseWriter, r *http.Request) { earnings, _, err := GetValidatorEarnings(queryValidatorIndices, GetCurrency(r)) if err != nil { - logger.WithError(err).WithField("route", r.URL.String()).Errorf("error retrieving validator earnings") + utils.LogError(err, "error retrieving validator earnings", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) } @@ -942,7 +960,7 @@ func DashboardDataEarnings(w http.ResponseWriter, r *http.Request) { err = json.NewEncoder(w).Encode(earnings) if err != nil { - logger.WithError(err).WithField("route", r.URL.String()).Errorf("error enconding json response") + utils.LogError(err, "error enconding json response", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } @@ -956,6 +974,8 @@ func DashboardDataEffectiveness(w http.ResponseWriter, r *http.Request) { return } + errFieldMap := map[string]interface{}{"route": r.URL.String()} + filter := pq.Array(filterArr) var activeValidators []uint64 @@ -963,7 +983,7 @@ func DashboardDataEffectiveness(w http.ResponseWriter, r *http.Request) { SELECT validatorindex FROM validators where validatorindex = ANY($1) and activationepoch < $2 AND exitepoch > $2 `, filter, services.LatestEpoch()) if err != nil { - logger.Errorf("error retrieving active validators") + utils.LogError(err, "error retrieving active validators", 0, errFieldMap) } if len(activeValidators) == 0 { @@ -979,18 +999,19 @@ func DashboardDataEffectiveness(w http.ResponseWriter, r *http.Request) { } effectiveness, err := db.BigtableClient.GetValidatorEffectiveness(activeValidators, epoch) - for _, e := range effectiveness { - avgIncDistance = append(avgIncDistance, e.AttestationEfficiency) - } if err != nil { - logger.Errorf("error retrieving AverageAttestationInclusionDistance: %v", err) + utils.LogError(err, "error retrieving validator effectiveness", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } + for _, e := range effectiveness { + avgIncDistance = append(avgIncDistance, e.AttestationEfficiency) + } + err = json.NewEncoder(w).Encode(avgIncDistance) if err != nil { - logger.Errorf("error enconding json response for %v route: %v", r.URL.String(), err) + utils.LogError(err, "error enconding json response", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } @@ -1004,6 +1025,8 @@ func DashboardDataProposalsHistory(w http.ResponseWriter, r *http.Request) { return } + errFieldMap := map[string]interface{}{"route": r.URL.String()} + filter := pq.Array(filterArr) proposals := []struct { @@ -1021,14 +1044,14 @@ func DashboardDataProposalsHistory(w http.ResponseWriter, r *http.Request) { WHERE validatorindex = ANY($1) AND (proposed_blocks IS NOT NULL OR missed_blocks IS NOT NULL OR orphaned_blocks IS NOT NULL) ORDER BY day DESC`, filter) if err != nil { - logger.WithError(err).WithField("route", r.URL.String()).Error("error retrieving validator_stats") + utils.LogError(err, "error retrieving validator_stats", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } lastDay, err := db.GetLastExportedStatisticDay() if err != nil && err != db.ErrNoStats { - logger.WithError(err).WithField("route", r.URL.String()).Error("error retrieving last exported statistic day") + utils.LogError(err, "error retrieving last exported statistic day", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } @@ -1044,7 +1067,7 @@ func DashboardDataProposalsHistory(w http.ResponseWriter, r *http.Request) { WHERE proposer = ANY($1) AND epoch > $2 group by proposer`, filter, lastExportedEpoch) if err != nil { - logger.WithError(err).WithField("route", r.URL.String()).Error("error retrieving validator_stats") + utils.LogError(err, "error retrieving validator_stats", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } @@ -1078,7 +1101,7 @@ func DashboardDataProposalsHistory(w http.ResponseWriter, r *http.Request) { err = json.NewEncoder(w).Encode(proposalsHistResult) if err != nil { - logger.WithError(err).WithField("route", r.URL.String()).Error("error enconding json response") + utils.LogError(err, "error enconding json response", 0, errFieldMap) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return }