addClassPaths('Collector'); } public function getFormService(): CollectorForm { if ($this->formServiceInstance === null) { $this->formServiceInstance = new CollectorForm(); $this->formServiceInstance->setAttributes([ 'pk_field' => $this->model->getPKField(), 'title_field' => $this->model->getTitleField(), 'table' => $this->model->getTable(), 'useAutoIncrement' => $this->model->useAutoIncrement(), 'class_path' => $this->getClassPaths(false) ]); } return $this->formServiceInstance; } public function getHelper(): CollectorHelper { if ($this->helperInstance === null) { $this->helperInstance = new CollectorHelper(); $this->helperInstance->setAttributes([ 'pk_field' => $this->model->getPKField(), 'title_field' => $this->model->getTitleField(), 'table' => $this->model->getTable(), 'useAutoIncrement' => $this->model->useAutoIncrement(), 'class_path' => $this->getClassPaths(false) ]); } return $this->helperInstance; } //기본 기능부분 public function create(object $dto): CollectorEntity { if (!$dto instanceof CollectorDTO) { throw new RuntimeException(__METHOD__ . "에서 오류발생:" . get_class($dto) . "는 사용할수 없습니다."); } return parent::create($dto); } public function modify($uid, object $dto): CollectorEntity { if (!$dto instanceof CollectorDTO) { throw new RuntimeException(__METHOD__ . "에서 오류발생:" . get_class($dto) . "는 사용할수 없습니다."); } return parent::modify($uid, $dto); } //List 검색용 //FormFilter 조건절 처리 //검색어조건절처리 public function setSearchWord(string $word): void { $this->model->orLike($this->model->getTable() . "." . $this->model->getTitleField(), $word, 'both'); parent::setSearchWord($word); } //SNMP연결 private function getSNMPOctets(TrafficEntity $trafficEntity, string $oid): ?int { $fullOid = $oid . $trafficEntity->getInterface(); $community = $trafficEntity->getCommunity(); $ip = $trafficEntity->getIP(); // snmp2_get을 사용하여 SNMP v2c로 요청 // 💡 snmp2_get() 함수가 존재하지 않는다는 LSP 오류를 무시하기 위해 @suppress 태그 사용 /** @phpstan-ignore-next-line */ $result = @snmp2_get($ip, $community, $fullOid, 100000, 3); if ($result === false || $result === null) { log_message('error', "SNMP 통신 실패: {$ip} ({$fullOid}, Community: {$community})"); return null; } // 💡 정규식 수정: /\d+$/ (문자열 끝의 숫자만 추출) if (preg_match('/\d+$/', $result, $matches)) { // SNMP Counter는 BigInt가 될 수 있으므로 intval 대신 (int) 캐스팅을 사용하여 // 최대한 큰 정수로 변환합니다. PHP 64비트 환경이 필요합니다. return (int)$matches[0]; } return null; } public function getCalculatedData(TrafficEntity $trafficEntity): array { $currentInOctets = $this->getSNMPOctets($trafficEntity, self::OID_IF_IN_OCTETS); $currentOutOctets = $this->getSNMPOctets($trafficEntity, self::OID_IF_OUT_OCTETS); if ($currentInOctets === null || $currentOutOctets === null) { $message = "트래픽 수집 실패: {$trafficEntity->getIP()} - IF{$trafficEntity->getInterface()} (UID: {$trafficEntity->getPK()})"; log_message('warning', $message); throw new \Exception($message); } // 이전 데이터를 조회하여 Rate 계산에 사용 $lastEntity = $this->model->getLastEntity($trafficEntity->getPK()); $inKbitsSec = 0; $outKbitsSec = 0; // 이전 데이터가 있어야만 Rate 계산 가능 if ($lastEntity !== null) { $lastTime = Time::parse($lastEntity->getCreatedAt())->getTimestamp(); $deltaTime = Time::now()->getTimestamp() - $lastTime; if ($deltaTime > 0) { // Raw Octets 값의 차분 계산 $deltaInOctets = $currentInOctets - $lastEntity->getRawIn(); $deltaOutOctets = $currentOutOctets - $lastEntity->getRawOut(); // Kbit/s 계산: (Delta_Octets * 8 bits) / Delta_Time_Seconds / 1000 (-> Kbit/s) $inKbitsSec = ($deltaInOctets * 8) / $deltaTime / 1000; $outKbitsSec = ($deltaOutOctets * 8) / $deltaTime / 1000; } else { log_message('error', "시간 차이 오류 발생: {$trafficEntity->getIP()} - {$deltaTime}초 (UID: {$trafficEntity->getPK()})"); } } // DB에 저장할 데이터를 배열로 반환 return [ 'trafficinfo_uid' => (int)$trafficEntity->getPK(), 'in' => (int)$inKbitsSec, 'out' => (int)$outKbitsSec, 'raw_in' => (int)$currentInOctets, 'raw_out' => (int)$currentOutOctets, ]; } }