LogHole
Sistema de logging avancado para Laravel com armazenamento em base de dados, dashboard web, atributos PHP e ferramentas CLI.
Overview
O LogHole e um pacote de logging moderno e flexivel para Laravel com suporte a multiplos drivers de base de dados. Integra-se nativamente com a facade Log do Laravel atraves de um canal Monolog personalizado, oferecendo um dashboard web, comandos CLI e atributos PHP 8.2+ para logging declarativo.
Funcionalidades principais
- Canal Monolog para base de dados -- tabela
logs_holeconfiguravel - Multi-database -- MySQL, MariaDB, PostgreSQL, SQLite, SQL Server
- Dashboard web -- Tailwind CSS v3 + Alpine.js com dark/light mode
- Atributos PHP 8.2+ --
#[Loggable]a nivel de classe e metodo - LogLevel enum -- com badges coloridos por nivel
- Ferramentas CLI --
log-hole:tailcom filtragem e purge - Strategy Pattern --
LogDriverInterfacepara drivers customizados - Auto-refresh -- dashboard com atualizacao automatica a cada 5 segundos
Instalacao
Instale via Composer, publique a configuracao e execute as migrations.
composer require digitaldev-lx/log-hole
php artisan vendor:publish --tag="log-hole-config"
php artisan migrate
Configuracao
O ficheiro de configuracao e publicado em config/log-hole.php:
return [
'database' => [
'driver' => 'custom',
'via' => DigitalDevLx\LogHole\Channels\DatabaseChannel::class,
'level' => env('LOG_LEVEL', 'debug'),
'table' => 'logs_hole',
],
'connection' => env('LOG_HOLE_DB_CONNECTION', null),
'authorized_users' => [],
'dashboard_route' => 'log-hole',
'per_page' => 25,
'auto_refresh' => false,
];
Adicionar o canal de logging
Adicione o canal database ao ficheiro config/logging.php:
'channels' => [
'database' => config('log-hole.database'),
],
Opcoes de utilizacao do canal
LOG_CHANNEL=database
'stack' => [
'driver' => 'stack',
'channels' => ['single', 'database'],
],
Log::channel('database')->info('Mensagem aqui');
Conexao de base de dados personalizada
Para guardar logs numa base de dados separada:
LOG_HOLE_DB_CONNECTION=mysql_logs
Utilizacao
Utilize a facade Log standard do Laravel. Todos os niveis PSR-3 sao suportados: emergency, alert, critical, error, warning, notice, info, debug.
use Illuminate\Support\Facades\Log;
Log::info('Utilizador autenticou', ['user_id' => 1]);
Log::error('Falha no pagamento', [
'order_id' => 42,
'reason' => 'timeout',
]);
Log::warning('Espaco em disco a esgotar');
// Especificar canal explicitamente
Log::channel('database')->debug('Info de debug', [
'context' => 'value',
]);
Atributos PHP
O atributo #[Loggable] permite logging declarativo a nivel de classe e metodo. Requer a configuracao do middleware.
Configurar middleware
use DigitalDevLx\LogHole\Middlewares\LogHoleMiddleware;
->withMiddleware(function (Middleware $middleware) {
$middleware->append(LogHoleMiddleware::class);
})
protected $middlewareGroups = [
'web' => [
\DigitalDevLx\LogHole\Middlewares\LogHoleMiddleware::class,
],
];
Atributo a nivel de metodo
use DigitalDevLx\LogHole\Attributes\Loggable;
class OrderController extends Controller
{
#[Loggable(message: 'Encomenda criada', level: 'info')]
public function store(Request $request)
{
// logica aqui
}
#[Loggable(message: 'Encomenda eliminada', level: 'warning')]
public function destroy(Order $order)
{
// logica aqui
}
}
Atributo a nivel de classe
Aplicado a classe, todos os metodos sao registados automaticamente. Atributos de metodo tem prioridade sobre os da classe.
use DigitalDevLx\LogHole\Attributes\Loggable;
#[Loggable(level: 'info')]
class UserController extends Controller
{
public function index() { /* registado automaticamente */ }
public function show(User $user) { /* registado automaticamente */ }
}
Parametros do atributo
| Parametro | Tipo | Default | Descricao |
|---|---|---|---|
| message | string | '' | Mensagem custom; default "{method} was called" |
| level | LogLevel|string | LogLevel::Info | Nivel do log como enum ou string |
| includeRequest | bool | false | Incluir metodo HTTP, URL e IP |
| channel | ?string | null | Canal de destino especifico |
Usar o LogLevel enum
use DigitalDevLx\LogHole\Attributes\Loggable;
use DigitalDevLx\LogHole\Enums\LogLevel;
#[Loggable(
message: 'Acao critica executada',
level: LogLevel::Critical,
includeRequest: true
)]
public function dangerousAction()
{
// logica aqui
}
Dashboard Web
O LogHole inclui um dashboard web completo, acessivel em /log-hole (configuravel via dashboard_route). Construido com Tailwind CSS v3 e Alpine.js.
Funcionalidades
- Barra de estatisticas -- total e contadores por nivel com badges coloridos
- Filtros server-side -- por nivel, termo de pesquisa e intervalo de datas
- Contexto JSON expandivel -- visualizacao formatada por entrada
- Timestamps relativos -- "ha 5 minutos", "ha 2 horas"
- Dark/light mode -- com persistencia via localStorage
- Auto-refresh -- atualizacao a cada 5 segundos (toggle on/off)
- Paginacao -- styled com Tailwind CSS
Controlo de acesso
Restrinja o acesso definindo os emails autorizados. Utilizadores nao autorizados recebem um erro 403.
'authorized_users' => [
'admin@empresa.pt',
'developer@empresa.pt',
],
Tambem pode usar o Gate do Laravel para autorizacao programatica:
if (Gate::allows('viewLogHole')) {
// utilizador tem acesso
}
Ferramentas CLI
O comando log-hole:tail permite consultar e gerir logs directamente no terminal, com output tabular e contexto JSON formatado.
# Ultimos 10 logs
php artisan log-hole:tail
# Filtrar por nivel
php artisan log-hole:tail --error
php artisan log-hole:tail --critical
php artisan log-hole:tail --warning
# Filtrar por intervalo de datas
php artisan log-hole:tail --error --from=2024-10-01 --to=2024-10-31
# Limitar resultados
php artisan log-hole:tail --critical --take=5
# Purgar todos os logs (com confirmacao)
php artisan log-hole:tail --purge
Opcoes disponiveis
| Opcao | Descricao |
|---|---|
| --emergency | Filtrar por nivel EMERGENCY |
| --alert | Filtrar por nivel ALERT |
| --critical | Filtrar por nivel CRITICAL |
| --error | Filtrar por nivel ERROR |
| --warning | Filtrar por nivel WARNING |
| --notice | Filtrar por nivel NOTICE |
| --info | Filtrar por nivel INFO |
| --debug | Filtrar por nivel DEBUG |
| --from= | Data inicial (YYYY-MM-DD) |
| --to= | Data final (YYYY-MM-DD) |
| --take= | Limitar entradas (default: 10) |
| --purge | Purgar todos os logs (com confirmacao) |
Arquitetura de Drivers
O LogHole v2 implementa o Strategy Pattern com a interface LogDriverInterface. O DriverFactory deteta automaticamente a base de dados e retorna o driver adequado.
| Base de Dados | Driver | Funcionalidades |
|---|---|---|
| MySQL | MySqlDriver | JSON_EXTRACT para pesquisa de contexto |
| MariaDB | MariaDbDriver | Auto-detetado via PDO version string |
| PostgreSQL | PostgreSqlDriver | ILIKE para pesquisa case-insensitive |
| SQLite | SqliteDriver | DELETE em vez de TRUNCATE para purge |
| SQL Server | SqlServerDriver | CAST para NVARCHAR na pesquisa de contexto |
Usar o driver directamente
use DigitalDevLx\LogHole\Drivers\Contracts\LogDriverInterface;
use DigitalDevLx\LogHole\Enums\LogLevel;
$driver = app(LogDriverInterface::class);
// Inserir um log
$driver->insert(LogLevel::Info, 'Hello', ['key' => 'value'], now());
// Consultar com filtros
$logs = $driver->query(
level: LogLevel::Error,
search: 'payment',
limit: 20
);
// Resultados paginados
$paginated = $driver->paginate(
level: LogLevel::Warning,
perPage: 25
);
// Estatisticas
$stats = $driver->stats();
echo $stats->total;
echo $stats->countForLevel(LogLevel::Error);
// Purgar logs
$driver->purge(); // todos
$driver->purge(level: LogLevel::Debug); // por nivel
$driver->purge(before: now()->subMonth()); // por data
Boas Praticas
Usar contexto estruturado
Passe sempre um array de contexto com dados relevantes. Contexto estruturado facilita a filtragem e analise no dashboard. Evite mensagens genericas -- inclua IDs, nomes de operacao e dados que ajudem no debug.
Escolher o nivel correto
Use debug para troubleshooting, info para eventos normais, warning para situacoes anomalas mas recuperaveis, e error para falhas que requerem atencao.
Combinar com o stack channel
Use o canal stack do Laravel para enviar logs simultaneamente para ficheiro e base de dados, garantindo redundancia.
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['single', 'database'],
],
],
Purgar logs periodicamente
Use o driver directamente no scheduler para purgar logs antigos e evitar que a tabela cresca indefinidamente.
// routes/console.php
use DigitalDevLx\LogHole\Drivers\Contracts\LogDriverInterface;
Schedule::call(function () {
app(LogDriverInterface::class)->purge(
before: now()->subDays(30)
);
})->daily()->at('03:00');
Proteger o dashboard
Mantenha a lista de authorized_users atualizada. O dashboard mostra informacao sensivel -- trate-o como uma ferramenta interna.
Nao logar dados sensiveis
Nunca inclua passwords, tokens, numeros de cartao de credito ou dados pessoais identificaveis no contexto dos logs. Mascare ou omita informacao sensivel.
Testes
O pacote inclui 95 testes com Pest PHP, analise estatica com PHPStan Level 5 e formatacao PSR-12 com Laravel Pint.
# Todos os testes (Pest)
composer run test
# Testes com cobertura
composer run test-coverage
# Analise estatica (PHPStan Level 5)
composer run analyse
# Formatacao de codigo (PSR-12)
composer run format
# Verificacao completa (analyse + format)
composer run check
$ composer require digitaldev-lx/log-hole
Logging que funciona para si
Consulte o repositorio no GitHub para a documentacao completa, issues e contribuicoes.