directorytree/metrics
Record and query metrics in Laravel with a simple, elegant API. Track page views, API calls, signups, and other events with optional values, categories, dates, hourly buckets, model-scoped metrics, and custom attributes. Supports Redis and extensible drivers.
First Steps:
composer require directorytree/metrics
php artisan vendor:publish --tag="metrics-migrations"
php artisan migrate
use DirectoryTree\Metrics\Facades\Metrics;
Metrics::record(new \DirectoryTree\Metrics\MetricData('page_views'));
Or use the helper:
metric('page_views')->record();
Where to Look First:
config/metrics.php (for driver/configuration)app/Console/Kernel.php (for scheduling metrics:commit if using Redis)app/Providers/AppServiceProvider.php (for global metric capturing)Basic Tracking:
// In a controller/middleware
metric('api_calls')->record();
Batch Recording:
Metrics::capture(); // Start batch
metric('events')->record(50); // Bulk increment
Metrics::commit(); // Flush to DB
Model-Associated Metrics:
// User model with HasMetrics trait
class User extends Model { use HasMetrics; }
// Track logins per user
metric('user_logins')->measurable(auth()->user())->record();
$user->metrics()->where('name', 'user_logins')->sum('value');
Segmented Analytics:
// Track by category + attributes
metric('purchases')
->category('premium')
->with(['source' => 'campaign_a'])
->record();
Metric::where('name', 'purchases')
->where('category', 'premium')
->where('source', 'campaign_a')
->sum('value');
// app/Http/Middleware/TrackApiCalls.php
public function handle($request, Closure $next) {
metric('api_requests')->record();
return $next($request);
}
registered, created):
// In an event listener
metric('user_registrations')->record();
// app/Jobs/RecordMetrics.php
public function handle() {
Metrics::capture();
// Record multiple metrics...
Metrics::commit();
}
Redis Driver Quirks:
metrics:commit is scheduled (e.g., hourly) to avoid metric loss.auto_commit in config if committing manually:
'auto_commit' => env('METRICS_AUTO_COMMIT', false),
Hourly Metrics Overhead:
hourly() scope:
Metric::thisHour()->where('name', 'api_calls')->sum('value');
Attribute Conflicts:
name, value). Example:
// Fails silently (name ignored)
metric('dynamic_name')->with(['name' => 'override'])->record();
Model Metrics Pitfalls:
measurable_type and measurable_id are indexed in the DB for performance.$user->metrics()->whereDeleted()->delete();
// Dump pending metrics (if using Redis or capture)
dd(Metrics::getPendingMetrics());
# Check Redis keys (adjust pattern)
redis-cli keys "metrics:*"
category, measurable_id):
Schema::table('metrics', function (Blueprint $table) {
$table->index(['name', 'category']);
});
select('name', 'value') to limit columns in queries.Custom Metric Models:
Metric model to add scopes:
class CustomMetric extends \DirectoryTree\Metrics\Metric {
public function scopeBySource($query, $source) {
return $query->where('source', $source);
}
}
AppServiceProvider:
Metrics::setMetricModel(CustomMetric::class);
Queue Commit Jobs:
Metrics\Jobs\CommitMetrics manually for async commits:
CommitMetrics::dispatch();
Custom Drivers:
DirectoryTree\Metrics\Contracts\MetricDriver for non-Redis/DB storage (e.g., DynamoDB).How can I help you explore Laravel packages today?