Mastering Production Monitoring: A Comprehensive Guide to Laravel Nightwatch
Overview
Modern web applications are complex webs of interactions. A single user request might trigger multiple database queries, dispatch background jobs, send emails, and ping external APIs. When something fails or slows down, finding the root cause often feels like searching for a needle in a haystack.
Unlike generic monitoring tools, Nightwatch understands the internal architecture of your application. It doesn't just see a generic 500 error; it sees which middleware was active, exactly which line of a controller failed, and which authenticated user was affected. By contextualizing truths rather than just dumping logs, it allows developers to move from a reactive posture—waiting for a customer to complain—to a proactive one where bottlenecks are identified before they impact the user experience.
Prerequisites
To get the most out of this tutorial, you should have a solid grasp of the following:
- Laravel Fundamentals: Familiarity with controllers, middleware, models, and environment configuration.
- Composer: Knowledge of managing PHP dependencies via the command line.
- Server Environment: A basic understanding of long-running processes (daemons) and how to manage them using tools like Supervisor.
- HTTP & Databases: Understanding of status codes, P95 metrics, and SQL query performance.
Key Libraries & Tools
- Nightwatch Agent: A composer package installed in your Laravel app that collects and batches performance data.
- Laravel Forge: An optional server management tool used to easily deploy the Nightwatch agent daemon.
- Laravel Cloud: A platform-as-a-service environment that supports Nightwatch background workers natively.
- P95 Metrics: The primary statistical tool used in the dashboard to filter out outliers and show the performance experienced by 95% of users.
Code Walkthrough
Setting up Nightwatch involves three primary phases: installation, configuration of the logging environment, and launching the monitoring agent.
Step 1: Installing the Agent
First, you must pull the agent package into your project using Composer. This agent sits inside your application, listening for events without significantly impacting performance.
composer require laravel/nightwatch
Step 2: Environment Configuration
Nightwatch requires a unique token to authenticate your application with the centralized dashboard. You also need to configure your log channel so that Laravel knows to pipe information to the Nightwatch driver.
In your .env file, add your application token and update the log channel:
NIGHTWATCH_TOKEN=your_token_here
LOG_CHANNEL=nightwatch
If you want to keep your existing logs while adding Nightwatch, you can add it to a stack in config/logging.php. This ensures you don't lose local file logging while gaining remote monitoring.
Step 3: Implementing Sampling and Filters
For high-traffic applications, sending 100% of events to a monitoring service can be expensive or unnecessary. Nightwatch provides granular sampling controls via environment variables.
# Send only 10% of standard requests
NIGHTWATCH_SAMPLING_RATE=0.1
# Capture 100% of exceptions regardless of request sampling
NIGHTWATCH_EXCEPTION_SAMPLING_RATE=1.0
# Ignore specific event types to save on event counts
NIGHTWATCH_IGNORE_MAIL=true
NIGHTWATCH_IGNORE_QUERIES=false
Step 4: Running the Agent Daemon
The Nightwatch agent is a long-running process. It collects data in memory, batches it, and sends it to the server every few seconds (usually every 2 to 10 seconds). You start it with an artisan command:
php artisan nightwatch:agent
In production, you should never run this manually in a terminal. Instead, use a process monitor like Supervisor to ensure the agent restarts automatically if it crashes. On
Syntax Notes
- Sampling Logic: When you set
NIGHTWATCH_SAMPLING_RATE=0.1, Nightwatch uses a deterministic algorithm to ensure that if a request is sampled, all related events (queries, mail, jobs) within that request are also captured. This provides a complete trace rather than fragmented data. - Log Stacks: By using the
stackdriver inconfig/logging.php, you can includenightwatchalongsidedailyorsyslog. This follows the standard Laravel pattern for multi-channel logging. - Thresholds: Nightwatch allows you to define performance thresholds. For instance, a route taking over 1500ms can automatically trigger the creation of an 'Issue' in the dashboard, even if it didn't throw a formal exception.
Practical Examples
Solving the "Slow Checkout" Mystery
Imagine a scenario where users complain that the checkout page is "sometimes slow." In a traditional log, you might see nothing because the request eventually succeeds. In the Nightwatch dashboard, you would:
- Filter for the
/checkoutroute. - Look at the P95 Duration.
- Identify a spike and click the Timeline.
- Discover that an Outgoing Request to a shipping provider's API is taking 4.5 seconds.
With this data, you can move that API call to a background job or implement a timeout, immediately improving the user experience.
Identifying N+1 Query Bottlenecks
Nightwatch captures the full SQL of your queries and their origin in your code. If a single request triggers 50 identical queries to a destinations table, Nightwatch flags this. It shows you the exact controller and line number where the eager loading is missing. This prevents death-by-a-thousand-cuts performance degradation.
Tips & Gotchas
- The Daemon Requirement: A common mistake is assuming Nightwatch works like a standard HTTP request. It requires the
nightwatch:agentcommand to be running constantly. If this command stops, you stop receiving data. - Storage Regions: When creating your organization, choose the storage region (US or EU) closest to your servers to minimize latency and comply with local data residency laws.
- User Privacy: By default, Nightwatch identifies users by their email and name if they are authenticated. If you are in a highly regulated industry (like healthcare), use the provided hooks in the Nightwatch configuration to mask or anonymize user data before it leaves your server.
- Don't Ignore Local Testing: While primarily for production, running Nightwatch locally for an hour can reveal inefficient queries that are hard to spot with the naked eye during development. Just remember to turn it off to save your event quota!
