테스트 완료

This commit is contained in:
cho
2026-02-11 13:24:44 +09:00
parent 48fae94b48
commit 72d8912597
11 changed files with 67 additions and 48 deletions
@@ -28,8 +28,9 @@ public class AlarmService {
protected static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT); protected static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
final static String ALARM_GROUP = "Alarm"; final static String ALARM_GROUP = "Alarm";
final static String ALARM_KEY = "Alarm"; final static String ALARM_KEY = "{ALARM}";
final static String ALARM_RECIVER = "{RECIVER}"; final static String ALARM_RECIVER = "{RECIVER}";
final static String ALARM_EABLE = "enable.alarm";
public Map<AlarmKey, AlarmPolicy> getAlarmPolicy() { public Map<AlarmKey, AlarmPolicy> getAlarmPolicy() {
@@ -40,16 +41,16 @@ public class AlarmService {
Properties props = PropManager.getInstance().getProperties(ALARM_GROUP); Properties props = PropManager.getInstance().getProperties(ALARM_GROUP);
props.forEach((key, value) -> { props.forEach((key, value) -> {
String keyName = (String) key; String keyName = (String) key;
String configStr = (String) value; String configStr = (String) value;
if (keyName.contains(ALARM_RECIVER)) return; if (keyName.contains(ALARM_KEY)) {
AlarmPolicy newPolicy = buildAlarmPolicy(keyName, configStr); AlarmPolicy newPolicy = buildAlarmPolicy(keyName, configStr);
policyMap.put(newPolicy.getAlarmKey(), newPolicy);
policyMap.put(newPolicy.getAlarmKey(), newPolicy);
}
}); });
} catch (Exception e) { } catch (Exception e) {
@@ -60,29 +61,33 @@ public class AlarmService {
return policyMap; return policyMap;
} }
public boolean isAlarmEnabled() {
return Optional.ofNullable(PropManager.getInstance().getProperty(ALARM_GROUP, ALARM_EABLE))
.map(Boolean::valueOf).orElse(false);
}
private AlarmPolicy buildAlarmPolicy(String key, String configJsonStr) { private AlarmPolicy buildAlarmPolicy(String key, String configJsonStr) {
JsonObject alarmConfig = Jsons.GSON.fromJson(configJsonStr, JsonObject.class); JsonObject alarmConfig = Jsons.GSON.fromJson(configJsonStr, JsonObject.class);
String policyType = alarmConfig.get("type").getAsString(); String policyType = alarmConfig.get("type").getAsString();
int coolDownSec = Optional.ofNullable(alarmConfig.get("coolDownSec")).map(i -> i.getAsInt()).orElse(60);
int thresholdCount = Optional.ofNullable(alarmConfig.get("thresholdCount")).map(i -> i.getAsInt()).orElse(5); int thresholdCount = Optional.ofNullable(alarmConfig.get("thresholdCount")).map(i -> i.getAsInt()).orElse(5);
int timeWindowSec = Optional.ofNullable(alarmConfig.get("timeWindowSec")).map(i -> i.getAsInt()).orElse(60); int timeWindowSec = Optional.ofNullable(alarmConfig.get("timeWindowSec")).map(i -> i.getAsInt()).orElse(60);
AlarmPolicy alarmPolicy; AlarmPolicy alarmPolicy;
if ("count".equals(policyType)) { if ("count".equals(policyType)) {
alarmPolicy = CounterPolicy.builder().alarmKey(new DynamicAlarmKey(key)).coolDownMs(coolDownSec * 1000) alarmPolicy = CounterPolicy.builder().alarmKey(new DynamicAlarmKey(key)).thresholdCount(thresholdCount)
.thresholdCount(thresholdCount).build(); .build();
} else { } else {
alarmPolicy = TimerPolicy.builder().alarmKey(new DynamicAlarmKey(key)).coolDownMs(coolDownSec * 1000) alarmPolicy = TimerPolicy.builder().alarmKey(new DynamicAlarmKey(key)).timeWindowMs(timeWindowSec * 1000)
.timeWindowMs(timeWindowSec * 1000).build(); .build();
} }
return alarmPolicy; return alarmPolicy;
} }
public Map<AlarmKey, SendPolicy> getSendPolicy() { public Map<AlarmKey, SendPolicy> getSendPolicy() {
Map<AlarmKey, SendPolicy> policyMap = new HashMap<AlarmKey, SendPolicy>(); Map<AlarmKey, SendPolicy> policyMap = new HashMap<AlarmKey, SendPolicy>();
@@ -95,11 +100,11 @@ public class AlarmService {
String keyName = (String) key; String keyName = (String) key;
String configStr = (String) value; String configStr = (String) value;
if (!keyName.contains(ALARM_RECIVER)) return; if (!keyName.contains(ALARM_RECIVER))
return;
SendPolicy newPolicy = buildSendPolicy(keyName, configStr); SendPolicy newPolicy = buildSendPolicy(keyName, configStr);
policyMap.put(newPolicy.getAlarmKey(), newPolicy); policyMap.put(newPolicy.getAlarmKey(), newPolicy);
}); });
@@ -111,12 +116,13 @@ public class AlarmService {
return policyMap; return policyMap;
} }
private SendPolicy buildSendPolicy(String key, String configStr) { private SendPolicy buildSendPolicy(String key, String configStr) {
List<String> reciverList = Optional.ofNullable(configStr).map( t -> Arrays.asList(t.split(",")) ).orElse(Collections.EMPTY_LIST); List<String> reciverList = Optional.ofNullable(configStr).map(t -> Arrays.asList(t.split(",")))
.orElse(Collections.EMPTY_LIST);
key = key.replaceAll(ALARM_RECIVER, "").trim();
key = key.replace(ALARM_RECIVER, "").trim() + "{ALARM}";
SendPolicy sendPolicy = new SendPolicy(key, reciverList); SendPolicy sendPolicy = new SendPolicy(key, reciverList);
@@ -1,6 +1,7 @@
package com.eactive.eai.custom.alarm; package com.eactive.eai.custom.alarm;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@@ -11,7 +12,6 @@ import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.eactive.eai.common.property.PropManager;
import com.eactive.eai.common.util.ApplicationContextProvider; import com.eactive.eai.common.util.ApplicationContextProvider;
import com.eactive.eai.common.util.Logger; import com.eactive.eai.common.util.Logger;
import com.eactive.eai.custom.alarm.event.AlarmEvent; import com.eactive.eai.custom.alarm.event.AlarmEvent;
@@ -85,19 +85,36 @@ public class AlarmStateManager {
private void fireAlarm() { private void fireAlarm() {
Map<AlarmKey, AlarmPolicy> alarmPolicyMap = alarmService.getAlarmPolicy(); Map<AlarmKey, AlarmPolicy> alarmPolicyMap = alarmService.getAlarmPolicy();
Map<AlarmKey, SendPolicy> sendPolicyMap = alarmService.getSendPolicy(); Map<AlarmKey, SendPolicy> sendPolicyMap = alarmService.getSendPolicy();
for (AlarmEvent event : registerAlarmList) { Iterator<AlarmEvent> iterator = registerAlarmList.iterator();
while (iterator.hasNext()) {
AlarmEvent event = iterator.next();
AlarmPolicy alarmPolicy = alarmPolicyMap.get(event.getKey()); AlarmPolicy alarmPolicy = alarmPolicyMap.get(event.getKey());
if (alarmPolicy.isAlarmTriggered(event)) { if (alarmPolicy != null && alarmPolicy.isAlarmTriggered(event)) {
// 알람 발송 로직
SendPolicy sendPolicy = sendPolicyMap.get(event.getKey()); SendPolicy sendPolicy = sendPolicyMap.get(event.getKey());
if (alarmService.isAlarmEnabled()) {
send(sendPolicy, event); send(sendPolicy, event);
} else {
logger.info("Alarm is disabled, event = {}, policy = {}", event, sendPolicy);
}
// 리스트에서 안전하게 제거
iterator.remove();
}else { //트리거 조건이 안되더라도, 이벤트발생한지 오래 되었으면 제거하여 OOM 예방.
long firstOcurredAt = event.getCondition().getOcurredAt();
long diffInMs = System.currentTimeMillis() - firstOcurredAt;
if ( diffInMs >= TimeUnit.MINUTES.toMillis(60) ) { //1시간 지난거면 삭제
iterator.remove();
}
} }
} }
} }
@@ -108,7 +125,7 @@ public class AlarmStateManager {
try { try {
List<String> cellPhoneList = sendPolicy.getCellpohoneList(); List<String> cellPhoneList = sendPolicy.getCellPhoneList();
for (String cellPhone : cellPhoneList) { for (String cellPhone : cellPhoneList) {
@@ -2,12 +2,15 @@ package com.eactive.eai.custom.alarm.condition;
import lombok.Builder; import lombok.Builder;
import lombok.Getter; import lombok.Getter;
import lombok.ToString;
@Builder @Builder
@Getter @Getter
@ToString
public class AlarmCondition { public class AlarmCondition {
final long ocurredAt = System.currentTimeMillis(); final long ocurredAt = System.currentTimeMillis();
long lastOcurredAt; // 일단, 미사용 long lastOcurredAt; // 일단, 미사용
@Builder.Default
long count = 1; long count = 1;
public void onOcurr() { public void onOcurr() {
@@ -10,10 +10,12 @@ import com.eactive.eai.custom.alarm.policy.CounterPolicy;
import lombok.Builder; import lombok.Builder;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.ToString;
@Setter @Setter
@Getter @Getter
@Builder @Builder
@ToString
public class AlarmEvent { public class AlarmEvent {
AlarmKey key; AlarmKey key;
AlarmCondition condition; AlarmCondition condition;
@@ -1,5 +1,6 @@
package com.eactive.eai.custom.alarm.key; package com.eactive.eai.custom.alarm.key;
public interface AlarmKey { public interface AlarmKey {
String code(); String code();
} }
@@ -4,9 +4,9 @@ public final class CoreAlarmKey {
private CoreAlarmKey() { } private CoreAlarmKey() { }
public static final AlarmKey CircuitBreaker = new DynamicAlarmKey("CircuitBreaker"); public static final AlarmKey CircuitBreaker = new DynamicAlarmKey("CircuitBreaker{ALARM}");
public static final AlarmKey Timeout = new DynamicAlarmKey("Timeout"); public static final AlarmKey Timeout = new DynamicAlarmKey("Timeout{ALARM}");
} }
@@ -1,5 +1,8 @@
package com.eactive.eai.custom.alarm.key; package com.eactive.eai.custom.alarm.key;
import lombok.ToString;
@ToString
public final class DynamicAlarmKey implements AlarmKey { public final class DynamicAlarmKey implements AlarmKey {
private final String code; private final String code;
@@ -1,6 +1,5 @@
package com.eactive.eai.custom.alarm.policy; package com.eactive.eai.custom.alarm.policy;
import com.eactive.eai.custom.alarm.condition.AlarmCondition;
import com.eactive.eai.custom.alarm.event.AlarmEvent; import com.eactive.eai.custom.alarm.event.AlarmEvent;
import com.eactive.eai.custom.alarm.key.AlarmKey; import com.eactive.eai.custom.alarm.key.AlarmKey;
@@ -12,13 +11,10 @@ public abstract class AlarmPolicy {
private long timeWindowMs; private long timeWindowMs;
private long coolDownMs;
protected AlarmPolicy(Builder<?> builder) { protected AlarmPolicy(Builder<?> builder) {
this.alarmKey = builder.alarmKey; this.alarmKey = builder.alarmKey;
this.thresholdCount = builder.thresholdCount; this.thresholdCount = builder.thresholdCount;
this.timeWindowMs = builder.timeWindowMs; this.timeWindowMs = builder.timeWindowMs;
this.coolDownMs = builder.coolDownMs;
} }
public AlarmKey getAlarmKey() { public AlarmKey getAlarmKey() {
@@ -33,10 +29,6 @@ public abstract class AlarmPolicy {
return timeWindowMs; return timeWindowMs;
} }
public long getCoolDownMs() {
return coolDownMs;
}
public abstract boolean isAlarmTriggered(AlarmEvent event); public abstract boolean isAlarmTriggered(AlarmEvent event);
@@ -55,7 +47,6 @@ public abstract class AlarmPolicy {
private AlarmKey alarmKey; private AlarmKey alarmKey;
private int thresholdCount; private int thresholdCount;
private long timeWindowMs; private long timeWindowMs;
private long coolDownMs;
public T alarmKey(AlarmKey alarmKey) { public T alarmKey(AlarmKey alarmKey) {
this.alarmKey = alarmKey; this.alarmKey = alarmKey;
@@ -72,11 +63,6 @@ public abstract class AlarmPolicy {
return self(); return self();
} }
public T coolDownMs(long coolDownMs) {
this.coolDownMs = coolDownMs;
return self();
}
protected abstract T self(); protected abstract T self();
abstract AlarmPolicy build(); abstract AlarmPolicy build();
@@ -11,7 +11,7 @@ public class CounterPolicy extends AlarmPolicy {
@Override @Override
public boolean isAlarmTriggered(AlarmEvent event) { public boolean isAlarmTriggered(AlarmEvent event) {
if (!event.equals(getAlarmKey())) { if (!event.getKey().equals(getAlarmKey())) {
return false; return false;
} }
@@ -1,22 +1,23 @@
package com.eactive.eai.custom.alarm.policy; package com.eactive.eai.custom.alarm.policy;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.eactive.eai.custom.alarm.key.AlarmKey; import com.eactive.eai.custom.alarm.key.AlarmKey;
import com.eactive.eai.custom.alarm.key.DynamicAlarmKey; import com.eactive.eai.custom.alarm.key.DynamicAlarmKey;
import lombok.Getter; import lombok.Getter;
import lombok.ToString;
@ToString
@Getter @Getter
public class SendPolicy { public class SendPolicy {
final AlarmKey alarmKey; final AlarmKey alarmKey;
final List<String> cellpohoneList = new ArrayList<String>(); final List<String> cellPhoneList;
public SendPolicy(String alarmKey, List<String> cellPhoneList) { public SendPolicy(String alarmKey, List<String> cellPhoneList) {
this.alarmKey = new DynamicAlarmKey(alarmKey); this.alarmKey = new DynamicAlarmKey(alarmKey);
this.cellPhoneList = cellPhoneList;
} }
} }
@@ -13,7 +13,7 @@ public class TimerPolicy extends AlarmPolicy {
@Override @Override
public boolean isAlarmTriggered(AlarmEvent event) { public boolean isAlarmTriggered(AlarmEvent event) {
if (event.equals(getAlarmKey())) { if (event.getKey().equals(getAlarmKey())) {
AlarmCondition condition = event.getCondition(); AlarmCondition condition = event.getCondition();