A powerful toolkit for monitoring and optimizing Symfony applications, offering real-time performance metrics, N+1 query detection, cognitive complexity analysis, automated reporting, a secure web dashboard, and seamless CI/CD integration.
- π Real-time Performance Metrics: Monitor request response time, database queries, memory usage, and CLI command performance.
- π N+1 Query Detection: Identify and resolve N+1 query issues with detailed analysis.
- π§ Cognitive Complexity Analysis: Detect complex code structures (threshold > 10) to improve maintainability.
- π Automated Reporting: Generate HTML, JSON, or SVG badge reports for CI/CD pipelines.
- π Secure Web Dashboard: Visualize performance trends and metrics at
/_performance. - π Performance Alerts: Configurable thresholds for response time, memory usage, query count, and complexity.
- πΎ Flexible Storage: Store data using Doctrine ORM (
DatabaseStorage) or JSON files (FileStorage) with retention policies. - π Internationalization: Supports English and French translations.
- π Extensibility: Add custom analyzers, collectors, and event listeners.
- β Standards Compliance: Enforced with PHPStan (max level), PHPUnit (100% coverage), ECS, and Rector.
- β‘ Performance Optimizations: Request sampling, degraded mode, and circuit breaker for external services.
Install the bundle via Composer:
composer require 2a/symfony-performance-analyzerEnable the bundle in config/bundles.php:
return [
// ...
AA\PerformanceAnalyzer\PerformanceAnalyzerBundle::class => ['all' => true],
];Generate and apply database migrations (for database storage):
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrateInstall assets for the web dashboard:
php bin/console assets:install --symlinkCreate a configuration file at config/packages/symfony_performance_analyzer.yaml:
symfony_performance_analyzer:
enabled: true
storage:
type: database # or 'file'
file_path: '%kernel.project_dir%/var/performance'
retention:
days: 30 # Retain data for 30 days
max_records: 10000 # Maximum number of records
analyzers:
memory: true
n_plus_one: true
cognitive_complexity: true
thresholds:
max_memory_mb: 256 # Maximum memory in MB
max_response_time_ms: 500 # Maximum response time in ms
max_db_queries: 50 # Maximum number of database queries
max_cognitive_complexity: 10 # Maximum cognitive complexity score
sampling:
rate: 1.0 # Analyze 100% of requests (0.0 to 1.0)
degraded_mode: false # Enable degraded mode under high load
degraded_threshold_ms: 1000 # Trigger degraded mode above this response time (ms)
circuit_breaker:
enabled: false # Enable circuit breaker for external services
failure_threshold: 5 # Number of failures before opening circuit
retry_timeout: 60 # Seconds to wait before retrying
dashboard:
enabled: true
route_prefix: /_performance
security:
enable_firewall: false
allowed_ips: [] # Restrict dashboard access to specific IPs
profiler:
enabled: true
toolbar: true # Enable Symfony debug toolbar integration
ci_cd:
enabled: false
level: warning # Report level: error, warning, notice
output_format: json # Report format: json, htmlFor file-based storage, ensure the storage directory is writable:
mkdir -p var/performance
chmod -R 775 var/performanceAnalyze performance and generate reports:
# Generate an HTML performance report
php bin/console performance:generate-report --format=html --output=report.html
# Generate a JSON report for CI/CD
php bin/console performance:generate-report --format=json --dry-run > ci-report.json
# Generate a CI/CD badge
php bin/console performance:generate-ci-badge --output=badge.svg
# Profile a CLI command
php bin/console performance:profile app:my-commandExample JSON report output:
{
"logs": [
{
"route": "app_home",
"response_time": 100,
"memory_usage": 32,
"query_count": 5
}
],
"stats": {
"avg_response_time": 100,
"avg_memory_usage": 32,
"max_query_count": 10
},
"issues": [
{
"type": "high_complexity",
"message": "Complexity 12 > 10",
"severity": "high"
}
]
}Access the performance dashboard at /_performance. Secure it by enabling the firewall and restricting IP access:
symfony_performance_analyzer:
dashboard:
security:
enable_firewall: true
allowed_ips: ['127.0.0.1', '192.168.1.0/24']Customize the dashboard route in config/routes.yaml:
performance_dashboard:
path: /_performance
controller: AA\PerformanceAnalyzer\Controller\DashboardController::indexThe bundle integrates with Symfonyβs debug toolbar, displaying request time, query count, memory usage, and performance issues. Enable it in the configuration:
symfony_performance_analyzer:
profiler:
toolbar: trueThe bundle collects and analyzes the following metrics:
| Metric | Description | Expected Range | Source |
|---|---|---|---|
| Request Time | HTTP request execution time | 0β500 ms | PerformanceTracker, Timer |
| Database Queries | Query count, duration, and N+1 issues | 0β50 queries | DatabaseQueryCollector, QueryAnalyzer |
| Memory Usage | Peak memory consumption | 0β256 MB | MemoryAnalyzer |
| Cognitive Complexity | Code complexity score | 0β10 | CognitiveComplexityAnalyzer |
| CLI Performance | Command execution time | 0β5000 ms | PerformanceTracker |
| Issues | Performance violations detected | 0β10 issues | AnalysisResult |
Create a custom analyzer by implementing AnalyzerInterface:
namespace App\Analyzer;
use AA\PerformanceAnalyzer\Model\AnalysisResult;
use AA\PerformanceAnalyzer\Model\PerformanceResult;
use AA\PerformanceAnalyzer\Service\Analyzer\AnalyzerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class CustomAnalyzer implements AnalyzerInterface
{
public function analyze(Request $request, Response $response, PerformanceResult $result): AnalysisResult
{
$analysisResult = new AnalysisResult();
if ($response->getStatusCode() >= 500) {
$analysisResult->addIssue('server_error', [
'message' => 'Server error detected',
'status_code' => $response->getStatusCode(),
'severity' => 'high'
]);
}
return $analysisResult;
}
}Register the analyzer in config/services.yaml:
App\Analyzer\CustomAnalyzer:
tags: ['performance.analyzer']Create a custom collector by implementing CollectorInterface:
namespace App\Collector;
use AA\PerformanceAnalyzer\Service\Collector\CollectorInterface;
class CustomCollector implements CollectorInterface
{
private array $data = [];
public function start(string $identifier): void
{
$this->data[$identifier] = ['start_time' => microtime(true)];
}
public function collect(string $identifier): array
{
return [
'custom_duration' => microtime(true) - $this->data[$identifier]['start_time']
];
}
}Register the collector:
App\Collector\CustomCollector:
tags: ['performance.collector']- Request Sampling: Set
sampling.rateto a value less than 1.0 (e.g., 0.1 for 10% of requests) in production to reduce overhead. - Degraded Mode: Enable
sampling.degraded_modeto skip non-essential collectors when response time exceedsdegraded_threshold_ms. - Circuit Breaker: Activate
circuit_breaker.enabledto protect against external service failures, with configurable failure thresholds and retry timeouts. - Data Retention: Configure
storage.retentionto limit database or file storage growth, specifying retention days and maximum records. - Overhead: Performance tests ensure tracking overhead is below 5ms per request.
Run the test suite:
vendor/bin/phpunitPerform static analysis and linting:
vendor/bin/phpstan analyze
vendor/bin/ecs check
vendor/bin/rector process --dry-runThe bundle includes:
- Unit Tests: Cover all services and components (100% coverage).
- Integration Tests: Validate end-to-end workflows with database storage.
- Performance Tests: Measure tracking overhead.
- Edge Case Tests: Handle database failures and high-load scenarios.
Remove the bundle:
composer remove 2a/symfony-performance-analyzerDrop database tables (if using database storage):
php bin/console doctrine:query:sql "DROP TABLE performance_log, performance_stat"Remove configuration files and assets:
rm config/packages/symfony_performance_analyzer.yaml
rm -rf var/performance- Fork the repository.
- Create a feature branch:
git checkout -b feature/my-feature - Commit changes:
git commit -am 'Add my feature' - Push to the branch:
git push origin feature/my-feature - Open a Pull Request.
Ensure all tests pass and adhere to coding standards (ECS, Rector, PHPStan).
This bundle is licensed under the MIT License. See the LICENSE file for details.