feat: Mejorar el manejo de errores en el sistema de feature flags con logging detallado y agregar script de depuración

This commit is contained in:
Shni
2025-10-31 21:33:35 -05:00
parent 76ce4e4e4d
commit 65d030448e
4 changed files with 267 additions and 21 deletions

146
README/FEATURE_FLAGS_FIX.md Normal file
View File

@@ -0,0 +1,146 @@
# 🔧 Solución a Errores de Feature Flags
## ❌ Problema Encontrado
Los errores mostrados:
```
[FeatureFlags] Error al setear flag "alianzas_blacklist_31_10_2025":
[FeatureFlagsCmd]
[FeatureFlags] Error al inicializar:
```
## ✅ Causas Identificadas
1. **Base de datos vacía**: No había flags iniciales
2. **Logger sin detalles**: No mostraba el error completo
3. **Posible inicialización incompleta**: Bot intentó usar servicio antes de inicializar
## 🛠️ Soluciones Aplicadas
### 1. Mejorado Logging de Errores
**Archivo**: `src/core/services/FeatureFlagService.ts`
- Agregado logging detallado con `message`, `stack`, `code`, `meta`
- Ahora muestra errores completos de Prisma
**Archivo**: `src/core/loaders/featureFlagsLoader.ts`
- Logging extendido en múltiples líneas
- Muestra cada propiedad del error por separado
### 2. Creado Script de Debug
**Archivo**: `scripts/debugFeatureFlags.ts`
- Lista todos los flags en DB
- Verifica parsing de JSON
- Test de creación/eliminación
- Muestra detalles completos de cada flag
### 3. Ejecutado Setup Inicial
**Comando**: `npx tsx scripts/setupFeatureFlags.ts`
**Flags creados** (8 ejemplos):
-`new_shop_system` (disabled)
-`inventory_ui_v2` (enabled)
-`improved_combat_algorithm` (rollout 25%)
-`economy_system_v2` (gradual rollout)
-`halloween_2025` (evento temporal)
-`experimental_features` (whitelist)
-`premium_features` (disabled con metadata)
-`trading_system` (maintenance)
### 4. Verificado Funcionamiento
**Test realizado**: ✅ Exitoso
```bash
✅ Servicio inicializado
📊 8 flags cargados
✅ Todos los flags parseados correctamente
```
## 🚀 Próximos Pasos
### 1. Reiniciar el Bot
```bash
# El bot ahora debe inicializar correctamente
npm run dev
```
### 2. Verificar en Discord
```
/featureflags list
```
### 3. Crear Nuevos Flags
```
/featureflags create name:mi_feature status:disabled target:global
/featureflags update flag:mi_feature status:enabled
```
### 4. Ver Estadísticas
```
/featureflags stats flag:inventory_ui_v2
```
## 📝 Comandos Útiles
### Debug Manual
```bash
# Ver todos los flags en DB
npx tsx scripts/debugFeatureFlags.ts
# Test del servicio
npx tsx -e "
import { featureFlagService } from './src/core/services/FeatureFlagService';
await featureFlagService.initialize();
console.log(featureFlagService.getFlags());
"
```
### Resetear Flags
```bash
# Eliminar todos los flags
npx tsx -e "
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
await prisma.featureFlag.deleteMany({});
await prisma.\$disconnect();
"
# Recrear flags de ejemplo
npx tsx scripts/setupFeatureFlags.ts
```
## 🔍 Debugging Futuro
Si vuelven a aparecer errores:
1. **Ejecutar debug script**:
```bash
npx tsx scripts/debugFeatureFlags.ts
```
2. **Verificar logs mejorados**: Ahora muestran:
- `error.message`
- `error.stack`
- `error.code` (código de Prisma)
- `error.meta` (metadata de Prisma)
3. **Test de conexión**:
```bash
npx tsx -e "
import { prisma } from './src/core/database/prisma';
const count = await prisma.featureFlag.count();
console.log('Flags en DB:', count);
"
```
## ✅ Estado Actual
- ✅ Tabla `FeatureFlag` creada y sincronizada
- ✅ 8 flags de ejemplo en DB
- ✅ Servicio funcionando correctamente
- ✅ Logging mejorado
- ✅ Script de debug disponible
**El sistema está listo para usar.** 🎮

View File

