PHPackages                             risetechapps/monitoring-for-laravel - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Logging &amp; Monitoring](/categories/logging)
4. /
5. risetechapps/monitoring-for-laravel

ActiveLibrary[Logging &amp; Monitoring](/categories/logging)

risetechapps/monitoring-for-laravel
===================================

3.0.0(2mo ago)0480↓60.3%4MITPHPPHP ^8.3CI failing

Since Dec 8Pushed 2mo ago1 watchersCompare

[ Source](https://github.com/risetechapps/monitoring-for-laravel)[ Packagist](https://packagist.org/packages/risetechapps/monitoring-for-laravel)[ Docs](https://github.com/risetechapps/monitoring-for-laravel)[ RSS](/packages/risetechapps-monitoring-for-laravel/feed)WikiDiscussions main Synced 3w ago

READMEChangelogDependencies (14)Versions (10)Used By (4)

Monitoring for Laravel
======================

[](#monitoring-for-laravel)

[![Latest Version on Packagist](https://camo.githubusercontent.com/7a8cf900c7ae5403d5f5f444613a35f563bdf35dfd37e078eb3785bf10ba9b75/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7269736574656368617070732f6d6f6e69746f72696e672d666f722d6c61726176656c2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/risetechapps/monitoring-for-laravel)[![PHP Version](https://camo.githubusercontent.com/ef0054230522e542bc1f908ac005c6c75888dea255bac910f9015e12095e31d7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253545382e332d626c7565)](https://www.php.net)[![Laravel Version](https://camo.githubusercontent.com/ec976ad699fb5ffbb43421eabc292424a8b0bc5bed7a28e11e6349c67e2b6599/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c61726176656c2d25354531322e302d726564)](https://laravel.com)[![License: MIT](https://camo.githubusercontent.com/fdf2982b9f5d7489dcf44570e714e3a15fce6253e0cc6b5aa61a075aac2ff71b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f772e737667)](https://opensource.org/licenses/MIT)

**Monitoring for Laravel** é um pacote de monitoramento completo para aplicações Laravel, desenvolvido pela [RiseTechApps](https://github.com/risetechapps). Ele captura automaticamente eventos da aplicação — requisições HTTP, exceções, jobs, comandos, notificações, e-mails, gates de autorização, eventos e muito mais — com suporte a múltiplos drivers de armazenamento.

---

Requisitos
----------

[](#requisitos)

- PHP `^8.3`
- Laravel `^12.0`
- Laravel Sanctum `^4.0`

---

Instalação
----------

[](#instalação)

Instale o pacote via Composer:

```
composer require risetechapps/monitoring-for-laravel
```

O pacote se registra automaticamente via *auto-discovery* do Laravel. O `ServiceProvider` e o alias `Logs` são configurados automaticamente.

### Publicar a configuração

[](#publicar-a-configuração)

```
php artisan vendor:publish --tag=config --provider="RiseTechApps\Monitoring\MonitoringServiceProvider"
```

Isso criará o arquivo `config/monitoring.php` na sua aplicação.

### Executar as migrações (drivers MySQL / PostgreSQL)

[](#executar-as-migrações-drivers-mysql--postgresql)

```
php artisan migrate
```

As migrações criam:

- A tabela `monitoring` com os campos padrão
- Índices para otimização de consultas
- **Campos de resolução de exceções** (`resolved_at`, `resolved_by`) — úteis para marcar exceções como "resolvidas"

---

Configuração
------------

[](#configuração)

O arquivo `config/monitoring.php` centraliza todas as opções do pacote.

### Opções principais

[](#opções-principais)

```
return [
    // Habilita ou desabilita o monitoramento globalmente
    'enabled' => env('MONITORING_ENABLED', true),

    // Driver de armazenamento: 'single' ou 'database'
    'driver' => env('MONITORING_DRIVER', 'single'),

    // Quantidade de entradas acumuladas antes de persistir (buffer)
    'buffer_size' => (int) env('MONITORING_BUFFER_SIZE', 5),

    'watchers' => [ ... ],

    'drivers' => [ ... ],
];
```

### Variáveis de ambiente

[](#variáveis-de-ambiente)

VariávelPadrãoDescrição`MONITORING_ENABLED``true`Liga/desliga o monitoramento`MONITORING_DRIVER``single`Driver de armazenamento---

Drivers de Armazenamento
------------------------

[](#drivers-de-armazenamento)

O pacote suporta quatro drivers, configuráveis via `MONITORING_DRIVER`.

### `single` — Arquivo de Log

[](#single--arquivo-de-log)

Persiste os eventos em um arquivo local (`storage/logs/monitoring.log`). Ideal para desenvolvimento ou ambientes sem banco de dados.

```
MONITORING_DRIVER=single
```

### `mysql` — MySQL

[](#mysql--mysql)

Armazena os eventos na tabela `monitoring` de uma conexão MySQL.

```
MONITORING_DRIVER=mysql
DB_CONNECTION=mysql
```

```
// config/monitoring.php
'mysql' => [
    'connection' => env('DB_CONNECTION', 'mysql'),
],
```

### `pgsql` — PostgreSQL

[](#pgsql--postgresql)

Idêntico ao driver MySQL, mas para conexões PostgreSQL.

```
MONITORING_DRIVER=pgsql
DB_CONNECTION=pgsql
```

```
'pgsql' => [
    'connection' => env('DB_CONNECTION', 'pgsql'),
],
```

---

Watchers
--------

[](#watchers)

Os *watchers* são os componentes responsáveis por interceptar e registrar cada categoria de evento. Todos podem ser habilitados/desabilitados individualmente no arquivo de configuração.

### RequestWatcher — Requisições HTTP

[](#requestwatcher--requisições-http)

Monitora todas as requisições HTTP recebidas pela aplicação.

**Dados coletados:** IP do cliente, URI, método HTTP, controller/action, middlewares, headers, payload, sessão, resposta, duração (ms) e uso de memória (MB).

**Opções de filtro:**

```
\RiseTechApps\Monitoring\Watchers\RequestWatcher::class => [
    'enabled' => true,
    'options' => [
        'ignore_http_methods' => ['options'],   // Ignora métodos HTTP específicos
        'ignore_status_codes' => [404],         // Ignora códigos de status HTTP
        'ignore_paths' => ['telescope', 'horizon'], // Ignora paths específicos
        'size_limit' => 64,                     // Limite de tamanho da resposta em KB
    ],
],
```

> **Segurança:** Os campos `password`, `password_confirmation`, `authorization` e `php-auth-pw` são automaticamente mascarados como `********`.

---

### ExceptionWatcher — Exceções

[](#exceptionwatcher--exceções)

Captura exceções registradas via `Log::error()`, `Log::critical()` e similares que passem uma instância de `Throwable` no contexto.

**Dados coletados:** classe da exceção, arquivo, linha, mensagem, contexto adicional, stack trace e preview de código (linhas ao redor da exceção).

**Opções:**

```
\RiseTechApps\Monitoring\Watchers\ExceptionWatcher::class => [
    'enabled' => true,
    'options' => [
        // Ignorar classes de exceção específicas
        'ignore_exceptions' => [
            \Illuminate\Validation\ValidationException::class,
            \Symfony\Component\HttpKernel\Exception\NotFoundHttpException::class,
        ],
        // Ignorar exceções cujas mensagens contenham estes textos
        'ignore_messages_containing' => ['password', 'sensitive_data'],
        // Ignorar exceções de arquivos que contenham estes caminhos
        'ignore_files_containing' => ['/vendor/'],
    ],
],
```

---

### EventWatcher — Eventos

[](#eventwatcher--eventos)

Registra os eventos disparados na aplicação, excluindo eventos internos do framework por padrão.

**Dados coletados:** nome do evento, payload formatado, lista de listeners e indicação se o evento é broadcast.

**Opções:**

```
\RiseTechApps\Monitoring\Watchers\EventWatcher::class => [
    'enabled' => true,
    'options' => [
        'ignore' => [
            'App\Events\MeuEventoInterno',
        ],
    ],
],
```

---

### CommandWatcher — Artisan Commands

[](#commandwatcher--artisan-commands)

Monitora comandos Artisan executados.

**Dados coletados:** nome do comando, código de saída (`exit_code`), argumentos e opções.

> Os comandos `schedule:run`, `schedule:finish`, `package:discover`, `horizon:*`, `migrate:*` e outros comandos internos são ignorados automaticamente.

**Opções:**

```
\RiseTechApps\Monitoring\Watchers\CommandWatcher::class => [
    'enabled' => true,
    'options' => [
        'ignore' => ['meu:comando-interno'],
    ],
],
```

---

### ScheduleWatcher — Tarefas Agendadas

[](#schedulewatcher--tarefas-agendadas)

Registra a execução das tarefas agendadas do Laravel Scheduler.

**Dados coletados:** comando ou closure, descrição, expressão cron, timezone, usuário e saída do comando.

**Opções:**

```
\RiseTechApps\Monitoring\Watchers\ScheduleWatcher::class => [
    'enabled' => true,
    'options' => [
        // Ignorar comandos agendados específicos
        'ignore_commands' => ['my:scheduled-command'],
        // Ignorar closures (tarefas agendadas como closures)
        'ignore_closures' => false,
    ],
],
```

---

### JobWatcher — Jobs de Fila

[](#jobwatcher--jobs-de-fila)

Monitora o ciclo de vida completo de jobs, incluindo pendente, processado e falho.

**Dados coletados:**

- **Pendente:** nome, conexão, fila, tentativas, timeout, payload, `batch_id`
- **Processado:** status, nome do job, tentativas, hostname
- **Falho:** status, nome do job, mensagem de exceção, trace, preview de código, hostname

**Opções:**

```
\RiseTechApps\Monitoring\Watchers\JobWatcher::class => [
    'enabled' => true,
    'options' => [
        // Ignorar namespaces de jobs
        'ignore_namespaces' => [
            'App\Jobs\Internal\',
        ],
        // Ignorar jobs específicos
        'ignore_jobs' => [
            \App\Jobs\HeavyLoggingJob::class,
        ],
    ],
],
```

> Jobs do próprio pacote, Telescope, Horizon e Pulse são ignorados automaticamente.

---

### QueueWatcher — Worker de Fila

[](#queuewatcher--worker-de-fila)

Detecta parada e retomada do worker de fila. Cria um arquivo `storage/framework/queue_stopping` ao parar e o remove ao retomar.

---

### GateWatcher — Autorização

[](#gatewatcher--autorização)

Monitora todas as verificações de autorização (Gates e Policies).

**Dados coletados:** ability verificada, resultado (`allowed`/`denied`), argumentos e arquivo/linha de origem da chamada.

**Opções:**

```
\RiseTechApps\Monitoring\Watchers\GateWatcher::class => [
    'enabled' => true,
    'options' => [
        'ignore_abilities' => ['viewNova'],
    ],
],
```

---

### NotificationWatcher — Notificações

[](#notificationwatcher--notificações)

Captura notificações enviadas pela aplicação.

**Dados coletados:** classe da notificação, se é queued, notifiable, canal, resposta e UUID da notificação.

**Opções:**

```
\RiseTechApps\Monitoring\Watchers\NotificationWatcher::class => [
    'enabled' => true,
    'options' => [
        // Ignorar classes de notificação específicas
        'ignore_notifications' => [
            \App\Notifications\TestNotification::class,
        ],
        // Ignorar canais específicos
        'ignore_channels' => ['broadcast', 'slack'],
        // Ignorar notificações anônimas (AnonymousNotifiable)
        'ignore_anonymous' => false,
    ],
],
```

---

### MailWatcher — E-mails

[](#mailwatcher--e-mails)

Registra todos os e-mails enviados.

**Dados coletados:** classe mailable, se é queued, remetente, reply-to, destinatários (to, cc, bcc), assunto, corpo HTML e e-mail bruto.

**Opções:**

```
\RiseTechApps\Monitoring\Watchers\MailWatcher::class => [
    'enabled' => true,
    'options' => [
        // Ignorar classes Mailable específicas
        'ignore_mailables' => [
            \App\Mail\TestMail::class,
        ],
        // Ignorar e-mails cujo assunto contenha estes textos
        'ignore_subjects_containing' => ['[Test]', '[Local]'],
        // Ignorar e-mails de remetentes específicos
        'ignore_from_addresses' => ['noreply@example.com'],
        // Ignorar e-mails para destinatários específicos
        'ignore_to_addresses' => ['test@example.com'],
    ],
],
```

---

### ClientRequestWatcher — HTTP Client (Saída)

[](#clientrequestwatcher--http-client-saída)

Monitora requisições HTTP feitas *pela* aplicação usando o `Http::` facade do Laravel.

**Dados coletados:** método, URI, headers, payload, status da resposta, headers da resposta, corpo da resposta e duração (ms).

> Requisições para os hosts da própria plataforma de monitoramento são ignoradas automaticamente para evitar loops.

**Opções:**

```
\RiseTechApps\Monitoring\Watchers\ClientRequestWatcher::class => [
    'enabled' => true,
    'options' => [
        'ignore_hosts' => ['api.interna.com'],
        'size_limit' => 64,
    ],
],

---

### QueryWatcher — Queries Lentas

Monitora automaticamente queries SQL que excedem um tempo limite configurado.

**Dados coletados:** SQL completo, bindings, tempo de execução, conexão utilizada, arquivo e linha de origem.

**Opções:**

```php
\RiseTechApps\Monitoring\Watchers\QueryWatcher::class => [
    'enabled' => true,
    'options' => [
        // Threshold em ms para considerar query lenta
        'slow_query_threshold_ms' => 100,
        // Padrões de SQL que devem ser ignorados
        'ignore_patterns' => ['information_schema', 'migrations', 'telescope'],
        // Logar bindings das queries
        'log_bindings' => true,
        // Tamanho máximo do SQL antes de truncar
        'max_sql_length' => 5000,
    ],
],
```

**Exemplo de uso:**

```
# Ver queries lentas
GET /monitoring/type/query

# Buscar queries específicas
GET /monitoring/search?q=SELECT * FROM orders
```

---

### CacheWatcher — Operações de Cache

[](#cachewatcher--operações-de-cache)

Monitora hits, misses, escritas e deleções no cache da aplicação.

**Dados coletados:** operação (hit/miss/write/delete), key, store (redis/memcached/file), TTL (para writes).

**Opções:**

```
\RiseTechApps\Monitoring\Watchers\CacheWatcher::class => [
    'enabled' => true,
    'options' => [
        // Registrar cache hits
        'track_hits' => true,
        // Registrar cache misses
        'track_misses' => true,
        // Chaves de cache que devem ser ignoradas
        'ignore_keys' => ['config', 'routes', 'telescope'],
    ],
],
```

**Casos de uso:**

- Identificar keys com baixo hit rate
- Detectar cache thrashing (misses excessivos)
- Analisar TTL efetivo das keys

```

---

## Loggly — Logger Estruturado

O `Loggly` é o componente de log manual do pacote, acessível via função helper global. Ele oferece uma API fluente para registrar logs ricos e estruturados.

### Helpers disponíveis

```php
loggly()          // Info (padrão)
logglyInfo()      // Nível INFO
logglyDebug()     // Nível DEBUG
logglyWarning()   // Nível WARNING
logglyNotice()    // Nível NOTICE
logglyError()     // Nível ERROR
logglyCritical()  // Nível CRITICAL
logglyAlert()     // Nível ALERT
logglyEmergency() // Nível EMERGENCY
logglyModel()     // Nível MODEL

```

### API fluente

[](#api-fluente)

```
loggly()
    ->level('error')                        // Define o nível
    ->performedOn($user)                    // Modelo ou string do contexto
    ->exception($exception)                 // Captura dados da exceção
    ->withProperties(['key' => 'value'])    // Propriedades extras
    ->withContext(['request_id' => '123'])  // Contexto adicional
    ->withTags(['pagamento', 'critico'])    // Tags para categorização
    ->withRequest($request->all())          // Dados da requisição
    ->withResponse($response->json())       // Dados da resposta
    ->at(new DateTime())                    // Timestamp personalizado
    ->encrypt()                             // Encripta a mensagem
    ->to('loggly')                          // Destino: 'loggly' ou 'file'
    ->log('Mensagem do log');
```

### Exemplos de uso

[](#exemplos-de-uso)

**Log simples:**

```
logglyInfo()->log('Usuário autenticado com sucesso.');
```

**Log de exceção com contexto:**

```
try {
    // ...
} catch (Exception $e) {
    logglyError()
        ->performedOn(PaymentService::class)
        ->exception($e)
        ->withProperties(['order_id' => $orderId])
        ->log('Falha ao processar pagamento.');
}
```

**Log de modelo:**

```
logglyModel()
    ->performedOn($produto)
    ->withContext(['acao' => 'preco_atualizado'])
    ->log('Preço do produto foi alterado.');
```

**Salvar em arquivo (sem enviar para o driver principal):**

```
loggly()->to('file')->log('Debug local.');
```

---

Trait `HasLoggly` — Auditoria de Models
---------------------------------------

[](#trait-hasloggly--auditoria-de-models)

Adicione a trait `HasLoggly` a qualquer Model Eloquent para registrar automaticamente as operações de criação, atualização, exclusão e restauração.

```
use RiseTechApps\Monitoring\Traits\HasLoggly\HasLoggly;

class Produto extends Model
{
    use HasLoggly;
}
```

### Eventos monitorados

[](#eventos-monitorados)

Evento EloquentAção registrada`created``Created record.``updated``Updated record.` (com diff dos campos alterados)`deleted``Deleted record.` ou `Force deleted record.``restored``Restored record.` (apenas com SoftDeletes)### Dados coletados

[](#dados-coletados)

- **updated:** classe do model, valores antigos, valores novos e um diff com `old`/`new` para cada campo alterado.
- **created/deleted/restored:** classe do model e atributos atuais do model.

> Se o Model usar `SoftDeletes`, o evento `restored` é monitorado automaticamente.

---

Métricas Customizáveis
----------------------

[](#métricas-customizáveis)

Além dos watchers automáticos, você pode registrar métricas de negócio personalizadas usando o helper `monitoring()`.

### Tipos de Métricas

[](#tipos-de-métricas)

#### Gauge (Valor Pontual)

[](#gauge-valor-pontual)

Registra um valor em um momento específico. Ideal para contagens, estados ou níveis.

```
// Contagem de pedidos pendentes
monitoring()->gauge('pedidos_pendentes', Pedido::where('status', 'pendente')->count());

// Valor em estoque de um produto
monitoring()->gauge('estoque_produto', $produto->quantidade, ['produto_id' => $produto->id]);

// Usuários ativos no momento
monitoring()->gauge('usuarios_ativos', Cache::get('online_users', 0));
```

#### Counter (Contador)

[](#counter-contador)

Incrementa um contador. Ideal para eventos discretos.

```
// Checkout concluído
monitoring()->increment('checkout_concluido');

// Incremento com valor personalizado
monitoring()->increment('itens_vendidos', $quantidade);

// Com tags adicionais
monitoring()->increment('pagamentos', 1, ['metodo' => 'cartao']);
monitoring()->increment('pagamentos', 1, ['metodo' => 'boleto']);
```

#### Histogram (Distribuição)

[](#histogram-distribuição)

Registra valores em uma distribuição. Ideal para tempos e tamanhos.

```
// Tempo de processamento em milissegundos
monitoring()->histogram('tempo_processamento', 250);

// Tamanho da resposta da API
monitoring()->histogram('tamanho_resposta_api', strlen($responseBody));

// Com tags para segmentação
monitoring()->histogram('tempo_db', $queryTime, ['tabela' => 'pedidos']);
```

#### Timer (Medidor de Tempo)

[](#timer-medidor-de-tempo)

Executa um código e automaticamente registra o tempo de execução.

```
// Medir tempo de uma operação
$resultado = monitoring()->timer('processar_pedido', function() use ($pedido) {
    return $this->processarPedido($pedido);
});

// Medir chamada de API externa
$dados = monitoring()->timer('api_pagamento', function() use ($payload) {
    return Http::post('https://api.pagamento.com', $payload)->json();
});

// Com tags
$relatorio = monitoring()->timer('gerar_relatorio', function() {
    return $this->gerarRelatorioVendas();
}, ['tipo' => 'vendas', 'periodo' => 'mensal']);
```

### Dados Coletados

[](#dados-coletados-1)

Cada métrica registra:

CampoDescrição`metric_type`Tipo: `gauge`, `counter`, `histogram``metric_name`Nome da métrica (ex: `checkout_concluido`)`value`Valor numérico registrado`tags`Tags adicionais para segmentação`created_at`Timestamp do registro### Exemplos de Uso na Prática

[](#exemplos-de-uso-na-prática)

**Controller de Checkout:**

```
class CheckoutController extends Controller
{
    public function processar(Request $request)
    {
        $resultado = monitoring()->timer('checkout_total', function() use ($request) {
            // Validação
            $dados = $request->validate([...]);

            // Processamento do pagamento
            $pagamento = monitoring()->timer('processar_pagamento', function() use ($dados) {
                return $this->pagamentoService->processar($dados);
            }, ['gateway' => $dados['gateway']]);

            // Criar pedido
            $pedido = Pedido::create([...]);

            // Atualizar estoque
            monitoring()->gauge('estoque_reduzido', $this->atualizarEstoque($pedido));

            return $pedido;
        });

        monitoring()->increment('pedidos_criados', 1, [
            'metodo_pagamento' => $resultado->metodo
        ]);

        return response()->json($resultado);
    }
}
```

**Job de Processamento:**

```
class ProcessarImportacaoJob implements ShouldQueue
{
    public function handle()
    {
        monitoring()->gauge('registros_a_processar', $this->totalRegistros);

        foreach ($this->registros as $registro) {
            $processado = monitoring()->timer('processar_registro', function() use ($registro) {
                return $this->processar($registro);
            });

            if ($processado) {
                monitoring()->increment('registros_sucesso');
            } else {
                monitoring()->increment('registros_falha');
            }
        }

        monitoring()->gauge('registros_restantes', 0);
    }
}
```

**Comando Artisan:**

```
class LimparCacheCommand extends Command
{
    public function handle()
    {
        $chavesRemovidas = monitoring()->timer('limpar_cache', function() {
            return Cache::flush();
        });

        monitoring()->increment('cache_limpo', $chavesRemovidas);
        monitoring()->gauge('cache_tamanho', Cache::getMemoryUsage());

        $this->info("Cache limpo: {$chavesRemovidas} chaves removidas.");
    }
}
```

### Consultando Métricas

[](#consultando-métricas)

As métricas são registradas com `type = 'metric'` e podem ser consultadas via API ou repositório:

```
use RiseTechApps\Monitoring\Entry\EntryType;

// Todas as métricas
$metricas = $monitoring->getEventsByTypes(EntryType::METRIC);

// Filtrar por nome de métrica
$checkouts = $metricas->filter(fn($m) => $m['content']['metric_name'] === 'checkout_concluido');

// Calcular estatísticas
$totalCheckouts = $checkouts->sum('content.value');
$tempoMedio = $checkouts->where('content.metric_type', 'histogram')->avg('content.value');
```

---

Middleware `monitoring.disable`
-------------------------------

[](#middleware-monitoringdisable)

Use o middleware para desabilitar o monitoramento em rotas específicas, como painéis administrativos ou endpoints de health check.

### Registrando nas rotas

[](#registrando-nas-rotas)

```
// routes/web.php ou routes/api.php

Route::middleware('monitoring.disable')->group(function () {
    Route::get('/health', fn () => response()->json(['status' => 'ok']));
    Route::get('/admin/dashboard', [AdminController::class, 'index']);
});
```

### Aplicando em um controller

[](#aplicando-em-um-controller)

```
public function __construct()
{
    $this->middleware('monitoring.disable');
}
```

---

Controle Programático
---------------------

[](#controle-programático)

### Desabilitar o monitoramento

[](#desabilitar-o-monitoramento)

```
use RiseTechApps\Monitoring\Monitoring;

Monitoring::disable();
```

### Verificar se está habilitado

[](#verificar-se-está-habilitado)

```
if (Monitoring::isEnabled()) {
    // ...
}
```

### Adicionar tags globais a todas as entradas

[](#adicionar-tags-globais-a-todas-as-entradas)

```
// Em um ServiceProvider
Monitoring::tag(function ($entry) {
    return ['ambiente:' . app()->environment()];
});
```

### Ocultar parâmetros sensíveis

[](#ocultar-parâmetros-sensíveis)

```
// Em um ServiceProvider
Monitoring::$hiddenRequestParameters = ['cartao_numero', 'cvv'];
Monitoring::$hiddenResponseParameters = ['token_acesso', 'secret'];
```

### Registrar rotas do pacote

[](#registrar-rotas-do-pacote)

```
Monitoring::routes();
```

---

Estrutura da Tabela (`monitoring`)
----------------------------------

[](#estrutura-da-tabela-monitoring)

Quando usando os drivers `mysql` ou `pgsql`, os eventos são armazenados na tabela `monitoring`:

ColunaTipoDescrição`id`UUID (PK)Identificador primário`uuid`UUID (unique)Identificador único da entrada`batch_id`UUIDAgrupa entradas de uma mesma requisição/job`type`string(20)Tipo da entrada (veja abaixo)`content`JSONDados específicos do evento`tags`JSONTags associadas à entrada`user`JSONDados do usuário autenticado`device`JSONDados do dispositivo/browser`resolved_at`timestamp (nullable)Quando a exceção foi marcada como resolvida`resolved_by`string (nullable)Identificador de quem resolveu (email/user\_id)`created_at`timestamp—`updated_at`timestamp—### Tipos de entrada (`type`)

[](#tipos-de-entrada-type)

ConstanteValorDescrição`EntryType::REQUEST``request`Requisição HTTP recebida`EntryType::EXCEPTION``exception`Exceção capturada`EntryType::EVENT``event`Evento da aplicação`EntryType::COMMAND``command`Comando Artisan`EntryType::SCHEDULED_TASK``schedule`Tarefa agendada`EntryType::JOB``job`Job de fila`EntryType::GATE``gate`Verificação de autorização`EntryType::NOTIFICATION``notification`Notificação enviada`EntryType::MAIL``mail`E-mail enviado`EntryType::CLIENT_REQUEST``client_request`Requisição HTTP de saída`EntryType::LOG``log`Log manual via Loggly`EntryType::MODEL``model`Operação em Model Eloquent`EntryType::QUERY``query`Query no banco de dados`EntryType::METRIC``metric`Métrica de negócio customizada---

Buffer de Entradas
------------------

[](#buffer-de-entradas)

O pacote utiliza um buffer em memória para otimizar a performance, evitando uma escrita no storage para cada evento individualmente.

- As entradas são acumuladas no buffer até atingir `buffer_size` (padrão: `5`).
- O buffer é descarregado automaticamente ao final de cada requisição HTTP (evento `RequestHandled`).
- Em ambientes de console (jobs, commands), o buffer é descarregado imediatamente após cada entrada.

Configure o tamanho do buffer:

```
MONITORING_BUFFER_SIZE=10
```

---

Consultando os Registros de Monitoramento
-----------------------------------------

[](#consultando-os-registros-de-monitoramento)

O pacote fornece um repositório com métodos padronizados para leitura dos eventos, disponíveis para os drivers `dabase`. O driver `single` (arquivo) **não suporta leitura** — seus métodos retornam coleções vazias.

### Injetando o Repositório

[](#injetando-o-repositório)

Você pode injetar o `MonitoringRepositoryInterface` em qualquer controller, service ou job:

```
use RiseTechApps\Monitoring\Repository\Contracts\MonitoringRepositoryInterface;

class MonitoringDashboardController extends Controller
{
    public function __construct(
        protected MonitoringRepositoryInterface $monitoring
    ) {}
}
```

Ou resolver diretamente via container:

```
$monitoring = app(MonitoringRepositoryInterface::class);
```

---

### Métodos de Consulta

[](#métodos-de-consulta)

Todos os métodos retornam uma `Illuminate\Support\Collection`.

#### Todos os eventos

[](#todos-os-eventos)

```
$events = $monitoring->getAllEvents();
// Retorna todos os registros ordenados por created_at DESC
```

#### Evento por ID

[](#evento-por-id)

Retorna o evento específico **e todos os eventos relacionados do mesmo `batch_id`** no campo `related_events`.

```
$event = $monitoring->getEventById('uuid-ou-id-aqui');

// Estrutura de retorno:
// [
//   'id'             => '...',
//   'uuid'           => '...',
//   'batch_id'       => '...',
//   'type'           => 'request',
//   'content'        => [...],
//   'tags'           => [...],
//   'user'           => [...],
//   'device'         => [...],
//   'created_at'     => '...',
//   'updated_at'     => '...',
//   'related_events' => [...],  // outros eventos do mesmo batch
// ]
```

#### Eventos por tipo

[](#eventos-por-tipo)

Filtra por um dos tipos definidos em `EntryType`. Retorna cada evento com seu `related_events`.

```
use RiseTechApps\Monitoring\Entry\EntryType;

$requests    = $monitoring->getEventsByTypes(EntryType::REQUEST);
$exceptions  = $monitoring->getEventsByTypes(EntryType::EXCEPTION);
$jobs        = $monitoring->getEventsByTypes(EntryType::JOB);
$commands    = $monitoring->getEventsByTypes(EntryType::COMMAND);
$mails       = $monitoring->getEventsByTypes(EntryType::MAIL);
$logs        = $monitoring->getEventsByTypes(EntryType::LOG);
$models      = $monitoring->getEventsByTypes(EntryType::MODEL);
$gates       = $monitoring->getEventsByTypes(EntryType::GATE);
$events      = $monitoring->getEventsByTypes(EntryType::EVENT);
$schedules   = $monitoring->getEventsByTypes(EntryType::SCHEDULED_TASK);
$notifs      = $monitoring->getEventsByTypes(EntryType::NOTIFICATION);
$outbound    = $monitoring->getEventsByTypes(EntryType::CLIENT_REQUEST);
```

#### Eventos por batch

[](#eventos-por-batch)

Retorna todos os eventos que pertencem a um mesmo ciclo de requisição ou job, agrupados pelo `batch_id`.

```
$batchEvents = $monitoring->getByBatch('batch-uuid-aqui');
```

#### Lista de tipos disponíveis

[](#lista-de-tipos-disponíveis)

```
$types = $monitoring->getEventsByTags();
// Retorna: ['command', 'event', 'exception', 'job', 'log', 'mail',
//           'model', 'notification', 'query', 'request',
//           'schedule', 'client_request', 'gate']
```

---

### Consulta por Período

[](#consulta-por-período)

Filtra eventos pelos períodos pré-definidos:

```
$monitoring->getLast24Hours();  // Últimas 24 horas
$monitoring->getLast7Days();    // Últimos 7 dias
$monitoring->getLast15Days();   // Últimos 15 dias
$monitoring->getLast30Days();   // Últimos 30 dias
$monitoring->getLast60Days();   // Últimos 60 dias
$monitoring->getLast90Days();   // Últimos 90 dias
```

---

### Suporte por Driver

[](#suporte-por-driver)

Método`database``single``getAllEvents()`✅❌`getEventById()`✅❌`getEventsByTypes()`✅❌`getEventsByTags()`✅✅\*`getByBatch()`✅❌`getTimelineByTag()`✅❌`gauge()`✅✅`increment()`✅✅`histogram()`✅✅`timer()`✅✅`getLast24Hours()`✅❌`getLast7Days()`✅❌`getLast15Days()`✅❌`getLast30Days()`✅❌`getLast60Days()`✅❌`getLast90Days()`✅❌`resolveEvent()`✅❌`resolveExceptionType()`✅❌`unresolveEvent()`✅❌`getUnresolvedExceptions()`✅❌> \*`getEventsByTags()` no driver `single` retorna apenas a lista de tipos disponíveis.

---

### Rotas HTTP de Consulta

[](#rotas-http-de-consulta)

O pacote disponibiliza rotas prontas para expor os eventos via API. Registre-as no `AppServiceProvider` ou `RouteServiceProvider`:

```
use RiseTechApps\Monitoring\Monitoring;

// Registro básico (usa middleware 'api' por padrão)
Monitoring::routes();
```

**Opções disponíveis:**

```
Monitoring::routes([
    'middleware'  => ['api', 'auth:sanctum'],  // middlewares customizados
    'authorize'   => 'view-monitoring',         // Gate/Policy de autorização
    'rate_limit'  => '60,1',                    // throttle: 60 req/min
    'as'          => 'monitoring.',             // prefixo dos nomes das rotas
]);
```

**Endpoints registrados:**

MétodoURINomeDescrição`GET``/monitoring``monitoring.index`Lista todos os eventos`GET``/monitoring/{id}``monitoring.show`Detalhe de um evento + relacionados`GET``/monitoring/type/{type}``monitoring.type`Filtra por tipo`POST``/monitoring/tags``monitoring.tags`Lista tipos disponíveis`GET``/monitoring/timeline/{tag}/{value}``monitoring.timeline`Timeline cronológico por tag**Rotas de Health Check:**

MétodoURINomeDescrição`GET``/monitoring/health``monitoring.health`Verifica saúde da aplicação (DB, Cache, Queue, Storage)**Rotas de Busca e Comparação:**

MétodoURINomeDescrição`GET``/monitoring/search``monitoring.search`Busca full-text nos eventos`GET``/monitoring/compare``monitoring.compare`Compara métricas entre dois períodos**Rotas de Resolução de Exceções:**

MétodoURINomeDescrição`GET``/monitoring/exceptions/unresolved``monitoring.exceptions.unresolved`Lista exceções não resolvidas agrupadas por tipo`POST``/monitoring/resolve-exception``monitoring.exceptions.resolve-type`Marca todas as exceções de um tipo como resolvidas`POST``/monitoring/{id}/resolve``monitoring.resolve`Marca um evento específico como resolvido`POST``/monitoring/{id}/unresolve``monitoring.unresolve`Remove o status de resolvido de um evento> As rotas do painel de monitoramento usam automaticamente o middleware `monitoring.disable` para não serem monitoradas.

---

### Timeline por Tag

[](#timeline-por-tag)

Visualize o fluxo completo de eventos relacionados a uma tag específica em ordem cronológica. Útil para rastrear o ciclo de vida de um pedido, usuário, ou qualquer entidade monitorada.

#### Endpoint

[](#endpoint)

```
GET /monitoring/timeline/{tag}/{value}?period=24%20hours
```

**Parâmetros:**

ParâmetroTipoObrigatórioDescrição`tag`stringSimNome da tag (ex: `pedido_id`)`value`stringSimValor da tag (ex: `123`)`period`stringNãoPeríodo de busca. Padrão: `24 hours`. Opções: `1 hour`, `6 hours`, `12 hours`, `24 hours`, `7 days`, `30 days`, `90 days`#### Exemplos de uso

[](#exemplos-de-uso-1)

**Timeline de um pedido:**

```
GET /monitoring/timeline/pedido_id/123?period=24%20hours
```

**Timeline de um usuário específico:**

```
GET /monitoring/timeline/user_id/550e8400-e29b-41d4-a716-446655440000?period=7%20days
```

#### Resposta

[](#resposta)

```
{
  "tag": "pedido_id",
  "value": "123",
  "period": "24 hours",
  "total_batches": 2,
  "timeline": [
    {
      "batch_id": "abc-123-uuid",
      "started_at": "2025-01-15 10:23:15",
      "timeline": [
        {
          "id": "...",
          "type": "request",
          "type_label": "Requisição HTTP",
          "icon": "🌐",
          "content": { "method": "POST", "uri": "/api/pedidos", ... },
          "tags": { "pedido_id": "123" },
          "created_at": "2025-01-15 10:23:15"
        },
        {
          "id": "...",
          "type": "query",
          "type_label": "Query SQL",
          "icon": "🗄️",
          "content": { "sql": "INSERT INTO pedidos...", "time_ms": 45 },
          "tags": { "pedido_id": "123" },
          "created_at": "2025-01-15 10:23:15"
        },
        {
          "id": "...",
          "type": "job",
          "type_label": "Job",
          "icon": "⚙️",
          "content": { "displayName": "ProcessarPedidoJob", ... },
          "tags": { "pedido_id": "123" },
          "created_at": "2025-01-15 10:23:16"
        },
        {
          "id": "...",
          "type": "mail",
          "type_label": "E-mail",
          "icon": "📧",
          "content": { "subject": "Pedido #123 recebido", ... },
          "tags": { "pedido_id": "123" },
          "created_at": "2025-01-15 10:23:18"
        }
      ],
      "duration_ms": 3000,
      "event_count": 4
    },
    {
      "batch_id": "def-456-uuid",
      "started_at": "2025-01-15 14:45:22",
      "timeline": [
        {
          "id": "...",
          "type": "request",
          "type_label": "Requisição HTTP",
          "icon": "🌐",
          "content": { "method": "PUT", "uri": "/api/pedidos/123", ... },
          "tags": { "pedido_id": "123" },
          "created_at": "2025-01-15 14:45:22"
        },
        {
          "id": "...",
          "type": "query",
          "type_label": "Query SQL",
          "icon": "🗄️",
          "content": { "sql": "UPDATE pedidos...", "time_ms": 23 },
          "tags": { "pedido_id": "123" },
          "created_at": "2025-01-15 14:45:22"
        }
      ],
      "duration_ms": 800,
      "event_count": 2
    }
  ]
}

> **Nota:** Os eventos são agrupados por `batch_id` único. Se múltiplos eventos
> compartilharem o mesmo batch_id, você recebe apenas uma entrada na timeline
> contendo todos os eventos relacionados.
```

#### Uso programático

[](#uso-programático)

```
use RiseTechApps\Monitoring\Repository\Contracts\MonitoringRepositoryInterface;

class PedidoController extends Controller
{
    public function __construct(
        protected MonitoringRepositoryInterface $monitoring
    ) {}

    public function timeline(string $pedidoId)
    {
        // Busca todos os eventos relacionados ao pedido nas últimas 24h
        // Agrupados por batch_id único
        $timeline = $this->monitoring->getTimelineByTag('pedido_id', $pedidoId, '24 hours');

        return response()->json([
            'pedido_id' => $pedidoId,
            'total_operacoes' => $timeline->count(),
            'operacoes' => $timeline->map(function ($batch) {
                return [
                    'batch_id' => $batch['batch_id'],
                    'inicio' => $batch['started_at'],
                    'fim' => $batch['timeline']->last()['created_at'] ?? null,
                    'duracao_ms' => $batch['duration_ms'],
                    'eventos' => $batch['event_count'],
                    'passos' => $batch['timeline']->map(fn ($e) => [
                        'hora' => $e['created_at'],
                        'tipo' => $e['type_label'],
                        'icone' => $e['icon'],
                    ]),
                ];
            }),
        ]);
    }
}
```

---

### Gerenciamento de Exceções Resolvidas

[](#gerenciamento-de-exceções-resolvidas)

O pacote permite marcar exceções como "resolvidas", facilitando o acompanhamento de bugs e evitando poluição visual no dashboard.

#### Campos adicionais na resposta

[](#campos-adicionais-na-resposta)

Quando um evento é resolvido, os seguintes campos são adicionados à resposta:

```
[
  'id'             => '...',
  'uuid'           => '...',
  'type'           => 'exception',
  'content'        => [...],
  // ... outros campos ...
  'resolved_at'    => '2025-01-15 14:30:00',  // quando foi resolvido
  'resolved_by'    => 'user@example.com',     // quem resolveu
  'is_resolved'    => true,                   // flag booleana
]
```

#### Listar exceções não resolvidas

[](#listar-exceções-não-resolvidas)

```
GET /monitoring/exceptions/unresolved
```

**Resposta:**

```
[
  {
    "exception_class": "App\\Exceptions\\CustomException",
    "count": 15,
    "last_occurrence": "2025-01-15 10:23:00"
  },
  {
    "exception_class": "Illuminate\\Validation\\ValidationException",
    "count": 3,
    "last_occurrence": "2025-01-15 09:45:00"
  }
]
```

#### Marcar uma exceção como resolvida

[](#marcar-uma-exceção-como-resolvida)

```
POST /monitoring/{id}/resolve
Content-Type: application/json

{
  "resolved_by": "user@example.com"
}
```

#### Marcar múltiplas exceções do mesmo tipo como resolvidas

[](#marcar-múltiplas-exceções-do-mesmo-tipo-como-resolvidas)

```
POST /monitoring/resolve-exception
Content-Type: application/json

{
  "exception_class": "App\\Exceptions\\CustomException",
  "resolved_by": "user@example.com"
}
```

**Resposta:**

```
{
  "message": "15 exceções marcadas como resolvidas.",
  "exception_class": "App\\Exceptions\\CustomException",
  "count": 15
}
```

#### Desfazer a resolução

[](#desfazer-a-resolução)

```
POST /monitoring/{id}/unresolve
```

#### Uso programático

[](#uso-programático-1)

```
use RiseTechApps\Monitoring\Repository\Contracts\MonitoringRepositoryInterface;

class ExceptionController extends Controller
{
    public function __construct(
        protected MonitoringRepositoryInterface $monitoring
    ) {}

    // Marcar como resolvida
    public function resolve(string $id)
    {
        $success = $this->monitoring->resolveEvent(
            $id,
            auth()->user()?->email
        );

        return $success
            ? response()->json(['message' => 'Resolvido!'])
            : response()->json(['message' => 'Não encontrado'], 404);
    }

    // Listar não resolvidas
    public function unresolved()
    {
        $exceptions = $this->monitoring->getUnresolvedExceptions();

        return response()->json($exceptions);
    }
}
```

---

Health Check
------------

[](#health-check)

Endpoint para verificar a saúde da aplicação e suas dependências.

### Endpoint

[](#endpoint-1)

```
GET /monitoring/health
```

### Resposta

[](#resposta-1)

```
{
    "status": "healthy",
    "checks": {
        "database": { "status": "ok" },
        "cache": { "status": "ok", "driver": "redis" },
        "queue": { "status": "ok", "driver": "redis", "queue_size": 0 },
        "storage": { "status": "ok", "disk": "local" }
    },
    "performance": {
        "apdex_score": 0.94,
        "throughput_per_minute": 245,
        "error_rate_percent": 0.5
    },
    "timestamp": "2025-01-15T10:30:00Z"
}
```

### Status possíveis

[](#status-possíveis)

StatusSignificado`healthy`Todos os sistemas OK`degraded`Algum sistema com problemas leves`unhealthy`Falha crítica em algum sistema### Uso em Load Balancers

[](#uso-em-load-balancers)

```
# Health check para load balancer
GET /monitoring/health

# Retorna 200 se healthy/degraded
# Retorna 503 se unhealthy
```

---

Sistema de Alertas
------------------

[](#sistema-de-alertas)

Configure notificações automáticas para eventos críticos via Slack, Discord ou Email.

### Configuração

[](#configuração-1)

```
// config/monitoring.php
'alerts' => [
    'enabled' => env('MONITORING_ALERTS_ENABLED', true),

    // Webhooks
    'slack_webhook' => env('MONITORING_SLACK_WEBHOOK'),
    'discord_webhook' => env('MONITORING_DISCORD_WEBHOOK'),

    // Email
    'email' => [
        'enabled' => true,
        'to' => ['devops@empresa.com'],
        'from' => 'monitoring@empresa.com',
    ],

    // Thresholds
    'thresholds' => [
        'exceptions_per_minute' => 10,
        'failed_jobs_per_hour' => 5,
        'slow_request_ms' => 5000,
        'slow_queries_per_minute' => 10,
        'error_rate_percent' => 5.0,
    ],

    // Cooldown entre alertas (minutos)
    'cooldown_minutes' => 5,
],
```

### Variáveis de ambiente

[](#variáveis-de-ambiente-1)

```
MONITORING_ALERTS_ENABLED=true
MONITORING_SLACK_WEBHOOK=https://hooks.slack.com/services/...
MONITORING_DISCORD_WEBHOOK=https://discord.com/api/webhooks/...
MONITORING_ALERTS_EMAIL_TO=devops@empresa.com,admin@empresa.com
```

### Alertas Disparados

[](#alertas-disparados)

EventoThresholdMensagemExceção em produçãoQualquer🚨 Exceção: `{class}` - `{message}`Requisição lenta&gt; 5000ms⏱️ Requisição lenta: `{uri}` - `{duration}ms`Job falho&gt; 5/hora🔥 Job falhou: `{job}`Query lenta&gt; 100ms🐢 Query lenta: `{time}ms`### Cooldown

[](#cooldown)

Para evitar spam, o mesmo tipo de alerta só é enviado a cada 5 minutos (configurável).

---

Relatórios Automáticos
----------------------

[](#relatórios-automáticos)

Gere relatórios periódicos (diário, semanal, mensal) com métricas e estatísticas completas do sistema de monitoramento.

### Configuração

[](#configuração-2)

```
// config/monitoring.php
'reports' => [
    'auto_schedule' => env('MONITORING_REPORTS_AUTO_SCHEDULE', false),
    'timezone' => 'America/Sao_Paulo',

    'daily' => [
        'enabled' => true,
        'send_at' => '08:00',
    ],
    'weekly' => [
        'enabled' => true,
        'send_at' => '08:00',
        'day' => 'monday',
    ],
    'monthly' => [
        'enabled' => true,
        'send_at' => '08:00',
    ],

    'channels' => [
        'email' => [
            'enabled' => true,
            'to' => ['devops@empresa.com'],
            'from' => 'monitoring@empresa.com',
        ],
        'slack' => ['enabled' => true],
        'discord' => ['enabled' => true],
    ],
],
```

### Variáveis de Ambiente

[](#variáveis-de-ambiente-2)

```
MONITORING_REPORTS_AUTO_SCHEDULE=true
MONITORING_REPORT_EMAIL_TO=devops@empresa.com,admin@empresa.com
MONITORING_REPORT_EMAIL_FROM=monitoring@empresa.com

# Canais
MONITORING_REPORT_EMAIL_ENABLED=true
MONITORING_REPORT_SLACK_ENABLED=true
MONITORING_REPORT_DISCORD_ENABLED=false
```

### Comando Artisan

[](#comando-artisan)

```
# Gerar relatório diário
php artisan monitoring:report daily

# Gerar e enviar automaticamente
php artisan monitoring:report daily --send

# Enviar para canais específicos
php artisan monitoring:report weekly --send --channels=email,slack

# Preview no console
php artisan monitoring:report monthly --preview

# Salvar HTML no storage
php artisan monitoring:report daily --save
```

### Conteúdo do Relatório

[](#conteúdo-do-relatório)

Cada relatório inclui:

**1. Resumo Executivo**

- Total de eventos
- Exceções, requisições, jobs
- Taxa de erro
- Tempo médio de resposta

**2. Métricas de Performance**

- Apdex Score
- Tempo mínimo, máximo e médio
- Queries lentas

**3. Eventos por Tipo**

- Distribuição percentual
- Gráficos de barras

**4. Top Erros**

- Exceções mais frequentes (não resolvidas)
- Contagem de ocorrências

**5. Tendências**

- Comparação com período anterior
- Indicadores de crescimento/queda

### Agendamento Automático

[](#agendamento-automático)

Com `MONITORING_REPORTS_AUTO_SCHEDULE=true`:

RelatórioFrequênciaHorárioDiárioTodo dia08:00SemanalSegundas-feiras08:00MensalDia 1 de cada mês08:00---

Relatórios Customizáveis (100% Autônomo)
----------------------------------------

[](#relatórios-customizáveis-100-autônomo)

O sistema de relatórios permite **100% de autonomia** no envio. Você pode usar:

1. **Handlers Customizados** - Substituir canais específicos ou todos
2. **Event Listener** - Controle total via evento `ReportGenerated`
3. **Notificações Padrão** - Email, Slack, Discord (funciona sem configuração extra)

### Controle Total - Desabilitar Padrão

[](#controle-total---desabilitar-padrão)

Para usar **apenas** suas notificações customizadas:

```
// Em um ServiceProvider
use RiseTechApps\Monitoring\Services\Reporting\ReportService;

public function boot(): void
{
    // Desabilita notificações padrão
    ReportService::disableDefaultNotifications();
}
```

### Handler Customizado para Relatórios

[](#handler-customizado-para-relatórios)

Implemente `ReportHandlerInterface` para criar seu próprio envio:

```
