[ADN] Fase 10: Saneamiento y Consolidación - Un solo punto de verdad

- S1: Eliminar 'triggers' duplicado en run (líneas 109/131)
- S2: Eliminar cli/commit.rb (truncado, sin uso)
- S3: Eliminar cli/inicio.rb y cli/cierre.rb (legacy, jornada.rb los reemplaza)
- S4: Mover 4 planes obsoletos de docs/plan/adn/ a docs/_hist/plan/adn/
- S5: Mover 14 backups de planes y 3 docs técnicos a docs/_hist/
- S6: Eliminar manifiesto vacío P2604_proyecto_p2604.md
- S7: Corregir referencia a plan obsoleto en run
- S8: Dejar de cargar core/validador.rb obsoleto en run
- S9: Limpiar progreso duplicado en P2604_mejoras_ADN.md
- Agregar Fase 10 al plan P2604 con 10 tareas
- Un solo punto de verdad: adn/README.md
- Un solo plan: docs/proy/p2604_mejoras_ADN/P2604_mejoras_ADN.md
- Registro en bitácora: evento 1073
This commit is contained in:
Ricardo Monla
2026-03-15 14:33:32 -03:00
parent b13a389568
commit cfd0e8452a
36 changed files with 1563 additions and 238 deletions
+50 -13
View File
@@ -4,7 +4,7 @@
# ====================================================================
# Este módulo proporciona logging estructurado en JSON para todas las
# herramientas del sistema ADN. Los logs se almacenan en `logs/adn/`
# con rotación diaria automática.
# con rotación diaria automática y por tamaño.
require 'json'
require 'fileutils'
@@ -13,32 +13,30 @@ require 'time'
module ADN
class Logger
# Niveles de log soportados
NIVELES = %w[DEBUG INFO EXITO ADVERTENCIA ERROR].freeze
# Configuración de rotación
MAX_TAMANO_MB = 10
MAX_ARCHIVOS = 7
require_relative 'colores'
# Inicializa el logger
#
# @param opts [Hash] Opciones de configuración
# @option opts [String] :directorio Directorio para logs (default: logs/adn/)
# @option opts [Boolean] :terminal Mostrar logs en terminal (default: true)
# @option opts [Boolean] :colores Usar colores en terminal (default: true)
# @option opts [String] :archivo Nombre base del archivo de log (default: fecha actual)
def initialize(opts = {})
@directorio = opts[:directorio] || File.join(File.expand_path('../../..', __dir__), 'logs', 'adn')
@mostrar_terminal = opts.fetch(:terminal, true)
@usar_colores = opts.fetch(:colores, true)
@archivo_base = opts[:archivo] || Date.today.iso8601
# Nivel mínimo de log (configurable)
@nivel_minimo = opts[:nivel] || 'DEBUG'
# Crear directorio si no existe
FileUtils.mkdir_p(@directorio) unless Dir.exist?(@directorio)
# Ruta completa del archivo de log
@ruta_log = File.join(@directorio, "#{@archivo_base}.log")
# Buffer para logs (útil para pruebas o modo batch)
@buffer = []
# Verificar rotación al iniciar
verificar_rotacion
end
# Registra un mensaje de nivel DEBUG
@@ -209,6 +207,45 @@ module ADN
'adn.desconocido'
end
# Verifica y ejecuta rotación de logs si es necesario
def verificar_rotacion
return unless File.exist?(@ruta_log)
tamano_mb = File.size(@ruta_log) / (1024.0 * 1024.0)
if tamano_mb > MAX_TAMANO_MB
rotar_por_tamano
end
end
# Rota el log por tamaño (archivo muy grande)
def rotar_por_tamano
timestamp = Time.now.strftime('%Y%m%d_%H%M%S')
archivo_rotado = "#{@ruta_log}.#{timestamp}"
FileUtils.mv(@ruta_log, archivo_rotado)
limpiar_logs_antiguos
puts "#{Color::YELLOW}⚠ Log rotado por tamaño: #{archivo_rotado}#{Color::RESET}"
end
# Limpia logs antiguos (más de MAX_ARCHIVOS)
def limpiar_logs_antiguos
patron = File.join(@directorio, '*.log.*')
archivos = Dir.glob(patron).sort_by { |f| File.mtime(f) }
archivos[0...-MAX_ARCHIVOS].each do |archivo|
File.delete(archivo) if File.exist?(archivo)
end
end
# Verifica si el nivel está habilitado
def nivel_habilitado?(nivel)
idx_actual = NIVELES.index(@nivel_minimo) || 0
idx_nivel = NIVELES.index(nivel) || 0
idx_nivel >= idx_actual
end
end
# Logger global preconfigurado para uso rápido