You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
5.1 KiB

# 🧠 **errs: Gestión de Errores Estructurada para Go**
*Parte del núcleo de Active-Go Core*
`errs` es un módulo esencial de la librería core de Active-Go, diseñado para modernizar y enriquecer el manejo de errores en Go, especialmente en sistemas distribuidos y arquitecturas de microservicios. Proporciona una estructura robusta que permite **clasificar**, **componer** y **contextualizar** los errores de forma precisa y eficaz.
---
## 🚀 Filosofía
La motivación detrás de `errs` surge de nuestra experiencia en ActiveThing.com enfrentando la complejidad de sistemas reales. Go proporciona un tipo `error` simple, pero limitado. `errs` expande este modelo con:
### ✅ Clasificación Estructurada
* Define jerarquías de errores (`modulo::clase.subclase`) para evitar comparaciones de strings frágiles.
* Permite identificar errores como `auth::invalid_token` o `db::not_found.user` y aplicar lógicas según su clase o módulo.
### 🧩 Composición y Contexto
* Usa el patrón de **composición** para añadir metadatos sin alterar la clase del error.
* Agrega mensajes, códigos, causas, stack traces, fechas, trazabilidad, etc.
### 🌐 Trazabilidad en Microservicios
* Unifica el lenguaje de errores entre servicios.
* Los errores conservan su contexto a lo largo de la cadena (auth → pedidos → API Gateway).
### 🔍 Visibilidad para Operaciones
* Logs ricos con jerarquías, metadatos y stack traces.
* Salida formateada para mejorar la observabilidad.
### 🧱 Inmutabilidad y Predictibilidad
* Los errores compuestos son inmutables.
* Facilita debugging seguro y reduce efectos colaterales.
### 📊 Errores como Datos
* Los errores transportan información tipificada útil para monitoreo y lógica programática.
---
## 🛠️ Uso Básico
### 📌 Crear Errores
```go
var (
ErrNotFound = errs.CreateErr("app::not_found")
ErrInvalidInput = errs.CreateErr("app::invalid_input")
)
```
### 🧬 Subclases
```go
var (
ErrUserNotFound = errs.CreateSubclassOf(ErrNotFound, "user")
ErrProductNotFound = errs.CreateSubclassOf(ErrNotFound, "product")
)
if errs.IsSubclassOf(err, ErrNotFound) {
// Es una variante de "no encontrado"
}
```
### 🧠 Composición con Contexto
```go
err := errs.ComposeWithMessage(ErrInvalidInput, "Campo 'nombre_usuario' es obligatorio")
original := errors.New("DB desconectada")
errWithCause := errs.ComposeWithCause(errs.CreateErr("db::internal_error"), original)
complexErr := errs.Compose(
ErrUserNotFound,
errs.WithMessage("ID %d no encontrado", 12345),
errs.WithCode(404),
errs.WithDate(),
errs.WithStack(),
errs.WithRetryable(errs.RetryableCanRetry|errs.RetryableIsTemporary, 5*time.Second),
errs.WithInfo("El usuario no existe", "Verifique el ID", "https://docs/errors/user-404"),
errs.WithOrigin("user_service", "alpha"),
errs.WithObservedBy("api_gateway"),
errs.WithMeta("trace_id", "abc123xyz"),
errs.WithMetas(
errs.CreateMeta("http_status", 500, errs.MetaTypeInt),
errs.CreateMeta("is_critical", true, errs.MetaTypeBool),
),
)
```
---
## 🔍 Acceso a Metadatos
```go
if ewc, ok := complexErr.(errs.ErrorWithCode); ok {
fmt.Println("Código:", ewc.Code())
}
if ewc, ok := complexErr.(errs.ErrorWithCause); ok {
fmt.Println("Causa:", ewc.Cause())
}
if ewst, ok := complexErr.(errs.ErrorWithStack); ok {
fmt.Println("Stack:", ewst.Stack())
}
if ewms, ok := complexErr.(errs.ErrorWithMetas); ok {
for _, meta := range ewms.Metas() {
fmt.Printf("%s = %v (%s)\n", meta.Name(), meta.Value(), meta.Type())
}
}
```
---
## 🧾 Formato Avanzado para Logs
```go
fmt.Printf("Error básico: %v\n", complexErr)
fmt.Printf("Solo clase: %s\n", complexErr)
fmt.Printf("Detallado: %+v\n", complexErr)
fmt.Printf("Debug: %#v\n", complexErr)
```
Soporte para **salida con color** en terminales compatibles para mayor claridad.
---
## 📚 Manejo de Listas de Errores
```go
var errsList errs.ErrorList
errsList = errsList.Append(err1)
errsList = errsList.AppendNotNil(err2)
if errsList.Any() {
fmt.Printf("%d errores encontrados: %v\n", errsList.Count(), errsList.Clean())
first := errsList.First()
last := errsList.Last()
}
```
---
## 🧩 Funcionalidades Clave
* ✅ Interfaces de Go: `error`, `fmt.Formatter`, `errors.Is`, `errors.Unwrap`
* 📐 `Err`: tipo base con jerarquía (`modulo::clase.subclase`)
* 🔗 Jerarquía de errores:
* `CreateErr(string)`
* `CreateSubclassOf(parent, name)`
* `IsSubclassOf(err, parent)`
* Métodos: `Parent()`, `Class()`, `Module()`
* 🏷️ Metadatos tipados: `int`, `bool`, `string`, etc.
* 🧠 Composición segura y declarativa
* 🔁 Soporte para errores reintentables
* 📊 Visualización enriquecida para monitoreo
---
## 🧪 Recomendado para:
* Sistemas distribuidos con múltiples servicios
* Aplicaciones con alto requerimiento de trazabilidad
* Equipos que priorizan depuración clara y mantenibilidad
---
**Repositorio oficial:** [Active-Go Core](https://github.com/active-go/core)
**Documentación:** [https://docs.active-go.com/errors](https://g.activething.com/errors)
---
> *Diseñado con propósito. Inspirado por la complejidad. Refinado en producción.*

Powered by TurnKey Linux.