env->getBool('ERROR_AGGREGATION_ENABLED', true); if(!$enabled) { return new NullErrorAggregator(); } return new ErrorAggregator( storage: $container->get(ErrorStorageInterface::class), cache: $container->get(Cache::class), clock: $container->get(Clock::class), alertQueue: $container->get(Queue::class), logger: $container->get(Logger::class), batchSize: $this->env->getInt('ERROR_AGGREGATION_BATCH_SIZE', 100), maxRetentionDays: $this->env->getInt('ERROR_AGGREGATION_MAX_RETENTION_DAYS', 90) ); } #[Initializer] public function initialize(Container $container): void { $env = $container->get(Environment::class); $enabled = $env->getBool('ERROR_AGGREGATION_ENABLED', true); // Storage $container->bind(ErrorStorageInterface::class, function (Container $container) use ($enabled) { if (! $enabled) { // Return a no-op storage if disabled return new DatabaseErrorStorage( connection: $container->get(ConnectionInterface::class) ); } return new DatabaseErrorStorage( connection: $container->get(ConnectionInterface::class) ); }); // Error Aggregator Interface - bind to concrete or Null implementation // $container->bind(ErrorAggregatorInterface::class, function (Container $container) use ($enabled) { // if (! $enabled) { // return new NullErrorAggregator(); // } // // $env = $container->get(Environment::class); // return new ErrorAggregator( // storage: $container->get(ErrorStorageInterface::class), // cache: $container->get(Cache::class), // clock: $container->get(Clock::class), // alertQueue: $container->get(Queue::class), // logger: $container->get(Logger::class), // batchSize: $env->getInt('ERROR_AGGREGATION_BATCH_SIZE', 100), // maxRetentionDays: $env->getInt('ERROR_AGGREGATION_MAX_RETENTION_DAYS', 90) // ); // }); // Error Aggregator (concrete class) - delegate to interface $container->bind(ErrorAggregator::class, function (Container $container) use ($enabled) { if (! $enabled) { throw new \RuntimeException('ErrorAggregator is disabled. Use ErrorAggregatorInterface instead.'); } $env = $container->get(Environment::class); return new ErrorAggregator( storage: $container->get(ErrorStorageInterface::class), cache: $container->get(Cache::class), clock: $container->get(Clock::class), alertQueue: $container->get(Queue::class), logger: $container->get(Logger::class), batchSize: $env->getInt('ERROR_AGGREGATION_BATCH_SIZE', 100), maxRetentionDays: $env->getInt('ERROR_AGGREGATION_MAX_RETENTION_DAYS', 90) ); }); // Alert Manager $container->bind(AlertManager::class, function (Container $container) { $env = $container->get(Environment::class); $channels = []; // Email channel (if configured) $emailRecipients = $env->get('ALERT_EMAIL_RECIPIENTS'); if (! empty($emailRecipients)) { $recipients = explode(',', $emailRecipients); $channels[] = new EmailAlertChannel( transport: $container->get(TransportInterface::class), recipients: array_map('trim', $recipients), fromEmail: $env->get('ALERT_FROM_EMAIL', 'alerts@example.com'), fromName: $env->get('ALERT_FROM_NAME', 'Error Alert System') ); } return new AlertManager( cache: $container->get(Cache::class), clock: $container->get(Clock::class), retryQueue: $container->get(Queue::class), logger: $container->get(Logger::class), channels: $channels, throttleConfig: [ 'urgent' => $env->getInt('ALERT_THROTTLE_URGENT', 300), 'high' => $env->getInt('ALERT_THROTTLE_HIGH', 900), 'medium' => $env->getInt('ALERT_THROTTLE_MEDIUM', 3600), 'low' => $env->getInt('ALERT_THROTTLE_LOW', 86400), ] ); }); // Middleware $container->bind(ErrorAggregationMiddleware::class, function (Container $container) use ($enabled) { return new ErrorAggregationMiddleware( errorAggregator: $container->get(ErrorAggregator::class), enabled: $enabled ); }); } }