feat: 그룹 유량제어 메트릭 API 추가
- GroupMetricDTO: allowed/rejectedPerSecond/rejectedThreshold/rejectRatio 등
- InflowGroupMetricService: DualInflowControlManager를 통한 메트릭 조회·초기화
(getManager() protected 처리 — 단위 테스트 서브클래싱 지원)
- InflowGroupMetricController: 4개 엔드포인트
GET /{groupId}/metric, GET /metric
POST /{groupId}/metric/reset, POST /metric/reset
- 단위 테스트 2종 (Service 16건, Controller 8건) 전체 통과
- elink-online-common 서브모듈 포인터 업데이트
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
package com.eactive.eai.manage.inflow;
|
||||
|
||||
public class GroupMetricDTO {
|
||||
private String groupId;
|
||||
private String groupName;
|
||||
private boolean activate;
|
||||
private long allowed;
|
||||
private long rejectedPerSecond;
|
||||
private long rejectedThreshold;
|
||||
private long totalRequests;
|
||||
private double rejectRatio;
|
||||
private long lastResetTime;
|
||||
|
||||
public String getGroupId() { return groupId; }
|
||||
public void setGroupId(String groupId) { this.groupId = groupId; }
|
||||
|
||||
public String getGroupName() { return groupName; }
|
||||
public void setGroupName(String groupName) { this.groupName = groupName; }
|
||||
|
||||
public boolean isActivate() { return activate; }
|
||||
public void setActivate(boolean activate) { this.activate = activate; }
|
||||
|
||||
public long getAllowed() { return allowed; }
|
||||
public void setAllowed(long allowed) { this.allowed = allowed; }
|
||||
|
||||
public long getRejectedPerSecond() { return rejectedPerSecond; }
|
||||
public void setRejectedPerSecond(long rejectedPerSecond) { this.rejectedPerSecond = rejectedPerSecond; }
|
||||
|
||||
public long getRejectedThreshold() { return rejectedThreshold; }
|
||||
public void setRejectedThreshold(long rejectedThreshold) { this.rejectedThreshold = rejectedThreshold; }
|
||||
|
||||
public long getTotalRequests() { return totalRequests; }
|
||||
public void setTotalRequests(long totalRequests) { this.totalRequests = totalRequests; }
|
||||
|
||||
public double getRejectRatio() { return rejectRatio; }
|
||||
public void setRejectRatio(double rejectRatio) { this.rejectRatio = rejectRatio; }
|
||||
|
||||
public long getLastResetTime() { return lastResetTime; }
|
||||
public void setLastResetTime(long lastResetTime) { this.lastResetTime = lastResetTime; }
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.eactive.eai.manage.inflow;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/manage/inflow/group")
|
||||
public class InflowGroupMetricController {
|
||||
|
||||
@Autowired
|
||||
private InflowGroupMetricService metricService;
|
||||
|
||||
/**
|
||||
* 특정 그룹의 메트릭 조회
|
||||
* GET /manage/inflow/group/{groupId}/metric
|
||||
*/
|
||||
@GetMapping("/{groupId}/metric")
|
||||
public ResponseEntity<?> getGroupMetric(@PathVariable String groupId) {
|
||||
GroupMetricDTO metric = metricService.getGroupMetric(groupId);
|
||||
|
||||
if (metric == null) {
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "그룹을 찾을 수 없습니다: " + groupId);
|
||||
return ResponseEntity.ok(error);
|
||||
}
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("success", true);
|
||||
result.put("data", metric);
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 모든 그룹의 메트릭 조회
|
||||
* GET /manage/inflow/group/metric
|
||||
*/
|
||||
@GetMapping("/metric")
|
||||
public ResponseEntity<?> getAllGroupMetrics() {
|
||||
List<GroupMetricDTO> list = metricService.getAllGroupMetrics();
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("success", true);
|
||||
result.put("data", list);
|
||||
result.put("count", list.size());
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 그룹의 메트릭 초기화
|
||||
* POST /manage/inflow/group/{groupId}/metric/reset
|
||||
*/
|
||||
@PostMapping("/{groupId}/metric/reset")
|
||||
public ResponseEntity<?> resetGroupMetric(@PathVariable String groupId) {
|
||||
boolean ok = metricService.resetGroupMetric(groupId);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("success", ok);
|
||||
result.put("message", ok ? "초기화 완료: " + groupId : "그룹을 찾을 수 없습니다: " + groupId);
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 전체 그룹 메트릭 초기화
|
||||
* POST /manage/inflow/group/metric/reset
|
||||
*/
|
||||
@PostMapping("/metric/reset")
|
||||
public ResponseEntity<?> resetAllGroupMetrics() {
|
||||
metricService.resetAllGroupMetrics();
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("success", true);
|
||||
result.put("message", "전체 그룹 메트릭 초기화 완료");
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.eactive.eai.manage.inflow;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.eactive.eai.common.inflow.Bucket;
|
||||
import com.eactive.eai.common.inflow.InflowControlUtil;
|
||||
import com.eactive.eai.common.inflow.InflowGroupVO;
|
||||
import com.eactive.eai.common.inflow.dual.DualInflowControlManager;
|
||||
|
||||
@Service
|
||||
public class InflowGroupMetricService {
|
||||
|
||||
public GroupMetricDTO getGroupMetric(String groupId) {
|
||||
DualInflowControlManager manager = getManager();
|
||||
if (manager == null) return null;
|
||||
|
||||
InflowGroupVO groupVo = manager.getGroupInflowThreshold(groupId);
|
||||
if (groupVo == null) return null;
|
||||
|
||||
return buildDTO(groupId, groupVo, manager.getGroupMetrics(groupId));
|
||||
}
|
||||
|
||||
public List<GroupMetricDTO> getAllGroupMetrics() {
|
||||
DualInflowControlManager manager = getManager();
|
||||
if (manager == null) return new ArrayList<>();
|
||||
|
||||
List<GroupMetricDTO> result = new ArrayList<>();
|
||||
for (String groupId : manager.getGroupAllKeys()) {
|
||||
GroupMetricDTO dto = getGroupMetric(groupId);
|
||||
if (dto != null) result.add(dto);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean resetGroupMetric(String groupId) {
|
||||
DualInflowControlManager manager = getManager();
|
||||
if (manager == null) return false;
|
||||
if (manager.getGroupInflowThreshold(groupId) == null) return false;
|
||||
manager.resetGroupMetrics(groupId);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void resetAllGroupMetrics() {
|
||||
DualInflowControlManager manager = getManager();
|
||||
if (manager != null) manager.resetAllGroupMetrics();
|
||||
}
|
||||
|
||||
protected DualInflowControlManager getManager() {
|
||||
Bucket bucket = InflowControlUtil.getBucket();
|
||||
return (bucket instanceof DualInflowControlManager)
|
||||
? (DualInflowControlManager) bucket
|
||||
: null;
|
||||
}
|
||||
|
||||
private GroupMetricDTO buildDTO(String groupId, InflowGroupVO groupVo,
|
||||
DualInflowControlManager.TargetMetrics m) {
|
||||
GroupMetricDTO dto = new GroupMetricDTO();
|
||||
dto.setGroupId(groupId);
|
||||
dto.setGroupName(groupVo.getGroupName());
|
||||
dto.setActivate(groupVo.isActivate());
|
||||
|
||||
if (m != null) {
|
||||
long allowed = m.allowed.get();
|
||||
long rejPs = m.rejectedPerSecond.get();
|
||||
long rejTh = m.rejectedThreshold.get();
|
||||
long total = allowed + rejPs + rejTh;
|
||||
dto.setAllowed(allowed);
|
||||
dto.setRejectedPerSecond(rejPs);
|
||||
dto.setRejectedThreshold(rejTh);
|
||||
dto.setTotalRequests(total);
|
||||
dto.setRejectRatio(total > 0
|
||||
? Math.round((double)(rejPs + rejTh) / total * 10000) / 100.0
|
||||
: 0.0);
|
||||
dto.setLastResetTime(m.lastResetTime);
|
||||
}
|
||||
return dto;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user