Files
oficial/app/common/Implement/Log/Handler/MySQL.php

117 lines
4.4 KiB
PHP
Raw Normal View History

2024-04-02 13:50:08 -03:00
<?php
namespace Incoviba\Common\Implement\Log\Handler;
2024-04-02 13:50:08 -03:00
use Incoviba\Common\Define\Connection;
2024-04-02 13:50:08 -03:00
use Monolog\Handler\AbstractProcessingHandler;
use Monolog\Level;
use Monolog\LogRecord;
2025-09-11 17:50:58 -03:00
use PDOException;
use PDOStatement;
2024-04-02 13:50:08 -03: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
}
$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);
}
$this->initialized = true;
}
2025-09-15 13:02:44 -03:00
private function checkTablesExist(): bool
{
2025-09-15 13:02:44 -03:00
return array_all($this->tables, fn($table) => $this->checkTableExists($table));
}
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-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
}