2024-04-02 13:50:08 -03:00
< ? php
2025-07-22 13:18:00 +00:00
namespace Incoviba\Common\Implement\Log\Handler ;
2024-04-02 13:50:08 -03:00
2025-07-22 13:18:00 +00:00
use Incoviba\Common\Define\Connection ;
2024-04-02 13:50:08 -03:00
use Monolog\Handler\AbstractProcessingHandler ;
use Monolog\Level ;
2025-07-22 13:18:00 +00:00
use Monolog\LogRecord ;
2025-09-11 17:50:58 -03:00
use PDOException ;
2025-07-22 13:18:00 +00:00
use PDOStatement ;
2024-04-02 13:50:08 -03:00
2025-07-22 13:18:00 +00:00
class MySQL extends AbstractProcessingHandler
2024-04-02 13:50:08 -03:00
{
private bool $initialized = false ;
2025-09-15 13:02:44 -03:00
private array $tables = [
'default' => 'monolog' ,
'deprecated' => 'monolog_deprecated'
];
private array $statements = [
'default' => null ,
'deprecated' => null
];
private array $baseQueries = [
'check' => " SHOW TABLES LIKE '%s' " ,
'create' => " CREATE TABLE IF NOT EXISTS %s (channel VARCHAR(255), level VARCHAR(100), message LONGTEXT, time DATETIME, context LONGTEXT, extra LONGTEXT) " ,
'insert' => " INSERT INTO %s (channel, level, message, time, context, extra) VALUES (:channel, :level, :message, :time, :context, :extra) " ,
'delete' => " DELETE FROM %s WHERE time < DATE_SUB(CURDATE(), INTERVAL %d DAY) "
];
2024-04-02 13:50:08 -03:00
2025-09-11 17:35:02 -03:00
public function __construct ( protected Connection $connection , protected int $retainDays = 90 ,
int | string | Level $level = Level :: Debug , bool $bubble = true )
2024-04-02 13:50:08 -03:00
{
parent :: __construct ( $level , $bubble );
}
public function write ( LogRecord $record ) : void
{
if ( ! $this -> initialized ) {
2025-09-15 13:02:44 -03:00
if ( ! $this -> checkTablesExist ()) {
$this -> createTables ();
2025-09-11 17:35:02 -03:00
}
2025-07-22 13:18:00 +00:00
$this -> cleanup ();
2024-04-02 13:50:08 -03:00
$this -> initialized ();
}
2025-09-11 17:35:02 -03:00
if ( str_contains ( strtolower ( $record -> message ), 'deprecated:' )) {
2025-09-15 13:02:44 -03:00
$this -> statements [ 'deprecated' ] -> execute ([
2025-09-11 17:35:02 -03:00
'channel' => $record -> channel ,
'level' => $record -> level -> getName (),
'message' => $record -> formatted ,
'time' => $record -> datetime -> format ( 'Y-m-d H:i:s.u' ),
'context' => ( count ( $record -> context ) > 0 ) ? json_encode ( $record -> context , JSON_UNESCAPED_SLASHES ) : '' ,
'extra' => ( count ( $record -> extra ) > 0 ) ? json_encode ( $record -> extra , JSON_UNESCAPED_SLASHES ) : ''
]);
return ;
}
2025-09-15 13:02:44 -03:00
$this -> statements [ 'default' ] -> execute ([
2024-04-02 13:50:08 -03:00
'channel' => $record -> channel ,
'level' => $record -> level -> getName (),
'message' => $record -> formatted ,
'time' => $record -> datetime -> format ( 'Y-m-d H:i:s.u' ),
'context' => ( count ( $record -> context ) > 0 ) ? json_encode ( $record -> context , JSON_UNESCAPED_SLASHES ) : '' ,
'extra' => ( count ( $record -> extra ) > 0 ) ? json_encode ( $record -> extra , JSON_UNESCAPED_SLASHES ) : ''
]);
}
private function initialized () : void
{
2025-09-15 13:02:44 -03:00
foreach ( $this -> tables as $type => $table ) {
$query = sprintf ( $this -> baseQueries [ 'insert' ], $table );
$this -> statements [ $type ] = $this -> connection -> getPDO () -> prepare ( $query );
}
2025-07-22 13:18:00 +00:00
$this -> initialized = true ;
}
2025-09-15 13:02:44 -03:00
private function checkTablesExist () : bool
2025-07-22 13:18:00 +00:00
{
2025-09-15 13:02:44 -03:00
return array_all ( $this -> tables , fn ( $table ) => $this -> checkTableExists ( $table ));
2025-07-22 13:18:00 +00:00
}
2025-09-15 13:02:44 -03:00
private function checkTableExists ( string $table ) : bool
2025-09-11 17:35:02 -03:00
{
2025-09-15 13:02:44 -03:00
$query = sprintf ( $this -> baseQueries [ 'check' ], $table );
2025-09-11 17:50:58 -03:00
try {
$result = $this -> connection -> query ( $query );
} catch ( PDOException ) {
return false ;
}
2025-09-11 17:35:02 -03:00
return $result -> rowCount () > 0 ;
}
2025-09-15 13:02:44 -03:00
private function createTables () : void
2025-07-22 13:18:00 +00:00
{
2025-09-15 13:02:44 -03:00
foreach ( $this -> tables as $table ) {
if ( ! $this -> checkTableExists ( $table )) {
$this -> createTable ( $table );
}
}
2024-04-02 13:50:08 -03:00
}
2025-09-15 13:02:44 -03:00
private function createTable ( string $table ) : void
2025-09-11 17:35:02 -03:00
{
2025-09-15 13:02:44 -03:00
$query = sprintf ( $this -> baseQueries [ 'create' ], $table );
try {
$result = $this -> connection -> getPDO () -> exec ( $query );
if ( $result === false ) {
throw new PDOException ( 'Failed to create table: ' . $table );
}
} catch ( PDOException ) {}
2025-09-11 17:35:02 -03:00
}
2024-04-02 13:50:08 -03:00
private function cleanup () : void
{
2025-09-15 13:02:44 -03:00
foreach ( $this -> tables as $table ) {
$query = sprintf ( $this -> baseQueries [ 'delete' ], $table , $this -> retainDays );
try {
$result = $this -> connection -> getPDO () -> query ( $query );
if ( $result === false ) {
throw new PDOException ( 'Failed to delete from table: ' . $table );
}
} catch ( PDOException ) {}
}
2025-09-11 17:35:02 -03:00
}
2024-04-02 13:50:08 -03:00
}