Ctrl K
ComunidadGuías…

internal/listerr/listerr.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
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
}