develop (#45)
Co-authored-by: Juan Pablo Vial <jpvialb@incoviba.cl> Reviewed-on: #45
This commit is contained in:
116
app/common/Implement/Log/Handler/MySQL.php
Normal file
116
app/common/Implement/Log/Handler/MySQL.php
Normal file
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
namespace Incoviba\Common\Implement\Log\Handler;
|
||||
|
||||
use Incoviba\Common\Define\Connection;
|
||||
use Monolog\Handler\AbstractProcessingHandler;
|
||||
use Monolog\Level;
|
||||
use Monolog\LogRecord;
|
||||
use PDOException;
|
||||
use PDOStatement;
|
||||
|
||||
class MySQL extends AbstractProcessingHandler
|
||||
{
|
||||
private bool $initialized = false;
|
||||
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)"
|
||||
];
|
||||
|
||||
public function __construct(protected Connection $connection, protected int $retainDays = 90,
|
||||
int|string|Level $level = Level::Debug, bool $bubble = true)
|
||||
{
|
||||
parent::__construct($level, $bubble);
|
||||
}
|
||||
public function write(LogRecord $record): void
|
||||
{
|
||||
if (!$this->initialized) {
|
||||
if (!$this->checkTablesExist()) {
|
||||
$this->createTables();
|
||||
}
|
||||
$this->cleanup();
|
||||
$this->initialized();
|
||||
}
|
||||
if (str_contains(strtolower($record->message), 'deprecated:')) {
|
||||
$this->statements['deprecated']->execute([
|
||||
'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;
|
||||
}
|
||||
$this->statements['default']->execute([
|
||||
'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
|
||||
{
|
||||
foreach ($this->tables as $type => $table) {
|
||||
$query = sprintf($this->baseQueries['insert'], $table);
|
||||
$this->statements[$type] = $this->connection->getPDO()->prepare($query);
|
||||
}
|
||||
$this->initialized = true;
|
||||
}
|
||||
private function checkTablesExist(): bool
|
||||
{
|
||||
return array_all($this->tables, fn($table) => $this->checkTableExists($table));
|
||||
}
|
||||
private function checkTableExists(string $table): bool
|
||||
{
|
||||
$query = sprintf($this->baseQueries['check'], $table);
|
||||
try {
|
||||
$result = $this->connection->query($query);
|
||||
} catch (PDOException) {
|
||||
return false;
|
||||
}
|
||||
return $result->rowCount() > 0;
|
||||
}
|
||||
private function createTables(): void
|
||||
{
|
||||
foreach ($this->tables as $table) {
|
||||
if (!$this->checkTableExists($table)) {
|
||||
$this->createTable($table);
|
||||
}
|
||||
}
|
||||
}
|
||||
private function createTable(string $table): void
|
||||
{
|
||||
$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) {}
|
||||
}
|
||||
private function cleanup(): void
|
||||
{
|
||||
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) {}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user