Files
michaelschiemer/tests/Database/QueryOptimization/QueryLoggerTest.php
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
2025-10-25 19:18:37 +02:00

187 lines
6.2 KiB
PHP

<?php
declare(strict_types=1);
use App\Framework\Database\QueryOptimization\QueryLogger;
describe('QueryLogger', function () {
beforeEach(function () {
$this->logger = new QueryLogger();
});
it('starts disabled by default', function () {
expect($this->logger->isEnabled())->toBeFalse();
});
it('enables and disables logging', function () {
$this->logger->enable();
expect($this->logger->isEnabled())->toBeTrue();
$this->logger->disable();
expect($this->logger->isEnabled())->toBeFalse();
});
it('ignores queries when disabled', function () {
$this->logger->disable();
$this->logger->logQuery('SELECT * FROM users', [], 5.0);
expect($this->logger->getQueryCount())->toBe(0);
});
it('logs queries when enabled', function () {
$this->logger->enable();
$this->logger->logQuery('SELECT * FROM users WHERE id = ?', [1], 5.5, 1);
expect($this->logger->getQueryCount())->toBe(1);
$logs = $this->logger->getQueryLogs();
expect($logs)->toHaveCount(1);
expect($logs[0]->sql)->toBe('SELECT * FROM users WHERE id = ?');
expect($logs[0]->bindings)->toBe([1]);
expect($logs[0]->executionTimeMs)->toBe(5.5);
expect($logs[0]->rowCount)->toBe(1);
});
it('captures stack trace', function () {
$this->logger->enable();
$this->logger->logQuery('SELECT * FROM users', [], 5.0);
$logs = $this->logger->getQueryLogs();
expect($logs[0]->stackTrace)->not->toBeEmpty();
});
it('identifies caller class and method', function () {
$this->logger->enable();
$this->logger->logQuery('SELECT * FROM users', [], 5.0);
$logs = $this->logger->getQueryLogs();
expect($logs[0]->callerClass)->not->toBeNull();
expect($logs[0]->callerMethod)->not->toBeNull();
});
it('calculates total execution time', function () {
$this->logger->enable();
$this->logger->logQuery('SELECT * FROM users', [], 5.0);
$this->logger->logQuery('SELECT * FROM posts', [], 10.0);
$this->logger->logQuery('SELECT * FROM comments', [], 3.5);
expect($this->logger->getTotalExecutionTime())->toBe(18.5);
});
it('groups queries by pattern', function () {
$this->logger->enable();
$this->logger->logQuery('SELECT * FROM users WHERE id = ?', [1], 5.0);
$this->logger->logQuery('SELECT * FROM users WHERE id = ?', [2], 4.5);
$this->logger->logQuery('SELECT * FROM posts WHERE user_id = ?', [1], 3.0);
$grouped = $this->logger->getGroupedByPattern();
expect($grouped)->toHaveCount(2);
expect($grouped['SELECT * FROM users WHERE id = ?'])->toHaveCount(2);
expect($grouped['SELECT * FROM posts WHERE user_id = ?'])->toHaveCount(1);
});
it('identifies slow queries', function () {
$this->logger->enable();
$this->logger->logQuery('SELECT * FROM users', [], 50.0);
$this->logger->logQuery('SELECT * FROM posts', [], 150.0);
$this->logger->logQuery('SELECT * FROM comments', [], 5.0);
$slowQueries = $this->logger->getSlowQueries(100.0);
expect($slowQueries)->toHaveCount(1);
expect($slowQueries[0]->sql)->toContain('posts');
expect($slowQueries[0]->executionTimeMs)->toBe(150.0);
});
it('clears logged queries', function () {
$this->logger->enable();
$this->logger->logQuery('SELECT * FROM users', [], 5.0);
$this->logger->logQuery('SELECT * FROM posts', [], 3.0);
expect($this->logger->getQueryCount())->toBe(2);
$this->logger->clear();
expect($this->logger->getQueryCount())->toBe(0);
expect($this->logger->getQueryLogs())->toBeEmpty();
});
it('generates query statistics', function () {
$this->logger->enable();
$this->logger->logQuery('SELECT * FROM users', [], 5.0);
$this->logger->logQuery('SELECT * FROM posts', [], 10.0);
$this->logger->logQuery('INSERT INTO logs (message) VALUES (?)', ['test'], 2.0);
$this->logger->logQuery('UPDATE users SET name = ? WHERE id = ?', ['John', 1], 3.0);
$this->logger->logQuery('DELETE FROM logs WHERE id = ?', [1], 1.5);
$this->logger->logQuery('SELECT * FROM users', [], 150.0); // Slow query
$stats = $this->logger->getStatistics();
expect($stats['total_queries'])->toBe(6);
expect($stats['total_time_ms'])->toBe(171.5);
expect($stats['select_count'])->toBe(3);
expect($stats['insert_count'])->toBe(1);
expect($stats['update_count'])->toBe(1);
expect($stats['delete_count'])->toBe(1);
expect($stats['slow_queries'])->toBe(1);
expect($stats['unique_patterns'])->toBe(5);
});
it('calculates average execution time', function () {
$this->logger->enable();
$this->logger->logQuery('SELECT * FROM users', [], 10.0);
$this->logger->logQuery('SELECT * FROM posts', [], 20.0);
$this->logger->logQuery('SELECT * FROM comments', [], 30.0);
$stats = $this->logger->getStatistics();
expect($stats['average_time_ms'])->toBe(20.0);
});
it('handles empty query logs in statistics', function () {
$this->logger->enable();
$stats = $this->logger->getStatistics();
expect($stats['total_queries'])->toBe(0);
expect($stats['average_time_ms'])->toBe(0.0);
});
it('skips framework internals when finding caller', function () {
$this->logger->enable();
$this->logger->logQuery('SELECT * FROM users', [], 5.0);
$logs = $this->logger->getQueryLogs();
// Caller should not be from /Framework/Database/ or /vendor/
if ($logs[0]->callerClass) {
expect($logs[0]->callerClass)->not->toContain('Framework\\Database');
expect($logs[0]->callerClass)->not->toContain('vendor');
}
});
it('formats stack trace correctly', function () {
$this->logger->enable();
$this->logger->logQuery('SELECT * FROM users', [], 5.0);
$logs = $this->logger->getQueryLogs();
$stackTrace = $logs[0]->stackTrace;
// Stack trace should contain class/method and file:line format
expect($stackTrace)->toMatch('/.+\(.+:\d+\)/');
});
});