- 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.
190 lines
6.1 KiB
PHP
190 lines
6.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Framework\Queue\MachineLearning;
|
|
|
|
use App\Framework\Config\Environment;
|
|
use App\Framework\DI\Container;
|
|
use App\Framework\DI\Attributes\Initializer;
|
|
use App\Framework\MachineLearning\ModelManagement\ModelPerformanceMonitor;
|
|
use App\Framework\MachineLearning\ModelManagement\ModelRegistry;
|
|
use App\Framework\Queue\Services\JobMetricsManagerInterface;
|
|
use App\Framework\Core\ValueObjects\Score;
|
|
use Psr\Log\LoggerInterface;
|
|
|
|
/**
|
|
* Job Anomaly Detection Initializer
|
|
*
|
|
* Registers ML-based job anomaly detection components in DI container.
|
|
*
|
|
* Registered Services:
|
|
* - JobFeatureExtractor: Extract 8 behavioral features from job sequences
|
|
* - JobAnomalyDetector: Statistical + heuristic anomaly detection
|
|
* - JobHistoryAnalyzer: Historical job pattern analysis coordinator
|
|
*
|
|
* Configuration:
|
|
* - Uses framework defaults for thresholds (customizable via environment)
|
|
* - Integrates with existing JobMetricsManager infrastructure
|
|
*/
|
|
final readonly class JobAnomalyDetectionInitializer
|
|
{
|
|
public function __construct(
|
|
private Container $container,
|
|
private Environment $environment,
|
|
private LoggerInterface $logger
|
|
) {}
|
|
|
|
#[Initializer]
|
|
public function initialize(Container $container): void
|
|
{
|
|
// Register JobFeatureExtractor
|
|
$container->singleton(JobFeatureExtractor::class, function() {
|
|
return new JobFeatureExtractor(
|
|
minConfidence: $this->getMinConfidence()
|
|
);
|
|
});
|
|
|
|
// Register JobAnomalyDetector
|
|
$container->singleton(JobAnomalyDetector::class, function() {
|
|
return new JobAnomalyDetector(
|
|
anomalyThreshold: $this->getAnomalyThreshold(),
|
|
zScoreThreshold: $this->getZScoreThreshold(),
|
|
iqrMultiplier: $this->getIqrMultiplier()
|
|
);
|
|
});
|
|
|
|
// Register JobHistoryAnalyzer
|
|
$container->singleton(JobHistoryAnalyzer::class, function(Container $container) {
|
|
return new JobHistoryAnalyzer(
|
|
metricsManager: $container->get(JobMetricsManagerInterface::class),
|
|
featureExtractor: $container->get(JobFeatureExtractor::class),
|
|
anomalyDetector: $container->get(JobAnomalyDetector::class)
|
|
);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get minimum confidence threshold for feature extraction
|
|
*
|
|
* Default: 0.6 (60%)
|
|
* Environment: JOB_ANOMALY_MIN_CONFIDENCE
|
|
*/
|
|
private function getMinConfidence(): float
|
|
{
|
|
$envValue = getenv('JOB_ANOMALY_MIN_CONFIDENCE');
|
|
|
|
if ($envValue !== false) {
|
|
$value = (float) $envValue;
|
|
return max(0.0, min(1.0, $value)); // Clamp to 0.0-1.0
|
|
}
|
|
|
|
return 0.6;
|
|
}
|
|
|
|
/**
|
|
* Get anomaly detection threshold
|
|
*
|
|
* Default: 0.5 (50% - Score of 50)
|
|
* Environment: JOB_ANOMALY_THRESHOLD
|
|
*/
|
|
private function getAnomalyThreshold(): Score
|
|
{
|
|
$envValue = getenv('JOB_ANOMALY_THRESHOLD');
|
|
|
|
if ($envValue !== false) {
|
|
$value = (int) $envValue;
|
|
$value = max(0, min(100, $value)); // Clamp to 0-100
|
|
return new Score($value);
|
|
}
|
|
|
|
return new Score(50); // 50% threshold
|
|
}
|
|
|
|
/**
|
|
* Get Z-score threshold for statistical outlier detection
|
|
*
|
|
* Default: 3.0 (3 standard deviations)
|
|
* Environment: JOB_ANOMALY_ZSCORE_THRESHOLD
|
|
*/
|
|
private function getZScoreThreshold(): float
|
|
{
|
|
$envValue = getenv('JOB_ANOMALY_ZSCORE_THRESHOLD');
|
|
|
|
if ($envValue !== false) {
|
|
$value = (float) $envValue;
|
|
return max(1.0, min(5.0, $value)); // Clamp to 1.0-5.0
|
|
}
|
|
|
|
return 3.0;
|
|
}
|
|
|
|
/**
|
|
* Get IQR multiplier for outlier detection
|
|
*
|
|
* Default: 1.5 (standard IQR method)
|
|
* Environment: JOB_ANOMALY_IQR_MULTIPLIER
|
|
*/
|
|
private function getIqrMultiplier(): float
|
|
{
|
|
$envValue = getenv('JOB_ANOMALY_IQR_MULTIPLIER');
|
|
|
|
if ($envValue !== false) {
|
|
$value = (float) $envValue;
|
|
return max(1.0, min(3.0, $value)); // Clamp to 1.0-3.0
|
|
}
|
|
|
|
return 1.5;
|
|
}
|
|
|
|
/**
|
|
* Initialize Queue Anomaly Model Adapter for ML Model Management integration
|
|
*/
|
|
#[Initializer]
|
|
public function initializeModelAdapter(): QueueAnomalyModelAdapter
|
|
{
|
|
$this->logger->info('Initializing Queue Anomaly Model Adapter');
|
|
|
|
try {
|
|
// Get required dependencies from container
|
|
$registry = $this->container->get(ModelRegistry::class);
|
|
$performanceMonitor = $this->container->get(ModelPerformanceMonitor::class);
|
|
$anomalyDetector = $this->container->get(JobAnomalyDetector::class);
|
|
|
|
$adapter = new QueueAnomalyModelAdapter(
|
|
registry: $registry,
|
|
performanceMonitor: $performanceMonitor,
|
|
detector: $anomalyDetector
|
|
);
|
|
|
|
// Auto-register current model version if enabled
|
|
if ($this->environment->getBool('QUEUE_ML_AUTO_REGISTER', true)) {
|
|
try {
|
|
$metadata = $adapter->registerCurrentModel();
|
|
$this->logger->info('Queue anomaly model auto-registered', [
|
|
'model_name' => $metadata->modelName,
|
|
'version' => $metadata->version->toString(),
|
|
'type' => $metadata->modelType->value,
|
|
]);
|
|
} catch (\Exception $e) {
|
|
// Model might already exist, which is fine
|
|
$this->logger->debug('Queue anomaly model registration skipped', [
|
|
'reason' => $e->getMessage(),
|
|
]);
|
|
}
|
|
}
|
|
|
|
$this->logger->info('Queue Anomaly Model Adapter initialized successfully');
|
|
|
|
return $adapter;
|
|
} catch (\Throwable $e) {
|
|
$this->logger->error('Failed to initialize Queue Anomaly Model Adapter', [
|
|
'error' => $e->getMessage(),
|
|
'trace' => $e->getTraceAsString(),
|
|
]);
|
|
|
|
throw $e;
|
|
}
|
|
}
|
|
}
|