theihasan / nightwatch-prometheus
Prometheus exporter package for Laravel Nightwatch metrics.
Package info
github.com/theihasan/nightwatch-prometheus
pkg:composer/theihasan/nightwatch-prometheus
Requires
- php: ^8.2
- illuminate/support: ^10.0|^11.0|^12.0|^13.0
- laravel/nightwatch: ^1.28
Requires (Dev)
- orchestra/testbench: ^11.0
README
theihasan/nightwatch-prometheus exposes Laravel Nightwatch records as Prometheus metrics.
It runs on top of laravel/nightwatch, but it does not require a Nightwatch subscription. Nightwatch is used as the in-app event collection layer, while this package replaces Nightwatch's default ingest path and exports metrics for Prometheus scraping.
Requirements
- PHP 8.2+
- Laravel 10, 11, 12, or 13
laravel/nightwatch^1.28- Redis for shared metric storage in real applications
How It Works
- Laravel Nightwatch collects request, query, queue, exception, log, and related runtime records.
- This package replaces Nightwatch's ingest implementation.
- Records are converted into Prometheus-friendly counters and histograms.
- Metrics are stored in Redis by default.
- Prometheus scrapes the
/metricsendpoint.
Nightwatch Subscription
This package does not need a Nightwatch subscription.
You still install and enable laravel/nightwatch, but you do not need to send data to the Nightwatch hosted service. This package uses Nightwatch's local record generation only.
Installation
Install Nightwatch and this package:
composer require laravel/nightwatch theihasan/nightwatch-promethus
Publish the package config:
php artisan vendor:publish --tag=nightwatch-promethus-config
Minimal Nightwatch Setup
Enable Nightwatch in your app and keep sampling at 1.0 for accurate counters.
Example .env values:
NIGHTWATCH_ENABLED=true NIGHTWATCH_TOKEN=dummy-token NIGHTWATCH_REQUEST_SAMPLE_RATE=1.0 NIGHTWATCH_COMMAND_SAMPLE_RATE=1.0 NIGHTWATCH_EXCEPTION_SAMPLE_RATE=1.0 NIGHTWATCH_SCHEDULED_TASK_SAMPLE_RATE=1.0 NIGHTWATCH_PROMETHUS_ENABLED=true NIGHTWATCH_PROMETHUS_STORAGE_DRIVER=redis NIGHTWATCH_PROMETHUS_REDIS_CONNECTION=default NIGHTWATCH_PROMETHUS_REDIS_PREFIX=nightwatch_promethus
Notes:
- The token does not need to be a real Nightwatch subscription token for this package's exporter flow.
- Redis is recommended because metrics must be shared across requests, workers, and scheduled/queue processes.
Routes
By default:
- metrics endpoint:
/metrics - debug endpoint:
/nightwatch-promethus/debug
The metrics route is enabled by default.
The debug route is disabled by default in production unless explicitly enabled.
Configurable route settings live in config/nightwatch-promethus.php.
Available Metrics
Currently implemented:
nightwatch_http_requests_totalnightwatch_http_request_duration_secondsnightwatch_http_request_stage_duration_secondsnightwatch_http_request_peak_memory_bytesnightwatch_http_request_queries_totalnightwatch_exceptions_totalnightwatch_db_queries_totalnightwatch_db_query_duration_secondsnightwatch_outgoing_http_requests_totalnightwatch_outgoing_http_request_duration_secondsnightwatch_jobs_queued_totalnightwatch_job_attempts_totalnightwatch_job_attempt_duration_secondsnightwatch_scheduled_task_runs_totalnightwatch_command_executions_totalnightwatch_command_duration_secondsnightwatch_cache_events_totalnightwatch_logs_totalnightwatch_notifications_totalnightwatch_notification_duration_seconds
Log Metric Caution
nightwatch_logs_total is verified working through the dedicated Nightwatch log channel.
If you want normal application logs to be captured by Nightwatch in a typical Laravel stack setup, include the nightwatch channel in your log stack.
Example:
LOG_CHANNEL=stack LOG_STACK=single,nightwatch
Then clear config:
php artisan config:clear
Known Limitation
These two metrics are implemented in the package, but they may not appear in real worker flows until the upstream Nightwatch issue is fixed:
nightwatch_job_attempts_totalnightwatch_job_attempt_duration_seconds
Upstream issue:
laravel/nightwatch#406- laravel/nightwatch#406
Current status:
nightwatch_jobs_queued_totalworksjob-attemptrecord emission appears to be blocked by Nightwatch worker behavior in realqueue:workprocessing
Example PromQL
Request rate:
sum(rate(nightwatch_http_requests_total[5m]))
Requests by route:
sum by (route) (rate(nightwatch_http_requests_total[5m]))
95th percentile request duration:
histogram_quantile(
0.95,
sum by (le, route) (rate(nightwatch_http_request_duration_seconds_bucket[5m]))
)
Query count by route:
sum by (route) (rate(nightwatch_http_request_queries_total[5m]))
Database query rate by connection:
sum by (connection, connection_type) (rate(nightwatch_db_queries_total[5m]))
95th percentile database query duration:
histogram_quantile(
0.95,
sum by (le, connection) (rate(nightwatch_db_query_duration_seconds_bucket[5m]))
)
Outgoing HTTP request rate by host:
sum by (host) (rate(nightwatch_outgoing_http_requests_total[5m]))
95th percentile outgoing HTTP request duration:
histogram_quantile(
0.95,
sum by (le, host) (rate(nightwatch_outgoing_http_request_duration_seconds_bucket[5m]))
)
Unhandled exceptions:
sum(rate(nightwatch_exceptions_total{result="unhandled"}[5m]))
Command execution rate:
sum by (name) (rate(nightwatch_command_executions_total[5m]))
Job attempts by result:
sum by (result) (rate(nightwatch_job_attempts_total[5m]))
Scheduled task runs:
sum by (name, result) (rate(nightwatch_scheduled_task_runs_total[15m]))
Cache hit rate:
sum(rate(nightwatch_cache_events_total{cache_event_type="hit"}[5m]))
Cache miss rate:
sum(rate(nightwatch_cache_events_total{cache_event_type="miss"}[5m]))
Cache hit ratio:
sum(rate(nightwatch_cache_events_total{cache_event_type="hit"}[5m]))
/
(
sum(rate(nightwatch_cache_events_total{cache_event_type="hit"}[5m]))
+
sum(rate(nightwatch_cache_events_total{cache_event_type="miss"}[5m]))
)
Notification throughput by channel:
sum by (channel) (rate(nightwatch_notifications_total[5m]))
95th percentile notification duration:
histogram_quantile(
0.95,
sum by (le, channel) (rate(nightwatch_notification_duration_seconds_bucket[5m]))
)
Prometheus Scrape Config Example
scrape_configs: - job_name: 'laravel-nightwatch-promethus' scrape_interval: 15s metrics_path: /metrics static_configs: - targets: - your-app.test
If your metrics route path is customized in config/nightwatch-promethus.php, update metrics_path to match.