aeatech/snapshot-profiler
Laravel/PHP snapshot profiler that captures lightweight performance snapshots of requests and code execution. Helps you track timing, memory usage, and key metrics over time for debugging and regression detection, with simple integration into existing apps.
Installation
composer require aeatech/snapshot-profiler
Ensure aeatech/snapshot-profiler-contracts is also installed (dependency).
Service Provider Registration
Add to config/app.php under providers:
AEATech\SnapshotProfiler\SnapshotProfilerServiceProvider::class,
Publish Config (Optional)
php artisan vendor:publish --provider="AEATech\SnapshotProfiler\SnapshotProfilerServiceProvider" --tag="config"
Default config is minimal; customize paths (e.g., storage/app/snapshots) and storage drivers (e.g., local, s3).
First Use Case: Profiling a Route Bind the profiler to a route or middleware:
use AEATech\SnapshotProfiler\SnapshotProfiler;
Route::get('/profile', function (SnapshotProfiler $profiler) {
$profiler->start('route_profiling');
// Your logic here...
$profiler->stop('route_profiling');
return $profiler->getSnapshot('route_profiling');
});
Manual Profiling
Use ProfilerInterface methods in controllers, commands, or jobs:
$profiler->start('database_operations');
DB::table('users')->get();
$profiler->stop('database_operations');
$snapshot = $profiler->getSnapshot('database_operations');
Middleware Integration Create a middleware to auto-profile requests:
namespace App\Http\Middleware;
use AEATech\SnapshotProfiler\SnapshotProfiler;
use Closure;
class ProfileRequests
{
public function __construct(private SnapshotProfiler $profiler) {}
public function handle($request, Closure $next)
{
$this->profiler->start('request_' . $request->path());
$response = $next($request);
$this->profiler->stop('request_' . $request->path());
return $response;
}
}
Event-Based Profiling Profile events or listeners:
use AEATech\SnapshotProfiler\SnapshotProfiler;
use Illuminate\Queue\Events\JobProcessed;
class ProfileJobs
{
public function __construct(private SnapshotProfiler $profiler) {}
public function handle(JobProcessed $event)
{
$this->profiler->start('job_' . $event->job->resolveName());
// Event logic...
$this->profiler->stop('job_' . $event->job->resolveName());
}
}
Queue Job Profiling
Extend Illuminate\Bus\Queueable jobs:
use AEATech\SnapshotProfiler\SnapshotProfiler;
class ProcessOrder implements ShouldQueue
{
public function __construct(private SnapshotProfiler $profiler) {}
public function handle()
{
$this->profiler->start('process_order');
// Job logic...
$this->profiler->stop('process_order');
}
}
Nested Profiling Use unique IDs for nested operations:
$profiler->start('user_creation');
$profiler->start('user_creation/validation');
// Validation logic...
$profiler->stop('user_creation/validation');
$profiler->stop('user_creation');
Conditional Profiling Enable profiling only in specific environments:
if (app()->environment('staging')) {
$profiler->start('staging_profiling');
// ...
}
Custom Storage Override storage logic via config:
'storage' => [
'driver' => 's3',
'key' => env('AWS_SNAPSHOT_KEY'),
'secret' => env('AWS_SNAPSHOT_SECRET'),
'bucket' => 'my-snapshots',
],
Memory Leaks
stop() can bloat memory usage.try-catch-finally to ensure stop() is always called:
try {
$profiler->start('operation');
// Risky logic...
} finally {
$profiler->stop('operation');
}
Overhead in Production
if (!app()->environment('production')) {
$profiler->start('safe_operation');
// ...
}
Snapshot Naming Collisions
stop() overwrites data.$name = 'user_' . Str::uuid()->toString();
$profiler->start($name);
Storage Driver Quirks
local driver may fill disk if unchecked.'ttl' => 24, // Hours
Check Profiler Status
Inject ProfilerInterface and call isRunning() to verify:
if ($profiler->isRunning('critical_operation')) {
// Handle error: profiling was not stopped.
}
Log Snapshots Dump snapshots to Laravel logs for debugging:
\Log::debug('Snapshot:', $profiler->getSnapshot('debug_operation'));
Custom Profiler Logic
Extend ProfilerInterface to add metrics (e.g., memory usage):
class CustomProfiler implements ProfilerInterface {
public function start(string $name) {
// Custom start logic (e.g., memory baseline).
}
// ...
}
Event Dispatching Trigger events when snapshots are saved:
// In SnapshotProfilerServiceProvider::boot()
event(new \AEATech\SnapshotProfiler\Events\SnapshotSaved($snapshot));
GUI Integration Build a dashboard using the stored snapshots (e.g., with Laravel Nova or custom admin panel).
Default Storage Path
If not published, defaults to storage/app/snapshots. Ensure the directory is writable:
mkdir -p storage/app/snapshots
chmod -R 775 storage/app/snapshots
Driver-Specific Settings
For s3, ensure the bucket exists and credentials are valid. Test with:
php artisan storage:link
How can I help you explore Laravel packages today?