Keepers ff6c1eaf8d
adds purely informational alerts to the fault bus (#4434)
Adds a new type of entry to the fault bus: Alerts. These values are for non-erroneous messages that we want 1/ clearly displayed to the user at the end of an operation and 2/ persisted with the backup for later review.

---

#### Does this PR need a docs update or release note?

- [x]  No

#### Type of change

- [x] 🌻 Feature

#### Issue(s)

* #4264

#### Test Plan

- [x]  Unit test
2023-10-09 21:57:36 +00:00

81 lines
1.9 KiB
Go

package operations
import (
"context"
"fmt"
"github.com/alcionai/clues"
"github.com/alcionai/corso/src/pkg/control"
"github.com/alcionai/corso/src/pkg/fault"
"github.com/alcionai/corso/src/pkg/logger"
)
// finalizeErrorHandling ensures the operation follows the
// failure policy requirements.
func finalizeErrorHandling(
ctx context.Context,
opts control.Options,
errs *fault.Bus,
prefix string,
) {
rcvd := errs.Recovered()
// under certain conditions, there's nothing else left to do
if opts.FailureHandling == control.BestEffort ||
errs.Failure() != nil ||
len(rcvd) == 0 {
return
}
if opts.FailureHandling == control.FailAfterRecovery {
msg := fmt.Sprintf("%s: partial success: %d errors occurred", prefix, len(rcvd))
logger.Ctx(ctx).Error(msg)
if len(rcvd) == 1 {
errs.Fail(rcvd[0])
return
}
errs.Fail(clues.New(msg))
}
}
// LogFaultErrors is a helper function that logs all entries in the Errors struct.
func LogFaultErrors(ctx context.Context, fe *fault.Errors, prefix string) {
if fe == nil {
return
}
var (
log = logger.Ctx(ctx)
pfxMsg = prefix + ":"
li, ls, lr, la = len(fe.Items), len(fe.Skipped), len(fe.Recovered), len(fe.Alerts)
)
if fe.Failure == nil && li+ls+lr == 0 {
log.Info(pfxMsg + " no issues")
return
}
if fe.Failure != nil {
log.With("error", fe.Failure).Errorf("%s primary failure: %s", pfxMsg, fe.Failure.Msg)
}
for i, item := range fe.Items {
log.With("failed_item", item).Errorf("%s item failure %d of %d: %s", pfxMsg, i+1, li, item.Cause)
}
for i, item := range fe.Skipped {
log.With("skipped_item", item).Errorf("%s skipped item %d of %d: %s", pfxMsg, i+1, ls, item.Item.Cause)
}
for i, err := range fe.Recovered {
log.With("recovered_error", err).Errorf("%s recoverable error %d of %d: %s", pfxMsg, i+1, lr, err.Msg)
}
for i, alert := range fe.Alerts {
log.With("alert", alert).Infof("%s alert %d of %d: %s", pfxMsg, i+1, la, alert.Message)
}
}