PHPackages                             npabisz/laravel-metrics - 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. npabisz/laravel-metrics

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

npabisz/laravel-metrics
=======================

Centralized monitoring system for Laravel applications - collects metrics, tracks slow queries and requests

v1.3.4(2mo ago)021↓75%MITPHPPHP ^8.1

Since Mar 19Pushed 2mo agoCompare

[ Source](https://github.com/npabisz/laravel-metrics)[ Packagist](https://packagist.org/packages/npabisz/laravel-metrics)[ RSS](/packages/npabisz-laravel-metrics/feed)WikiDiscussions master Synced 3w ago

READMEChangelog (10)Dependencies (8)Versions (25)Used By (0)

Laravel Metrics
===============

[](#laravel-metrics)

Centralized monitoring package for Laravel applications. Collects metrics every minute, tracks slow queries and requests, provides a web dashboard, JSON API, and scheduled alert notifications via mail, Slack, Discord, or Google Chat.

Requirements
------------

[](#requirements)

- PHP 8.1+
- Laravel 9 / 10 / 11 / 12
- Redis (for temporary metric aggregation between collection intervals)

Installation
------------

[](#installation)

```
composer require npabisz/laravel-metrics
```

Publish config and migrations:

```
php artisan vendor:publish --tag=metrics-config
php artisan vendor:publish --tag=metrics-migrations
php artisan migrate
```

Optionally publish the dashboard view for customization:

```
php artisan vendor:publish --tag=metrics-views
```

How It Works
------------

[](#how-it-works)

The package operates in four layers:

**1. Real-time tracking** (middleware + listener) — runs on every request:

- `RequestMonitor` middleware measures request duration, increments Redis counters, logs slow requests to DB
- `QueryListener` listens for `QueryExecuted` events, counts queries, logs slow ones to DB

**2. Periodic collection** (cron every minute):

- `monitoring:collect` runs all registered collectors, reads+flushes Redis counters, stores one aggregated row in `metrics`

**3. Scheduled alerts** (cron, configurable interval):

- `monitoring:alert` aggregates metrics from the configured lookback window, evaluates thresholds, sends notifications if issues are detected
- Supports per-alert cooldowns to prevent notification fatigue

**4. Hourly aggregation** (cron every hour):

- `monitoring:aggregate-hourly` rolls up per-minute data into `metrics_hourly` for efficient long-range queries (days/weeks)

**5. Cleanup** (cron daily at 04:00):

- `monitoring:clean` removes data older than retention period

All scheduled commands are registered automatically — no changes to `Kernel.php` needed.

Configuration
-------------

[](#configuration)

All settings are in `config/metrics.php`. Key environment variables:

```
# Core
METRICS_ENABLED=true
METRICS_SLOW_QUERY_MS=100
METRICS_TRACK_QUERIES=true
METRICS_TRACK_REQUESTS=true

# Dashboard (web UI, IP-protected)
METRICS_DASHBOARD_ENABLED=true
METRICS_DASHBOARD_PATH=metrics
METRICS_ALLOWED_IPS=123.45.67.89,98.76.54.32

# JSON API (bearer token auth)
METRICS_ROUTES_ENABLED=false
METRICS_API_TOKEN=your-secret-token

# Redis
METRICS_REDIS_PREFIX=monitoring:
METRICS_REDIS_CONNECTION=default

# Retention
METRICS_RETENTION_METRICS=30
METRICS_RETENTION_SLOW_LOGS=14

# Database (optional separate connection)
METRICS_DB_CONNECTION=null

# Alerts
METRICS_ALERT_INTERVAL=1          # minutes between alert checks
METRICS_ALERT_COOLDOWN=60         # default cooldown per alert (minutes)
```

### Slow Request Thresholds

[](#slow-request-thresholds)

Define per-route pattern thresholds in `config/metrics.php`. First match wins, `*` is the fallback:

```
'slow_request_thresholds' => [
    'api/payments/*'  => 500,   // 500ms for critical routes
    'api/*'           => 1000,  // 1s for API routes
    '*'               => 2000,  // 2s for everything else
],
```

### Middleware Group

[](#middleware-group)

By default, request tracking is registered as global middleware. To limit it to a specific group:

```
'middleware_group' => 'api',  // only track API routes
```

Set `track_requests` to `false` and apply `RequestMonitor::class` middleware manually for full control.

### Custom Metric Aggregation

[](#custom-metric-aggregation)

Define how custom metrics are aggregated for hourly rollups and dashboard summaries:

```
'aggregation' => [
    ['pattern' => 'checkout_avg_*',  'strategy' => 'avg', 'weight_key' => 'checkout_requests'],
    ['pattern' => 'my_snapshot_*',   'strategy' => 'latest'],
    ['pattern' => 'my_peak_*',      'strategy' => 'max'],
],
```

Strategies: `sum` (default), `avg` (weighted), `max`, `latest`. Unmatched keys are auto-detected by naming convention (`*_avg_*` → avg, `*_max_*` → max, gauge suffixes → latest).

Dashboard
---------

[](#dashboard)

Available at `/{path}` (default: `/metrics`). Protected by the `viewMetrics` gate.

**Features:**

- Summary cards — HTTP requests, response times, error rate, queue depth, DB queries, Redis stats, CPU, disk
- Timeline charts — requests/min, response time (avg+max), queue depth, DB queries/min
- Custom metric cards and charts — display any data from your custom collectors
- Ranked list sections — display top-N items (e.g. top domains by webhook count)
- Tabbed views — organize metrics into multiple pages for readability
- Slow logs browser — filterable table (all / requests / queries), sorted by duration or time, paginated
- Auto-refresh — configurable interval (10s / 30s / 60s)
- Period selector — 5min to 30 days
- Multi-resolution — raw 1-min data for short periods, 5-min grouped for mid-range, hourly rollups for days/weeks
- Crosshair sync — hovering on any chart shows a synced vertical line across all charts for time correlation
- Configurable chart labels — short display names via `labels` config, or dynamic labels via `labels_from`
- Configurable card colors — threshold-based color rules via `value_colors`
- Tooltip formatting — auto-detects units from key names, or uses explicit `format` config

### Authorization

[](#authorization)

The dashboard uses a `viewMetrics` gate with IP-based authorization (similar to Laravel Horizon):

- **Local environment** — all access allowed
- **Production** — only IPs listed in `METRICS_ALLOWED_IPS` are allowed
- Denied access is logged

To customize the gate, override it in a service provider:

```
Gate::define('viewMetrics', function ($user = null) {
    // your custom logic
});
```

### Dashboard Views

[](#dashboard-views)

When your application has many custom metrics, you can organize the dashboard into multiple tabbed pages using the `views` config. Each view has a label and an array of sections.

When `views` is empty (default), the dashboard shows a single page with all built-in panels, custom metric cards, and slow logs.

```
// config/metrics.php → dashboard.views
'views' => [
    [
        'label' => 'Overview',
        'sections' => [
            ['type' => 'built-in'],
            ['type' => 'cards', 'label' => 'Business', 'keys' => ['active_users', 'orders_total', 'revenue_usd']],
            ['type' => 'slow-logs'],
        ],
    ],
    [
        'label' => 'External APIs',
        'sections' => [
            ['type' => 'cards', 'label' => 'Payment Gateway', 'keys' => ['payment_api_*']],
            ['type' => 'chart', 'label' => 'Payment Calls', 'keys' => ['payment_api_calls', 'payment_api_errors'],
                'labels' => ['payment_api_calls' => 'Calls', 'payment_api_errors' => 'Errors'],
                'colors' => ['payment_api_errors' => 'red', 'payment_api_calls' => 'blue']],
        ],
    ],
    [
        'label' => 'Infrastructure',
        'sections' => [
            ['type' => 'cards', 'label' => 'Resources', 'keys' => ['cpu_usage_*', 'memory_*']],
            ['type' => 'chart', 'label' => 'CPU & Memory', 'keys' => ['cpu_usage_percent', 'memory_usage_percent'],
                'labels' => ['cpu_usage_percent' => 'CPU', 'memory_usage_percent' => 'Memory'],
                'chart_type' => 'line', 'gauge' => true, 'format' => ['suffix' => '%']],
        ],
    ],
],
```

#### Section Types

[](#section-types)

TypeDescription`built-in`Built-in card group. Set `'id'` to show only one: `'http'`, `'queue'`, `'database'`, `'system'`. Omit `id` for all four + timeline charts.`cards`Summary cards for custom metric keys matching `'keys'` patterns. Supports `value_colors` for threshold-based coloring.`list`Ranked list pairing `label_keys` with `value_keys` patterns (e.g. top N items).`chart`Chart panel for custom metric keys. Consecutive charts are grouped in a 3-column grid.`slow-logs`The slow logs table with type filters, sort buttons, and pagination.#### Chart/Card Options

[](#chartcard-options)

OptionDescription`label`Section title displayed above cards or as chart title.`keys`Array of metric key names. Supports `*` wildcard anywhere (e.g. `payment_*_calls`, `*_errors`).`labels`Keyed map of short display names: `['payment_api_calls' => 'Calls']`.`labels_from`Dynamic labels from custom summary: `['metric_count_key' => 'metric_label_key']`.`colors`Indexed array `['blue', 'red']` or keyed map `['errors' => 'red']`. Available: blue, red, green, yellow, purple, cyan, orange, pink.`chart_type``'bar'` (default) or `'line'`.`gauge``true` to use latest value instead of sum for aggregation.`format``['suffix' => '%', 'decimals' => 1]` — value formatting for tooltips and Y-axis.`value_colors`Card color rules: `[['key' => '*avg*', 'conditions' => [['op' => '',                 // >, >=,  'critical',          // critical or warning
        'label'     => 'Payment Errors',    // display name in notification
        'cooldown'  => 30,                  // optional per-alert cooldown (minutes)
    ],
],
```

### Alert Cooldowns

[](#alert-cooldowns)

After an alert fires, it enters a cooldown period during which it won't fire again. This prevents notification fatigue for persistent issues.

- **Global default**: `notifications.cooldown` (default: 60 minutes)
- **Per-alert override**: set `'cooldown' => 30` on any custom threshold rule
- **Disable cooldown**: set `'cooldown' => 0` for an alert that should fire every check

### Testing Notifications

[](#testing-notifications)

Send a test notification with sample data to verify channel configuration:

```
php artisan monitoring:alert --test
```

Collectors
----------

[](#collectors)

Built-in collectors:

CollectorMetrics`HttpCollector`requests total/2xx/4xx/5xx, avg/max duration, slow count`QueueCollector`queue depths (high/default/low priority), jobs processed/failed`DatabaseCollector`queries total, slow queries, avg/max query duration`RedisCollector`memory usage, connected clients, ops/sec, cache hit rate`SystemCollector`CPU load (1m), memory usage, disk free`HorizonCollector`Horizon supervisor status (disabled by default)### Custom Collectors

[](#custom-collectors)

Implement `CollectorInterface` and add to config:

```
