Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Web Snapshot Profiler Xhprof Bundle Laravel Package

aeatech/web-snapshot-profiler-xhprof-bundle

Symfony bundle for production-friendly web profiling with XHProf and XHGui. Capture snapshot profiles per request, control sampling via route/header/request param matchers, and configure flags for memory/internal function data. Requires PHP 8.2+ and ext-xhprof.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install Dependencies

    pecl install xhprof
    docker run -d -p 8080:80 --name xhgui xhgui/xhgui:0.22.1
    

    Ensure extension=xhprof.so is in your php.ini.

  2. Install the Bundle

    composer require aeatech/web-snapshot-profiler-xhprof-bundle
    

    Enable in config/bundles.php:

    AEATech\WebSnapshotProfilerXhprofBundle\AEATechWebSnapshotProfilerXhprofBundle::class => ['dev' => true, 'prod' => true],
    
  3. Configure Set is_profiling_enabled: true in config/packages/aea_tech_web_snapshot_profiler_xhprof.yaml and define AEA_TECH_WEB_SNAPSHOT_PROFILER_XHPROF_XHGUI in .env:

    AEA_TECH_WEB_SNAPSHOT_PROFILER_XHPROF_XHGUI=http://localhost:8080
    
  4. First Use Case Trigger a profile by visiting a route or manually in code:

    $profiler = $this->container->get('aea_tech_web_snapshot_profiler_xhprof.profiler');
    $profiler->start('my_custom_snapshot_name');
    // ... code to profile ...
    $profiler->stop();
    

Implementation Patterns

Workflows

  1. Conditional Profiling Enable profiling only for specific routes or environments:

    # config/packages/aea_tech_web_snapshot_profiler_xhprof.yaml
    aea_tech_web_snapshot_profiler_xhprof:
        is_profiling_enabled: '%kernel.debug%'  # Only in dev
    
  2. Automatic Profiling for Critical Paths Use middleware to profile high-traffic routes:

    // src/Kernel.php
    protected function build(Request $request): Response
    {
        if ($request->isMethod('GET') && $request->getPathInfo() === '/api/heavy-endpoint') {
            $profiler = $this->getContainer()->get('aea_tech_web_snapshot_profiler_xhprof.profiler');
            $profiler->start('heavy_endpoint');
        }
        // ...
    }
    
  3. Custom Snapshot Naming Override snapshot naming logic in a service:

    // src/Service/ProfilerService.php
    public function start(string $name): void
    {
        $profiler = $this->container->get('aea_tech_web_snapshot_profiler_xhprof.profiler');
        $profiler->start(sprintf('user_%s_%s', auth()->id(), $name));
    }
    
  4. Integration with Symfony Profiler Correlate XHProf snapshots with Symfony’s profiler toolbar:

    // src/EventListener/ProfilerListener.php
    public function onKernelRequest(GetResponseEvent $event)
    {
        if ($event->isMasterRequest() && $this->profiler->isStarted()) {
            $token = $event->getRequest()->query->get('_profiler');
            $this->profiler->setMetadata(['_profiler_token' => $token]);
        }
    }
    

Integration Tips

  • Database Queries: Profile slow queries by wrapping DBAL calls:
    $profiler->start('query_execution');
    $result = $connection->executeQuery('SELECT ...');
    $profiler->stop();
    
  • HTTP Calls: Use with Guzzle or Symfony HttpClient:
    $profiler->start('http_request');
    $client->request('GET', 'https://api.example.com');
    $profiler->stop();
    
  • Cron Jobs: Profile background tasks by injecting the profiler into commands:
    // src/Command/ProcessDataCommand.php
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $profiler = $this->getContainer()->get('aea_tech_web_snapshot_profiler_xhprof.profiler');
        $profiler->start('cron_process_data');
        // ... task logic ...
        $profiler->stop();
    }
    

Gotchas and Tips

Pitfalls

  1. XHProf Extension Conflicts

    • Ensure xhprof is not loaded in php.ini for CLI (use php -n for web requests only).
    • Conflict with xdebug: Disable xdebug when profiling with XHProf to avoid overhead:
      XDEBUG_MODE=off
      
  2. Snapshot Overwrite Risks

    • Default naming (app_version + timestamp) may overwrite snapshots. Customize naming to avoid collisions:
      aea_tech_web_snapshot_profiler_xhprof:
          app_version: 'v1.0.0'
      
      Or use a UUID:
      $profiler->start('snapshot_' . Str::uuid()->toString());
      
  3. XHGUI Connection Issues

    • If snapshots don’t appear in XHGUI, verify:
      • import_uri in config matches XHGUI’s base URL.
      • XHGUI’s xhprof_runs_dir is writable by the web server.
      • No firewall/proxy blocks the upload endpoint.
  4. Performance Overhead

    • Profiling adds ~5-10% overhead. Disable in production unless debugging:
      aea_tech_web_snapshot_profiler_xhprof:
          is_profiling_enabled: '%kernel.debug%'
      

Debugging

  • Missing Snapshots Check XHGUI logs (/var/log/xhgui.log) and PHP errors (storage/logs/). Ensure the profiler is started before the code to profile:

    // WRONG: Profiler started after DB call
    $connection->executeQuery('SELECT * FROM users');
    $profiler->start('query');
    
    // CORRECT: Profiler started before
    $profiler->start('query');
    $connection->executeQuery('SELECT * FROM users');
    
  • Corrupted Snapshots If snapshots are empty or malformed:

    • Restart the web server after enabling xhprof.
    • Clear XHGUI’s cache (rm -rf xhgui/xhprof_runs/*).

Extension Points

  1. Custom Profiler Service Extend the profiler to add metadata:

    // src/Service/CustomProfiler.php
    class CustomProfiler extends \AEATech\WebSnapshotProfilerXhprofBundle\Profiler
    {
        public function start(string $name, array $metadata = []): void
        {
            $this->metadata = array_merge($this->metadata, $metadata);
            parent::start($name);
        }
    }
    

    Register as a service in config/services.yaml:

    services:
        AEATech\WebSnapshotProfilerXhprofBundle\Profiler:
            alias: App\Service\CustomProfiler
    
  2. Post-Processing Snapshots Hook into the post_stop event to process snapshots:

    // src/EventListener/SnapshotListener.php
    public function onPostStop(PostStopEvent $event)
    {
        $snapshot = $event->getSnapshot();
        if ($snapshot->getDuration() > 1.0) { // >1s
            $this->notifyTeam($snapshot);
        }
    }
    

    Bind the listener in services.yaml:

    services:
        App\EventListener\SnapshotListener:
            tags:
                - { name: kernel.event_listener, event: aea_tech_web_snapshot_profiler_xhprof.post_stop }
    
  3. Dynamic Profiling Triggers Use Symfony’s EventDispatcher to start/stop profiling based on events:

    // src/EventListener/RouteListener.php
    public function onKernelRequest(GetResponseEvent $event)
    {
        if ($event->getRequest()->attributes->get('_route') === 'slow_route') {
            $this->profiler->start('slow_route');
        }
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager