Skip to content

Performance Monitoring ​

Track application performance metrics and identify bottlenecks.

Overview ​

Nadi can capture performance data alongside error tracking:

  • Slow database queries
  • HTTP request timing
  • Queue job duration
  • Custom performance spans

Slow Query Tracking ​

Enable slow query tracking to capture database queries that exceed a threshold.

Configuration ​

php
// config/nadi.php
'capture_slow_queries' => true,
'slow_query_threshold' => 1000, // milliseconds

Environment Variables ​

env
NADI_CAPTURE_SLOW_QUERIES=true
NADI_SLOW_QUERY_THRESHOLD=1000

What's Captured ​

For each slow query, Nadi captures:

DataDescription
SQLThe query (with bindings)
DurationExecution time in ms
ConnectionDatabase connection name
LocationFile and line where query was executed

Example Output ​

json
{
  "type": "slow_query",
  "query": "SELECT * FROM orders WHERE user_id = ? AND status = ?",
  "bindings": [1234, "pending"],
  "duration_ms": 1523,
  "connection": "mysql",
  "location": "app/Services/OrderService.php:45"
}

Filtering Queries ​

Exclude certain queries from tracking:

php
// config/nadi.php
'slow_query_ignore' => [
    'SHOW *',      // Ignore SHOW queries
    '* information_schema *',  // Ignore schema queries
],

Request Performance ​

Track overall request performance:

Enable Request Timing ​

php
// config/nadi.php
'capture_request_timing' => true,

Captured Metrics ​

MetricDescription
Total DurationTotal request time
Time to First ByteServer processing time
Database TimeTotal time in database queries
Memory PeakPeak memory usage

Queue Job Performance ​

Track queue job execution time:

Configuration ​

php
// config/nadi.php
'capture_queue_performance' => true,
'slow_job_threshold' => 30000, // 30 seconds

Captured Data ​

json
{
  "type": "slow_job",
  "job": "App\\Jobs\\ProcessOrder",
  "queue": "orders",
  "duration_ms": 45000,
  "attempts": 1,
  "memory_mb": 128
}

Custom Performance Spans ​

Create custom performance measurements:

Basic Usage ​

php
use Nadi\Laravel\Facades\Nadi;

$span = Nadi::startSpan('process_order');

try {
    $this->processOrder($order);
} finally {
    $span->finish();
}

With Additional Data ​

php
$span = Nadi::startSpan('api_call', [
    'service' => 'payment_gateway',
    'endpoint' => '/charge',
]);

try {
    $response = Http::post('https://api.stripe.com/charge', $data);

    $span->setData([
        'status' => $response->status(),
        'response_size' => strlen($response->body()),
    ]);
} finally {
    $span->finish();
}

Nested Spans ​

php
$parentSpan = Nadi::startSpan('checkout_process');

try {
    $validateSpan = Nadi::startSpan('validate_cart');
    $this->validateCart();
    $validateSpan->finish();

    $paymentSpan = Nadi::startSpan('process_payment');
    $this->processPayment();
    $paymentSpan->finish();

    $fulfillSpan = Nadi::startSpan('fulfill_order');
    $this->fulfillOrder();
    $fulfillSpan->finish();
} finally {
    $parentSpan->finish();
}

HTTP Client Performance ​

Track outgoing HTTP requests:

Using Laravel's HTTP Client ​

The SDK automatically instruments Laravel's HTTP client when enabled:

php
// config/nadi.php
'capture_http_client' => true,

Captured Data ​

json
{
  "type": "http_request",
  "method": "POST",
  "url": "https://api.example.com/users",
  "duration_ms": 234,
  "status": 200,
  "response_size": 1024
}

Memory Tracking ​

Monitor memory usage:

php
use Nadi\Laravel\Facades\Nadi;

// Log current memory usage
Nadi::recordMemory('after_data_load');

// Check peak memory
$peakMb = memory_get_peak_usage(true) / 1024 / 1024;
if ($peakMb > 100) {
    Nadi::captureMessage('High memory usage detected', 'warning', [
        'extra' => ['peak_memory_mb' => $peakMb],
    ]);
}

Performance Budgets ​

Alert when performance exceeds thresholds:

php
use Nadi\Laravel\Facades\Nadi;

class PerformanceMiddleware
{
    public function handle($request, $next)
    {
        $startTime = microtime(true);

        $response = $next($request);

        $duration = (microtime(true) - $startTime) * 1000;

        // Alert if request exceeds budget
        if ($duration > 3000) { // 3 seconds
            Nadi::captureMessage('Request exceeded performance budget', 'warning', [
                'tags' => ['performance' => 'slow_request'],
                'extra' => [
                    'duration_ms' => $duration,
                    'route' => $request->route()?->getName(),
                    'url' => $request->url(),
                ],
            ]);
        }

        return $response;
    }
}

Viewing Performance Data ​

In the Nadi dashboard:

  1. Performance Tab - Overview of slow queries and requests
  2. Error Details - Performance context for each error
  3. Trends - Performance metrics over time

Best Practices ​

Do ​

  • Set appropriate thresholds for your application
  • Track critical business operations
  • Include relevant context with spans
  • Monitor trends over time

Don't ​

  • Set thresholds too low (creates noise)
  • Track every operation (creates overhead)
  • Include sensitive data in span names
  • Ignore consistently slow operations

Optimization Tips ​

When you identify slow operations:

  1. Database Queries

    • Add missing indexes
    • Optimize query structure
    • Implement caching
  2. External APIs

    • Add timeouts
    • Implement retries with backoff
    • Cache responses when possible
  3. Queue Jobs

    • Break into smaller jobs
    • Optimize database operations
    • Use job batching

Next Steps ​

Released under the MIT License.