diff --git a/worker/alerts.go b/worker/alerts.go index fd3657e05..5ab5092b7 100644 --- a/worker/alerts.go +++ b/worker/alerts.go @@ -1,6 +1,7 @@ package worker import ( + "errors" "time" "go.sia.tech/core/types" @@ -49,6 +50,18 @@ func newUploadFailedAlert(bucket, path, contractSet, mimeType string, minShards, data["multipart"] = true } + hostErr := err + for errors.Unwrap(hostErr) != nil { + hostErr = errors.Unwrap(hostErr) + } + if set, ok := hostErr.(HostErrorSet); ok { + hostErrors := make(map[string]string, len(set)) + for hk, err := range set { + hostErrors[hk.String()] = err.Error() + } + data["hosts"] = hostErrors + } + return alerts.Alert{ ID: randomAlertID(), Severity: alerts.SeverityError, diff --git a/worker/alerts_test.go b/worker/alerts_test.go new file mode 100644 index 000000000..137838a39 --- /dev/null +++ b/worker/alerts_test.go @@ -0,0 +1,48 @@ +package worker + +import ( + "errors" + "fmt" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "go.sia.tech/core/types" + "go.sia.tech/renterd/alerts" +) + +// TestUploadFailedAlertErrorSet is a test to verify that an upload failing with a HostErrorSet error registers an alert with all the individual errors of any host in the payload. +func TestUploadFailedAlertErrorSet(t *testing.T) { + hostErrSet := HostErrorSet{ + types.PublicKey{1, 1, 1}: errors.New("test"), + } + wrapped := fmt.Errorf("wrapped error: %w", hostErrSet) + + alert := newUploadFailedAlert("bucket", "path", "set", "mimeType", 1, 2, 3, true, false, wrapped) + + alert.ID = types.Hash256{1, 2, 3} + alert.Timestamp = time.Time{} + + expectedAlert := alerts.Alert{ + ID: types.Hash256{1, 2, 3}, + Severity: alerts.SeverityError, + Message: "Upload failed", + Data: map[string]any{ + "bucket": "bucket", + "contractSet": "set", + "contracts": 3, + "error": wrapped.Error(), + "hosts": map[string]string{ + types.PublicKey{1, 1, 1}.String(): "test", + }, + "mimeType": "mimeType", + "minShards": 1, + "packing": true, + "path": "path", + "totalShards": 2, + }, + } + if !cmp.Equal(alert, expectedAlert) { + t.Fatal(cmp.Diff(alert, expectedAlert)) + } +}