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; } //기본 기능부분 protected function create_process(array $formDatas): CollectorEntity { //CollectorEntity를 생성하면 Setter가 자동 호출됩니다. return new CollectorEntity($formDatas); } public function create(object $dto): CollectorEntity { if (!$dto instanceof CollectorDTO) { throw new RuntimeException(__METHOD__ . "에서 오류발생:" . get_class($dto) . "는 사용할수 없습니다."); } return parent::create($dto); } protected function modify_process($uid, array $formDatas): CollectorEntity { if (!$uid) { throw new \Exception("수집 번호가 정의 되지 않았습니다."); } $entity = $this->getEntity($uid); if (!$entity instanceof CollectorEntity) { throw new \Exception("{$uid}에 해당하는 수집정보을 찾을수 없습니다."); } // 변경 사항을 Entity에 적용합니다. (Dirty Tracking 활성화) $formDatas[$this->model->getPKField()] = $uid; $entity->fill($formDatas); // 💡 부모 호출 제거: 변경된 Entity 객체를 반환합니다. return $entity; } 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 GET 요청을 실행하고 Octet 값을 추출합니다. * @param string $ip 장비 IP * @param int $ifIndex 인터페이스 인덱스 * @param string $community SNMP 커뮤니티 문자열 * @param string $oid OID (접두사) * @return int|null 수집된 Octet 값 또는 오류 시 null */ protected function getOctets(string $ip, int $ifIndex, string $community, string $oid): ?int { $fullOid = $oid . $ifIndex; // snmp2_get을 사용하여 SNMP v2c로 요청 (64비트 카운터 지원에 유리) $result = @snmp2_get($ip, $community, $fullOid, 100000, 3); // 3초 타임아웃 if ($result === false || $result === null) { log_message('error', "SNMP 통신 실패: {$ip} ({$fullOid}, Community: {$community})"); return null; } // 결과 문자열에서 숫자 값만 추출하여 정수로 변환 if (preg_match('/\d+/', $result, $matches)) { return (int)$matches[0]; } return null; } /** * 트래픽을 수집하고 Kbit/s를 계산하여 DB에 저장합니다. * @param int $trafficInfoUid traffic_info 테이블의 기본 키 (연계 키) * @param string $ip 장비 IP * @param int $ifIndex 인터페이스 인덱스 * @param string $community SNMP 커뮤니티 문자열 */ public function collectAndCalculate(int $trafficInfoUid, string $ip, int $ifIndex, string $community): void { $currentInOctets = $this->getOctets($ip, $ifIndex, $community, self::OID_IF_IN_OCTETS); $currentOutOctets = $this->getOctets($ip, $ifIndex, $community, self::OID_IF_OUT_OCTETS); $currentTime = Time::now()->toDateTimeString(); if ($currentInOctets === null || $currentOutOctets === null) { log_message('warning', "트래픽 수집 실패: {$ip} - IF{$ifIndex} (UID: {$trafficInfoUid})"); return; } // 이전 데이터를 조회하여 Rate 계산에 사용 $lastEntry = $this->model->getLastEntryByInfoUid($trafficInfoUid); $inKbitsSec = 0.0; $outKbitsSec = 0.0; // 이전 데이터가 있어야만 Rate 계산 가능 if ($lastEntry !== null) { $lastTime = Time::parse($lastEntry['created_at'])->getTimestamp(); $deltaTime = Time::now()->getTimestamp() - $lastTime; if ($deltaTime > 0) { // Raw Octets 값의 차분 계산 $deltaInOctets = $currentInOctets - $lastEntry['raw_in_octets']; $deltaOutOctets = $currentOutOctets - $lastEntry['raw_out_octets']; // 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', "시간 차이 오류 발생: {$ip} - {$deltaTime}초 (UID: {$trafficInfoUid})"); } } // Collector DB에 결과 저장 $this->model->insert([ 'trafficinfo_uid' => $trafficInfoUid, 'in_kbits_sec' => round($inKbitsSec, 2), 'out_kbits_sec' => round($outKbitsSec, 2), 'raw_in_octets' => $currentInOctets, // 다음 계산을 위해 Raw 값 저장 'raw_out_octets' => $currentOutOctets, // 다음 계산을 위해 Raw 값 저장 'created_at' => $currentTime, ]); log_message('info', "트래픽 계산 및 저장 완료 (UID: {$trafficInfoUid}), In: {$inKbitsSec} Kb/s"); } }