trafficmonitor init...1

This commit is contained in:
choi.jh 2025-11-13 18:44:58 +09:00
parent 2d83db4cad
commit f58e4ae2b6

View File

@ -15,44 +15,52 @@ class CollectorService extends CommonService
{ {
private $_form = null; private $_form = null;
private $_helper = null; private $_helper = null;
const OID_IF_IN_OCTETS = '1.3.6.1.2.1.2.2.1.10.'; // ifInOctets (Raw Octets) // 💡 64비트 카운터를 위해 High Capacity OID로 변경: ifHCInOctets
const OID_IF_OUT_OCTETS = '1.3.6.1.2.1.2.2.1.16.'; // ifOutOctets (Raw Octets) const OID_IF_IN_OCTETS = '1.3.6.1.2.1.31.1.1.1.6.';
// 💡 64비트 카운터를 위해 High Capacity OID로 변경: ifHCOutOctets
const OID_IF_OUT_OCTETS = '1.3.6.1.2.1.31.1.1.1.10.';
const SNMP_VERSION = '2c'; const SNMP_VERSION = '2c';
// Counter32의 최대값 + 1 (오버플로우 보정을 위해 사용)
const MAX_COUNTER_32BIT = 4294967296; // 💡 32비트 롤오버 로직을 제거했으므로 해당 상수는 필요 없습니다.
// const MAX_COUNTER_32BIT = 4294967296;
public function __construct(CollectorModel $model) public function __construct(CollectorModel $model)
{ {
parent::__construct($model); parent::__construct($model);
$this->addClassPaths('Collector'); $this->addClassPaths('Collector');
} }
public function getFormService(): CollectorForm public function getFormService(): CollectorForm
{ {
if ($this->_form === null) { if ($this->_form === null) {
$this->_form = new CollectorForm(); $this->_form = new CollectorForm();
$this->_form->setAttributes([ $this->_form->setAttributes([
'pk_field' => $this->model->getPKField(), 'pk_field' => $this->model->getPKField(),
'title_field' => $this->model->getTitleField(), 'title_field' => $this->model->getTitleField(),
'table' => $this->model->getTable(), 'table' => $this->model->getTable(),
'useAutoIncrement' => $this->model->useAutoIncrement(), 'useAutoIncrement' => $this->model->useAutoIncrement(),
'class_path' => $this->getClassPaths(false), 'class_path' => $this->getClassPaths(false),
]); ]);
} }
return $this->_form; return $this->_form;
} }
public function getHelper(): CollectorHelper public function getHelper(): CollectorHelper
{ {
if ($this->_helper === null) { if ($this->_helper === null) {
$this->_helper = new CollectorHelper(); $this->_helper = new CollectorHelper();
$this->_helper->setAttributes([ $this->_helper->setAttributes([
'pk_field' => $this->model->getPKField(), 'pk_field' => $this->model->getPKField(),
'title_field' => $this->model->getTitleField(), 'title_field' => $this->model->getTitleField(),
'table' => $this->model->getTable(), 'table' => $this->model->getTable(),
'useAutoIncrement' => $this->model->useAutoIncrement(), 'useAutoIncrement' => $this->model->useAutoIncrement(),
'class_path' => $this->getClassPaths(false), 'class_path' => $this->getClassPaths(false),
]); ]);
} }
return $this->_helper; return $this->_helper;
} }
//기본 기능부분 //기본 기능부분
public function create(object $dto): CollectorEntity public function create(object $dto): CollectorEntity
{ {
@ -61,6 +69,7 @@ class CollectorService extends CommonService
} }
return parent::create($dto); return parent::create($dto);
} }
public function modify($uid, object $dto): CollectorEntity public function modify($uid, object $dto): CollectorEntity
{ {
if (!$dto instanceof CollectorDTO) { if (!$dto instanceof CollectorDTO) {
@ -68,6 +77,7 @@ class CollectorService extends CommonService
} }
return parent::modify($uid, $dto); return parent::modify($uid, $dto);
} }
//List 검색용 //List 검색용
//FormFilter 조건절 처리 //FormFilter 조건절 처리
//검색어조건절처리 //검색어조건절처리
@ -76,6 +86,7 @@ class CollectorService extends CommonService
$this->model->orLike($this->model->getTable() . "." . $this->model->getTitleField(), $word, 'both'); $this->model->orLike($this->model->getTable() . "." . $this->model->getTitleField(), $word, 'both');
parent::setSearchWord($word); parent::setSearchWord($word);
} }
//Chart용 //Chart용
public function getAggregateDatas(TrafficEntity $trafficEntity, string $startDate, string $endDate): array public function getAggregateDatas(TrafficEntity $trafficEntity, string $startDate, string $endDate): array
{ {
@ -85,28 +96,34 @@ class CollectorService extends CommonService
} }
return $entities; return $entities;
} }
//SNMP연결 //SNMP연결
private function getSNMPOctets(TrafficEntity $trafficEntity, string $oid): ?int private function getSNMPOctets(TrafficEntity $trafficEntity, string $oid): ?int
{ {
$fullOid = $oid . $trafficEntity->getInterface(); $fullOid = $oid . $trafficEntity->getInterface();
$community = $trafficEntity->getCommunity(); $community = $trafficEntity->getCommunity();
$ip = $trafficEntity->getIP(); $ip = $trafficEntity->getIP();
// snmp2_get을 사용하여 SNMP v2c로 요청 // snmp2_get을 사용하여 SNMP v2c로 요청
// 💡 snmp2_get() 함수가 존재하지 않는다는 LSP 오류를 무시하기 위해 @suppress 태그 사용 // 💡 snmp2_get() 함수가 존재하지 않는다는 LSP 오류를 무시하기 위해 @suppress 태그 사용
/** @phpstan-ignore-next-line */ /** @phpstan-ignore-next-line */
$result = @snmp2_get($ip, $community, $fullOid, 100000, 3); $result = @snmp2_get($ip, $community, $fullOid, 100000, 3);
if ($result === false || $result === null) { if ($result === false || $result === null) {
log_message('error', "SNMP 통신 실패: {$ip} ({$fullOid}, Community: {$community})"); log_message('error', "SNMP 통신 실패: {$ip} ({$fullOid}, Community: {$community})");
return null; return null;
} }
// 💡 정규식 수정: /\d+$/ (문자열 끝의 숫자만 추출) // 💡 정규식 수정: /\d+$/ (문자열 끝의 숫자만 추출)
if (preg_match('/\d+$/', $result, $matches)) { if (preg_match('/\d+$/', $result, $matches)) {
// SNMP Counter는 BigInt가 될 수 있으므로 intval 대신 (int) 캐스팅을 사용하여 // SNMP Counter는 64비트 BigInt가 될 수 있으므로, 64비트 PHP 환경에서는
// 최대한 큰 정수로 변환합니다. PHP 64비트 환경이 필요합니다. // (int) 캐스팅을 사용하여 안전하게 64비트 정수로 변환합니다.
// (BigInt 값을 DB에 저장할 때도 PHP의 정수형/문자열 처리 능력이 중요합니다.)
return (int)$matches[0]; return (int)$matches[0];
} }
return null; return null;
} }
public function getCalculatedData(TrafficEntity $trafficEntity): array public function getCalculatedData(TrafficEntity $trafficEntity): array
{ {
$currentInOctets = $this->getSNMPOctets($trafficEntity, self::OID_IF_IN_OCTETS); $currentInOctets = $this->getSNMPOctets($trafficEntity, self::OID_IF_IN_OCTETS);
@ -131,28 +148,19 @@ class CollectorService extends CommonService
$deltaTime = Time::now()->getTimestamp() - $lastTime; $deltaTime = Time::now()->getTimestamp() - $lastTime;
if ($deltaTime > 0) { if ($deltaTime > 0) {
// DB에서 가져온 값도 BIGINT 타입으로 잘 처리되어야 합니다.
// PHP 64비트 환경이라면 자동으로 64비트 정수로 가져옵니다.
$lastIn = $lastEntity->getRawIn(); $lastIn = $lastEntity->getRawIn();
$lastOut = $lastEntity->getRawOut(); $lastOut = $lastEntity->getRawOut();
// 💡 1. 인바운드 Octets 차분 계산 (오버플로우 처리) // 💡 1. 인바운드 Octets 차분 계산 (32비트 롤오버 로직 제거)
if ($currentInOctets < $lastIn) { // 64비트 카운터(BIGINT)를 사용하기 때문에 단순 뺄셈으로 처리합니다.
// 카운터 롤오버 발생: Delta = (MAX - Last) + Current // 64비트 카운터는 실질적으로 롤오버될 일이 없습니다.
$deltaInOctets = (self::MAX_COUNTER_32BIT - $lastIn) + $currentInOctets; $deltaInOctets = $currentInOctets - $lastIn;
log_message('info', "Inbound Rollover Detected for UID: {$trafficEntity->getPK()}. Delta: {$deltaInOctets}");
} else {
// 정상적인 차분
$deltaInOctets = $currentInOctets - $lastIn;
}
// 💡 2. 아웃바운드 Octets 차분 계산 (오버플로우 처리) // 💡 2. 아웃바운드 Octets 차분 계산 (32비트 롤오버 로직 제거)
if ($currentOutOctets < $lastOut) { // 64비트 카운터(BIGINT)를 사용하기 때문에 단순 뺄셈으로 처리합니다.
// 카운터 롤오버 발생 $deltaOutOctets = $currentOutOctets - $lastOut;
$deltaOutOctets = (self::MAX_COUNTER_32BIT - $lastOut) + $currentOutOctets;
log_message('info', "Outbound Rollover Detected for UID: {$trafficEntity->getPK()}. Delta: {$deltaOutOctets}");
} else {
// 정상적인 차분
$deltaOutOctets = $currentOutOctets - $lastOut;
}
// Kbit/s 계산: (Delta_Octets * 8 bits) / Delta_Time_Seconds / 1000 (-> Kbit/s) // Kbit/s 계산: (Delta_Octets * 8 bits) / Delta_Time_Seconds / 1000 (-> Kbit/s)
// 실수(float) 연산으로 정확도를 높입니다. // 실수(float) 연산으로 정확도를 높입니다.
@ -165,12 +173,13 @@ class CollectorService extends CommonService
// DB에 저장할 데이터를 배열로 반환 // DB에 저장할 데이터를 배열로 반환
return [ return [
// 💡 요청에 따라 'in'과 'out' 값을 정수형으로 캐스팅하여 소수점 이하를 버림 // 'raw_in'과 'raw_out'은 이제 64비트 정수(BIGINT)를 담습니다.
// PHP에서 (int) 캐스팅은 64비트 환경에서 64비트 정수를 의미합니다.
'trafficinfo_uid' => (int)$trafficEntity->getPK(), 'trafficinfo_uid' => (int)$trafficEntity->getPK(),
'in' => (int)$inKbitsSec, // 정수형으로 반환 'in' => (int)$inKbitsSec, // 정수형으로 반환
'out' => (int)$outKbitsSec, // 정수형으로 반환 'out' => (int)$outKbitsSec, // 정수형으로 반환
'raw_in' => (int)$currentInOctets, 'raw_in' => (int)$currentInOctets,
'raw_out' => (int)$currentOutOctets, 'raw_out' => (int)$currentOutOctets,
]; ];
} }
} }