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