You can't fix what you can't see. Your API is running, so you need to know whether it is healthy, whether requests are getting slower, and whether errors are happening.
Monitoring gives you visibility. It tells you when things are going wrong before your users notice. It lets you optimize based on real data, not guesses.
This chapter is about instrumenting your API so you know what's happening at all times.
Health Check Endpoint
Route::get('/health', HealthController::class);
class HealthController extends Controller
{
public function __invoke(): Response
{
$health = [
'status' => 'ok',
'timestamp' => now()->toIso8601String(),
'services' => [
'database' => $this->checkDatabase(),
'cache' => $this->checkCache(),
'queue' => $this->checkQueue(),
],
];
$allHealthy = collect($health['services'])
->every(fn ($service) => $service['status'] !== 'down');
return response()->json(
['data' => $health],
$allHealthy ? 200 : 503
);
}
private function checkDatabase(): array
{
try {
DB::select('SELECT 1');
return ['status' => 'connected'];
} catch (Exception $e) {
return ['status' => 'down', 'error' => $e->getMessage()];
}
}
private function checkCache(): array
{
try {
Cache::put('health_check', true, now()->addMinute());
Cache::forget('health_check');
return ['status' => 'connected'];
} catch (Exception $e) {
return ['status' => 'down', 'error' => $e->getMessage()];
}
}
private function checkQueue(): array
{
try {
Queue::connection()->connection();
return ['status' => 'active'];
} catch (Exception $e) {
return ['status' => 'down'];
}
}
}
Request/Response Logging
Log all requests for analysis:
class LogApiRequestsMiddleware
{
public function handle(Request $request, Closure $next): Response
{
// Skip noise
if ($request->is('*/health')) {
return $next($request);
}
$start = microtime(true);
$response = $next($request);
$duration = round((microtime(true) - $start) * 1000);
Log::channel('api')->info('API Request', [
'timestamp' => now()->toIso8601String(),
'method' => $request->getMethod(),
'path' => $request->getPathInfo(),
'status' => $response->getStatusCode(),
'duration_ms' => $duration,
'user_id' => auth()->id(),
'remote_ip' => $request->ip(),
]);
return $response;
}
}
Error Tracking Integration
Integrate with services like Sentry for automatic error reporting:
composer require sentry/sentry-laravel
php artisan sentry:publish
// config/sentry.php
return [
'dsn' => env('SENTRY_LARAVEL_DSN'),
'traces_sample_rate' => 0.1, // Sample 10% of requests
'environment' => env('APP_ENV'),
];
// Exceptions automatically sent to Sentry
try {
// Code
} catch (Exception $e) {
\Sentry\captureException($e);
throw $e;
}
Custom Metrics
Track application-specific metrics:
class MetricsService
{
public function recordApiCall(string $endpoint, int $duration): void
{
Metrics::record('api_call_duration', $duration, [
'endpoint' => $endpoint,
'status' => 'success',
]);
}
public function recordError(string $code): void
{
Metrics::increment('api_errors_total', [
'code' => $code,
]);
}
public function recordRateLimit(): void
{
Metrics::increment('rate_limits_hit');
}
}
// Use in middleware
class LogApiRequestsMiddleware
{
public function handle(Request $request, Closure $next): Response
{
$start = microtime(true);
$response = $next($request);
app(MetricsService::class)->recordApiCall(
endpoint: $request->getPathInfo(),
duration: (microtime(true) - $start) * 1000,
);
return $response;
}
}
Alert Policy
Define alerts for critical issues:
Alert "High Error Rate"
When: Error rate > 5% in last 5 minutes
Then: Page on-call engineer
Alert "Slow API Response"
When: p95 latency > 500ms
Then: Page infrastructure team
Alert "Database Down"
When: Health check fails for >1 minute
Then: Page database team immediately
Chapter 8 Summary
Monitoring is visibility. You can't fix what you can't see.
Key instrumentation:
- Health checks for quick status
- Request/response logging with details
- Slow query logging
- Error tracking with stack traces
- Metrics on response times, error rates
- Alerts for critical issues
You don't need enterprise tools to start. Basic logging gets you 80% of the way there. The key is collecting the right data and acting on it.