ums Alarm 작업..

This commit is contained in:
cho
2026-02-06 09:43:58 +09:00
parent fcedbabfc9
commit 0340f63a79
13 changed files with 452 additions and 0 deletions
@@ -0,0 +1,10 @@
package com.eactive.eai.common.util;
import com.google.gson.Gson;
public final class Jsons {
private Jsons() {}
public static final Gson GSON = new Gson();
}
@@ -0,0 +1,80 @@
package com.eactive.eai.custom.alarm;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Properties;
import org.springframework.stereotype.Service;
import com.eactive.eai.common.property.PropManager;
import com.eactive.eai.common.util.Jsons;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.custom.alarm.key.DynamicAlarmKey;
import com.eactive.eai.custom.alarm.policy.AlarmPolicy;
import com.eactive.eai.custom.alarm.policy.CounterPolicy;
import com.eactive.eai.custom.alarm.policy.TimerPolicy;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
@Service
public class AlarmService {
protected static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
final static String ALARM_GROUP = "Alarm";
final static String ALARM_KEY = "Alarm";
final static String ALARM_RECIVER = "{RECIVER}";
public List<AlarmPolicy> getAlarmPolicy() {
List<AlarmPolicy> policyList = new ArrayList<AlarmPolicy>();
try {
Properties props = PropManager.getInstance().getProperties(ALARM_GROUP);
props.forEach((key, value) -> {
String keyName = (String) key;
String configStr = (String) value;
if (keyName.contains(ALARM_RECIVER))
return;
policyList.add(buildAlarmPolicy(keyName, configStr));
});
} catch (Exception e) {
logger.error("getAlarmPolicy fail.", e);
return Collections.EMPTY_LIST;
}
return null;
}
AlarmPolicy buildAlarmPolicy(String key, String configJsonStr) {
JsonObject alarmConfig = Jsons.GSON.fromJson(configJsonStr, JsonObject.class);
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 timeWindowSec = Optional.ofNullable(alarmConfig.get("timeWindowSec")).map(i -> i.getAsInt()).orElse(60);
AlarmPolicy alarmPolicy;
if ("CountPolicy".equals(policyType)) {
alarmPolicy = CounterPolicy.builder().alarmKey(new DynamicAlarmKey(key)).coolDownMs(coolDownSec * 1000)
.thresholdCount(thresholdCount).build();
} else {
alarmPolicy = TimerPolicy.builder().alarmKey(new DynamicAlarmKey(key)).coolDownMs(coolDownSec * 1000)
.timeWindowMs(timeWindowSec * 1000).build();
}
return alarmPolicy;
}
}
@@ -0,0 +1,78 @@
package com.eactive.eai.custom.alarm;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.springframework.stereotype.Component;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.custom.alarm.event.AlarmEvent;
@Component
public class AlarmStateManager {
List<AlarmEvent> registerAlarmList = new ArrayList<AlarmEvent>();
private final ScheduledExecutorService scheduler;
protected static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
public AlarmStateManager() {
this.scheduler = Executors.newSingleThreadScheduledExecutor(r -> {
Thread t = new Thread(r);
t.setName("AlarmStateManager-worker");
t.setDaemon(false);
return t;
});
scheduler.scheduleWithFixedDelay(() -> {
try {
// === 여기에 지속 실행할 로직 ===
fireAlarm();
} catch (Throwable e) {
// 반드시 예외 잡기 (안 잡으면 스케줄 자체가 죽음)
logger.error("fireAlarm fail", e);
}
}, 0, 5, TimeUnit.SECONDS); // 최초 0초, 이후 5초 간격
}
public void onEvnet(AlarmEvent alaramEvent) {
Optional<AlarmEvent> existEvent =
registerAlarmList.stream()
.filter(e -> e.equals(alaramEvent))
.findFirst();
if (existEvent.isPresent()) {
AlarmEvent event = existEvent.get();
event.onOcurr();
} else {
registerAlarmList.add(alaramEvent);
}
}
private void fireAlarm() {
for(AlarmEvent event : registerAlarmList) {
}
}
}
@@ -0,0 +1,19 @@
package com.eactive.eai.custom.alarm.condition;
import lombok.Builder;
import lombok.Getter;
@Builder
@Getter
public class AlarmCondition {
AlarmLevel level;
final long ocurredAt;
long lastOcurredAt;
long count = 1;
public void onOcurr() {
this.lastOcurredAt = System.currentTimeMillis();
this.count++;
}
}
@@ -0,0 +1,5 @@
package com.eactive.eai.custom.alarm.condition;
public enum AlarmLevel {
ERROR, WARN, FATAL
}
@@ -0,0 +1,37 @@
package com.eactive.eai.custom.alarm.event;
import java.util.Objects;
import com.eactive.eai.custom.alarm.condition.AlarmCondition;
import com.eactive.eai.custom.alarm.key.AlarmKey;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@Builder
public class AlarmEvent {
AlarmKey key;
AlarmCondition condition;
String message;
public void onOcurr() {
condition.onOcurr();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AlarmEvent)) return false;
AlarmEvent that = (AlarmEvent) o;
return Objects.equals(this.key, that.key);
}
@Override
public int hashCode() {
return Objects.hash(key);
}
}
@@ -0,0 +1,5 @@
package com.eactive.eai.custom.alarm.key;
public interface AlarmKey {
String code();
}
@@ -0,0 +1,9 @@
package com.eactive.eai.custom.alarm.key;
public enum CoreAlarmKey implements AlarmKey {
CircuitBreaker;
@Override
public String code() {
return name();
}
}
@@ -0,0 +1,30 @@
package com.eactive.eai.custom.alarm.key;
public final class DynamicAlarmKey implements AlarmKey {
private final String code;
public DynamicAlarmKey(String code) {
if (code == null || code.isEmpty()) {
throw new IllegalArgumentException("AlarmKey code must not be empty");
}
this.code = code;
}
@Override
public String code() {
return code;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AlarmKey)) return false;
return code.equals(((AlarmKey) o).code());
}
@Override
public int hashCode() {
return code.hashCode();
}
}
@@ -0,0 +1,83 @@
package com.eactive.eai.custom.alarm.policy;
import com.eactive.eai.custom.alarm.event.AlarmEvent;
import com.eactive.eai.custom.alarm.key.AlarmKey;
public abstract class AlarmPolicy {
private AlarmKey alarmKey;
private int thresholdCount;
private long timeWindowMs;
private long coolDownMs;
protected AlarmPolicy(Builder<?> builder) {
this.alarmKey = builder.alarmKey;
this.thresholdCount = builder.thresholdCount;
this.timeWindowMs = builder.timeWindowMs;
this.coolDownMs = builder.coolDownMs;
}
public AlarmKey getAlarmKey() {
return alarmKey;
}
public int getThresholdCount() {
return thresholdCount;
}
public long getTimeWindowMs() {
return timeWindowMs;
}
public long getCoolDownMs() {
return coolDownMs;
}
abstract boolean isAlarmTriggered(AlarmEvent event);
public boolean hasElapsed(long baseTimeMs, long currentTimeMs) {
return currentTimeMs - baseTimeMs >= timeWindowMs;
}
public boolean hasExceededLimit(long count) {
return count >= thresholdCount;
}
public abstract static class Builder<T extends Builder<T>> {
private AlarmKey alarmKey;
private int thresholdCount;
private long timeWindowMs;
private long coolDownMs;
public T alarmKey(AlarmKey alarmKey) {
this.alarmKey = alarmKey;
return self();
}
public T thresholdCount(int thresholdCount) {
this.thresholdCount = thresholdCount;
return self();
}
public T timeWindowMs(long timeWindowMs) {
this.timeWindowMs = timeWindowMs;
return self();
}
public T coolDownMs(long coolDownMs) {
this.coolDownMs = coolDownMs;
return self();
}
protected abstract T self();
abstract AlarmPolicy build();
}
}
@@ -0,0 +1,5 @@
package com.eactive.eai.custom.alarm.policy;
public enum AlarmType {
COUNT, TIMER
}
@@ -0,0 +1,39 @@
package com.eactive.eai.custom.alarm.policy;
import com.eactive.eai.custom.alarm.event.AlarmEvent;
public class CounterPolicy extends AlarmPolicy {
private CounterPolicy(Builder builder) {
super(builder);
}
@Override
boolean isAlarmTriggered(AlarmEvent event) {
if (!event.equals(getAlarmKey())) {
return false;
}
long count = event.getCondition().getCount();
return hasExceededLimit(count);
}
public static Builder builder() {
return new Builder();
}
public static class Builder extends AlarmPolicy.Builder<Builder> {
@Override
protected Builder self() {
return this;
}
@Override
public CounterPolicy build() {
return new CounterPolicy(this);
}
}
}
@@ -0,0 +1,52 @@
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.policy.CounterPolicy.Builder;
public class TimerPolicy extends AlarmPolicy {
private TimerPolicy(Builder builder) {
super(builder);
}
@Override
boolean isAlarmTriggered(AlarmEvent event) {
if (event.equals(getAlarmKey())) {
AlarmCondition condition = event.getCondition();
long baseTimeMs = condition.getOcurredAt();
long lastTimeMs = condition.getLastOcurredAt();
if (hasElapsed(baseTimeMs, lastTimeMs)) {
return true;
} else {
return false;
}
}
return false;
}
public static Builder builder() {
return new Builder();
}
public static class Builder extends AlarmPolicy.Builder<Builder> {
@Override
protected Builder self() {
return this;
}
@Override
public TimerPolicy build() {
return new TimerPolicy(this);
}
}
}