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.
This commit is contained in:
2025-10-25 19:18:37 +02:00
parent caa85db796
commit fc3d7e6357
83016 changed files with 378904 additions and 20919 deletions

View File

@@ -0,0 +1,210 @@
<?php
declare(strict_types=1);
use App\Framework\LiveComponents\Observability\ComponentMetricsCollector;
describe('ComponentMetricsCollector - Basic Functionality', function () {
it('can be instantiated', function () {
$collector = new ComponentMetricsCollector();
expect($collector)->toBeInstanceOf(ComponentMetricsCollector::class);
});
it('starts with empty metrics', function () {
$collector = new ComponentMetricsCollector();
$metrics = $collector->getMetrics();
expect($metrics)->toBeArray();
expect(count($metrics))->toBe(0);
});
it('records render metrics', function () {
$collector = new ComponentMetricsCollector();
$collector->recordRender('comp-123', 45.5, false);
$metrics = $collector->getMetrics();
expect(count($metrics))->toBeGreaterThan(0);
});
it('records action execution', function () {
$collector = new ComponentMetricsCollector();
$collector->recordAction('comp-123', 'handleClick', 25.5, true);
$metrics = $collector->getMetrics();
expect(count($metrics))->toBeGreaterThan(0);
});
it('records cache hits', function () {
$collector = new ComponentMetricsCollector();
$collector->recordCacheHit('comp-123', true);
$metrics = $collector->getMetrics();
expect(count($metrics))->toBeGreaterThan(0);
});
it('records cache misses', function () {
$collector = new ComponentMetricsCollector();
$collector->recordCacheHit('comp-123', false);
$metrics = $collector->getMetrics();
expect(count($metrics))->toBeGreaterThan(0);
});
it('records event dispatching', function () {
$collector = new ComponentMetricsCollector();
$collector->recordEventDispatched('comp-123', 'user:updated');
$metrics = $collector->getMetrics();
expect(count($metrics))->toBeGreaterThan(0);
});
it('records event receiving', function () {
$collector = new ComponentMetricsCollector();
$collector->recordEventReceived('comp-123', 'data:loaded');
$metrics = $collector->getMetrics();
expect(count($metrics))->toBeGreaterThan(0);
});
it('records hydration time', function () {
$collector = new ComponentMetricsCollector();
$collector->recordHydration('comp-123', 15.5);
$metrics = $collector->getMetrics();
expect(count($metrics))->toBeGreaterThan(0);
});
it('records batch operations', function () {
$collector = new ComponentMetricsCollector();
$collector->recordBatch(10, 125.5, 8, 2);
$metrics = $collector->getMetrics();
expect(count($metrics))->toBeGreaterThan(0);
});
it('records fragment updates', function () {
$collector = new ComponentMetricsCollector();
$collector->recordFragmentUpdate('comp-123', 3, 45.5);
$metrics = $collector->getMetrics();
expect(count($metrics))->toBeGreaterThan(0);
});
it('records upload chunks', function () {
$collector = new ComponentMetricsCollector();
$collector->recordUploadChunk('session-abc', 0, 125.5, true);
$metrics = $collector->getMetrics();
expect(count($metrics))->toBeGreaterThan(0);
});
it('records upload completion', function () {
$collector = new ComponentMetricsCollector();
$collector->recordUploadComplete('session-abc', 1500.5, 5);
$metrics = $collector->getMetrics();
expect(count($metrics))->toBeGreaterThan(0);
});
it('generates summary statistics', function () {
$collector = new ComponentMetricsCollector();
$collector->recordRender('comp-1', 45.5, false);
$collector->recordAction('comp-1', 'handleClick', 25.5, true);
$collector->recordCacheHit('comp-1', true);
$summary = $collector->getSummary();
expect($summary)->toBeArray();
expect(isset($summary['total_renders']))->toBeTrue();
expect(isset($summary['total_actions']))->toBeTrue();
expect(isset($summary['cache_hits']))->toBeTrue();
expect(isset($summary['cache_misses']))->toBeTrue();
expect(isset($summary['cache_hit_rate']))->toBeTrue();
});
it('exports Prometheus format', function () {
$collector = new ComponentMetricsCollector();
$collector->recordRender('comp-1', 45.5, false);
$collector->recordAction('comp-1', 'handleClick', 25.5, true);
$prometheus = $collector->exportPrometheus();
expect($prometheus)->toBeString();
expect(str_contains($prometheus, '# HELP'))->toBeTrue();
expect(str_contains($prometheus, 'livecomponent_'))->toBeTrue();
});
it('can reset metrics', function () {
$collector = new ComponentMetricsCollector();
$collector->recordRender('comp-1', 45.5, false);
expect(count($collector->getMetrics()))->toBeGreaterThan(0);
$collector->reset();
expect(count($collector->getMetrics()))->toBe(0);
});
it('calculates cache hit rate correctly', function () {
$collector = new ComponentMetricsCollector();
// 2 hits, 1 miss = 66.7% hit rate
$collector->recordCacheHit('comp-1', true);
$collector->recordCacheHit('comp-2', true);
$collector->recordCacheHit('comp-3', false);
$summary = $collector->getSummary();
expect($summary['cache_hits'])->toBe(2);
expect($summary['cache_misses'])->toBe(1);
expect($summary['cache_hit_rate'])->toBeGreaterThan(60.0);
expect($summary['cache_hit_rate'])->toBeLessThan(70.0);
});
it('handles action errors separately', function () {
$collector = new ComponentMetricsCollector();
$collector->recordAction('comp-1', 'handleClick', 25.5, false);
$summary = $collector->getSummary();
expect($summary['action_errors'])->toBe(1);
});
it('tracks multiple components', function () {
$collector = new ComponentMetricsCollector();
$collector->recordRender('comp-1', 45.5, false);
$collector->recordRender('comp-2', 30.2, true);
$collector->recordAction('comp-1', 'handleClick', 25.5, true);
$collector->recordAction('comp-2', 'handleSubmit', 35.8, true);
$summary = $collector->getSummary();
expect($summary['total_renders'])->toBe(2);
expect($summary['total_actions'])->toBe(2);
});
it('handles zero operations gracefully', function () {
$collector = new ComponentMetricsCollector();
$summary = $collector->getSummary();
expect($summary['total_renders'])->toBe(0);
expect($summary['total_actions'])->toBe(0);
expect($summary['cache_hit_rate'])->toBe(0.0);
});
});