*
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
?>