'integer', 'park_id' => 'integer', 'user_id' => 'integer', 'contract_id' => 'integer', 'error_code' => 'integer', 'created_at' => 'datetime' ]; /** * エラーコードの定数 */ const ERROR_CODE_THRESHOLD = 100; // エラー判定閾値(>=100がエラー) /** * updateされない設定(created_atのみ) * * @var bool */ public $timestamps = false; /** * 駐輪場との関連 * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function park() { return $this->belongsTo(Park::class, 'park_id', 'park_id'); } /** * ユーザーとの関連 * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function user() { return $this->belongsTo(User::class, 'user_id', 'user_id'); } /** * 契約との関連 * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function contract() { return $this->belongsTo(RegularContract::class, 'contract_id', 'contract_id'); } /** * 過去15分間のエラーログを取得 * * @return \Illuminate\Database\Eloquent\Collection */ public static function getRecentErrorLogs() { $fifteenMinutesAgo = Carbon::now()->subMinutes(15); return self::where('created_at', '>=', $fifteenMinutesAgo) ->where('error_code', '>=', self::ERROR_CODE_THRESHOLD) ->orderBy('created_at', 'desc') ->get(); } /** * 指定期間内のエラーログを取得 * * @param string $startTime 開始時刻 * @param string $endTime 終了時刻 * @return \Illuminate\Database\Eloquent\Collection */ public static function getErrorLogsByPeriod(string $startTime, string $endTime) { return self::whereBetween('created_at', [$startTime, $endTime]) ->where('error_code', '>=', self::ERROR_CODE_THRESHOLD) ->orderBy('created_at', 'desc') ->get(); } /** * 指定期間内の全ログを取得 * * @param string $startTime 開始時刻 * @param string $endTime 終了時刻 * @return \Illuminate\Database\Eloquent\Collection */ public static function getLogsByPeriod(string $startTime, string $endTime) { return self::whereBetween('created_at', [$startTime, $endTime]) ->orderBy('created_at', 'desc') ->get(); } /** * プリンタジョブログを作成 * * @param array $data ログデータ * @return PrintJobLog 作成されたログ */ public static function createLog(array $data): PrintJobLog { $defaultData = [ 'park_id' => null, 'user_id' => null, 'contract_id' => null, 'process_name' => '', 'job_name' => '', 'status' => '', 'error_code' => 0, 'status_comment' => '', 'created_at' => now() ]; $mergedData = array_merge($defaultData, $data); return self::create($mergedData); } /** * エラーログかどうかを判定 * * @return bool エラーログかどうか */ public function isError(): bool { return $this->error_code >= self::ERROR_CODE_THRESHOLD; } /** * 正常ログかどうかを判定 * * @return bool 正常ログかどうか */ public function isNormal(): bool { return $this->error_code < self::ERROR_CODE_THRESHOLD; } /** * エラーレベルを取得 * * @return string エラーレベル */ public function getErrorLevel(): string { if ($this->error_code >= 200) { return '重大エラー'; } elseif ($this->error_code >= self::ERROR_CODE_THRESHOLD) { return 'エラー'; } else { return '正常'; } } /** * エラーログの統計情報を取得 * * @param string $startTime 開始時刻 * @param string $endTime 終了時刻 * @return array 統計情報 */ public static function getErrorStatistics(string $startTime, string $endTime): array { $errorLogs = self::getErrorLogsByPeriod($startTime, $endTime); $totalLogs = self::getLogsByPeriod($startTime, $endTime); $errorByCode = $errorLogs->groupBy('error_code')->map->count(); $errorByProcess = $errorLogs->groupBy('process_name')->map->count(); return [ 'total_logs' => $totalLogs->count(), 'error_logs' => $errorLogs->count(), 'error_rate' => $totalLogs->count() > 0 ? round(($errorLogs->count() / $totalLogs->count()) * 100, 2) : 0, 'error_by_code' => $errorByCode->toArray(), 'error_by_process' => $errorByProcess->toArray(), 'period' => [ 'start' => $startTime, 'end' => $endTime ] ]; } /** * 文字列表現 * * @return string */ public function __toString(): string { return sprintf( 'PrintJobLog[ID:%d, Process:%s, ErrorCode:%d, Time:%s]', $this->log_id, $this->process_name, $this->error_code, $this->created_at ? $this->created_at->format('Y-m-d H:i:s') : 'N/A' ); } }