Files
oficial/app/common/Implement/Log/Handler/MySQL.php
2025-09-11 17:50:58 -03:00

128 lines
4.2 KiB
PHP

<?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 PDOStatement $statement;
private PDOStatement $statementDeprecated;
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->checkTableExists()) {
$this->createTable();
}
if (!$this->checkTableDeprecatedExists()) {
$this->createTableDeprecated();
}
$this->cleanup();
$this->cleanupDeprecated();
$this->initialized();
}
if (str_contains(strtolower($record->message), 'deprecated:')) {
$this->statementDeprecated->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->statement->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
{
$query = <<<QUERY
INSERT INTO monolog (channel, level, message, time, context, extra)
VALUES (:channel, :level, :message, :time, :context, :extra)
QUERY;
$this->statement = $this->connection->getPDO()->prepare($query);
$query = <<<QUERY
INSERT INTO monolog_deprecated (channel, level, message, time, context, extra)
VALUES (:channel, :level, :message, :time, :context, :extra)
QUERY;
$this->statementDeprecated = $this->connection->getPDO()->prepare($query);
$this->initialized = true;
}
private function checkTableExists(): bool
{
$query = "SHOW TABLES LIKE 'monolog'";
try {
$result = $this->connection->query($query);
} catch (PDOException) {
return false;
}
return $result->rowCount() > 0;
}
private function checkTableDeprecatedExists(): bool
{
$query = "SHOW TABLES LIKE 'monolog_deprecated'";
try {
$result = $this->connection->query($query);
} catch (PDOException) {
return false;
}
return $result->rowCount() > 0;
}
private function createTable(): void
{
$query = <<<QUERY
CREATE TABLE IF NOT EXISTS monolog (
channel VARCHAR(255),
level VARCHAR(100),
message LONGTEXT,
time DATETIME,
context LONGTEXT,
extra LONGTEXT
)
QUERY;
$this->connection->getPDO()->exec($query);
}
private function createTableDeprecated(): void
{
$query = <<<QUERY
CREATE TABLE IF NOT EXISTS monolog_deprecated (
channel VARCHAR(255),
level VARCHAR(100),
message LONGTEXT,
time DATETIME,
context LONGTEXT,
extra LONGTEXT
)
QUERY;
}
private function cleanup(): void
{
$query = "DELETE FROM monolog WHERE time < DATE_SUB(CURDATE(), INTERVAL {$this->retainDays} DAY)";
$this->connection->query($query);
}
private function cleanupDeprecated(): void
{
$query = "DELETE FROM monolog_deprecated WHERE time < DATE_SUB(CURDATE(), INTERVAL {$this->retainDays} DAY)";
}
}