*
  • PANIC 0
  • *
  • ERROR 1
  • *
  • WARNING 2
  • *
  • NOTICE 3
  • *
  • DEBUG_USER 4
  • *
  • DEBUG_IGEP 5
  • * * * @version $Id: IgepDebug.php 17368 2023-07-05 10:56:32Z vnavarro $ * @author Toni * @author Vero * @author David * * @package gvHidra */ require_once "igep_utils/DBAL/gvHidraDBAL.php"; use gvHidraDBAL\gvHidraDBAL; class IgepDebug { public static $nombreTabla = 'tcmn_errlog'; public static function setDebug ($tipo, $mensaje, $dsn=null) { if (!is_numeric($tipo)) { throw new Exception('IgepDebug: el tipo de mensaje no está definido: '.$tipo); } $conf = ConfigFramework::getConfig(); $debug = $conf->getLogStatus(); //Comprobamos si tenemos que insertar if($tipo >= $debug) { // NO ESTÁ DEFINIDO EL LOG STATUS DEL DEBUG //error_log("ERROR -> setDebug() tipo >= log_status ".$tipo." >= ".$debug); return; } //Obtenemos DSN if (empty($dsn)) { $dsn = $conf->getDSNLog(); } //Obtenemos los datos $aplicacion = IgepSession::dameAplicacion(); $modulo = ''; $version = $conf->getAppVersion(); if (strlen($version) > 10) { $version = substr($version,-10); } $usuario = IgepSession::dameUsuario(); if (empty($usuario)) { $usuario = $_SERVER['REMOTE_ADDR']; if (empty($usuario)) { $usuario = 'UNKNOWN'; } } //reemplazamos caracter octal 0 con string \000 (relacionados con serialización de objetos) $mensaje = str_replace("\000",'\\000', $mensaje);//REVIEW: Coste //Realizamos la insercion try { IgepDebug::_setDB($tipo, $mensaje, $aplicacion, $modulo, $version, $usuario, $dsn); } catch (Exception $e) { error_log('Error en debug ('.$e->getMessage().') al intentar registrar: '.$mensaje); } } public static function _setDB($tipo, $mensaje, $aplicacion, $modulo, $version, $usuario, $dsn_log) { /** @var boolean Se utiliza para evitar bucles infiitos en el registro de errores del LOG */ static $excl; /** @var gvHidraDBAL Instancia del objeto conectado que se almacena en ConfigFramework */ static $conexion = null; static $ins_prepared = null; $nombreTabla = self::$nombreTabla; if(empty($dsn_log)) { throw new Exception (__CLASS__.'::'.__METHOD__.': Error DSN vacío'); } $driver = gvHidraDBAL::MDB2_DRIVER; if (mb_strtoupper(trim($dsn_log['driver']), 'UTF-8') == 'PDO') { $driver = gvHidraDBAL::PDO_DRIVER; } $dbms = gvHidraDBAL::getNormalizedSGBDType($dsn_log); if ($dbms == gvHidraDBAL::SGBD_MYSQL) { $sqlIdError = 'null'; $sqlFechaActual = 'SYSDATE()'; } elseif ($dbms == gvHidraDBAL::SGBD_ORACLE) { $sqlIdError = '(scmn_id_errlog.nextval)'; $sqlFechaActual = 'CURRENT_TIMESTAMP'; } elseif ($dbms == gvHidraDBAL::SGBD_POSTGRESQL) { $sqlIdError = "(nextval('scmn_id_errlog'))"; $sqlFechaActual = 'CURRENT_TIMESTAMP'; } elseif ($dbms == gvHidraDBAL::SGBD_SQLITE) { $sqlIdError = 'null';//Aplica un RowId automático $sqlFechaActual = "STRFTIME('%Y/%m/%d %H:%M:%f', 'NOW', 'localtime')"; try { $dsn_log['xmlhost'] = self::buildSQLiteResource($dsn_log); } catch (Exception $e) { $errMsj = 'Error con el uso de SQLite para el DEBUG: '.$e->getMessage(); throw new Exception($errMsj); } } else { $dsn_log['username'] = ''; $dsn_log['password'] = ''; $errMsj = 'El tipo de conexión no está soportado por gvHidraDBAL: '.print_r($dsn_log, true); throw new Exception($errMsj); } //Conexion persistente para el log $conf = ConfigFramework::getConfig(); $conexion = $conf->getLogConnection(); if(!is_object($conexion)) {//Si no está fijada, conectamos if ($excl === true) { $excl = false; throw new Exception('Error de conexión al debug, desactivelo (pase a LOG_NONE) o corrija el problema. Posiblemente se trata de un error en los parámetros de conexion. La descripcción del problema es: '.$conexion->obj_conexion->userinfo); } try { $codificacion = 'UTF-8'; if (isset($dsn_log['xmlcharset'])) { $codificacion = $dsn_log['xmlcharset']; } $conexion = gvHidraDBAL::makeConnection($dsn_log, $codificacion, $driver); } catch (Exception $e) { $errMsj = __CLASS__.'::'.__METHOD__.': Error de conexión al debug, desactivelo (pase a LOG_NONE) o corrija el problema.'; $errMsj.=' Posiblemente se trata de un error en los parámetros de conexión. Descrición: '.$e->getMessage(); throw new Exception($errMsj); } $conf->setLogConnection($conexion);//Gaurdamos la conexión VIVA } /* Preparamos la operación SQL */ $exprBindMensaje = ':msj0';//Variable BIND para insertar el texto del mensaje $vTypesInsertMensaje = array('msj0' => gvHidraDBAL::T_CLOB); $vValuesInsertMensaje = array ('msj0' => $mensaje); // Tratamos el problema de ORACLE con PDOStatement::bindValue() con longitud mayor a 1332 bytes // REVIEW: https://bugs.php.net/bug.php?id=55138 //Para ello concatemos variables bind de longitud $chunkSize if (($dbms == gvHidraDBAL::SGBD_ORACLE) && ($driver == gvHidraDBAL::PDO_DRIVER) && (strlen($mensaje)>1332)) { $vTypesInsertMensaje = array(); $vValuesInsertMensaje = array(); $chunkSize = 700;//Al trabajar con UTF-8 co hasta 3 bytes por caracter, es mejor irse alejarse de los 1332 $vMensaje = str_split($mensaje, $chunkSize); //$vMensaje = mb_str_split($mensaje, $chunkSize, $conexion->getClientEncoding());//REVIEW: A partir de PHP7 foreach ($vMensaje as $key => $chunkMensaje) { $indice = 'msj'.$key; $vTypesInsertMensaje[$indice] = gvHidraDBAL::T_CLOB; $vValuesInsertMensaje[$indice] = $chunkMensaje; } //Construimos la expressión de bind del insert $vBindVars = array_keys($vValuesInsertMensaje); $exprBindMensaje = '( :'; $exprBindMensaje.= implode(" || :", $vBindVars); $exprBindMensaje.= ' )'; } //$tipo, $mensaje, $aplicacion, $modulo, $version, $usuario $vTypesInsert = array ( 'aplicacion' => gvHidraDBAL::T_STRING ,'version' => gvHidraDBAL::T_STRING ,'usuario' => gvHidraDBAL::T_STRING ,'tipo' => gvHidraDBAL::T_INTEGER //Falta msj0 y si es el caso el resto: msj1, msj2... ); $vTypesInsert = array_merge($vTypesInsert, $vTypesInsertMensaje); $vValuesInsert = array ( 'aplicacion' => $aplicacion ,'version' => $version ,'usuario' => $usuario ,'tipo' => $tipo //Falta msj0 y si es el caso el resto: msj1, msj2... ); $vValuesInsert = array_merge($vValuesInsert, $vValuesInsertMensaje); $ins_prepared =<<prepare($ins_prepared, $vTypesInsert); } catch (Exception $e) { $mensaje = __CLASS__.'::'.__METHOD__.': Error en la preparación de la SQL para inserción del DEBUG: '.$e->getMessage(); $mensaje.= "Aryay de tipos: ".print_r($vTypesInsert,true); throw new Exception($mensaje); } try { $conexion->execute($vValuesInsert); } catch (Exception $e) { $mensaje = __CLASS__.'::'.__METHOD__.': Error en la ejecución de la SQL para inserción del DEBUG: '.$e->getMessage(); $mensaje.= ". Array de tipos: ".print_r($vTypesInsert,true); $mensaje.= ". Array de valores: ".print_r($vValuesInsert,true); $mensaje.= ". SQL: ".$ins_prepared; throw new Exception($mensaje); } }//_setDB /** * Elimina los LOGS de más de $dias en tablas para el $usuario especificado (o todos si es vacío) * @param integer $dias * @param string $usuario * @return */ public static function purgeDBLog($dias=30, $usuario = null, $dsn_log = null) { if (empty($dsn_log)) { $conf = ConfigFramework::getConfig(); $dsn_log = $conf->getDSNLog(); } $dbms = gvHidraDBAL::getNormalizedSGBDType($dsn_log); if ($dbms == gvHidraDBAL::SGBD_SQLITE) { try { $dsn_log['xmlOrig'] = $dsn_log['xmlhost']; $dsn_log['xmlhost'] = IgepDebug::getSqlitePDOResource($dsn_log, $usuario); $usuario = '%'; } catch (Exception $e) { $msg = 'Error al purgar BD SQLite: '.$e->getMessage(); throw new Exception($msg); } } if (empty($usuario)) { $usuario = '%'; } $codificacion = 'UTF-8'; if (isset($dsn_log['xmlcharset'])) { $codificacion = $dsn_log['xmlcharset']; } $driver = gvHidraDBAL::MDB2_DRIVER; if (mb_strtoupper(trim($dsn_log['driver']), 'UTF-8') == 'PDO') { $driver = gvHidraDBAL::PDO_DRIVER; } try { $conDBAL = gvHidraDBAL::makeConnection($dsn_log, $codificacion, $driver); } catch (Exception $e) { $msg = __CLASS__.':'.__METHOD__.': Error al conectar al DEBUG para purga: '.$e->getMessage(); throw new Exception($msg); } $nombreTable = self::$nombreTabla; $formatSGBDenPHP = $conDBAL->getMask('timestamp','php'); $fechaBD = date($formatSGBDenPHP, strtotime("-$dias day"));//days $sql = "DELETE FROM $nombreTable WHERE iderror > 1 AND usuario like '$usuario' AND fecha < '$fechaBD'"; try { $conDBAL->prepare($sql); $conDBAL->execute(); } catch (Exception $e) { $msg = __CLASS__.':'.__METHOD__.': Error al ejecutar la purga: '.$e->getMessage(); throw new Exception($msg); } }//Fin public static function getSqlitePDOResource($dsnLog, $usuario = null) { if (mb_strtoupper(trim($dsnLog['driver']), 'UTF-8') == 'MDB2') { $msg = 'No es posible utilizar MDB2 para conectar a SQLite. Utilice PDO.'; throw new Exception($msg); } if (empty($usuario)) { $usuario = IgepSession::dameUsuario(); } $parte = pathinfo($dsnLog['xmlhost']); $dir = isset($parte['dirname'])?$parte['dirname']:'./'; $sufijo = isset($parte['filename'])?$parte['filename']:'_DBIgepDebug'; $extension = isset($parte['extension'])?('.'.$parte['extension']):'.sqlite3'; $ficheroDB = $usuario.$sufijo.$extension; $recurso = realpath($dir).DIRECTORY_SEPARATOR.$ficheroDB; if (!file_exists($recurso)) { $msg = 'No existe la BD de LOG para para: '.$usuario; error_log(__CLASS__.__METHOD__.':: '.$msg); throw new \Exception ($msg); } return $recurso; }//Fin /** * Crea la BD si no existe y devuelve la ruta a la misma */ private static function buildSQLiteResource($dsnLog) { //Obtenemos los datos $aplicacion = IgepSession::dameAplicacion(); $usuario = IgepSession::dameUsuario(); if (empty($usuario)) { $usuario = 'UNKNOWN'; } $tipo = DEBUG_IGEP; $mensaje = "Create SQLite BD LOG para $usuario"; $recurso = null; $parte = pathinfo($dsnLog['xmlhost']); $ruta = isset($parte['dirname'])?$parte['dirname']:'.'; $sufijo = isset($parte['filename'])?$parte['filename']:'DBIgepDebug_'; $extension = isset($parte['extension'])?('.'.$parte['extension']):'.sqlite3'; $ficheroDB = $usuario.$sufijo.$extension; if (file_exists($ruta.DIRECTORY_SEPARATOR.$ficheroDB)) { $recurso = realpath($ruta).DIRECTORY_SEPARATOR.$ficheroDB; return ($recurso); } else { if (!is_dir($ruta)) { if (!mkdir($ruta, 700, true)) { $msg = 'No pudo crearse el directorio: '. $ruta; throw new Exception($msg); } $ruta = realpath($ruta); } try { $recurso = $ruta.DIRECTORY_SEPARATOR.$ficheroDB; //Creamos el fichero físico al conectar $connectionString = 'sqlite:'.$recurso; $conDB = new PDO ($connectionString, null, null, array ( PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, //Marcamos el fetchMode asociativo por defecto PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, //En caso de error, se lanza excepción ) ); $ddl = <<exec($ddl); } catch (Exception $e) { $msg = 'No pudo crearse la BD de Log con SQLite: '.$e->getMessage(); throw new Exception($msg); } //1a inserción try { $insertSQL = <<exec($insertSQL); } catch (Exception $e) { $conDB = null; $msg = 'No pudo insertarse en el LOG de SQLite: '.$e->getMessage(); @unlink($ficheroDB); throw new Exception($msg); } }//Fin if/else return ($recurso); }//Fin buildSQLiteResource }//Fin IgepDebug ?>