deviceModel = $deviceModel; $this->hardwareCheckLogModel = $hardwareCheckLogModel; $this->printJobLogModel = $printJobLogModel; $this->batchLogModel = $batchLogModel; $this->operatorQueModel = $operatorQueModel; $this->mailSendService = $mailSendService; } /** * SHJ-6 サーバ死活監視処理メイン実行 * * 処理フロー: * 【処理1】サーバ死活監視(DBアクセス) * 【処理2】デバイス管理マスタを取得する * 【処理3】デバイス毎のハードウェア状態を取得する * 【処理4】プリンタ制御プログラムログを取得する * 【判断3】エラーログ有無 * 【処理5】バッチ処理ログを作成する * ※ 異常時は共通A処理を実行 * * @return array 処理結果 */ public function executeServerMonitoring(): array { $batchLogId = null; $warnings = []; $errorDetails = []; try { // バッチ処理開始ログ作成 $batchLog = BatchLog::createBatchLog( 'shj6', BatchLog::STATUS_START, [], 'SHJ-6 サーバ死活監視処理開始' ); $batchLogId = $batchLog->id; Log::info('SHJ-6 サーバ死活監視処理開始', [ 'batch_log_id' => $batchLogId ]); // 【処理1】サーバ死活監視(DBアクセス) $dbAccessResult = $this->checkDatabaseAccess(); if (!$dbAccessResult['success']) { // DB接続NGの場合は共通A処理実行 $this->executeCommonProcessA($batchLogId, 'DB接続エラー: ' . $dbAccessResult['message']); return [ 'success' => false, 'message' => 'データベース接続エラーが発生しました', 'error_details' => [$dbAccessResult['message']], 'batch_log_id' => $batchLogId ]; } // 【処理2】デバイス管理マスタを取得する $devices = $this->getDeviceManagementData(); Log::info('デバイス管理マスタ取得完了', [ 'device_count' => count($devices) ]); // 【処理3】デバイス毎のハードウェア状態を取得する $hardwareStatusResult = $this->getHardwareStatus($devices); if (!$hardwareStatusResult['success']) { // ハードウェア状態取得できなかった場合は共通A処理実行 $this->executeCommonProcessA($batchLogId, 'ハードウェア状態取得エラー: ' . $hardwareStatusResult['message']); $warnings[] = 'ハードウェア状態の一部で異常を検出しました'; $errorDetails[] = $hardwareStatusResult['message']; } // 【処理4】プリンタ制御プログラムログを取得する $printerLogResult = $this->getPrinterControlLogs(); // 【判断3】エラーログ有無 if ($printerLogResult['has_errors']) { // エラーログ有の場合は共通A処理実行 $this->executeCommonProcessA($batchLogId, 'プリンタエラーログ検出: ' . $printerLogResult['error_summary']); $warnings[] = 'プリンタ制御でエラーが検出されました'; $errorDetails[] = $printerLogResult['error_summary']; } // 【処理5】バッチ処理ログを作成する $monitoringSummary = $this->createMonitoringSummary($devices, $hardwareStatusResult, $printerLogResult); $status = empty($warnings) ? BatchLog::STATUS_SUCCESS : BatchLog::STATUS_WARNING; $message = empty($warnings) ? 'SHJ-6 サーバ死活監視処理正常完了' : 'SHJ-6 サーバ死活監視処理完了(警告あり)'; $batchLog->update([ 'status' => $status, 'end_time' => now(), 'message' => $message, 'success_count' => 1 ]); Log::info('SHJ-6 サーバ死活監視処理完了', [ 'batch_log_id' => $batchLogId, 'monitoring_summary' => $monitoringSummary, 'warnings' => $warnings ]); return [ 'success' => true, 'message' => 'SHJ-6 サーバ死活監視処理が完了しました', 'monitoring_summary' => $monitoringSummary, 'warnings' => $warnings, 'error_details' => $errorDetails, 'batch_log_id' => $batchLogId ]; } catch (\Exception $e) { $errorMessage = 'SHJ-6 サーバ死活監視処理でエラーが発生: ' . $e->getMessage(); if (isset($batchLog) && $batchLog) { $batchLog->update([ 'status' => BatchLog::STATUS_ERROR, 'end_time' => now(), 'message' => $errorMessage, 'error_details' => $e->getMessage(), 'error_count' => 1 ]); } // 例外発生時も共通A処理実行 $this->executeCommonProcessA($batchLogId, $errorMessage); Log::error('SHJ-6 サーバ死活監視処理エラー', [ 'batch_log_id' => $batchLogId, 'exception' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return [ 'success' => false, 'message' => $errorMessage, 'error_details' => [$e->getMessage()], 'batch_log_id' => $batchLogId ]; } } /** * 【処理1】サーバ死活監視(DBアクセス) * * @return array アクセス結果 */ private function checkDatabaseAccess(): array { try { // 設定マスタテーブルへの簡単なクエリでDB接続確認 $result = DB::select('SELECT 1 as test'); if (empty($result)) { return [ 'success' => false, 'message' => 'データベースクエリの結果が空です' ]; } Log::info('データベース接続確認成功'); return [ 'success' => true, 'message' => 'データベース接続正常' ]; } catch (\Exception $e) { Log::error('データベース接続エラー', [ 'error' => $e->getMessage() ]); return [ 'success' => false, 'message' => $e->getMessage() ]; } } /** * 【処理2】デバイス管理マスタを取得する * * @return array デバイス情報 */ private function getDeviceManagementData(): array { try { $devices = DB::table('device') ->select([ 'device_id', 'park_id', 'device_type', 'device_subject', 'device_identifier', 'device_work', 'device_workstart', 'device_replace', 'device_remarks', 'operator_id' ]) ->where('device_workstart', '<=', now()) ->whereNull('device_replace') ->get() ->toArray(); Log::info('デバイス管理マスタ取得完了', [ 'device_count' => count($devices) ]); return $devices; } catch (\Exception $e) { Log::error('デバイス管理マスタ取得エラー', [ 'error' => $e->getMessage() ]); throw $e; } } /** * 【処理3】デバイス毎のハードウェア状態を取得する * * @param array $devices デバイス一覧 * @return array ハードウェア状態結果 */ private function getHardwareStatus(array $devices): array { try { $normalDevices = 0; $abnormalDevices = 0; $abnormalDetails = []; foreach ($devices as $device) { $latestStatus = HardwareCheckLog::getLatestStatusByDevice($device->device_id); if (!$latestStatus) { $abnormalDevices++; $abnormalDetails[] = "デバイスID {$device->device_id}: ハードウェア状態ログが存在しません"; continue; } if ($latestStatus->isNormal()) { $normalDevices++; } else { $abnormalDevices++; $abnormalDetails[] = "デバイスID {$device->device_id}: {$latestStatus->getStatusNameAttribute()} - {$latestStatus->status_comment}"; } } Log::info('ハードウェア状態取得完了', [ 'total_devices' => count($devices), 'normal_devices' => $normalDevices, 'abnormal_devices' => $abnormalDevices ]); return [ 'success' => $abnormalDevices === 0, 'total_devices' => count($devices), 'normal_devices' => $normalDevices, 'abnormal_devices' => $abnormalDevices, 'abnormal_details' => $abnormalDetails, 'message' => $abnormalDevices > 0 ? "{$abnormalDevices}台のデバイスで異常を検出" : '全デバイス正常' ]; } catch (\Exception $e) { Log::error('ハードウェア状態取得エラー', [ 'error' => $e->getMessage() ]); return [ 'success' => false, 'message' => $e->getMessage(), 'abnormal_details' => ["ハードウェア状態取得中にエラーが発生: " . $e->getMessage()] ]; } } /** * 【処理4】プリンタ制御プログラムログを取得する * * @return array プリンタログ結果 */ private function getPrinterControlLogs(): array { try { // 過去15分間のエラーログを取得 $errorLogs = PrintJobLog::getRecentErrorLogs(); $hasErrors = $errorLogs->count() > 0; $errorSummary = ''; $errorDetails = []; if ($hasErrors) { $errorsByCode = $errorLogs->groupBy('error_code'); $errorSummaryParts = []; foreach ($errorsByCode as $errorCode => $logs) { $count = $logs->count(); $errorSummaryParts[] = "エラーコード{$errorCode}: {$count}件"; foreach ($logs as $log) { $errorDetails[] = sprintf( "[%s] %s - エラーコード: %d, %s", $log->created_at->format('Y-m-d H:i:s'), $log->process_name, $log->error_code, $log->status_comment ); } } $errorSummary = implode(', ', $errorSummaryParts); } Log::info('プリンタ制御プログラムログ取得完了', [ 'monitoring_period_minutes' => self::PRINTER_LOG_MONITOR_MINUTES, 'error_logs_count' => $errorLogs->count(), 'has_errors' => $hasErrors ]); return [ 'success' => true, 'has_errors' => $hasErrors, 'error_count' => $errorLogs->count(), 'error_summary' => $errorSummary, 'error_details' => $errorDetails, 'monitoring_period' => self::PRINTER_LOG_MONITOR_MINUTES . '分間' ]; } catch (\Exception $e) { Log::error('プリンタ制御プログラムログ取得エラー', [ 'error' => $e->getMessage() ]); return [ 'success' => false, 'has_errors' => true, 'error_summary' => 'ログ取得エラー: ' . $e->getMessage(), 'error_details' => ["プリンタログ取得中にエラーが発生: " . $e->getMessage()] ]; } } /** * 監視結果サマリーを作成 * * @param array $devices デバイス一覧 * @param array $hardwareResult ハードウェア結果 * @param array $printerResult プリンタ結果 * @return string 監視サマリー */ private function createMonitoringSummary(array $devices, array $hardwareResult, array $printerResult): string { $summary = [ 'デバイス数: ' . count($devices), 'ハードウェア正常: ' . ($hardwareResult['normal_devices'] ?? 0) . '台', 'ハードウェア異常: ' . ($hardwareResult['abnormal_devices'] ?? 0) . '台', 'プリンタエラー: ' . ($printerResult['error_count'] ?? 0) . '件' ]; return implode(', ', $summary); } /** * 共通A処理:監視結果を反映 * * @param int|null $batchLogId バッチログID * @param string $alertMessage アラートメッセージ * @return void */ private function executeCommonProcessA(?int $batchLogId, string $alertMessage): void { try { Log::info('共通A処理開始', [ 'batch_log_id' => $batchLogId, 'alert_message' => $alertMessage ]); // 【共通判断1】DB反映可否判定 $canReflectToDb = $this->canReflectToDatabase(); if ($canReflectToDb) { // 【共通処理1】オペレータキューを登録する $this->registerOperatorQueue($alertMessage, $batchLogId); // 【共通処理2】メール送信対象オペレータを取得する $operators = $this->getMailTargetOperators(); // 【共通判断2】送信対象有無 if (!empty($operators)) { foreach ($operators as $operator) { $this->sendAlertMail($operator['email'], $alertMessage, 'オペレータ'); } } // 【共通処理3】駐輪場管理者を取得する $parkManagers = $this->getParkManagers(); // 【共通判断3】送信対象有無 if (!empty($parkManagers)) { foreach ($parkManagers as $manager) { $this->sendAlertMail($manager['email'], $alertMessage, '駐輪場管理者'); } } } else { // DB反映NGの場合は固定メールアドレスに送信 $this->sendAlertMail(self::FIXED_EMAIL_ADDRESS, $alertMessage, 'システム管理者'); } Log::info('共通A処理完了', [ 'batch_log_id' => $batchLogId ]); } catch (\Exception $e) { Log::error('共通A処理エラー', [ 'batch_log_id' => $batchLogId, 'error' => $e->getMessage() ]); } } /** * DB反映可否判定 * * @return bool 反映可能かどうか */ private function canReflectToDatabase(): bool { try { // 簡単なINSERTテストでDB反映可否を確認 DB::beginTransaction(); $testId = DB::table('operator_que')->insertGetId([ 'que_class' => 6, 'que_comment' => 'DB反映テスト', 'que_status' => 0, 'created_at' => now(), 'updated_at' => now() ]); // テストレコードを削除 DB::table('operator_que')->where('que_id', $testId)->delete(); DB::commit(); return true; } catch (\Exception $e) { DB::rollBack(); Log::warning('DB反映不可', ['error' => $e->getMessage()]); return false; } } /** * オペレータキューを登録 * * @param string $alertMessage アラートメッセージ * @param int|null $batchLogId バッチログID * @return void */ private function registerOperatorQueue(string $alertMessage, ?int $batchLogId): void { try { OperatorQue::create([ 'que_class' => 6, // SHJ-6用のクラス 'user_id' => null, 'contract_id' => null, 'park_id' => null, 'que_comment' => $alertMessage, 'que_status' => 0, // 待機中 'que_status_comment' => 'システム監視アラート', 'work_instructions' => "SHJ-6監視処理 BatchLogID: {$batchLogId}", 'created_at' => now(), 'updated_at' => now() ]); Log::info('オペレータキュー登録完了', [ 'batch_log_id' => $batchLogId, 'alert_message' => $alertMessage ]); } catch (\Exception $e) { Log::error('オペレータキュー登録エラー', [ 'batch_log_id' => $batchLogId, 'error' => $e->getMessage() ]); } } /** * メール送信対象オペレータを取得 * * @return array オペレータ一覧 */ private function getMailTargetOperators(): array { try { // user_typeがオペレータのユーザーを取得(仮の条件) $operators = DB::table('users') ->select(['user_id', 'email', 'name']) ->where('user_type', 'operator') // 実際のテーブル構造に合わせて調整 ->whereNotNull('email') ->where('email', '!=', '') ->get() ->map(function ($user) { return [ 'user_id' => $user->user_id, 'email' => $user->email, 'name' => $user->name ?? 'オペレータ' ]; }) ->toArray(); Log::info('メール送信対象オペレータ取得完了', [ 'operator_count' => count($operators) ]); return $operators; } catch (\Exception $e) { Log::error('メール送信対象オペレータ取得エラー', [ 'error' => $e->getMessage() ]); return []; } } /** * 駐輪場管理者を取得 * * @return array 駐輪場管理者一覧 */ private function getParkManagers(): array { try { // 駐輪場管理者を取得(仮の条件) $managers = DB::table('users') ->select(['user_id', 'email', 'name']) ->where('user_type', 'park_manager') // 実際のテーブル構造に合わせて調整 ->whereNotNull('email') ->where('email', '!=', '') ->get() ->map(function ($user) { return [ 'user_id' => $user->user_id, 'email' => $user->email, 'name' => $user->name ?? '駐輪場管理者' ]; }) ->toArray(); Log::info('駐輪場管理者取得完了', [ 'manager_count' => count($managers) ]); return $managers; } catch (\Exception $e) { Log::error('駐輪場管理者取得エラー', [ 'error' => $e->getMessage() ]); return []; } } /** * アラートメールを送信 * * @param string $email メールアドレス * @param string $alertMessage アラートメッセージ * @param string $recipientType 受信者タイプ * @return void */ private function sendAlertMail(string $email, string $alertMessage, string $recipientType): void { try { // SHJメール送信機能を使用(メールテンプレートID=1を使用、実際の値に調整) $result = $this->mailSendService->executeMailSend( $email, '', // 予備メールアドレスは空 1 // システムアラート用メールテンプレートID ); if ($result['success']) { Log::info('アラートメール送信成功', [ 'email' => $email, 'recipient_type' => $recipientType, 'alert_message' => $alertMessage ]); } else { Log::error('アラートメール送信失敗', [ 'email' => $email, 'recipient_type' => $recipientType, 'error' => $result['message'] ]); } } catch (\Exception $e) { Log::error('アラートメール送信エラー', [ 'email' => $email, 'recipient_type' => $recipientType, 'error' => $e->getMessage() ]); } } }