aeatech/snapshot-profiler-contracts
Contracts/interfaces for integrating a snapshot-based profiler into Laravel/PHP apps. Provides the core abstractions used by the Snapshot Profiler package ecosystem for capturing, storing, and reporting performance snapshots across implementations.
Installation Add the package via Composer:
composer require aeatech/snapshot-profiler-contracts
First Use Case: Define a Profiler Contract Create a simple profiler class implementing the core interface:
use Aeatech\SnapshotProfilerContracts\Profiler;
class MyProfiler implements Profiler
{
public function start(string $name): void
{
// Start profiling logic
}
public function stop(string $name): void
{
// Stop profiling logic
}
public function getSnapshot(string $name): array
{
return ['duration' => 100, 'memory' => '1MB'];
}
}
Register the Profiler
Bind your implementation in config/app.php or a service provider:
$app->bind(Profiler::class, MyProfiler::class);
Basic Usage Inject the profiler into a controller or service:
use Aeatech\SnapshotProfilerContracts\Profiler;
class MyController
{
public function __construct(private Profiler $profiler) {}
public function index()
{
$this->profiler->start('route.index');
// ... logic
$this->profiler->stop('route.index');
$snapshot = $this->profiler->getSnapshot('route.index');
}
}
$app->singleton(Profiler::class, function ($app) {
return new MyProfiler($app['log']);
});
$app->bindWhen(Profiler::class, function ($app, $context) {
return new TenantProfiler($context['tenantId']);
});
Leverage middleware to auto-profile routes:
use Aeatech\SnapshotProfilerContracts\Profiler;
class ProfileMiddleware
{
public function __construct(private Profiler $profiler) {}
public function handle($request, Closure $next)
{
$this->profiler->start('middleware.' . $request->route()->getName());
$response = $next($request);
$this->profiler->stop('middleware.' . $request->route()->getName());
return $response;
}
}
Attach profilers to Laravel events (e.g., Illuminate\Queue\Jobs\JobProcessed):
use Aeatech\SnapshotProfilerContracts\Profiler;
class JobProfiler
{
public function __construct(private Profiler $profiler) {}
public function handle(JobProcessed $event)
{
$this->profiler->start('job.' . $event->job->resolveName());
// ... post-job logic
$this->profiler->stop('job.' . $event->job->resolveName());
}
}
Wrap the profiler to add cross-cutting concerns (e.g., logging):
class LoggingProfiler implements Profiler
{
public function __construct(
private Profiler $profiler,
private LoggerInterface $logger
) {}
public function start(string $name): void
{
$this->logger->info("Profiling started: {$name}");
$this->profiler->start($name);
}
// Delegate other methods...
}
Naming Collisions
start()/stop() pairs to avoid corrupting snapshots.controller.user.show).Snapshot Leaks
start()/stop() calls will cause memory leaks. Use a try-finally pattern:
try {
$this->profiler->start('operation');
// ... logic
} finally {
$this->profiler->stop('operation');
}
Performance Overhead
'profiling' => env('APP_ENV') !== 'production',
Thread Safety
$app->when(Profiler::class)
->needs('$request')
->give(fn () => request());
$this->profiler->getSnapshot('name'); // Debug output
php artisan container:inspect Aeatech\SnapshotProfilerContracts\Profiler to verify registrations.Custom Metrics
Extend the Profiler interface to add methods like:
public function recordMetric(string $name, string $key, mixed $value): void;
Then implement in your concrete class.
Storage Backends
Decouple snapshots from the profiler by adding a SnapshotStorage interface:
interface SnapshotStorage {
public function store(string $name, array $data): void;
public function retrieve(string $name): ?array;
}
Async Profiling Use Laravel’s queue to offload snapshot processing:
$this->dispatch(new StoreSnapshotJob($name, $snapshot));
How can I help you explore Laravel packages today?