m6web/statsd
Simple StatsD client for PHP. Send counters, gauges, timers and sets to a StatsD/Graphite backend with minimal overhead. Designed for easy integration and straightforward API to instrument apps and collect metrics.
Installation
composer require m6web/statsd
Add to config/app.php under providers:
M6Web\Statsd\StatsdServiceProvider::class,
Publish config (optional):
php artisan vendor:publish --provider="M6Web\Statsd\StatsdServiceProvider" --tag=config
Basic Configuration
Edit .env:
STATSD_HOST=localhost
STATSD_PORT=8125
STATSD_PREFIX=myapp.
Or configure via config/statsd.php.
First Usage
Inject the Statsd facade or service:
use M6Web\Statsd\Facades\Statsd;
// Increment a counter
Statsd::increment('user.signups');
// Record a timing (in milliseconds)
Statsd::timing('user.signup.time', 150);
Quick Wins
Statsd::gauge() for real-time metrics (e.g., active users).Statsd::histogram() for distributions (e.g., request latency).Statsd::withTags() for dimensional analysis:
Statsd::withTags(['env' => 'production'])->increment('api.calls');
Request Metrics
// Middleware: Track request duration
public function handle($request, Closure $next) {
$start = microtime(true);
$response = $next($request);
Statsd::timing('http.requests', (microtime(true) - $start) * 1000);
return $response;
}
Database Query Tracking
// Log query execution time
DB::listen(function ($query) {
Statsd::timing('db.queries', $query->time * 1000);
Statsd::increment('db.queries.total');
});
Event-Based Metrics
// Track failed jobs
FailedJob::failed(function ($job, $exception) {
Statsd::increment('jobs.failed');
Statsd::histogram('jobs.duration', $job->attempts * 100);
});
Service Layer Instrumentation
// Track API call success/failure
public function fetchData() {
try {
$data = Http::get('https://api.example.com/data');
Statsd::increment('api.calls.success');
return $data;
} catch (\Exception $e) {
Statsd::increment('api.calls.failure');
throw $e;
}
}
$schedule->command('backup:run')->everyMinute()->then(function () {
Statsd::timing('cron.backup', 1000); // Example: 1s duration
});
// In worker bootstrap
Statsd::increment('queue.workers.active');
/metrics endpoint:
Route::get('/metrics', function () {
return Statsd::getMetrics(); // If supported by the package
});
Statsd::withTags(['user_id' => auth()->id()])->increment('user.actions');
if ($user->isPremium()) {
Statsd::increment('premium.user.actions');
}
// For high-volume events (e.g., logs)
Statsd::batch(function () {
Statsd::increment('logs.processed');
Statsd::timing('log.processing', 50);
});
Prefix Collisions
STATSD_PREFIX is unique to avoid mixing metrics with other services.myapp.users. vs. otherapp.users..Timing Granularity
Statsd::timing('request.time', (microtime(true) - $start) * 1000);
Tag Limits
// Bad: Too many tags
Statsd::withTags(['a' => 'long_value', 'b' => 'another_long_value'])->increment('metric');
// Good: Short, meaningful tags
Statsd::withTags(['env' => 'prod', 'type' => 'api'])->increment('calls');
Connection Issues
try {
Statsd::increment('fallback.test');
} catch (\Exception $e) {
Log::warning('StatsD unavailable, metric dropped', ['exception' => $e]);
}
Rate Limiting
loop.iterations) may overwhelm StatsD. Use sampling:
if (rand(1, 100) <= 10) { // 10% sample
Statsd::increment('loop.iterations');
}
Verify Metrics
Use statsd-nozzle or graphite-statsd to inspect incoming metrics:
docker run -p 8126:8126 hopsoft/statsd-nozzle
Then query http://localhost:8126/.
Check Config
Validate .env/config/statsd.php:
// Test connection
$client = Statsd::getClient();
$client->ping(); // If supported
Log Unsent Metrics Override the client to log drops:
Statsd::extend(function ($statsd) {
$originalFlush = $statsd->getClient()->flush;
$statsd->getClient()->flush = function () use ($originalFlush) {
Log::debug('Flushing metrics', ['queue' => $this->getClient()->getQueue()]);
$originalFlush();
};
});
Custom Metric Types
Extend the Statsd facade to add domain-specific methods:
Statsd::extend(function ($statsd) {
$statsd->trackPayment = function ($amount, $status) {
Statsd::gauge('payments.amount', $amount);
Statsd::increment("payments.status.{$status}");
};
});
Contextual Metrics Attach request/user context automatically:
Statsd::macro('withRequestContext', function () {
return $this->withTags([
'request_id' => request()->header('X-Request-ID'),
'user_id' => auth()->id(),
'route' => request()->route()->getName(),
]);
});
Async Flushing For high-throughput apps, flush metrics asynchronously:
Statsd::getClient()->setAsync(true);
Metric Sanitization Prevent invalid characters in metric names:
Statsd::macro('safeIncrement', function ($name) {
$sanitized = preg_replace('/[^a-zA-Z0-9._-]/', '_', $name);
$this->increment($sanitized);
});
How can I help you explore Laravel packages today?