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; } } }