> LOADING LOG-HOLE v2.0...

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.

PHP 8.2+ Laravel 10-11 MIT License 95 Tests PHPStan Level 5 PSR-12

Funcionalidades principais

  • Canal Monolog para base de dados -- tabela logs_hole configuravel
  • 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:tail com filtragem e purge
  • Strategy Pattern -- LogDriverInterface para drivers customizados
  • Auto-refresh -- dashboard com atualizacao automatica a cada 5 segundos

Instalacao

Instale via Composer, publique a configuracao e execute as migrations.

Instalacao
bash
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:

config/log-hole.php
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:

config/logging.php
php
'channels' => [
    'database' => config('log-hole.database'),
],

Opcoes de utilizacao do canal

Definir como canal por defeito no .env
bash
LOG_CHANNEL=database
Usar num stack
php
'stack' => [
    'driver' => 'stack',
    'channels' => ['single', 'database'],
],
Usar on-demand
php
Log::channel('database')->info('Mensagem aqui');

Conexao de base de dados personalizada

Para guardar logs numa base de dados separada:

.env
bash
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.

Logging via Facade
php
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

Laravel 11.x - bootstrap/app.php
php
use DigitalDevLx\LogHole\Middlewares\LogHoleMiddleware;

->withMiddleware(function (Middleware $middleware) {
    $middleware->append(LogHoleMiddleware::class);
})
Laravel 10.x - app/Http/Kernel.php
php
protected $middlewareGroups = [
    'web' => [
        \DigitalDevLx\LogHole\Middlewares\LogHoleMiddleware::class,
    ],
];

Atributo a nivel de metodo

Logging por metodo
php
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.

Logging de classe inteira
php
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

LogLevel enum
php
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.

config/log-hole.php
php
'authorized_users' => [
    'admin@empresa.pt',
    'developer@empresa.pt',
],

Tambem pode usar o Gate do Laravel para autorizacao programatica:

Gate authorization
php
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.

Exemplos de utilizacao
bash
# 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

LogDriverInterface
php
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.

config/logging.php - Stack channel
php
'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.

Purge agendado
php
// 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.

Comandos de desenvolvimento
bash
# 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.

> COOKIE_CONSENT_REQUIRED

Utilizamos cookies essenciais para o funcionamento do site e cookies analíticos (Google Analytics) para compreender como utiliza o nosso site. Os cookies analíticos só são ativados com o seu consentimento. Política de Privacidade