internal/listerr/listerr.go
Rama main · réplica de lectura del repositorio original.
package listerr
import (
"errors"
"fmt"
"slices"
"strings"
"sync"
"unicode/utf8"
"github.com/sophotechlabs/spinoza/internal/safe"
)
const (
maxDetails = 3
maxFailureSize = 256
)
type Collector struct {
mu sync.Mutex
attempted map[string]struct{}
failures map[string]string
}
func New() *Collector {
return &Collector{attempted: map[string]struct{}{}, failures: map[string]string{}}
}
func (c *Collector) Record(resource string, err error) {
c.mu.Lock()
defer c.mu.Unlock()
if c.attempted == nil {
c.attempted = map[string]struct{}{}
}
c.attempted[resource] = struct{}{}
if err == nil {
return
}
if c.failures == nil {
c.failures = map[string]string{}
}
c.failures[resource] = shorten(err.Error())
}
func (c *Collector) RecordPanic(resource, what string, caught any) {
if caught == nil {
return
}
safe.Log(what, caught)
c.Record(resource, errors.New("spinoza could not finish reading this resource"))
}
func shorten(message string) string {
if len(message) <= maxFailureSize {
return message
}
end := maxFailureSize - len("...")
for end > 0 && !utf8.RuneStart(message[end]) {
end--
}
return message[:end] + "..."
}
func (c *Collector) Message() string {
c.mu.Lock()
defer c.mu.Unlock()
if len(c.failures) == 0 {
return ""
}
names := make([]string, 0, len(c.failures))
for name := range c.failures {
names = append(names, name)
}
slices.Sort(names)
head := fmt.Sprintf("%d of %d resource types could not be listed", len(names), len(c.attempted))
shown := names
if len(shown) > maxDetails {
shown = shown[:maxDetails]
}
details := make([]string, 0, len(shown))
for _, name := range shown {
details = append(details, fmt.Sprintf("%s (%s)", name, c.failures[name]))
}
message := head + ": " + strings.Join(details, "; ")
remaining := len(names) - len(shown)
if remaining > 0 {
message += fmt.Sprintf("; and %d more", remaining)
}
return message
}