Fix 'vouch_attestation_process_duration_seconds'.

This metric used to count the number of internal attestation processes
carried out, however a single attestation process can involve multiple
validators if they are attesting in the same slot and committee.  This
fix ensures that the metrics reflect the number of attestations, not the
number of processes.
This commit is contained in:
Jim McDonald 2020-12-16 14:05:11 +00:00
parent 4071dabf9e
commit ad1495bae6
No known key found for this signature in database
GPG Key ID: 89CEB61B2AD2A5E7
5 changed files with 20 additions and 14 deletions

View File

@ -1,4 +1,5 @@
Development:
- metric 'vouch_attestation_process_duration_seconds' now counts multiple attestations correctly
- re-implement accountmanager metrics
1.0.2:
- avoid crash in "best" attestationdata strategy

View File

@ -85,7 +85,7 @@ func (s *Service) Attest(ctx context.Context, data interface{}) ([]*spec.Attesta
duty, ok := data.(*attester.Duty)
if !ok {
s.monitor.AttestationCompleted(started, "failed")
s.monitor.AttestationsCompleted(started, len(duty.ValidatorIndices()), "failed")
return nil, errors.New("passed invalid data structure")
}
uints := make([]uint64, len(duty.ValidatorIndices()))
@ -97,28 +97,28 @@ func (s *Service) Attest(ctx context.Context, data interface{}) ([]*spec.Attesta
// Fetch the attestation data.
attestationData, err := s.attestationDataProvider.AttestationData(ctx, duty.Slot(), duty.CommitteeIndices()[0])
if err != nil {
s.monitor.AttestationCompleted(started, "failed")
s.monitor.AttestationsCompleted(started, len(duty.ValidatorIndices()), "failed")
return nil, errors.Wrap(err, "failed to obtain attestation data")
}
log.Trace().Dur("elapsed", time.Since(started)).Msg("Obtained attestation data")
if attestationData.Slot != duty.Slot() {
s.monitor.AttestationCompleted(started, "failed")
s.monitor.AttestationsCompleted(started, len(duty.ValidatorIndices()), "failed")
return nil, fmt.Errorf("attestation request for slot %d returned data for slot %d", duty.Slot(), attestationData.Slot)
}
if attestationData.Source.Epoch > attestationData.Target.Epoch {
s.monitor.AttestationCompleted(started, "failed")
s.monitor.AttestationsCompleted(started, len(duty.ValidatorIndices()), "failed")
return nil, fmt.Errorf("attestation request for slot %d returned source epoch %d greater than target epoch %d", duty.Slot(), attestationData.Source.Epoch, attestationData.Target.Epoch)
}
if attestationData.Target.Epoch > spec.Epoch(uint64(duty.Slot())/s.slotsPerEpoch) {
s.monitor.AttestationCompleted(started, "failed")
s.monitor.AttestationsCompleted(started, len(duty.ValidatorIndices()), "failed")
return nil, fmt.Errorf("attestation request for slot %d returned target epoch %d greater than current epoch %d", duty.Slot(), attestationData.Target.Epoch, spec.Epoch(uint64(duty.Slot())/s.slotsPerEpoch))
}
// Fetch the validating accounts.
validatingAccounts, err := s.validatingAccountsProvider.ValidatingAccountsForEpochByIndex(ctx, spec.Epoch(uint64(duty.Slot())/s.slotsPerEpoch), duty.ValidatorIndices())
if err != nil {
s.monitor.AttestationCompleted(started, "failed")
s.monitor.AttestationsCompleted(started, len(duty.ValidatorIndices()), "failed")
return nil, errors.New("failed to obtain attesting validator accounts")
}
log.Trace().Dur("elapsed", time.Since(started)).Msg("Obtained validating accounts")
@ -158,6 +158,7 @@ func (s *Service) Attest(ctx context.Context, data interface{}) ([]*spec.Attesta
)
if err != nil {
log.Error().Err(err).Msg("Failed to attest")
s.monitor.AttestationsCompleted(started, len(duty.ValidatorIndices()), "failed")
}
return attestations, nil
@ -234,6 +235,7 @@ func (s *Service) attest(
log.Warn().Err(err).Msg("Failed to submit attestations")
}
log.Trace().Dur("elapsed", time.Since(started)).Msg("Submitted attestations")
s.monitor.AttestationsCompleted(started, len(duty.ValidatorIndices()), "succeeded")
return attestations, nil
}

View File

@ -48,8 +48,8 @@ func (s *Service) BlockDelay(delay time.Duration) {}
// BeaconBlockProposalCompleted is called when a block proposal process has completed.
func (s *Service) BeaconBlockProposalCompleted(started time.Time, result string) {}
// AttestationCompleted is called when a block attestation process has completed.
func (s *Service) AttestationCompleted(started time.Time, result string) {}
// AttestationsCompleted is called when an attestation process has completed.
func (s *Service) AttestationsCompleted(started time.Time, count int, result string) {}
// AttestationAggregationCompleted is called when an attestation aggregation process has completed.
func (s *Service) AttestationAggregationCompleted(started time.Time, result string) {}

View File

@ -48,8 +48,11 @@ func (s *Service) setupAttestationMetrics() error {
return nil
}
// AttestationCompleted is called when a block attestation process has completed.
func (s *Service) AttestationCompleted(started time.Time, result string) {
s.attestationProcessTimer.Observe(time.Since(started).Seconds())
s.attestationProcessRequests.WithLabelValues(result).Inc()
// AttestationsCompleted is called when an attestation process has completed.
func (s *Service) AttestationsCompleted(started time.Time, count int, result string) {
duration := time.Since(started).Seconds()
for i := 0; i < count; i++ {
s.attestationProcessTimer.Observe(duration)
}
s.attestationProcessRequests.WithLabelValues(result).Add(float64(count))
}

View File

@ -47,8 +47,8 @@ type BeaconBlockProposalMonitor interface {
// AttestationMonitor provides methods to monitor the attestation process.
type AttestationMonitor interface {
// AttestationsCompleted is called when a attestation process has completed.
AttestationCompleted(started time.Time, result string)
// AttestationsCompleted is called when an attestation process has completed.
AttestationsCompleted(started time.Time, count int, result string)
}
// AttestationAggregationMonitor provides methods to monitor the attestation aggregation process.