diff --git a/php/consola/run.php b/php/consola/run.php index 28e5d4715a..00574aacd5 100644 --- a/php/consola/run.php +++ b/php/consola/run.php @@ -32,9 +32,12 @@ $consola->run( $argv ); $dir_logs = toba_modelo_instalacion::dir_base()."/logs_comandos"; - toba_logger::instancia()->set_directorio_logs($dir_logs); - toba_logger::instancia()->guardar_en_archivo('comandos.log'); - + $handler = toba_handler_log::instancia(); + $handler->set_directorio_logs($dir_logs); + $handler->set_archivo_destino('comandos.log'); + + toba_logger::instancia()->set_logger_instance($handler); + toba_logger::instancia()->guardar(); } else { echo " ATENCION: La variable de entorno 'toba_dir' no esta definida!"; } diff --git a/php/instalacion/toba_instalador.php b/php/instalacion/toba_instalador.php index 2df7880cc7..1e076d3d4f 100644 --- a/php/instalacion/toba_instalador.php +++ b/php/instalacion/toba_instalador.php @@ -36,8 +36,11 @@ function set_progreso($progreso) function grabar_logs() { $dir_logs = toba_modelo_instalacion::dir_base()."/logs_comandos"; - toba_logger::instancia()->set_directorio_logs($dir_logs); - toba_logger::instancia()->guardar_en_archivo('comandos.log'); + $handler = toba_handler_log::instancia(); + $handler->set_directorio_logs($dir_logs); + $handler->set_archivo_destino('comandos.log'); + toba_logger::instancia()->set_logger_instance($handler); + toba_logger::instancia()->guardar(); } //-------------------------------------------------------------- diff --git a/php/nucleo/lib/log_handlers/logger.php b/php/nucleo/lib/log_handlers/logger.php new file mode 100644 index 0000000000..b2fbf5e91f --- /dev/null +++ b/php/nucleo/lib/log_handlers/logger.php @@ -0,0 +1,138 @@ +proyecto_actual = $proyecto; + $this->mapeo_niveles = array_flip($this->get_niveles()); + } + + static function instancia($proyecto=null) + { + if (is_null($proyecto)) { + $proyecto = \toba_basic_logger::get_proyecto_actual(); + } + + if (! isset(self::$instancia[$proyecto])) { + self::$instancia[$proyecto] = new logger($proyecto); //Hay que cambiarlo por logger y setearle el handler especifico para que guarde + } + return self::$instancia[$proyecto]; + } + + public function set_logger_instance($writer, $proyecto=null) + { + if (is_null($proyecto)) { + $this->write_handler = array($writer); + } else { + $this->write_handler[$proyecto] = $writer; + } + } + + public function set_id_solicitud($solicitud) + { + $this->id_solicitud = $solicitud; + } + + public function log($level, $message, array $context = array()) + { + if (! $this->activo) { //Si no estoy logueando ni me gasto. + return; + } + // PSR-3 dice que el mensaje siempre debe ser un string + $mensaje = (is_object($message)) ? $message->__toString() : (string) $message; + /*if (strpos('{', $mensaje) !== false) { //Habria que parsear para ver si no existe algun replace en base al contexto. + //Hay que hacer el replace aca dentro del mensaje por ahora awanto + }*/ + + $nivel_toba = (is_int($level) && isset($this->ref_niveles[$level])); + if (! is_int($level)) { + $nivel_pedido = strtoupper($level); + } elseif ($nivel_toba) { + $nivel_pedido = $this->ref_niveles[$level]; + } + + $nivel_psr = (! is_int($level) && isset($this->mapeo_niveles[$nivel_pedido])); + if (($nivel_psr || $nivel_toba) && $this->mapeo_niveles[$nivel_pedido] <= $this->nivel_maximo) { + if (isset($context['exception']) && ($context['exception'] instanceof \Exception)) { + //Obtener la traza de la excepcion?. + } + $msg = $this->format_msg($mensaje, $nivel_pedido); + $this->escribir_msg($msg, $nivel_pedido); + } + } + + public function guardar() + { + foreach($this->write_handler as $handler) { + if (method_exists($handler, 'guardar')) { + $handler->guardar(); + } + } + } + + protected function escribir_msg($mensaje, $nivel) + { + if (isset($this->write_handler[$this->proyecto_actual])) { + $this->write_handler[$this->proyecto_actual]->log($nivel, $mensaje); + } else { //Si no hay uno especifico para el proyecto lo zampo a todos x es gral. + foreach($this->write_handler as $log_writer) { + $log_writer->log($nivel, $mensaje); + } + } + } + + protected function armar_mensaje($mensaje, $nivel) + { + return "[" . $this->id_solicitud . "][" .$this->proyecto_actual . "][" . $nivel ."] " . $mensaje . PHP_EOL; + } + + protected function format_msg($mensaje, $level) + { + $level = strtolower($level); + switch ($level) { + case LogLevel::EMERGENCY: + $msg = $this->armar_mensaje($mensaje, TOBA_LOG_EMERGENCY); + break; + case LogLevel::ALERT: + $msg = $this->armar_mensaje($mensaje, TOBA_LOG_ALERT); + break; + case LogLevel::CRITICAL: + $msg = $this->armar_mensaje($mensaje, TOBA_LOG_CRIT); + break; + case LogLevel::ERROR: + $msg = $this->armar_mensaje($mensaje, TOBA_LOG_ERROR); + break; + case LogLevel::WARNING: + $msg = $this->armar_mensaje($mensaje, TOBA_LOG_WARNING); + break; + case LogLevel::NOTICE: + $msg = $this->armar_mensaje($mensaje, TOBA_LOG_NOTICE); + break; + case LogLevel::INFO: + $msg = $this->armar_mensaje($mensaje, TOBA_LOG_INFO); + break; + case LogLevel::DEBUG: + $msg = $this->armar_mensaje($mensaje, TOBA_LOG_DEBUG); + break; + default: + // Unknown level --> PSR-3 says kaboom + throw new InvalidArgumentException("Severidad del msg desconocida" ); + } + return $msg; + } +} +?> \ No newline at end of file diff --git a/php/nucleo/lib/toba_basic_logger.php b/php/nucleo/lib/log_handlers/toba_basic_logger.php similarity index 65% rename from php/nucleo/lib/toba_basic_logger.php rename to php/nucleo/lib/log_handlers/toba_basic_logger.php index fc46723d02..aa85fd2a64 100644 --- a/php/nucleo/lib/toba_basic_logger.php +++ b/php/nucleo/lib/log_handlers/toba_basic_logger.php @@ -28,24 +28,16 @@ trait toba_basic_logger { - public static $separador = "-o-o-o-o-o-"; - public static $fin_encabezado = "=========="; - public static $limite_mensaje = 100000; //100 KB - protected $ref_niveles = array("EMERGENCY" , "ALERT", "CRITICAL", "ERROR", "WARNING", "NOTICE", "INFO", "DEBUG"); protected $mensajes = array(); protected $niveles = array(); protected $proyectos = array(); protected $proyecto_actual; - protected $proximo = 0; - protected $nivel_maximo = 7; - protected $activo = true; - - protected $es_php_compatible = true; + protected $nivel_maximo = 7; + protected $es_php_compatible = true; - - public function get_proyecto_actual() + static public function get_proyecto_actual() { if (class_exists('toba_proyecto')) { try { @@ -56,15 +48,6 @@ public function get_proyecto_actual() return 'toba'; } - public function get_usuario_actual() - { - if( php_sapi_name() === 'cli' ) { - return null; - } else { - return toba::usuario()->get_id(); - } - } - /** * Desactiva el logger durante todo el pedido de página actual */ @@ -84,6 +67,11 @@ public function get_cantidad_mensajes() return count($this->mensajes); } + function modo_debug() + { + return ($this->get_nivel() == TOBA_LOG_DEBUG); + } + public function get_mensajes_minimo_nivel() { $cantidad = array(); @@ -111,56 +99,9 @@ public function get_nivel() return $this->nivel_maximo; } - //------------------------------------------------------------------ - //---- Manejo de las fuentes de log - //------------------------------------------------------------------ - public function directorio_logs() - { - if (! isset($this->dir_logs)) { - $id_instancia = toba_instancia::get_id(); - $this->dir_logs = toba_nucleo::toba_instalacion_dir()."/i__$id_instancia/p__{$this->proyecto_actual}/logs"; - } - return $this->dir_logs; - } - - public function set_directorio_logs($dir) - { - $this->dir_logs = $dir; - } - - //-----------------------------------------------------------------------------------------------------------// - // METODOS AUXILIARES - //-----------------------------------------------------------------------------------------------------------// - protected function truncar_msg($msg) - { - if (strlen($msg) > self::$limite_mensaje) { - $msg = substr($msg, 0, self::$limite_mensaje). - "..TEXTO CORTADO POR EXCEDER EL LIMITE DE ". - self::$limite_mensaje. - " bytes"; - } - return $msg; - } - - protected function registrar_msg_cli($msg, $nivel) - { - if (PHP_SAPI != 'cli' && apex_log_error_log && $nivel <= apex_log_error_log_nivel) { - $error_log_max = ini_get("log_errors_max_len"); - if (! isset($error_log_max) || !is_numeric($error_log_max) || strlen($error_log_max) <= 1) { - $error_log_max = 1024; - } - $error_log_extra = "...SIGUE..."; - $msg_error_log = $msg; - if (strlen($msg_error_log) > $error_log_max) { - $msg_error_log = substr($msg_error_log, 0 , $error_log_max - strlen($error_log_extra)); - $msg_error_log .= $error_log_extra; - } - error_log($msg_error_log); - } - } - /** * @ignore + * @deprecated since version 3.2.3 */ protected function registrar_mensaje($mensaje, $proyecto, $nivel) { @@ -176,6 +117,7 @@ protected function registrar_mensaje($mensaje, $proyecto, $nivel) /** * @ignore + * @deprecated since version 3.2.3 */ protected function extraer_mensaje($mensaje) { @@ -224,12 +166,22 @@ protected function extraer_mensaje($mensaje) } } + /** + * @deprecated since version 3.2.3 + */ protected function parsear_msg($mensaje, $parametros=true) { $er = "/\([a-zA-Z'\"\s].+\)/i"; return ($parametros) ? $mensaje: preg_replace($er, '(args ignored)', $mensaje); } + /** + * + * @param type $con_parametros + * @param type $pasos + * @return string + * @deprecated since version 3.2.3 + */ protected function construir_traza($con_parametros=false, $pasos = null) { if (!isset($pasos)) { @@ -273,6 +225,12 @@ protected function construir_traza($con_parametros=false, $pasos = null) return $html; } + /** + * + * @param type $argumento + * @return type + * @deprecated since version 3.2.3 + */ protected function armar_parametros_traza($argumento) { $html = ''; @@ -288,6 +246,11 @@ protected function armar_parametros_traza($argumento) return $html; } + /** + * Arma un string con los mensajes y sus datos + * @return string + * @deprecated since version 3.2.3 + */ protected function armar_mensajes() { $texto = ''; @@ -299,7 +262,7 @@ protected function armar_mensajes() } return $texto; } - + protected function mensajes() { return $this->mensajes; @@ -319,72 +282,125 @@ protected function mascara_hasta($nivel) return ((1 << ($nivel + 1)) - 1); } - protected function ciclar_archivos_logs($path, $archivo) + //------------------------------------------------------------------ + //------ Entradas para los distintos tipos de error + //------------------------------------------------------------------ + + /** + * Registra un suceso de emergencia (hecatombe) + */ + function emergencia($mensaje, $proyecto=null) { - if (apex_log_archivo_backup_cant == 0) { - //Si es un unico archivo hay que borrarlo - unlink($path."/".$archivo); - return; - } - //Encuentra los archivos - $patron = "/$archivo\.([0-9]+)/"; - $archivos = toba_manejador_archivos::get_archivos_directorio($path, $patron); - sort($archivos); + return $this->log(TOBA_LOG_EMERGENCY, $mensaje, array('proyecto' => $proyecto)); + } + + /** + * Registra un suceso de alerta (un error que requiere intervencion humana) + */ + function alerta($mensaje, $proyecto=null) + { + return $this->log(TOBA_LOG_ALERT, $mensaje, array('proyecto' => $proyecto)); + } + + /** + * Registra un suceso CRITICO (un error muy grave) + */ + function crit($mensaje, $proyecto=null) + { + return $this->log(TOBA_LOG_CRIT, $mensaje, array('proyecto' => $proyecto)); + } - //¿Cual es el numero de cada uno? - $ultimo = 0; - $arch_ordenados = array(); - foreach ($archivos as $arch_actual) { - $version = array(); - preg_match($patron, $arch_actual, $version); - if (! empty($version) && count($version) > 1) { - $pos = $version[1]; - $arch_ordenados[$pos] = $arch_actual; - if ($pos > $ultimo) { - $ultimo = $pos; - } + /** + * Registra un error en la apl., este nivel es que el se usa en las excepciones + */ + function error($mensaje, $proyecto=null) + { + return $this->log(TOBA_LOG_ERROR, $mensaje, array('proyecto' => $proyecto)); + } + + /** + * Registra un suceso no contemplado pero que posiblemente no afecta la correctitud del proceso + */ + function warning($mensaje, $proyecto=null) + { + return $this->log(TOBA_LOG_WARNING, $mensaje, array('proyecto' => $proyecto)); + } + + /** + * Registra un suceso no contemplado que no es critico para la aplicacion + */ + function notice($mensaje, $proyecto=null) + { + return $this->log(TOBA_LOG_NOTICE, $mensaje, array('proyecto' => $proyecto)); + } + + /** + * Registra un suceso netamente informativo, para una inspección posterior + */ + function info($mensaje, $proyecto=null) + { + return $this->log(TOBA_LOG_INFO, $mensaje, array('proyecto' => $proyecto)); + } + + /** + * Registra un suceso útil para rastrear problemas o bugs en la aplicación + */ + function debug($mensaje, $proyecto=null) + { + return $this->log(TOBA_LOG_DEBUG, $mensaje, array('proyecto' => $proyecto)); + } + + //-----------------------------------------------------------------------------------------------// + // Entradas extra para tipos propios + //-----------------------------------------------------------------------------------------------// + /** + * Indica la llamada a un metodo/funcion obsoleto, es un alias de notice + * @param string $version Versión desde la cual el metodo/funcion deja de estar disponible + */ + function obsoleto($clase, $metodo, $version, $extra=null, $proyecto=null) + { + if (TOBA_LOG_NOTICE <= $this->nivel_maximo) { + $extra = ""; + //Se saca el archivo que llamo el metodo obsoleto solo cuando hay modo debug + if (TOBA_LOG_DEBUG <= $this->nivel_maximo) { + $traza = debug_backtrace(); + $archivo = $traza[2]['file']; + $linea = $traza[2]['line']; + $extra = "Archivo: $archivo, linea: $linea"; } - } - //Se determina el siguiente numero - $sig = $ultimo + 1; - - //¿Hay que purgar algunos? - $this->purgar_archivos_viejos($arch_ordenados); - - //Se procede a mover el archivo actual - $path_completo = $path . "/" . $archivo; - if (apex_log_archivo_backup_compr) { - //Se comprime - $nuevo = $path_completo . ".$sig.gz"; - toba_manejador_archivos::comprimir_archivo($path_completo, 5, $nuevo); - unlink($path_completo); - } else { - $nuevo = $path_completo . ".$sig"; - rename($path_completo, $nuevo); + if ($clase != '') { + $unidad = "Método '$clase::$metodo'"; + } elseif ($metodo != '') { + $unidad = "Función '$metodo'"; + } else { + $unidad = ''; + } + $msg = "OBSOLETO: $unidad desde versión $version. $extra"; + $this->notice($msg, $proyecto); } } - protected function purgar_archivos_viejos($lista_archivos) + /** + * Muestra la traza de ejecucion actual en el logger + */ + function trace($con_parametros=false, $proyecto = null) { - //¿Hay que purgar algunos? - $puede_purgar = (apex_log_archivo_backup_cant != -1); - $a_purgar = count($lista_archivos) - (apex_log_archivo_backup_cant -1); //Se dejan solo N-1 archivos - if ($puede_purgar && $a_purgar > 0) { - ksort($lista_archivos); - reset($lista_archivos); - do { - unlink(current($lista_archivos)); - $a_purgar--; - next($lista_archivos); - } while ($a_purgar > 0); - } + $this->debug($this->construir_traza($con_parametros), array('proyecto' => $proyecto)); + } + + /** + * Dumpea el contenido de una variable al logger + */ + function var_dump($variable, $proyecto = null) + { + $this->debug(var_export($variable, true), array('proyecto' =>$proyecto)); } - protected function anexar_a_archivo($texto, $archivo) + /** + * Inserta un mensaje de debug que permite al visualizador dividir en secciones la ejecución + */ + function seccion($mensaje, $proyecto=null) { - $res = file_put_contents($archivo, "$texto\r\n", FILE_APPEND); - if ($res === FALSE) { - throw new toba_error("Imposible guardar el archivo de log '$archivo'. Chequee los permisos de escritura del usuario apache sobre esta carpeta/archivo"); - } - } + return $this->log(TOBA_LOG_DEBUG, "[SECCION] ".$mensaje, array('proyecto' => $proyecto)); + } } \ No newline at end of file diff --git a/php/nucleo/lib/log_handlers/toba_handler_log.php b/php/nucleo/lib/log_handlers/toba_handler_log.php new file mode 100644 index 0000000000..54ff1f1524 --- /dev/null +++ b/php/nucleo/lib/log_handlers/toba_handler_log.php @@ -0,0 +1,302 @@ +proyecto_actual = $proyecto; + } + + /** + * Este es un singleton por proyecto + * @return logger + */ + static function instancia($proyecto=null) + { + if (is_null($proyecto)) { + $proyecto = \toba_basic_logger::get_proyecto_actual(); + } + if (!isset(self::$instancia[$proyecto])) { + self::$instancia[$proyecto] = new toba_handler_log($proyecto); + } + return self::$instancia[$proyecto]; + } + + static public function get_proyecto_actual() + { + if (class_exists('toba_proyecto')) { + try { + return toba_proyecto::get_id(); + } catch (Exception $e) { + } + } + return 'toba'; + } + + public function get_usuario_actual() + { + if( php_sapi_name() === 'cli' ) { + return null; + } else { + return toba::usuario()->get_id(); + } + } + + public function directorio_logs() + { + if (! isset($this->dir_logs)) { + $id_instancia = toba_instancia::get_id(); + $this->dir_logs = toba_nucleo::toba_instalacion_dir()."/i__$id_instancia/p__{$this->proyecto_actual}/logs"; + } + return $this->dir_logs; + } + public function set_directorio_logs($dir) + { + $this->dir_logs = $dir; + } + + public function set_archivo_destino($nombre) + { + $this->nombre_archivo = $nombre; + } + + public function log($nivel, $mensaje, $context = array()) + { + $this->registrar_mensaje($mensaje, $this->proyecto_actual, $nivel); + } + + public function guardar() + { + $this->guardar_en_archivo($this->nombre_archivo); + } + + public function guardar_en_archivo($archivo, $forzar_salida = false) + { + $salto = "\r\n"; + + $texto = $this->armar_encabezado(); + $texto .= self::$fin_encabezado.$salto; + $hay_salida = (! empty($this->mensajes)); + if ($hay_salida || $forzar_salida) { + $texto .= implode('', $this->mensajes); + $this->guardar_archivo_log($texto, $archivo); + } + } + + public function borrar_archivos_logs() + { + $patron = "/sistema.log/"; + $archivos = toba_manejador_archivos::get_archivos_directorio($this->directorio_logs(), $patron); + foreach ($archivos as $archivo) { + unlink($archivo); + } + } + + /** + * Permite redirigir el log desde el archivo web_services.log hacia stderr + * @param boolean $redirigir + */ + public function redirect_to_stderr($redirigir) + { + $this->modo_archivo = (! $redirigir); + } + + //-------------------------------------------------------------------------------------------------------------------// + // METODOS PROTEGIDOS + //-------------------------------------------------------------------------------------------------------------------// + protected function registrar_mensaje($mensaje, $proyecto, $nivel) + { + // $msg = $this->extraer_mensaje($mensaje); + $msg = $this->truncar_msg($mensaje); + $this->registrar_msg_cli($msg, $nivel); + + $this->mensajes[$this->proximo] = $msg; + //$this->niveles[$this->proximo] = $nivel; + $this->proyectos[$this->proximo] = (isset($proyecto)) ? $proyecto : $this->proyecto_actual; + $this->proximo++; + } + + protected function guardar_archivo_log($texto, $archivo) + { + $permisos = 0774; + $es_nuevo = false; + $dir_log = $this->directorio_logs(); + toba_manejador_archivos::crear_arbol_directorios($dir_log, $permisos); + $path_completo = $dir_log . '/' .$archivo; + + $stream_source = ($this->modo_archivo) ? 'file://' . $path_completo : 'php://stderr'; + if (file_exists($path_completo)) { + $excede_tamanio = (filesize($path_completo) > apex_log_archivo_tamanio * 1024); + if (apex_log_archivo_tamanio != null && $excede_tamanio) { + $this->ciclar_archivos_logs($dir_log, $this->nombre_archivo); + $es_nuevo = true; + } + $stream_handler = fopen($stream_source, 'a'); + } elseif ($this->modo_archivo) { + $stream_handler = fopen($stream_source, 'x'); + $es_nuevo = true; + } else { + $stream_handler = fopen($stream_source, 'a'); + + } + + if (false !== $stream_handler && false === fwrite($stream_handler, $texto)) { + $msg = ($this->modo_archivo) ? "Imposible guardar el archivo de log '$path_completo'. Chequee los permisos de escritura del usuario apache sobre esta carpeta/archivo" : "Imposible escribir el log en stderr"; + throw new toba_error($msg); + } + fclose($stream_handler); + if ($es_nuevo) { + //Cambiar permisos + @toba_manejador_archivos::chmod_recursivo($dir_log, $permisos); + } + } + + protected function armar_encabezado() + { + $salto = "\r\n"; + $texto = self::$separador.$salto; + $texto .= "Fecha: ".date("d-m-Y H:i:s").$salto; + if (class_exists('toba') && is_object(toba::solicitud())) { + $texto .= "Operacion: ".toba::solicitud()->get_datos_item('item_nombre').$salto; + } + $usuario = self::get_usuario_actual(); + if (isset($usuario)) { + $texto .= "Usuario: ".$usuario.$salto; + } + $texto .= "Version-PHP: ". phpversion().$salto; + if (isset($_SERVER['SERVER_NAME'])) { + $texto .= "Servidor: ".$_SERVER['SERVER_NAME'].$salto; + } + if (isset($_SERVER['REQUEST_URI'])) { + $texto .= "URI: ".$_SERVER['REQUEST_URI'].$salto; + } + if (isset($_SERVER["HTTP_REFERER"])) { + $texto .= "Referrer: ".$_SERVER["HTTP_REFERER"].$salto; + } + if (isset($_SERVER["REMOTE_ADDR"])) { + $texto .= "Host: ".$_SERVER["REMOTE_ADDR"].$salto; + } + if( php_sapi_name() === 'cli' ) { + global $argv; + $texto .= 'Ruta: '.getcwd().$salto; + $texto .= 'Argumentos: '.implode(' ', $argv).$salto; + } + return $texto; + } + + protected function truncar_msg($msg) + { + if (strlen($msg) > self::$limite_mensaje) { + $msg = substr($msg, 0, self::$limite_mensaje). + "..TEXTO CORTADO POR EXCEDER EL LIMITE DE ". + self::$limite_mensaje. + " bytes"; + } + return $msg; + } + + protected function registrar_msg_cli($msg, $nivel) + { + if (PHP_SAPI != 'cli' && apex_log_error_log && $nivel <= apex_log_error_log_nivel) { + $error_log_max = ini_get("log_errors_max_len"); + if (! isset($error_log_max) || !is_numeric($error_log_max) || strlen($error_log_max) <= 1) { + $error_log_max = 1024; + } + $error_log_extra = "...SIGUE..."; + $msg_error_log = $msg; + if (strlen($msg_error_log) > $error_log_max) { + $msg_error_log = substr($msg_error_log, 0 , $error_log_max - strlen($error_log_extra)); + $msg_error_log .= $error_log_extra; + } + error_log($msg_error_log); + } + } + + /** + * + * @param type $texto + * @param type $archivo + * @throws toba_error + * @deprecated since version 3.2.3 + */ + protected function anexar_a_archivo($texto, $archivo) + { + $res = file_put_contents($archivo, "$texto\r\n", FILE_APPEND); + if ($res === FALSE) { + throw new toba_error("Imposible guardar el archivo de log '$archivo'. Chequee los permisos de escritura del usuario apache sobre esta carpeta/archivo"); + } + } + + protected function ciclar_archivos_logs($path, $archivo) + { + if (apex_log_archivo_backup_cant == 0) { + //Si es un unico archivo hay que borrarlo + unlink($path."/".$archivo); + return; + } + //Encuentra los archivos + $patron = "/$archivo\.([0-9]+)/"; + $archivos = toba_manejador_archivos::get_archivos_directorio($path, $patron); + sort($archivos); + + //¿Cual es el numero de cada uno? + $ultimo = 0; + $arch_ordenados = array(); + foreach ($archivos as $arch_actual) { + $version = array(); + preg_match($patron, $arch_actual, $version); + if (! empty($version) && count($version) > 1) { + $pos = $version[1]; + $arch_ordenados[$pos] = $arch_actual; + if ($pos > $ultimo) { + $ultimo = $pos; + } + } + } + //Se determina el siguiente numero + $sig = $ultimo + 1; + + //¿Hay que purgar algunos? + $this->purgar_archivos_viejos($arch_ordenados); + + //Se procede a mover el archivo actual + $path_completo = $path . "/" . $archivo; + if (apex_log_archivo_backup_compr) { + //Se comprime + $nuevo = $path_completo . ".$sig.gz"; + toba_manejador_archivos::comprimir_archivo($path_completo, 5, $nuevo); + unlink($path_completo); + } else { + $nuevo = $path_completo . ".$sig"; + rename($path_completo, $nuevo); + } + } + + protected function purgar_archivos_viejos($lista_archivos) + { + //¿Hay que purgar algunos? + $puede_purgar = (apex_log_archivo_backup_cant != -1); + $a_purgar = count($lista_archivos) - (apex_log_archivo_backup_cant -1); //Se dejan solo N-1 archivos + if ($puede_purgar && $a_purgar > 0) { + ksort($lista_archivos); + reset($lista_archivos); + do { + unlink(current($lista_archivos)); + $a_purgar--; + next($lista_archivos); + } while ($a_purgar > 0); + } + } +} +?> \ No newline at end of file diff --git a/php/nucleo/lib/log_handlers/toba_ws_handler_log.php b/php/nucleo/lib/log_handlers/toba_ws_handler_log.php new file mode 100644 index 0000000000..1129d59d25 --- /dev/null +++ b/php/nucleo/lib/log_handlers/toba_ws_handler_log.php @@ -0,0 +1,112 @@ +proyecto_actual = (isset($proyecto)) ? $proyecto : $this->get_proyecto_actual(); + } + + /** + * Guarda los sucesos actuales en el sist. de archivos + */ + public function guardar() + { + if ($this->activo && $this->archivos_individuales) { + $this->guardar_en_archivo($this->get_nombre_archivo()); + } + } + + /** + * Permite disparar un guardado parcial de la informacion + */ + public function set_checkpoint() + { + $this->guardar(); + } + + /** + * Le dice al log que guarde un archivo por cada solicitud e ip + * @param boolean $activo + */ + public function loguear_pedidos_separados($activo) + { + $this->archivos_individuales = $activo; + } + + //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------// + // METODOS AUXILIARES + //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------// + protected function instanciar_handler() + { + $permisos = 0774; + $dir_log = $this->directorio_logs(); + toba_manejador_archivos::crear_arbol_directorios($dir_log, $permisos); + + $path_completo = realpath($dir_log) . '/' . $this->nombre_archivo; + $stream_source = ($this->modo_archivo) ? 'file://' . $path_completo : 'php://stderr'; + + if (file_exists($path_completo)) { + $excede_tamanio = (filesize($path_completo) > apex_log_archivo_tamanio * 1024); + if (apex_log_archivo_tamanio != null && $excede_tamanio) { + $this->ciclar_archivos_logs($dir_log, $this->nombre_archivo); + } + $this->stream_handler = fopen($stream_source, 'a'); + } elseif ($this->modo_archivo) { + $this->stream_handler = fopen($stream_source, 'x'); + } else { + $this->stream_handler = fopen($stream_source, 'a'); + } + } + + public function log($nivel, $mensaje, $context = array()) + { + if (! isset($this->stream_handler)) { + $this->instanciar_handler(); + } + fwrite($this->stream_handler, $mensaje); + } + + //------------------------------------------------------------------------------------------------------------------------------// + // METODOS PARA LOGUEO EN ARCHIVOS INDIVIDUALES + //------------------------------------------------------------------------------------------------------------------------------// + + protected function get_nombre_archivo() + { + if (! isset($this->nombre_archivo)) { + $ip = isset($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"]: 'sin_ip'; + $this->nombre_archivo = '/web_services/web_services_'. $ip. ".log"; //Agrego el dir final aca para mantener el viejo esquema + } + return $this->nombre_archivo; + } +} +?> diff --git a/php/nucleo/lib/toba_logger.php b/php/nucleo/lib/toba_logger.php index 5363c5d57d..1466259dc9 100644 --- a/php/nucleo/lib/toba_logger.php +++ b/php/nucleo/lib/toba_logger.php @@ -45,36 +45,21 @@ */ class toba_logger { - use \toba_basic_logger; + //use \toba_basic_logger; static protected $errores_manejables = array(E_WARNING, E_NOTICE, E_DEPRECATED); - static protected $instancia; - - protected $dir_logs; - //--- Variables que son necesarias para cuando el logger se muestra antes de terminar la pág. - protected $mostrado = false; //Ya fue guardado en este pedido de página - protected $cant_mostrada; //Cant. de logs que había cuando se mostro - - /** - * @todo Para sacar el path de la instalacion y la instancia se necesitaria tener acceso a la clase instalacion - * pero no se carga en el runtime, solo en la parte administrativa, por ahora se replica el lugar - * donde se encuentra el dir de instalacion - */ - protected function __construct($proyecto = null) - { - $this->proyecto_actual = (isset($proyecto)) ? $proyecto : $this->get_proyecto_actual(); - } - /** * Este es un singleton por proyecto * @return logger */ static function instancia($proyecto=null) { - if (!isset(self::$instancia[$proyecto])) { - self::$instancia[$proyecto] = new toba_logger($proyecto); - } - return self::$instancia[$proyecto]; + $logger = logger::instancia($proyecto); + $logger->set_logger_instance(toba_handler_log::instancia($proyecto), $proyecto); + if (class_exists('toba') && is_object(toba::solicitud())) { + $logger->set_id_solicitud(toba::solicitud()->get_id()); + } + return $logger; } static function manejador_errores_recuperables($error_nro, $error_string, $error_archivo = '', $error_linea = 0) @@ -85,248 +70,5 @@ static function manejador_errores_recuperables($error_nro, $error_string, $error return false; // Que lo trate el manejador de errores de PHP ya que no es uno de los que dejan texto nomas. } } - - //------------------------------------------------------------------ - //------ Entradas para los distintos tipos de error - //------------------------------------------------------------------ - - /** - * Registra un suceso de emergencia (hecatombe) - */ - function emergencia($mensaje, $proyecto=null) - { - return $this->log(TOBA_LOG_EMERGENCY, $mensaje, array('proyecto' => $proyecto)); - } - - /** - * Registra un suceso de alerta (un error que requiere intervencion humana) - */ - function alerta($mensaje, $proyecto=null) - { - return $this->log(TOBA_LOG_ALERT, $mensaje, array('proyecto' => $proyecto)); - } - - /** - * Registra un suceso CRITICO (un error muy grave) - */ - function crit($mensaje, $proyecto=null) - { - return $this->log(TOBA_LOG_CRIT, $mensaje, array('proyecto' => $proyecto)); - } - - /** - * Registra un error en la apl., este nivel es que el se usa en las excepciones - */ - function error($mensaje, $proyecto=null) - { - return $this->log(TOBA_LOG_ERROR, $mensaje, array('proyecto' => $proyecto)); - } - - /** - * Registra un suceso no contemplado pero que posiblemente no afecta la correctitud del proceso - */ - function warning($mensaje, $proyecto=null) - { - return $this->log(TOBA_LOG_WARNING, $mensaje, array('proyecto' => $proyecto)); - } - - /** - * Registra un suceso no contemplado que no es critico para la aplicacion - */ - function notice($mensaje, $proyecto=null) - { - return $this->log(TOBA_LOG_NOTICE, $mensaje, array('proyecto' => $proyecto)); - } - - /** - * Registra un suceso netamente informativo, para una inspección posterior - */ - function info($mensaje, $proyecto=null) - { - return $this->log(TOBA_LOG_INFO, $mensaje, array('proyecto' => $proyecto)); - } - - /** - * Registra un suceso útil para rastrear problemas o bugs en la aplicación - */ - function debug($mensaje, $proyecto=null) - { - return $this->log(TOBA_LOG_DEBUG, $mensaje, array('proyecto' => $proyecto)); - } - - //-----------------------------------------------------------------------------------------------// - // Entradas extra para tipos propios - //-----------------------------------------------------------------------------------------------// - /** - * Indica la llamada a un metodo/funcion obsoleto, es un alias de notice - * @param string $version Versión desde la cual el metodo/funcion deja de estar disponible - */ - function obsoleto($clase, $metodo, $version, $extra=null, $proyecto=null) - { - if (TOBA_LOG_NOTICE <= $this->nivel_maximo) { - $extra = ""; - //Se saca el archivo que llamo el metodo obsoleto solo cuando hay modo debug - if (TOBA_LOG_DEBUG <= $this->nivel_maximo) { - $traza = debug_backtrace(); - $archivo = $traza[2]['file']; - $linea = $traza[2]['line']; - $extra = "Archivo: $archivo, linea: $linea"; - } - if ($clase != '') { - $unidad = "Método '$clase::$metodo'"; - } elseif ($metodo != '') { - $unidad = "Función '$metodo'"; - } else { - $unidad = ''; - } - $msg = "OBSOLETO: $unidad desde versión $version. $extra"; - $this->notice($msg, $proyecto); - } - } - - /** - * Muestra la traza de ejecucion actual en el logger - */ - function trace($con_parametros=false, $proyecto = null) - { - $this->debug($this->construir_traza($con_parametros), $proyecto); - } - - /** - * Dumpea el contenido de una variable al logger - */ - function var_dump($variable, $proyecto = null) - { - $this->debug(var_export($variable, true), $proyecto); - } - - /** - * Inserta un mensaje de debug que permite al visualizador dividir en secciones la ejecución - */ - function seccion($mensaje, $proyecto=null) - { - return $this->log(TOBA_LOG_DEBUG, "[SECCION] ".$mensaje, array('proyecto' => $proyecto)); - } - - public function log($nivel, $mensaje, array $context = array()) - { - if ($nivel <= $this->nivel_maximo) { - $proyecto = (isset($context['proyecto'])) ? $context['proyecto'] :$this->proyecto_actual; - $this->registrar_mensaje($mensaje, $proyecto, $nivel); - } - } - - //-----------------------------------------------------------------------------------------------------------------// - // METODOS PUBLICOS - //-----------------------------------------------------------------------------------------------------------------// - - - function modo_debug() - { - return ($this->get_nivel() == TOBA_LOG_DEBUG); - } - - //----------------------------------------------------------------------------------------------------------------------------------// - // METODOS AUXILIARES - //----------------------------------------------------------------------------------------------------------------------------------// - - protected function armar_encabezado() - { - $salto = "\r\n"; - $texto = self::$separador.$salto; - $texto .= "Fecha: ".date("d-m-Y H:i:s").$salto; - if (class_exists('toba') && is_object(toba::solicitud())) { - $texto .= "Operacion: ".toba::solicitud()->get_datos_item('item_nombre').$salto; - } - $usuario = self::get_usuario_actual(); - if (isset($usuario)) { - $texto .= "Usuario: ".$usuario.$salto; - } - $texto .= "Version-PHP: ". phpversion().$salto; - if (isset($_SERVER['SERVER_NAME'])) { - $texto .= "Servidor: ".$_SERVER['SERVER_NAME'].$salto; - } - if (isset($_SERVER['REQUEST_URI'])) { - $texto .= "URI: ".$_SERVER['REQUEST_URI'].$salto; - } - if (isset($_SERVER["HTTP_REFERER"])) { - $texto .= "Referrer: ".$_SERVER["HTTP_REFERER"].$salto; - } - if (isset($_SERVER["REMOTE_ADDR"])) { - $texto .= "Host: ".$_SERVER["REMOTE_ADDR"].$salto; - } - if( php_sapi_name() === 'cli' ) { - global $argv; - $texto .= 'Ruta: '.getcwd().$salto; - $texto .= 'Argumentos: '.implode(' ', $argv).$salto; - } - return $texto; - } - - /** - * Guarda los sucesos actuales en el sist. de archivos - */ - function guardar() - { - if ($this->activo) { - $this->guardar_en_archivo("sistema.log"); - } - } - - function guardar_en_archivo($archivo, $forzar_salida = false) - { - $salto = "\r\n"; - - $texto = $this->armar_encabezado(); - $texto .= self::$fin_encabezado.$salto; - $mensajes = $this->armar_mensajes(); - $hay_salida = (trim($mensajes) != ''); - if ($hay_salida || $forzar_salida) { - $texto .= $mensajes; - $this->guardar_archivo_log($texto, $archivo); - } - } - - protected function guardar_archivo_log($texto, $archivo) - { - $permisos = 0774; - //--- Asegura que el path esta creado - $path = $this->directorio_logs(); - $path_completo = $path ."/".$archivo; - toba_manejador_archivos::crear_arbol_directorios($path, $permisos); - - $es_nuevo = false; - if (!file_exists($path_completo)) { - //Caso base el archivo no existe - $this->anexar_a_archivo($texto, $path_completo); - $es_nuevo = true; - } else { - //El archivo existe, ¿Hay que ciclarlo? - $excede_tamanio = (filesize($path_completo) > apex_log_archivo_tamanio * 1024); - if (apex_log_archivo_tamanio != null && $excede_tamanio) { - $this->ciclar_archivos_logs($path, $archivo); - $es_nuevo = true; - } - $this->anexar_a_archivo($texto, $path_completo); - } - - if ($es_nuevo) { - //Cambiar permisos - @toba_manejador_archivos::chmod_recursivo($path, $permisos); - } - } - - /** - * Borra físicamente todos los archivos de log del proyecto actual - */ - function borrar_archivos_logs() - { - $patron = "/sistema.log/"; - $archivos = toba_manejador_archivos::get_archivos_directorio($this->directorio_logs(), $patron); - foreach ($archivos as $archivo) { - unlink($archivo); - } - } - } ?> \ No newline at end of file diff --git a/php/nucleo/lib/toba_logger_ws.php b/php/nucleo/lib/toba_logger_ws.php index 4f35c28fd8..b3e57a775d 100644 --- a/php/nucleo/lib/toba_logger_ws.php +++ b/php/nucleo/lib/toba_logger_ws.php @@ -1,8 +1,4 @@ proyecto_actual = (isset($proyecto)) ? $proyecto : $this->get_proyecto_actual(); - $this->mapeo_niveles = array_flip($this->get_niveles()); - $this->id_solicitud = toba::solicitud()->get_id(); - } - - /** - * Funcion que permite asignar un recurso puntual al cual dirigir el log (stream write only) - * @param resource $log_handler - */ - public function set_log_handler($log_handler) - { - $this->stream_handler = $log_handler; - $this->modo_archivo = false; - } - - /** - * Permite redirigir el log desde el archivo web_services.log hacia stderr - * @param boolean $redirigir - */ - public function redirect_to_stderr($redirigir) - { - $this->modo_archivo = (! $redirigir); - } - - public function log($level, $message, array $context = array()) - { - if (! $this->activo) { //Si no estoy logueando ni me gasto. - return; - } - $nivel_pedido = strtoupper($level); - // PSR-3 dice que el mensaje siempre debe ser un string - $mensaje = (is_object($message)) ? $message->__toString() : (string) $message; - /*if (strpos('{', $mensaje) !== false) { //Habria que parsear para ver si no existe algun replace en base al contexto. - //Hay que hacer el replace aca dentro del mensaje por ahora awanto - - }*/ - if (isset($this->mapeo_niveles[$nivel_pedido]) && $this->mapeo_niveles[$nivel_pedido] <= $this->nivel_maximo) { - switch ($level) { - case LogLevel::EMERGENCY: - $this->stream_log($this->armar_mensaje($mensaje, TOBA_LOG_EMERGENCY)); - $this->registrar_mensaje($mensaje, null, TOBA_LOG_EMERGENCY); - break; - case LogLevel::ALERT: - $this->stream_log($this->armar_mensaje($mensaje, TOBA_LOG_ALERT)); - $this->registrar_mensaje($mensaje, null, TOBA_LOG_ALERT); - break; - case LogLevel::CRITICAL: - $this->stream_log($this->armar_mensaje($mensaje, TOBA_LOG_CRITICAL)); - $this->registrar_mensaje($mensaje, null, TOBA_LOG_CRITICAL); - break; - case LogLevel::ERROR: - $this->stream_log($this->armar_mensaje($mensaje, TOBA_LOG_ERROR)); - $this->registrar_mensaje($mensaje, null, TOBA_LOG_ERROR); - break; - case LogLevel::WARNING: - $this->stream_log($this->armar_mensaje($mensaje, TOBA_LOG_WARNING)); - $this->registrar_mensaje($mensaje, null, TOBA_LOG_WARNING); - break; - case LogLevel::NOTICE: - $this->stream_log($this->armar_mensaje($mensaje, TOBA_LOG_NOTICE)); - $this->registrar_mensaje($mensaje, null, TOBA_LOG_NOTICE); - break; - case LogLevel::INFO: - $this->stream_log($this->armar_mensaje($mensaje, TOBA_LOG_INFO)); - $this->registrar_mensaje($mensaje, null, TOBA_LOG_INFO); - break; - case LogLevel::DEBUG: - $this->stream_log($this->armar_mensaje($mensaje, TOBA_LOG_DEBUG)); - $this->registrar_mensaje($mensaje, null, TOBA_LOG_DEBUG); - break; - default: - // Unknown level --> PSR-3 says kaboom - throw new InvalidArgumentException("Severidad del msg desconocida" ); - } - } - } - - /** - * Guarda los sucesos actuales en el sist. de archivos - */ - public function guardar() { - if ($this->activo && $this->archivos_individuales) { - $this->guardar_en_archivo($this->get_nombre_archivo()); - } - } - - /** - * Permite disparar un guardado parcial de la informacion - */ - public function set_checkpoint() - { - $this->guardar(); - } - - /** - * Le dice al log que guarde un archivo por cada solicitud e ip - * @param boolean $activo - */ - public function loguear_pedidos_separados($activo) - { - $this->archivos_individuales = $activo; - } - - //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------// - // METODOS AUXILIARES - //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------// - protected function instanciar_handler() - { - $dir_log = $this->directorio_logs(); - $path_completo = realpath($dir_log) . '/' . $this->archivo_log; - $stream_source = ($this->modo_archivo) ? 'file://' . $path_completo : 'php://stderr'; - - if (file_exists($path_completo)) { - $excede_tamanio = (filesize($path_completo) > apex_log_archivo_tamanio * 1024); - if (apex_log_archivo_tamanio != null && $excede_tamanio) { - $this->ciclar_archivos_logs($dir_log, $this->archivo_log); - } - $this->stream_handler = fopen($stream_source, 'a'); - } elseif ($this->modo_archivo) { - $this->stream_handler = fopen($stream_source, 'x'); - } else { - $this->stream_handler = fopen($stream_source, 'a'); - } - } - - protected function stream_log($mensaje) - { - if (! isset($this->stream_handler)) { - $this->instanciar_handler(); - } - fwrite($this->stream_handler, $mensaje); - } - - protected function armar_mensaje($mensaje, $nivel) - { - return "[" . $this->id_solicitud . "][" .$this->proyecto_actual . "][" . $this->ref_niveles[$nivel] ."] " . $mensaje . PHP_EOL; - } - - //------------------------------------------------------------------------------------------------------------------------------// - // METODOS PARA LOGUEO EN ARCHIVOS INDIVIDUALES - //------------------------------------------------------------------------------------------------------------------------------// - protected function armar_encabezado() - { - $salto = "\r\n"; - $texto = self::$separador.$salto; - $texto .= "Fecha: ".date("d-m-Y H:i:s").$salto; - if (class_exists('toba') && is_object(toba::solicitud())) { - $texto .= "Operacion: ".toba::solicitud()->get_datos_item('item_nombre').$salto; - } - $usuario = self::get_usuario_actual(); - if (isset($usuario)) { - $texto .= "Usuario: ".$usuario.$salto; - } - $texto .= "Version-PHP: ". phpversion().$salto; - if (isset($_SERVER['SERVER_NAME'])) { - $texto .= "Servidor: ".$_SERVER['SERVER_NAME'].$salto; - } - if (isset($_SERVER['REQUEST_URI'])) { - $texto .= "URI: ".$_SERVER['REQUEST_URI'].$salto; - } - $this->hubo_encabezado = true; - return $texto; - } - - function guardar_en_archivo($archivo, $forzar_salida = false) - { - $salto = "\r\n"; - $texto = ''; - if (! $this->hubo_encabezado) { - $texto .= $this->armar_encabezado(); - $texto .= self::$fin_encabezado.$salto; - $this->hubo_encabezado = true; - } - $mensajes = $this->armar_mensajes(); - $hay_salida = (trim($mensajes) != ''); - if ($hay_salida || $forzar_salida) { - $texto .= $mensajes; - $this->guardar_archivo_log($texto, $archivo); - } - } - - protected function guardar_archivo_log($texto, $archivo) - { - $permisos = 0774; - //--- Asegura que el path esta creado - $path = $this->directorio_logs(); - $path_completo = $path ."/".$archivo; - toba_manejador_archivos::crear_arbol_directorios($path, $permisos); - - //Grabo el archivo - $es_nuevo = (!file_exists($path_completo)); - $this->anexar_a_archivo($texto, $path_completo); - - //Reseteo las variables internas para no escribir lo mismo varias veces - $this->proyectos = array(); - $this->mensajes = array(); - $this->niveles = array(); - $this->proximo = 0; - - if ($es_nuevo) { - //Cambiar permisos - @toba_manejador_archivos::chmod_recursivo($path, $permisos); - } + $logger = logger::instancia($proyecto); + $logger->set_logger_instance(toba_ws_handler_log::instancia($proyecto), $proyecto); + $logger->set_id_solicitud(toba::solicitud()->get_id()); + return $logger; } - - protected function get_nombre_archivo() - { - if (! isset($this->nombre_archivo)) { - $ip = isset($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"]: 'sin_ip'; - $this->nombre_archivo = '/web_services/web_services_'. $ip. "_{$this->id_solicitud}.log"; //Agrego el dir final aca para mantener el viejo esquema - } - return $this->nombre_archivo; - } - - /*protected function reemplazar_contexto($mensaje, array $context = array()) - { - $replace = array(); - foreach ($context as $key => $val) { - if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) { - $replace['{' . $key . '}'] = $val; - } - } - return strtr($mensaje, $replace); - }*/ } ?> diff --git a/php/nucleo/toba_nucleo.php b/php/nucleo/toba_nucleo.php index 5f77ecefbc..540772013f 100644 --- a/php/nucleo/toba_nucleo.php +++ b/php/nucleo/toba_nucleo.php @@ -222,9 +222,13 @@ function acceso_consola($instancia, $proyecto, $item) toba::logger()->debug('Estado Proceso: '.$estado_proceso, 'toba'); //toba::logger()->debug('Tiempo utilizado: ' . toba::cronometro()->tiempo_acumulado() . ' seg.'); $dir_logs = toba_modelo_instalacion::dir_base().'/logs_comandos'; - toba::logger()->set_directorio_logs($dir_logs); - toba::logger()->guardar_en_archivo('comandos.log'); - exit($estado_proceso); + $handler = toba_handler_log::instancia(); + $handler->set_directorio_logs($dir_logs); + $handler->set_archivo_destino('comandos.log'); + + toba::logger()->set_logger_instance($handler); + toba::logger()->guardar(); + exit($estado_proceso); } function iniciar_contexto_desde_consola($instancia, $proyecto) diff --git a/php/toba_autoload.php b/php/toba_autoload.php index a9cfc79c79..5656368d43 100644 --- a/php/toba_autoload.php +++ b/php/toba_autoload.php @@ -448,6 +448,10 @@ static function cargar($nombre) 'toba_interface_sesion' => 'nucleo/lib/toba_interface_sesion.php', 'toba_interface_usuario' => 'nucleo/lib/toba_interface_usuario.php', 'toba_js' => 'nucleo/lib/toba_js.php', + 'toba_basic_logger' => 'nucleo/lib/log_handlers/toba_basic_logger.php', + 'logger' => 'nucleo/lib/log_handlers/logger.php', + 'toba_handler_log' => 'nucleo/lib/log_handlers/toba_handler_log.php', + 'toba_ws_handler_log' => 'nucleo/lib/log_handlers/toba_ws_handler_log.php', 'toba_logger' => 'nucleo/lib/toba_logger.php', 'toba_logger_rdi' => 'nucleo/lib/toba_logger_rdi.php', 'toba_logger_ws' => 'nucleo/lib/toba_logger_ws.php', @@ -506,4 +510,4 @@ static function cargar($nombre) 'toba_migracion' => 'modelo/migraciones/toba_migracion.php', ); } -?> \ No newline at end of file +?>