@@ -0,0 +1,88 @@
/**
* Debug del sistema de Feature Flags
*/
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
async function debugFeatureFlags() {
console.log("🔍 Debugging Feature Flags...\n");
try {
// Listar todos los flags
const flags = await prisma.featureFlag.findMany();
console.log(`📊 Total de flags en DB: ${flags.length}\n`);
if (flags.length === 0) {
console.log(" No hay flags en la base de datos");
return;
}
// Mostrar cada flag
for (const flag of flags) {
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
console.log(`🎯 Flag: ${flag.name}`);
console.log(` ID: ${flag.id}`);
console.log(` Status: ${flag.status}`);
console.log(` Target: ${flag.target}`);
console.log(` Description: ${flag.description || "N/A"}`);
console.log(` Rollout Strategy: ${flag.rolloutStrategy || "N/A"}`);
console.log(` Rollout Config: ${flag.rolloutConfig || "N/A"}`);
console.log(` Start Date: ${flag.startDate || "N/A"}`);
console.log(` End Date: ${flag.endDate || "N/A"}`);
console.log(` Created: ${flag.createdAt}`);
console.log(` Updated: ${flag.updatedAt}`);
// Verificar si hay problemas con los datos
if (flag.rolloutConfig) {
try {
const parsed = JSON.parse(flag.rolloutConfig);
console.log(` ✅ Rollout Config parseable:`, parsed);
} catch (e: any) {
console.log(` ❌ ERROR parseando Rollout Config: ${e.message}`);
}
}
if (flag.metadata) {
try {
const parsed = JSON.parse(flag.metadata);
console.log(` ✅ Metadata parseable:`, parsed);
} catch (e: any) {
console.log(` ❌ ERROR parseando Metadata: ${e.message}`);
}
}
}
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
// Test de creación
console.log("🧪 Test: Crear flag temporal...");
const testFlag = await prisma.featureFlag.create({
data: {
name: `test_flag_${Date.now()}`,
description: "Flag de test temporal",
status: "disabled",
target: "global",
},
});
console.log(`✅ Flag creado: ${testFlag.name}`);
// Limpiar
await prisma.featureFlag.delete({
where: { name: testFlag.name },
});
console.log(`🗑️ Flag eliminado: ${testFlag.name}\n`);
console.log("✅ Sistema funcionando correctamente");
} catch (error: any) {
console.error("❌ ERROR:", error.message);
console.error("Stack:", error.stack);
console.error("Code:", error.code);
console.error("Meta:", error.meta);
} finally {
await prisma.$disconnect();
}
}
debugFeatureFlags();

View File

@@ -11,9 +11,12 @@ export async function loadFeatureFlags(): Promise<void> {
logger.info("[FeatureFlags] Inicializando servicio..."); logger.info("[FeatureFlags] Inicializando servicio...");
await featureFlagService.initialize(); await featureFlagService.initialize();
logger.info("[FeatureFlags] ✅ Servicio inicializado correctamente"); logger.info("[FeatureFlags] ✅ Servicio inicializado correctamente");
} catch (error) { } catch (error: any) {
//@ts-ignore logger.error("[FeatureFlags] ❌ Error al inicializar:");
logger.error("[FeatureFlags] ❌ Error al inicializar:", error); logger.error("[FeatureFlags] Message:", error?.message);
logger.error("[FeatureFlags] Stack:", error?.stack);
logger.error("[FeatureFlags] Code:", error?.code);
logger.error("[FeatureFlags] Meta:", error?.meta);
// No lanzamos el error para no bloquear el arranque del bot // No lanzamos el error para no bloquear el arranque del bot
// El servicio funcionará en modo fail-safe (todos los flags disabled) // El servicio funcionará en modo fail-safe (todos los flags disabled)
} }

View File

@@ -64,9 +64,12 @@ class FeatureFlagService {
logger.info( logger.info(
`[FeatureFlags] Inicializado con ${this.flagsCache.size} flags` `[FeatureFlags] Inicializado con ${this.flagsCache.size} flags`
); );
} catch (error) { } catch (error: any) {
//@ts-ignore logger.error("[FeatureFlags] Error al inicializar:", {
logger.error("[FeatureFlags] Error al inicializar:", error); message: error?.message,
stack: error?.stack,
name: error?.name,
});
throw error; throw error;
} }
} }
@@ -106,9 +109,13 @@ class FeatureFlagService {
logger.debug( logger.debug(
`[FeatureFlags] Caché actualizado: ${this.flagsCache.size} flags` `[FeatureFlags] Caché actualizado: ${this.flagsCache.size} flags`
); );
} catch (error) { } catch (error: any) {
//@ts-ignore logger.error("[FeatureFlags] Error al refrescar caché:", {
logger.error("[FeatureFlags] Error al refrescar caché:", error); message: error?.message,
stack: error?.stack,
code: error?.code,
meta: error?.meta,
});
throw error; throw error;
} }
} }
@@ -555,12 +562,13 @@ class FeatureFlagService {
this.flagsCache.set(config.name, config); this.flagsCache.set(config.name, config);
logger.info(`[FeatureFlags] Flag "${config.name}" actualizado`); logger.info(`[FeatureFlags] Flag "${config.name}" actualizado`);
} catch (error) { } catch (error: any) {
logger.error( logger.error(`[FeatureFlags] Error al setear flag "${config.name}":`, {
`[FeatureFlags] Error al setear flag "${config.name}":`, message: error?.message,
//@ts-ignore stack: error?.stack,
error code: error?.code,
); meta: error?.meta,
});
throw error; throw error;
} }
} }
@@ -578,12 +586,13 @@ class FeatureFlagService {
this.stats.delete(flagName); this.stats.delete(flagName);
logger.info(`[FeatureFlags] Flag "${flagName}" eliminado`); logger.info(`[FeatureFlags] Flag "${flagName}" eliminado`);
} catch (error) { } catch (error: any) {
logger.error( logger.error(`[FeatureFlags] Error al eliminar flag "${flagName}":`, {
`[FeatureFlags] Error al eliminar flag "${flagName}":`, message: error?.message,
//@ts-ignore stack: error?.stack,
error code: error?.code,
); meta: error?.meta,
});
throw error; throw error;
} }
} }