mirror of
https://github.com/dromara/hertzbeat.git
synced 2026-09-17 09:40:58 +00:00
[improve] fix some alarm relate bug, update alarm center ui (#2951)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
This commit is contained in:
+2
@@ -302,6 +302,8 @@ public class RealTimeAlertCalculator {
|
||||
String fingerprint = calculateFingerprint(fingerprints);
|
||||
SingleAlert firingAlert = firingAlertMap.remove(fingerprint);
|
||||
if (firingAlert != null) {
|
||||
// todo consider multi times to tig for resolved alert
|
||||
firingAlert.setTriggerTimes(1);
|
||||
firingAlert.setEndAt(System.currentTimeMillis());
|
||||
firingAlert.setStatus(CommonConstants.ALERT_STATUS_RESOLVED);
|
||||
alarmCommonReduce.reduceAndSendAlarm(firingAlert.clone());
|
||||
|
||||
+1
-2
@@ -55,12 +55,11 @@ public class AlertDefinesController {
|
||||
public ResponseEntity<Message<Page<AlertDefine>>> getAlertDefines(
|
||||
@Parameter(description = "Alarm Definition ID", example = "6565463543") @RequestParam(required = false) List<Long> ids,
|
||||
@Parameter(description = "Search-Target Expr Template", example = "x") @RequestParam(required = false) String search,
|
||||
@Parameter(description = "Alarm Definition Severity", example = "6565463543") @RequestParam(required = false) Byte priority,
|
||||
@Parameter(description = "Sort field, default id", example = "id") @RequestParam(defaultValue = "id") String sort,
|
||||
@Parameter(description = "Sort mode: asc: ascending, desc: descending", example = "desc") @RequestParam(defaultValue = "desc") String order,
|
||||
@Parameter(description = "List current page", example = "0") @RequestParam(defaultValue = "0") int pageIndex,
|
||||
@Parameter(description = "Number of list pages", example = "8") @RequestParam(defaultValue = "8") int pageSize) {
|
||||
Page<AlertDefine> alertDefinePage = alertDefineService.getAlertDefines(ids, search, priority, sort, order, pageIndex, pageSize);
|
||||
Page<AlertDefine> alertDefinePage = alertDefineService.getAlertDefines(ids, search, sort, order, pageIndex, pageSize);
|
||||
return ResponseEntity.ok(Message.success(alertDefinePage));
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -55,7 +55,7 @@ public class AlertsController {
|
||||
public ResponseEntity<Message<Page<SingleAlert>>> getAlerts(
|
||||
@Parameter(description = "Alarm Status", example = "resolved") @RequestParam(required = false) String status,
|
||||
@Parameter(description = "Alarm content fuzzy query", example = "linux") @RequestParam(required = false) String search,
|
||||
@Parameter(description = "Sort field, default id", example = "name") @RequestParam(defaultValue = "id") String sort,
|
||||
@Parameter(description = "Sort field, default id", example = "name") @RequestParam(defaultValue = "gmtUpdate") String sort,
|
||||
@Parameter(description = "Sort Type", example = "desc") @RequestParam(defaultValue = "desc") String order,
|
||||
@Parameter(description = "List current page", example = "0") @RequestParam(defaultValue = "0") int pageIndex,
|
||||
@Parameter(description = "Number of list pagination", example = "8") @RequestParam(defaultValue = "8") int pageSize) {
|
||||
@@ -68,7 +68,7 @@ public class AlertsController {
|
||||
public ResponseEntity<Message<Page<GroupAlert>>> getGroupAlerts(
|
||||
@Parameter(description = "Alarm Status", example = "resolved") @RequestParam(required = false) String status,
|
||||
@Parameter(description = "Alarm content fuzzy query", example = "linux") @RequestParam(required = false) String search,
|
||||
@Parameter(description = "Sort field, default id", example = "name") @RequestParam(defaultValue = "id") String sort,
|
||||
@Parameter(description = "Sort field, default id", example = "name") @RequestParam(defaultValue = "gmtUpdate") String sort,
|
||||
@Parameter(description = "Sort Type", example = "desc") @RequestParam(defaultValue = "desc") String order,
|
||||
@Parameter(description = "List current page", example = "0") @RequestParam(defaultValue = "0") int pageIndex,
|
||||
@Parameter(description = "Number of list pagination", example = "8") @RequestParam(defaultValue = "8") int pageSize) {
|
||||
@@ -88,7 +88,7 @@ public class AlertsController {
|
||||
}
|
||||
|
||||
@PutMapping(path = "/group/status/{status}")
|
||||
@Operation(summary = "Batch modify alarm status, set read and unread", description = "Batch modify alarm status, set read and unread")
|
||||
@Operation(summary = "Batch modify alarm status, set firing or resolved", description = "Batch modify alarm status, set firing or resolved")
|
||||
public ResponseEntity<Message<Void>> applyAlertDefinesStatus(
|
||||
@Parameter(description = "Alarm status value", example = "resolved") @PathVariable String status,
|
||||
@Parameter(description = "Alarm List IDS", example = "6565463543") @RequestParam(required = false) List<Long> ids) {
|
||||
|
||||
@@ -53,4 +53,11 @@ public interface GroupAlertDao extends JpaRepository<GroupAlert, Long>, JpaSpeci
|
||||
@Modifying
|
||||
@Query("update GroupAlert set status = :status where id in :ids")
|
||||
void updateGroupAlertsStatus(@Param(value = "status") String status, @Param(value = "ids") List<Long> ids);
|
||||
|
||||
/**
|
||||
* find group alerts by id list
|
||||
* @param ids ids
|
||||
* @return group alerts
|
||||
*/
|
||||
List<GroupAlert> findGroupAlertsByIdIn(HashSet<Long> ids);
|
||||
}
|
||||
|
||||
@@ -67,4 +67,11 @@ public interface SingleAlertDao extends JpaRepository<SingleAlert, Long>, JpaSpe
|
||||
@Modifying
|
||||
@Query("update SingleAlert set status = :status where id in :ids")
|
||||
void updateSingleAlertsStatus(@Param(value = "status") String status, @Param(value = "ids") List<Long> ids);
|
||||
|
||||
/**
|
||||
* delete alerts by fingerprint list
|
||||
* @param firingAlerts fingerprint list
|
||||
*/
|
||||
@Modifying
|
||||
void deleteSingleAlertsByFingerprintIn(List<String> firingAlerts);
|
||||
}
|
||||
|
||||
+51
-26
@@ -17,13 +17,17 @@
|
||||
|
||||
package org.apache.hertzbeat.alert.notice.impl;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.alert.dao.GroupAlertDao;
|
||||
import org.apache.hertzbeat.alert.dao.SingleAlertDao;
|
||||
import org.apache.hertzbeat.alert.notice.AlertStoreHandler;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
|
||||
import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -46,53 +50,74 @@ final class DbAlertStoreHandlerImpl implements AlertStoreHandler {
|
||||
log.error("The Group Alerts is empty, ignore store");
|
||||
return;
|
||||
}
|
||||
// 1. Find if there is an existing alert group
|
||||
// 1. Find existing alert group
|
||||
GroupAlert existGroupAlert = groupAlertDao.findByGroupKey(groupAlert.getGroupKey());
|
||||
|
||||
// 2. Process single alerts
|
||||
List<String> alertFingerprints = new LinkedList<>();
|
||||
// 2. Process individual alerts
|
||||
Set<String> alertFingerprints = new HashSet<>(8);
|
||||
groupAlert.getAlerts().forEach(singleAlert -> {
|
||||
// Check if there is an existing alert with same fingerprint
|
||||
SingleAlert existAlert = singleAlertDao.findByFingerprint(singleAlert.getFingerprint());
|
||||
if (existAlert != null) {
|
||||
// Update existing alert
|
||||
singleAlert.setId(existAlert.getId());
|
||||
singleAlert.setStartAt(existAlert.getStartAt());
|
||||
// If status changed from resolved to firing, update activeAt
|
||||
if ("resolved".equals(existAlert.getStatus()) && "firing".equals(singleAlert.getStatus())) {
|
||||
singleAlert.setActiveAt(System.currentTimeMillis());
|
||||
} else {
|
||||
singleAlert.setGmtCreate(existAlert.getGmtCreate());
|
||||
|
||||
// Status transition logic
|
||||
if (CommonConstants.ALERT_STATUS_FIRING.equals(singleAlert.getStatus())) {
|
||||
if (!CommonConstants.ALERT_STATUS_RESOLVED.equals(existAlert.getStatus())) {
|
||||
singleAlert.setStartAt(existAlert.getStartAt());
|
||||
singleAlert.setTriggerTimes(existAlert.getTriggerTimes() + singleAlert.getTriggerTimes());
|
||||
}
|
||||
} else if (CommonConstants.ALERT_STATUS_RESOLVED.equals(singleAlert.getStatus())) {
|
||||
// Transition to resolved state
|
||||
if (singleAlert.getEndAt() == null) {
|
||||
singleAlert.setEndAt(System.currentTimeMillis());
|
||||
}
|
||||
singleAlert.setStartAt(existAlert.getStartAt());
|
||||
singleAlert.setActiveAt(existAlert.getActiveAt());
|
||||
singleAlert.setTriggerTimes(existAlert.getTriggerTimes());
|
||||
}
|
||||
singleAlert.setTriggerTimes(existAlert.getTriggerTimes() + 1);
|
||||
}
|
||||
// Save new/updated alert
|
||||
alertFingerprints.add(singleAlert.getFingerprint());
|
||||
singleAlertDao.save(singleAlert);
|
||||
});
|
||||
|
||||
// 3. If there is an existing alert group, handle resolved alerts
|
||||
// 3. Process resolved alerts
|
||||
if (existGroupAlert != null) {
|
||||
List<String> existFingerprints = existGroupAlert.getAlertFingerprints();
|
||||
if (existFingerprints != null) {
|
||||
for (String fingerprint : existFingerprints) {
|
||||
if (!alertFingerprints.contains(fingerprint)) {
|
||||
// Old alert not in new alert list, mark as resolved
|
||||
SingleAlert alert = singleAlertDao.findByFingerprint(fingerprint);
|
||||
if (alert != null && !"resolved".equals(alert.getStatus())) {
|
||||
alert.setStatus("resolved");
|
||||
alert.setEndAt(System.currentTimeMillis());
|
||||
singleAlertDao.save(alert);
|
||||
}
|
||||
}
|
||||
alertFingerprints.addAll(existFingerprints);
|
||||
}
|
||||
// Merge group information
|
||||
groupAlert.setId(existGroupAlert.getId());
|
||||
groupAlert.setGmtCreate(existGroupAlert.getGmtCreate());
|
||||
// Merge other historical information to preserve
|
||||
Map<String, String> existCommonLabels = existGroupAlert.getCommonLabels();
|
||||
if (existCommonLabels != null) {
|
||||
Map<String, String> commonLabels = groupAlert.getCommonLabels();
|
||||
if (commonLabels != null) {
|
||||
// filter common label in commonLabels and existCommonLabels
|
||||
commonLabels = commonLabels.entrySet().stream()
|
||||
.filter(entry -> existCommonLabels.containsKey(entry.getKey()))
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
groupAlert.setCommonLabels(commonLabels);
|
||||
}
|
||||
}
|
||||
Map<String, String> existCommonAnnotations = existGroupAlert.getCommonAnnotations();
|
||||
if (existCommonAnnotations != null) {
|
||||
Map<String, String> commonAnnotations = groupAlert.getCommonAnnotations();
|
||||
if (commonAnnotations != null) {
|
||||
// filter common annotation in commonAnnotations and existCommonAnnotations
|
||||
commonAnnotations = commonAnnotations.entrySet().stream()
|
||||
.filter(entry -> existCommonAnnotations.containsKey(entry.getKey()))
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
groupAlert.setCommonAnnotations(commonAnnotations);
|
||||
}
|
||||
}
|
||||
// Update alert group ID
|
||||
groupAlert.setId(existGroupAlert.getId());
|
||||
}
|
||||
|
||||
// 4. Save alert group
|
||||
groupAlert.setAlertFingerprints(alertFingerprints);
|
||||
groupAlert.setAlertFingerprints(alertFingerprints.stream().toList());
|
||||
groupAlertDao.save(groupAlert);
|
||||
}
|
||||
}
|
||||
|
||||
+27
-22
@@ -20,6 +20,7 @@ package org.apache.hertzbeat.alert.reduce;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -32,6 +33,7 @@ import java.util.stream.Collectors;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.alert.dao.AlertGroupConvergeDao;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertGroupConverge;
|
||||
import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
|
||||
import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
|
||||
@@ -112,7 +114,6 @@ public class AlarmGroupReduce {
|
||||
if (shouldSendGroup(cache, now)) {
|
||||
sendGroupAlert(cache);
|
||||
cache.setLastSendTime(now);
|
||||
cache.getAlerts().clear();
|
||||
cache.getAlertFingerprints().clear();
|
||||
}
|
||||
});
|
||||
@@ -180,7 +181,7 @@ public class AlarmGroupReduce {
|
||||
newCache.setGroupLabels(extractedLabels);
|
||||
newCache.setGroupDefineName(defineName);
|
||||
newCache.setCreateTime(System.currentTimeMillis());
|
||||
newCache.setAlertFingerprints(new HashMap<>());
|
||||
newCache.setAlertFingerprints(new ConcurrentHashMap<>(8));
|
||||
return newCache;
|
||||
});
|
||||
String fingerprint = alert.getFingerprint();
|
||||
@@ -188,32 +189,31 @@ public class AlarmGroupReduce {
|
||||
SingleAlert existingAlert = cache.getAlertFingerprints().get(fingerprint);
|
||||
if (existingAlert != null) {
|
||||
// Update existing alert timestamp
|
||||
existingAlert.setActiveAt(System.currentTimeMillis());
|
||||
alert.setStartAt(existingAlert.getStartAt());
|
||||
cache.getAlertFingerprints().put(fingerprint, alert);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add new alert
|
||||
cache.getAlertFingerprints().put(fingerprint, alert);
|
||||
cache.getAlerts().add(alert);
|
||||
|
||||
if (shouldSendGroupImmediately(cache)) {
|
||||
sendGroupAlert(cache);
|
||||
cache.setLastSendTime(System.currentTimeMillis());
|
||||
cache.getAlerts().clear();
|
||||
cache.getAlertFingerprints().clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void sendGroupAlert(GroupAlertCache cache) {
|
||||
if (cache.getAlerts().isEmpty()) {
|
||||
if (cache.getAlertFingerprints().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
String status = determineGroupStatus(cache.getAlerts());
|
||||
String status = determineGroupStatus(cache.getAlertFingerprints().values());
|
||||
|
||||
// For firing alerts, check repeat interval
|
||||
if ("firing".equals(status)) {
|
||||
if (CommonConstants.ALERT_STATUS_FIRING.equals(status)) {
|
||||
AlertGroupConverge ruleConfig = groupDefines.get(cache.getGroupDefineName());
|
||||
long repeatInterval = ruleConfig.getRepeatInterval() != null
|
||||
? ruleConfig.getRepeatInterval() * MS_PER_SECOND : DEFAULT_REPEAT_INTERVAL;
|
||||
@@ -229,9 +229,9 @@ public class AlarmGroupReduce {
|
||||
GroupAlert groupAlert = GroupAlert.builder()
|
||||
.groupKey(cache.getGroupKey())
|
||||
.groupLabels(cache.getGroupLabels())
|
||||
.commonLabels(extractCommonLabels(cache.getAlerts()))
|
||||
.commonAnnotations(extractCommonAnnotations(cache.getAlerts()))
|
||||
.alerts(new ArrayList<>(cache.getAlerts()))
|
||||
.commonLabels(extractCommonLabels(cache.getAlertFingerprints().values()))
|
||||
.commonAnnotations(extractCommonAnnotations(cache.getAlertFingerprints().values()))
|
||||
.alerts(new ArrayList<>(cache.getAlertFingerprints().values()))
|
||||
.status(status)
|
||||
.build();
|
||||
|
||||
@@ -255,8 +255,8 @@ public class AlarmGroupReduce {
|
||||
|
||||
private boolean shouldSendGroupImmediately(GroupAlertCache cache) {
|
||||
// Check if all alerts are resolved
|
||||
return cache.getAlerts().stream()
|
||||
.allMatch(alert -> "resolved".equals(alert.getStatus()));
|
||||
return cache.getAlertFingerprints().values().stream()
|
||||
.allMatch(alert -> CommonConstants.ALERT_STATUS_RESOLVED.equals(alert.getStatus()));
|
||||
}
|
||||
|
||||
private void sendSingleAlert(SingleAlert alert) {
|
||||
@@ -281,9 +281,12 @@ public class AlarmGroupReduce {
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
private Map<String, String> extractCommonLabels(List<SingleAlert> alerts) {
|
||||
private Map<String, String> extractCommonLabels(Collection<SingleAlert> alerts) {
|
||||
// Extract common labels from all alerts
|
||||
Map<String, String> common = new HashMap<>(alerts.get(0).getLabels());
|
||||
if (alerts.isEmpty()) {
|
||||
return new HashMap<>(8);
|
||||
}
|
||||
Map<String, String> common = new HashMap<>(alerts.stream().findFirst().get().getLabels());
|
||||
alerts.forEach(alert -> {
|
||||
common.keySet().removeIf(key ->
|
||||
!alert.getLabels().containsKey(key)
|
||||
@@ -292,9 +295,12 @@ public class AlarmGroupReduce {
|
||||
return common;
|
||||
}
|
||||
|
||||
private Map<String, String> extractCommonAnnotations(List<SingleAlert> alerts) {
|
||||
private Map<String, String> extractCommonAnnotations(Collection<SingleAlert> alerts) {
|
||||
// Extract common annotations from all alerts
|
||||
Map<String, String> common = new HashMap<>(alerts.get(0).getAnnotations());
|
||||
if (alerts.isEmpty()) {
|
||||
return new HashMap<>(8);
|
||||
}
|
||||
Map<String, String> common = new HashMap<>(alerts.stream().findFirst().get().getAnnotations());
|
||||
alerts.forEach(alert -> {
|
||||
common.keySet().removeIf(key ->
|
||||
!alert.getAnnotations().containsKey(key)
|
||||
@@ -303,11 +309,11 @@ public class AlarmGroupReduce {
|
||||
return common;
|
||||
}
|
||||
|
||||
private String determineGroupStatus(List<SingleAlert> alerts) {
|
||||
private String determineGroupStatus(Collection<SingleAlert> alerts) {
|
||||
// If any alert is firing, group is firing
|
||||
return alerts.stream()
|
||||
.anyMatch(alert -> "firing".equals(alert.getStatus()))
|
||||
? "firing" : "resolved";
|
||||
.anyMatch(alert -> CommonConstants.ALERT_STATUS_FIRING.equals(alert.getStatus()))
|
||||
? CommonConstants.ALERT_STATUS_FIRING : CommonConstants.ALERT_STATUS_RESOLVED;
|
||||
}
|
||||
|
||||
@Data
|
||||
@@ -315,8 +321,7 @@ public class AlarmGroupReduce {
|
||||
private String groupDefineName;
|
||||
private String groupKey;
|
||||
private Map<String, String> groupLabels;
|
||||
private List<SingleAlert> alerts = new ArrayList<>();
|
||||
private Map<String, SingleAlert> alertFingerprints = new HashMap<>();
|
||||
private Map<String, SingleAlert> alertFingerprints = new ConcurrentHashMap<>(8);
|
||||
private long createTime;
|
||||
private long lastSendTime;
|
||||
private long lastRepeatTime;
|
||||
|
||||
+95
-120
@@ -17,11 +17,14 @@
|
||||
|
||||
package org.apache.hertzbeat.alert.reduce;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.alert.dao.AlertInhibitDao;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertInhibit;
|
||||
import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
@@ -47,6 +50,11 @@ public class AlarmInhibitReduce {
|
||||
*/
|
||||
private static final long SOURCE_ALERT_TTL = 4 * 60 * 60 * 1000L;
|
||||
|
||||
/**
|
||||
* Interval for checking and cleaning up expired source alerts
|
||||
*/
|
||||
private static final long CHECK_INTERVAL = 60_000L;
|
||||
|
||||
private final AlarmSilenceReduce alarmSilenceReduce;
|
||||
|
||||
private final Map<Long, AlertInhibit> inhibitRules;
|
||||
@@ -64,6 +72,29 @@ public class AlarmInhibitReduce {
|
||||
sourceAlertCache = new ConcurrentHashMap<>(8);
|
||||
List<AlertInhibit> inhibits = alertInhibitDao.findAlertInhibitsByEnableIsTrue();
|
||||
refreshInhibitRules(inhibits);
|
||||
startScheduledCleanupCache();
|
||||
}
|
||||
|
||||
private void startScheduledCleanupCache() {
|
||||
ThreadFactory threadFactory = new ThreadFactoryBuilder()
|
||||
.setUncaughtExceptionHandler((thread, throwable) -> {
|
||||
log.error("Scheduled clean up inhibit cache has uncaughtException.");
|
||||
log.error(throwable.getMessage(), throwable);
|
||||
})
|
||||
.setDaemon(true)
|
||||
.setNameFormat("inhibit-clean-up-%d")
|
||||
.build();
|
||||
ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor(threadFactory);
|
||||
// Scheduled cleanup of all expired source alerts
|
||||
scheduledExecutor.scheduleAtFixedRate(() -> {
|
||||
try {
|
||||
sourceAlertCache.values().forEach(this::cleanupExpiredEntries);
|
||||
// Remove empty rule caches
|
||||
sourceAlertCache.entrySet().removeIf(entry -> entry.getValue().isEmpty());
|
||||
} catch (Exception e) {
|
||||
log.error("Error during scheduled cleanup", e);
|
||||
}
|
||||
}, CHECK_INTERVAL, CHECK_INTERVAL, java.util.concurrent.TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,12 +106,8 @@ public class AlarmInhibitReduce {
|
||||
log.warn("Attempted to refresh inhibit rules with null list.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.inhibitRules.clear();
|
||||
rules.forEach(rule -> this.inhibitRules.put(rule.getId(), rule));
|
||||
} catch (Exception e) {
|
||||
log.error("Error refreshing inhibit rules", e);
|
||||
}
|
||||
this.inhibitRules.clear();
|
||||
rules.forEach(rule -> this.inhibitRules.put(rule.getId(), rule));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,15 +153,10 @@ public class AlarmInhibitReduce {
|
||||
log.warn("Received null alert or rule in isSourceAlert");
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
if (!"firing".equals(alert.getStatus())) {
|
||||
return false;
|
||||
}
|
||||
return matchLabels(alert.getCommonLabels(), rule.getSourceLabels());
|
||||
} catch (Exception e) {
|
||||
log.error("Error checking if alert is source alert", e);
|
||||
if (!"firing".equals(alert.getStatus())) {
|
||||
return false;
|
||||
}
|
||||
return matchLabels(alert.getCommonLabels(), rule.getSourceLabels());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,32 +168,27 @@ public class AlarmInhibitReduce {
|
||||
log.warn("Received null alert in shouldInhibit");
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
if ("resolved".equals(alert.getStatus())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (AlertInhibit rule : inhibitRules.values()) {
|
||||
if (!matchLabels(alert.getCommonLabels(), rule.getTargetLabels())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<GroupAlert> sourceAlerts = getActiveSourceAlerts(rule);
|
||||
if (sourceAlerts.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (GroupAlert source : sourceAlerts) {
|
||||
if (matchEqualLabels(source, alert, rule.getEqualLabels())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
log.error("Error checking if alert should be inhibited", e);
|
||||
if ("resolved".equals(alert.getStatus())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (AlertInhibit rule : inhibitRules.values()) {
|
||||
if (!matchLabels(alert.getCommonLabels(), rule.getTargetLabels())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<GroupAlert> sourceAlerts = getActiveSourceAlerts(rule);
|
||||
if (sourceAlerts.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (GroupAlert source : sourceAlerts) {
|
||||
if (matchEqualLabels(source, alert, rule.getEqualLabels())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,13 +201,8 @@ public class AlarmInhibitReduce {
|
||||
log.warn("Received null alertLabels or requiredLabels in matchLabels");
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return requiredLabels.entrySet().stream()
|
||||
.allMatch(entry -> entry.getValue().equals(alertLabels.get(entry.getKey())));
|
||||
} catch (Exception e) {
|
||||
log.error("Error matching labels", e);
|
||||
return false;
|
||||
}
|
||||
return requiredLabels.entrySet().stream()
|
||||
.allMatch(entry -> entry.getValue().equals(alertLabels.get(entry.getKey())));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -204,22 +216,17 @@ public class AlarmInhibitReduce {
|
||||
log.warn("Received null source or target in matchEqualLabels");
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
if (equalLabels == null || equalLabels.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
Map<String, String> sourceLabels = source.getCommonLabels();
|
||||
Map<String, String> targetLabels = target.getCommonLabels();
|
||||
|
||||
return equalLabels.stream().allMatch(label -> {
|
||||
String sourceValue = sourceLabels.get(label);
|
||||
String targetValue = targetLabels.get(label);
|
||||
return sourceValue != null && sourceValue.equals(targetValue);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
log.error("Error matching equal labels", e);
|
||||
return false;
|
||||
if (equalLabels == null || equalLabels.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
Map<String, String> sourceLabels = source.getCommonLabels();
|
||||
Map<String, String> targetLabels = target.getCommonLabels();
|
||||
|
||||
return equalLabels.stream().allMatch(label -> {
|
||||
String sourceValue = sourceLabels.get(label);
|
||||
String targetValue = targetLabels.get(label);
|
||||
return sourceValue != null && sourceValue.equals(targetValue);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,23 +239,19 @@ public class AlarmInhibitReduce {
|
||||
log.warn("Received null alert or rule in cacheSourceAlert");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Map<String, SourceAlertEntry> ruleCache = sourceAlertCache.computeIfAbsent(
|
||||
rule.getId(),
|
||||
k -> new ConcurrentHashMap<>()
|
||||
);
|
||||
Map<String, SourceAlertEntry> ruleCache = sourceAlertCache.computeIfAbsent(
|
||||
rule.getId(),
|
||||
k -> new ConcurrentHashMap<>()
|
||||
);
|
||||
|
||||
String fingerprint = generateAlertFingerprint(alert);
|
||||
SourceAlertEntry entry = new SourceAlertEntry(
|
||||
alert,
|
||||
System.currentTimeMillis(),
|
||||
System.currentTimeMillis() + SOURCE_ALERT_TTL
|
||||
);
|
||||
ruleCache.put(fingerprint, entry);
|
||||
cleanupExpiredEntries(ruleCache);
|
||||
} catch (Exception e) {
|
||||
log.error("Error caching source alert", e);
|
||||
}
|
||||
String fingerprint = generateAlertFingerprint(alert);
|
||||
SourceAlertEntry entry = new SourceAlertEntry(
|
||||
alert,
|
||||
System.currentTimeMillis(),
|
||||
System.currentTimeMillis() + SOURCE_ALERT_TTL
|
||||
);
|
||||
ruleCache.put(fingerprint, entry);
|
||||
cleanupExpiredEntries(ruleCache);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -260,21 +263,16 @@ public class AlarmInhibitReduce {
|
||||
log.warn("Received null rule in getActiveSourceAlerts");
|
||||
return Collections.emptyList();
|
||||
}
|
||||
try {
|
||||
Map<String, SourceAlertEntry> ruleCache = sourceAlertCache.get(rule.getId());
|
||||
if (ruleCache == null || ruleCache.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
return ruleCache.values().stream()
|
||||
.filter(entry -> entry.getExpiryTime() > now)
|
||||
.map(SourceAlertEntry::getAlert)
|
||||
.collect(Collectors.toList());
|
||||
} catch (Exception e) {
|
||||
log.error("Error getting active source alerts", e);
|
||||
Map<String, SourceAlertEntry> ruleCache = sourceAlertCache.get(rule.getId());
|
||||
if (ruleCache == null || ruleCache.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
return ruleCache.values().stream()
|
||||
.filter(entry -> entry.getExpiryTime() > now)
|
||||
.map(SourceAlertEntry::getAlert)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -286,18 +284,13 @@ public class AlarmInhibitReduce {
|
||||
log.warn("Received null alert in generateAlertFingerprint");
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
Map<String, String> labels = new HashMap<>(alert.getCommonLabels());
|
||||
labels.remove("timestamp");
|
||||
Map<String, String> labels = new HashMap<>(alert.getCommonLabels());
|
||||
labels.remove("timestamp");
|
||||
|
||||
return labels.entrySet().stream()
|
||||
.sorted(Map.Entry.comparingByKey())
|
||||
.map(e -> e.getKey() + ":" + e.getValue())
|
||||
.collect(Collectors.joining(","));
|
||||
} catch (Exception e) {
|
||||
log.error("Error generating alert fingerprint", e);
|
||||
return "";
|
||||
}
|
||||
return labels.entrySet().stream()
|
||||
.sorted(Map.Entry.comparingByKey())
|
||||
.map(e -> e.getKey() + ":" + e.getValue())
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -309,26 +302,8 @@ public class AlarmInhibitReduce {
|
||||
log.warn("Received null cache in cleanupExpiredEntries");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
cache.entrySet().removeIf(entry -> entry.getValue().getExpiryTime() <= now);
|
||||
} catch (Exception e) {
|
||||
log.error("Error cleaning up expired entries", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scheduled cleanup of all expired source alerts
|
||||
*/
|
||||
@Scheduled(fixedRate = 60_000) // Run every minute
|
||||
public void scheduledCleanup() {
|
||||
try {
|
||||
sourceAlertCache.values().forEach(this::cleanupExpiredEntries);
|
||||
// Remove empty rule caches
|
||||
sourceAlertCache.entrySet().removeIf(entry -> entry.getValue().isEmpty());
|
||||
} catch (Exception e) {
|
||||
log.error("Error during scheduled cleanup", e);
|
||||
}
|
||||
long now = System.currentTimeMillis();
|
||||
cache.entrySet().removeIf(entry -> entry.getValue().getExpiryTime() <= now);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-2
@@ -78,14 +78,13 @@ public interface AlertDefineService {
|
||||
* Dynamic conditional query
|
||||
* @param defineIds Alarm Definition ID List
|
||||
* @param search Search-Target Expr Template
|
||||
* @param priority Alarm Definition Severity
|
||||
* @param sort Sort field
|
||||
* @param order Sort mode: asc: ascending, desc: descending
|
||||
* @param pageIndex List current page
|
||||
* @param pageSize Number of list pages
|
||||
* @return The query results
|
||||
*/
|
||||
Page<AlertDefine> getAlertDefines(List<Long> defineIds, String search, Byte priority, String sort, String order, int pageIndex, int pageSize);
|
||||
Page<AlertDefine> getAlertDefines(List<Long> defineIds, String search, String sort, String order, int pageIndex, int pageSize);
|
||||
|
||||
/**
|
||||
* Export file configuration of specified type based on ID list and export file type
|
||||
|
||||
+4
-8
@@ -127,7 +127,7 @@ public class AlertDefineServiceImpl implements AlertDefineService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<AlertDefine> getAlertDefines(List<Long> defineIds, String search, Byte priority, String sort, String order, int pageIndex, int pageSize) {
|
||||
public Page<AlertDefine> getAlertDefines(List<Long> defineIds, String search, String sort, String order, int pageIndex, int pageSize) {
|
||||
// parse translation content list
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
List<String> searchList = Collections.emptyList();
|
||||
@@ -154,10 +154,10 @@ public class AlertDefineServiceImpl implements AlertDefineService {
|
||||
for (String searchContent : finalSearchList) {
|
||||
searchContent = searchContent.toLowerCase();
|
||||
Predicate predicate = criteriaBuilder.or(
|
||||
criteriaBuilder.like(criteriaBuilder.lower(root.get("app")), "%" + searchContent + "%"),
|
||||
criteriaBuilder.like(criteriaBuilder.lower(root.get("metric")), "%" + searchContent + "%"),
|
||||
criteriaBuilder.like(criteriaBuilder.lower(root.get("field")), "%" + searchContent + "%"),
|
||||
criteriaBuilder.like(criteriaBuilder.lower(root.get("name")), "%" + searchContent + "%"),
|
||||
criteriaBuilder.like(criteriaBuilder.lower(root.get("expr")), "%" + searchContent + "%"),
|
||||
criteriaBuilder.like(criteriaBuilder.lower(root.get("labels")), "%" + searchContent + "%"),
|
||||
criteriaBuilder.like(criteriaBuilder.lower(root.get("annotations")), "%" + searchContent + "%"),
|
||||
criteriaBuilder.like(criteriaBuilder.lower(root.get("template")), "%" + searchContent + "%")
|
||||
);
|
||||
searchPredicates.add(predicate);
|
||||
@@ -165,10 +165,6 @@ public class AlertDefineServiceImpl implements AlertDefineService {
|
||||
// all search keywords are connected with or
|
||||
andList.add(criteriaBuilder.or(searchPredicates.toArray(new Predicate[0])));
|
||||
}
|
||||
if (priority != null) {
|
||||
Predicate predicate = criteriaBuilder.equal(root.get("priority"), priority);
|
||||
andList.add(predicate);
|
||||
}
|
||||
Predicate[] predicates = new Predicate[andList.size()];
|
||||
return criteriaBuilder.and(andList.toArray(predicates));
|
||||
};
|
||||
|
||||
+44
-7
@@ -70,12 +70,28 @@ public class AlertServiceImpl implements AlertService {
|
||||
Predicate predicate = criteriaBuilder.equal(root.get("status"), status);
|
||||
andList.add(predicate);
|
||||
}
|
||||
Predicate[] andPredicates = new Predicate[andList.size()];
|
||||
Predicate andPredicate = criteriaBuilder.and(andList.toArray(andPredicates));
|
||||
List<Predicate> orList = new ArrayList<>();
|
||||
if (search != null && !search.isEmpty()) {
|
||||
Predicate predicateContent = criteriaBuilder.like(root.get("content"), "%" + search + "%");
|
||||
andList.add(predicateContent);
|
||||
orList.add(predicateContent);
|
||||
Predicate predicateLabels = criteriaBuilder.like(root.get("labels"), "%" + search + "%");
|
||||
orList.add(predicateLabels);
|
||||
Predicate predicateAnnotation = criteriaBuilder.like(root.get("annotations"), "%" + search + "%");
|
||||
orList.add(predicateAnnotation);
|
||||
}
|
||||
Predicate[] orPredicates = new Predicate[orList.size()];
|
||||
Predicate orPredicate = criteriaBuilder.or(orList.toArray(orPredicates));
|
||||
if (andPredicates.length == 0 && orPredicates.length == 0) {
|
||||
return query.where().getRestriction();
|
||||
} else if (andPredicates.length == 0) {
|
||||
return orPredicate;
|
||||
} else if (orPredicates.length == 0) {
|
||||
return andPredicate;
|
||||
} else {
|
||||
return query.where(andPredicate, orPredicate).getRestriction();
|
||||
}
|
||||
Predicate[] predicates = new Predicate[andList.size()];
|
||||
return criteriaBuilder.and(andList.toArray(predicates));
|
||||
};
|
||||
Sort sortExp = Sort.by(new Sort.Order(Sort.Direction.fromString(order), sort));
|
||||
PageRequest pageRequest = PageRequest.of(pageIndex, pageSize, sortExp);
|
||||
@@ -90,12 +106,28 @@ public class AlertServiceImpl implements AlertService {
|
||||
Predicate predicate = criteriaBuilder.equal(root.get("status"), status);
|
||||
andList.add(predicate);
|
||||
}
|
||||
Predicate[] andPredicates = new Predicate[andList.size()];
|
||||
Predicate andPredicate = criteriaBuilder.and(andList.toArray(andPredicates));
|
||||
List<Predicate> orList = new ArrayList<>();
|
||||
if (search != null && !search.isEmpty()) {
|
||||
Predicate predicateContent = criteriaBuilder.like(root.get("content"), "%" + search + "%");
|
||||
andList.add(predicateContent);
|
||||
Predicate predicateContent = criteriaBuilder.like(root.get("groupLabels"), "%" + search + "%");
|
||||
orList.add(predicateContent);
|
||||
Predicate predicateLabels = criteriaBuilder.like(root.get("commonLabels"), "%" + search + "%");
|
||||
orList.add(predicateLabels);
|
||||
Predicate predicateAnnotation = criteriaBuilder.like(root.get("commonAnnotations"), "%" + search + "%");
|
||||
orList.add(predicateAnnotation);
|
||||
}
|
||||
Predicate[] orPredicates = new Predicate[orList.size()];
|
||||
Predicate orPredicate = criteriaBuilder.or(orList.toArray(orPredicates));
|
||||
if (andPredicates.length == 0 && orPredicates.length == 0) {
|
||||
return query.where().getRestriction();
|
||||
} else if (andPredicates.length == 0) {
|
||||
return orPredicate;
|
||||
} else if (orPredicates.length == 0) {
|
||||
return andPredicate;
|
||||
} else {
|
||||
return query.where(andPredicate, orPredicate).getRestriction();
|
||||
}
|
||||
Predicate[] predicates = new Predicate[andList.size()];
|
||||
return criteriaBuilder.and(andList.toArray(predicates));
|
||||
};
|
||||
Sort sortExp = Sort.by(new Sort.Order(Sort.Direction.fromString(order), sort));
|
||||
PageRequest pageRequest = PageRequest.of(pageIndex, pageSize, sortExp);
|
||||
@@ -110,6 +142,11 @@ public class AlertServiceImpl implements AlertService {
|
||||
|
||||
@Override
|
||||
public void deleteGroupAlerts(HashSet<Long> ids) {
|
||||
List<GroupAlert> groupAlerts = groupAlertDao.findGroupAlertsByIdIn(ids);
|
||||
for (GroupAlert groupAlert : groupAlerts) {
|
||||
List<String> firingAlerts = groupAlert.getAlertFingerprints();
|
||||
singleAlertDao.deleteSingleAlertsByFingerprintIn(firingAlerts);
|
||||
}
|
||||
groupAlertDao.deleteGroupAlertsByIdIn(ids);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ class AlertDefinesControllerTest {
|
||||
// }
|
||||
// }))).thenReturn(new PageImpl<AlertDefine>(new ArrayList<AlertDefine>()));
|
||||
AlertDefine define = AlertDefine.builder().id(9L).expr("x").times(1).build();
|
||||
Mockito.when(alertDefineService.getAlertDefines(null, null, null, "id", "desc", 1, 10)).thenReturn(new PageImpl<>(Collections.singletonList(define)));
|
||||
Mockito.when(alertDefineService.getAlertDefines(null, null, "id", "desc", 1, 10)).thenReturn(new PageImpl<>(Collections.singletonList(define)));
|
||||
|
||||
mockMvc.perform(MockMvcRequestBuilders.get(
|
||||
"/api/alert/defines")
|
||||
|
||||
+1
-1
@@ -123,7 +123,7 @@ class AlertDefineServiceTest {
|
||||
@Test
|
||||
void getAlertDefines() {
|
||||
when(alertDefineDao.findAll(any(Specification.class), any(PageRequest.class))).thenReturn(Page.empty());
|
||||
assertNotNull(alertDefineService.getAlertDefines(null, null, null, "id", "desc", 1, 10));
|
||||
assertNotNull(alertDefineService.getAlertDefines(null, null, "id", "desc", 1, 10));
|
||||
verify(alertDefineDao, times(1)).findAll(any(Specification.class), any(PageRequest.class));
|
||||
}
|
||||
}
|
||||
|
||||
+21
@@ -29,6 +29,7 @@ import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.Transient;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.AllArgsConstructor;
|
||||
@@ -36,6 +37,10 @@ import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.hertzbeat.common.entity.manager.JsonStringListAttributeConverter;
|
||||
import org.springframework.data.annotation.CreatedBy;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedBy;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
/**
|
||||
@@ -82,6 +87,22 @@ public class GroupAlert {
|
||||
@Column(length = 2048)
|
||||
private List<String> alertFingerprints;
|
||||
|
||||
@Schema(title = "The creator of this record", example = "tom")
|
||||
@CreatedBy
|
||||
private String creator;
|
||||
|
||||
@Schema(title = "This record was last modified by", example = "tom")
|
||||
@LastModifiedBy
|
||||
private String modifier;
|
||||
|
||||
@Schema(title = "This record creation time (millisecond timestamp)")
|
||||
@CreatedDate
|
||||
private LocalDateTime gmtCreate;
|
||||
|
||||
@Schema(title = "Record the latest modification time (timestamp in milliseconds)")
|
||||
@LastModifiedDate
|
||||
private LocalDateTime gmtUpdate;
|
||||
|
||||
@Transient
|
||||
private List<SingleAlert> alerts;
|
||||
}
|
||||
|
||||
+21
@@ -28,12 +28,17 @@ import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.Table;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.springframework.data.annotation.CreatedBy;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedBy;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
/**
|
||||
@@ -85,6 +90,22 @@ public class SingleAlert {
|
||||
@Schema(title = "End At, when status is resolved has", example = "null")
|
||||
private Long endAt;
|
||||
|
||||
@Schema(title = "The creator of this record", example = "tom")
|
||||
@CreatedBy
|
||||
private String creator;
|
||||
|
||||
@Schema(title = "This record was last modified by", example = "tom")
|
||||
@LastModifiedBy
|
||||
private String modifier;
|
||||
|
||||
@Schema(title = "This record creation time (millisecond timestamp)")
|
||||
@CreatedDate
|
||||
private LocalDateTime gmtCreate;
|
||||
|
||||
@Schema(title = "Record the latest modification time (timestamp in milliseconds)")
|
||||
@LastModifiedDate
|
||||
private LocalDateTime gmtUpdate;
|
||||
|
||||
@Override
|
||||
public SingleAlert clone() {
|
||||
// deep clone
|
||||
|
||||
+4
-5
@@ -56,15 +56,14 @@ public class MonitorsController {
|
||||
public ResponseEntity<Message<Page<Monitor>>> getMonitors(
|
||||
@Parameter(description = "Monitor ID", example = "6565463543") @RequestParam(required = false) final List<Long> ids,
|
||||
@Parameter(description = "Monitor Type", example = "linux") @RequestParam(required = false) final String app,
|
||||
@Parameter(description = "Monitor Name support fuzzy query", example = "linux-127.0.0.1") @RequestParam(required = false) final String name,
|
||||
@Parameter(description = "Monitor Host support fuzzy query", example = "127.0.0.1") @RequestParam(required = false) final String host,
|
||||
@Parameter(description = "Monitor Status 0:no monitor,1:usable,2:disabled,9:all status", example = "1") @RequestParam(required = false) final Byte status,
|
||||
@Parameter(description = "Monitor Host support fuzzy query", example = "127.0.0.1") @RequestParam(required = false) final String search,
|
||||
@Parameter(description = "Monitor labels ", example = "env:prod,instance:22") @RequestParam(required = false) final String labels,
|
||||
@Parameter(description = "Sort Field ", example = "name") @RequestParam(defaultValue = "gmtCreate") final String sort,
|
||||
@Parameter(description = "Sort mode eg:asc desc", example = "desc") @RequestParam(defaultValue = "desc") final String order,
|
||||
@Parameter(description = "List current page", example = "0") @RequestParam(defaultValue = "0") int pageIndex,
|
||||
@Parameter(description = "Number of list pagination ", example = "8") @RequestParam(defaultValue = "8") int pageSize,
|
||||
@Parameter(description = "Monitor tag ", example = "env:prod") @RequestParam(required = false) final String tag) {
|
||||
Page<Monitor> monitorPage = monitorService.getMonitors(ids, app, name, host, status, sort, order, pageIndex, pageSize, tag);
|
||||
@Parameter(description = "Number of list pagination ", example = "8") @RequestParam(defaultValue = "8") int pageSize) {
|
||||
Page<Monitor> monitorPage = monitorService.getMonitors(ids, app, search, status, sort, order, pageIndex, pageSize, labels);
|
||||
return ResponseEntity.ok(Message.success(monitorPage));
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ public interface MonitorDao extends JpaRepository<Monitor, Long>, JpaSpecificati
|
||||
* @param status Monitor Status
|
||||
* @return Monitor List
|
||||
*/
|
||||
List<Monitor> findMonitorsByStatusNotInAndAndJobIdNotNull(List<Byte> status);
|
||||
List<Monitor> findMonitorsByStatusNotInAndJobIdNotNull(List<Byte> status);
|
||||
|
||||
/**
|
||||
* Query monitoring by monitoring name
|
||||
|
||||
+1
-1
@@ -96,7 +96,7 @@ public class SchedulerInit implements CommandLineRunner {
|
||||
.build();
|
||||
collectorScheduling.collectorGoOnline(CommonConstants.MAIN_COLLECTOR_NODE, collectorInfo);
|
||||
// init jobs
|
||||
List<Monitor> monitors = monitorDao.findMonitorsByStatusNotInAndAndJobIdNotNull(List.of(CommonConstants.MONITOR_PAUSED_CODE));
|
||||
List<Monitor> monitors = monitorDao.findMonitorsByStatusNotInAndJobIdNotNull(List.of(CommonConstants.MONITOR_PAUSED_CODE));
|
||||
List<CollectorMonitorBind> monitorBinds = collectorMonitorBindDao.findAll();
|
||||
final Set<Long> sdMonitorIds = monitorBindDao.findAllByType(CommonConstants.MONITOR_BIND_TYPE_SD_SUB_MONITOR).stream()
|
||||
.map(MonitorBind::getBizId)
|
||||
|
||||
+3
-4
@@ -102,17 +102,16 @@ public interface MonitorService {
|
||||
* Dynamic conditional query
|
||||
* @param monitorIds Monitor ID List
|
||||
* @param app Monitor Type
|
||||
* @param name Monitor Name support fuzzy query
|
||||
* @param host Monitor Host support fuzzy query
|
||||
* @param search Monitor Host support fuzzy query
|
||||
* @param status Monitor Status 0:no monitor,1:usable,2:disabled,9:all status
|
||||
* @param sort Sort Field
|
||||
* @param order Sort mode eg:asc desc
|
||||
* @param pageIndex List current page
|
||||
* @param pageSize Number of list pagination
|
||||
* @param tag Monitor tag
|
||||
* @param labels Monitor labels
|
||||
* @return Search Result
|
||||
*/
|
||||
Page<Monitor> getMonitors(List<Long> monitorIds, String app, String name, String host, Byte status, String sort, String order, int pageIndex, int pageSize, String tag);
|
||||
Page<Monitor> getMonitors(List<Long> monitorIds, String app, String search, Byte status, String sort, String order, int pageIndex, int pageSize, String labels);
|
||||
|
||||
/**
|
||||
* Unmanaged monitoring items in batches according to the monitoring ID list
|
||||
|
||||
+19
-23
@@ -20,8 +20,6 @@ package org.apache.hertzbeat.manager.service.impl;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.google.common.collect.Sets;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.JoinType;
|
||||
import jakarta.persistence.criteria.ListJoin;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.net.URLEncoder;
|
||||
@@ -556,7 +554,7 @@ public class MonitorServiceImpl implements MonitorService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Monitor> getMonitors(List<Long> monitorIds, String app, String name, String host, Byte status, String sort, String order, int pageIndex, int pageSize, String tag) {
|
||||
public Page<Monitor> getMonitors(List<Long> monitorIds, String app, String search, Byte status, String sort, String order, int pageIndex, int pageSize, String labels) {
|
||||
Specification<Monitor> specification = (root, query, criteriaBuilder) -> {
|
||||
List<Predicate> andList = new ArrayList<>();
|
||||
if (!CollectionUtils.isEmpty(monitorIds)) {
|
||||
@@ -574,33 +572,31 @@ public class MonitorServiceImpl implements MonitorService {
|
||||
Predicate predicateStatus = criteriaBuilder.equal(root.get("status"), status);
|
||||
andList.add(predicateStatus);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(tag)) {
|
||||
String[] tagArr = tag.split(":");
|
||||
String tagName = tagArr[0];
|
||||
ListJoin<Monitor, Tag> tagJoin = root
|
||||
.join(root.getModel()
|
||||
.getList("tags", org.apache.hertzbeat.common.entity.manager.Tag.class), JoinType.LEFT);
|
||||
if (tagArr.length == TAG_LENGTH) {
|
||||
String tagValue = tagArr[1];
|
||||
andList.add(criteriaBuilder.equal(tagJoin.get("name"), tagName));
|
||||
andList.add(criteriaBuilder.equal(tagJoin.get("tagValue"), tagValue));
|
||||
} else {
|
||||
andList.add(criteriaBuilder.equal(tagJoin.get("name"), tag));
|
||||
}
|
||||
}
|
||||
Predicate[] andPredicates = new Predicate[andList.size()];
|
||||
Predicate andPredicate = criteriaBuilder.and(andList.toArray(andPredicates));
|
||||
|
||||
List<Predicate> orList = new ArrayList<>();
|
||||
if (StringUtils.isNotBlank(host)) {
|
||||
Predicate predicateHost = criteriaBuilder.like(root.get("host"), "%" + host + "%");
|
||||
if (StringUtils.isNotBlank(search)) {
|
||||
Predicate predicateHost = criteriaBuilder.like(root.get("host"), "%" + search + "%");
|
||||
Predicate predicateName = criteriaBuilder.like(root.get("name"), "%" + search + "%");
|
||||
orList.add(predicateHost);
|
||||
}
|
||||
if (StringUtils.isNotBlank(name)) {
|
||||
Predicate predicateName = criteriaBuilder.like(root.get("name"), "%" + name + "%");
|
||||
orList.add(predicateName);
|
||||
}
|
||||
if (StringUtils.isNotBlank(labels)) {
|
||||
String[] labelAres = labels.split(",");
|
||||
for (String label : labelAres) {
|
||||
String[] labelArr = label.split(":");
|
||||
String labelName = labelArr[0];
|
||||
String labelValue = labelArr.length == 2 ? labelArr[1] : null;
|
||||
// create every label condition
|
||||
if (labelValue == null) {
|
||||
orList.add(criteriaBuilder.like(root.get("labels"), "%" + labelName + "%"));
|
||||
} else {
|
||||
String pattern = String.format("%%\"%s\":\"%s\"%%", labelName, labelValue);
|
||||
orList.add(criteriaBuilder.like(root.get("labels"), pattern));
|
||||
}
|
||||
}
|
||||
}
|
||||
Predicate[] orPredicates = new Predicate[orList.size()];
|
||||
Predicate orPredicate = criteriaBuilder.or(orList.toArray(orPredicates));
|
||||
|
||||
|
||||
+2
-2
@@ -90,9 +90,9 @@ class MonitorDaoTest extends AbstractSpringIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void findMonitorsByStatusNotInAndAndJobIdNotNull() {
|
||||
void findMonitorsByStatusNotInAndJobIdNotNull() {
|
||||
List<Byte> bytes = Arrays.asList((byte) 2, (byte) 3);
|
||||
List<Monitor> monitors = monitorDao.findMonitorsByStatusNotInAndAndJobIdNotNull(bytes);
|
||||
List<Monitor> monitors = monitorDao.findMonitorsByStatusNotInAndJobIdNotNull(bytes);
|
||||
assertNotNull(monitors);
|
||||
assertEquals(1, monitors.size());
|
||||
}
|
||||
|
||||
+1
-1
@@ -647,7 +647,7 @@ class MonitorServiceTest {
|
||||
@Test
|
||||
void getMonitors() {
|
||||
doReturn(Page.empty()).when(monitorDao).findAll(any(Specification.class), any(PageRequest.class));
|
||||
assertNotNull(monitorService.getMonitors(null, null, null, null, null, "gmtCreate", "desc", 1, 1, null));
|
||||
assertNotNull(monitorService.getMonitors(null, null, null, null, "gmtCreate", "desc", 1, 1, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+34
-2
@@ -17,8 +17,12 @@
|
||||
|
||||
package org.apache.hertzbeat.warehouse.store;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.message.CollectRep;
|
||||
import org.apache.hertzbeat.common.queue.CommonDataQueue;
|
||||
import org.apache.hertzbeat.plugin.PostCollectPlugin;
|
||||
@@ -26,6 +30,7 @@ import org.apache.hertzbeat.plugin.runner.PluginRunner;
|
||||
import org.apache.hertzbeat.warehouse.WarehouseWorkerPool;
|
||||
import org.apache.hertzbeat.warehouse.store.history.HistoryDataWriter;
|
||||
import org.apache.hertzbeat.warehouse.store.realtime.RealTimeDataWriter;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@@ -37,22 +42,26 @@ public class DataStorageDispatch {
|
||||
|
||||
private final CommonDataQueue commonDataQueue;
|
||||
private final WarehouseWorkerPool workerPool;
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final RealTimeDataWriter realTimeDataWriter;
|
||||
private final Optional<HistoryDataWriter> historyDataWriter;
|
||||
|
||||
private final PluginRunner pluginRunner;
|
||||
private final Set<Long> monitorDownStatusCache;
|
||||
|
||||
public DataStorageDispatch(CommonDataQueue commonDataQueue,
|
||||
WarehouseWorkerPool workerPool,
|
||||
JdbcTemplate jdbcTemplate,
|
||||
Optional<HistoryDataWriter> historyDataWriter,
|
||||
RealTimeDataWriter realTimeDataWriter,
|
||||
PluginRunner pluginRunner) {
|
||||
this.commonDataQueue = commonDataQueue;
|
||||
this.workerPool = workerPool;
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
this.realTimeDataWriter = realTimeDataWriter;
|
||||
this.historyDataWriter = historyDataWriter;
|
||||
this.pluginRunner = pluginRunner;
|
||||
this.monitorDownStatusCache = new ConcurrentSkipListSet<>();
|
||||
initMonitorDownStatusCache();
|
||||
startPersistentDataStorage();
|
||||
}
|
||||
|
||||
@@ -65,6 +74,7 @@ public class DataStorageDispatch {
|
||||
if (metricsData == null) {
|
||||
continue;
|
||||
}
|
||||
calculateMonitorStatus(metricsData);
|
||||
historyDataWriter.ifPresent(dataWriter -> dataWriter.saveData(metricsData));
|
||||
pluginRunner.pluginExecute(PostCollectPlugin.class, ((postCollectPlugin, pluginContext) -> postCollectPlugin.execute(metricsData, pluginContext)));
|
||||
realTimeDataWriter.saveData(metricsData);
|
||||
@@ -78,5 +88,27 @@ public class DataStorageDispatch {
|
||||
workerPool.executeJob(runnable);
|
||||
}
|
||||
|
||||
private void initMonitorDownStatusCache() {
|
||||
String sql = "SELECT id FROM hzb_monitor WHERE status = 2";
|
||||
List<Long> ids = jdbcTemplate.query(sql, (rs, rowNum) -> rs.getLong("id"));
|
||||
monitorDownStatusCache.addAll(ids);
|
||||
}
|
||||
|
||||
protected void calculateMonitorStatus(CollectRep.MetricsData metricsData) {
|
||||
if (metricsData.getPriority() == 0) {
|
||||
long id = metricsData.getId();
|
||||
CollectRep.Code code = metricsData.getCode();
|
||||
if (code == CollectRep.Code.SUCCESS && monitorDownStatusCache.contains(id)) {
|
||||
monitorDownStatusCache.remove(id);
|
||||
String sql = "UPDATE hzb_monitor SET status = ? WHERE id = ?";
|
||||
jdbcTemplate.update(sql, CommonConstants.MONITOR_UP_CODE, id);
|
||||
} else if (code != CollectRep.Code.SUCCESS && !monitorDownStatusCache.contains(id)) {
|
||||
monitorDownStatusCache.add(id);
|
||||
String sql = "UPDATE hzb_monitor SET status = ? WHERE id = ?";
|
||||
jdbcTemplate.update(sql, CommonConstants.MONITOR_DOWN_CODE, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ export class SingleAlert {
|
||||
startAt!: number;
|
||||
endAt!: number;
|
||||
activeAt!: number;
|
||||
triggerTime!: number;
|
||||
triggerTimes!: number;
|
||||
creator!: string;
|
||||
modifier!: string;
|
||||
gmtCreate!: number;
|
||||
|
||||
@@ -27,43 +27,38 @@
|
||||
<nz-divider></nz-divider>
|
||||
|
||||
<app-toolbar>
|
||||
<ng-template #left>
|
||||
<button nz-button nzType="primary" (click)="sync()" nz-tooltip [nzTooltipTitle]="'common.refresh' | i18n">
|
||||
<i nz-icon nzType="sync" nzTheme="outline"></i>
|
||||
</button>
|
||||
</ng-template>
|
||||
<ng-template #right>
|
||||
<nz-select
|
||||
class="mobile-hide"
|
||||
nzAllowClear
|
||||
[nzPlaceHolder]="'alert.center.filter-priority' | i18n"
|
||||
[(ngModel)]="filterPriority"
|
||||
(ngModelChange)="loadAlertsTable()"
|
||||
>
|
||||
<nz-option [nzLabel]="'alert.severity.all' | i18n" [nzValue]="9"></nz-option>
|
||||
<nz-option [nzLabel]="'alert.severity.2' | i18n" [nzValue]="2"></nz-option>
|
||||
<nz-option [nzLabel]="'alert.severity.1' | i18n" [nzValue]="1"></nz-option>
|
||||
<nz-option [nzLabel]="'alert.severity.0' | i18n" [nzValue]="0"></nz-option>
|
||||
</nz-select>
|
||||
<nz-select
|
||||
class="mobile-hide"
|
||||
nzAllowClear
|
||||
[nzPlaceHolder]="'alert.center.filter-status' | i18n"
|
||||
[(ngModel)]="filterStatus"
|
||||
(ngModelChange)="loadAlertsTable()"
|
||||
>
|
||||
<nz-option [nzLabel]="'alert.status.all' | i18n" [nzValue]="'all'"></nz-option>
|
||||
<nz-option [nzLabel]="'alert.status.0' | i18n" [nzValue]="'emergency'"></nz-option>
|
||||
<nz-option [nzLabel]="'alert.status.2' | i18n" [nzValue]="'critical'"></nz-option>
|
||||
<nz-option [nzLabel]="'alert.status.3' | i18n" [nzValue]="'warning'"></nz-option>
|
||||
</nz-select>
|
||||
<app-multi-func-input
|
||||
groupStyle="width: 250px;"
|
||||
class="mobile-hide"
|
||||
[placeholder]="'alert.center.search' | i18n"
|
||||
[(value)]="filterContent"
|
||||
(keydown.enter)="loadAlertsTable()"
|
||||
/>
|
||||
<ng-template #center>
|
||||
<div class="center-content">
|
||||
<button nz-button (click)="sync()" nz-tooltip [nzTooltipTitle]="'common.refresh' | i18n">
|
||||
<i nz-icon nzType="sync" nzTheme="outline"></i>
|
||||
</button>
|
||||
|
||||
<div class="search-wrapper">
|
||||
<nz-input-group [nzPrefix]="prefixTemplate" class="search-input">
|
||||
<input
|
||||
type="text"
|
||||
nz-input
|
||||
[(ngModel)]="filterContent"
|
||||
(keydown.enter)="loadAlertsTable()"
|
||||
[placeholder]="'alert.center.search' | i18n"
|
||||
/>
|
||||
</nz-input-group>
|
||||
<ng-template #prefixTemplate>
|
||||
<i nz-icon nzType="search"></i>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
<nz-select
|
||||
class="mobile-hide"
|
||||
nzAllowClear
|
||||
[nzPlaceHolder]="'alert.center.filter-status' | i18n"
|
||||
[(ngModel)]="filterStatus"
|
||||
(ngModelChange)="loadAlertsTable()"
|
||||
>
|
||||
<nz-option [nzLabel]="'alert.status.firing' | i18n" [nzValue]="'firing'"></nz-option>
|
||||
<nz-option [nzLabel]="'alert.status.resolved' | i18n" [nzValue]="'resolved'"></nz-option>
|
||||
</nz-select>
|
||||
</div>
|
||||
</ng-template>
|
||||
</app-toolbar>
|
||||
|
||||
@@ -73,40 +68,34 @@
|
||||
<div class="alert-header">
|
||||
<div class="alert-info">
|
||||
<div class="alert-labels">
|
||||
<nz-tag *ngFor="let label of recordEntries(group.groupLabels)">
|
||||
{{ label[0] + ':' + label[1] }}
|
||||
</nz-tag>
|
||||
<nz-tag *ngFor="let item of group.groupLabels | keyvalue">{{ item.key }}:{{ item.value }}</nz-tag>
|
||||
</div>
|
||||
<div class="alert-meta-info">
|
||||
<span class="alert-time">
|
||||
<i nz-icon nzType="clock-circle" nzTheme="outline"></i>
|
||||
{{ group.gmtCreate | date : 'yyyy-MM-dd HH:mm:ss' }}
|
||||
</span>
|
||||
<span class="alert-count" *ngIf="group?.alerts">
|
||||
<i nz-icon nzType="alert" nzTheme="outline"></i>
|
||||
{{ 'alert.center.time.tip' | i18n : { times: group?.alerts?.length } }}
|
||||
{{ group.gmtUpdate | date : 'yyyy-MM-dd HH:mm:ss' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert-actions">
|
||||
<button
|
||||
*ngIf="group.status != 'firing'"
|
||||
nz-button
|
||||
(click)="onMarkReadOneAlert(group.id)"
|
||||
nz-tooltip
|
||||
[nzTooltipTitle]="'alert.center.deal' | i18n"
|
||||
>
|
||||
<i nz-icon nzType="down-circle" nzTheme="outline"></i>
|
||||
</button>
|
||||
<button
|
||||
*ngIf="group.status == 'firing'"
|
||||
nz-button
|
||||
(click)="onMarkUnReadOneAlert(group.id)"
|
||||
nz-tooltip
|
||||
[nzTooltipTitle]="'alert.center.no-deal' | i18n"
|
||||
>
|
||||
<i nz-icon nzType="up-circle" nzTheme="outline"></i>
|
||||
</button>
|
||||
<!-- <button-->
|
||||
<!-- *ngIf="group.status != 'firing'"-->
|
||||
<!-- nz-button-->
|
||||
<!-- (click)="onMarkReadOneAlert(group.id)"-->
|
||||
<!-- nz-tooltip-->
|
||||
<!-- [nzTooltipTitle]="'alert.center.deal' | i18n"-->
|
||||
<!-- >-->
|
||||
<!-- <i nz-icon nzType="down-circle" nzTheme="outline"></i>-->
|
||||
<!-- </button>-->
|
||||
<!-- <button-->
|
||||
<!-- *ngIf="group.status == 'firing'"-->
|
||||
<!-- nz-button-->
|
||||
<!-- (click)="onMarkUnReadOneAlert(group.id)"-->
|
||||
<!-- nz-tooltip-->
|
||||
<!-- [nzTooltipTitle]="'alert.center.no-deal' | i18n"-->
|
||||
<!-- >-->
|
||||
<!-- <i nz-icon nzType="up-circle" nzTheme="outline"></i>-->
|
||||
<!-- </button>-->
|
||||
<button nz-button nzDanger (click)="onDeleteOneAlert(group.id)" nz-tooltip [nzTooltipTitle]="'alert.center.delete' | i18n">
|
||||
<i nz-icon nzType="delete" nzTheme="outline"></i>
|
||||
</button>
|
||||
@@ -117,6 +106,7 @@
|
||||
<div class="alert-details">
|
||||
<nz-collapse nzGhost>
|
||||
<nz-collapse-panel
|
||||
#panel
|
||||
*ngFor="let item of group.alerts"
|
||||
[nzHeader]="alertHeader"
|
||||
[nzExtra]="alertExtra"
|
||||
@@ -124,22 +114,33 @@
|
||||
[nzExpandedIcon]="expandedIcon"
|
||||
>
|
||||
<ng-template #alertHeader>
|
||||
<div class="alert-content">{{ item.content }}</div>
|
||||
<div class="alert-content">
|
||||
<nz-tag *ngIf="item.labels.alertname" style="font-size: 14px; margin-right: 8px">{{ item.labels.alertname }}</nz-tag>
|
||||
<span>{{ item.content }}</span>
|
||||
</div>
|
||||
</ng-template>
|
||||
<ng-template #alertExtra>
|
||||
<div class="alert-time">{{ item.activeAt | date : 'yyyy-MM-dd HH:mm:ss' }}</div>
|
||||
<div class="alert-time">{{
|
||||
item.endAt ? (item.endAt | date : 'yyyy-MM-dd HH:mm:ss') : (item.activeAt | date : 'yyyy-MM-dd HH:mm:ss')
|
||||
}}</div>
|
||||
</ng-template>
|
||||
<ng-template #expandedIcon let-active>
|
||||
<i nz-icon [nzType]="active ? 'caret-down' : 'caret-right'"></i>
|
||||
<ng-template #expandedIcon>
|
||||
<i nz-icon [nzType]="panel.nzActive ? 'caret-down' : 'caret-right'"></i>
|
||||
</ng-template>
|
||||
|
||||
<!-- Trigger Times -->
|
||||
<div class="detail-section" *ngIf="item.triggerTimes">
|
||||
<span class="alert-count" *ngIf="group?.alerts">
|
||||
<i style="margin-right: 4px" nz-icon nzType="alert" nzTheme="outline"></i>
|
||||
{{ 'alert.center.time.tip' | i18n : { times: item.triggerTimes } }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Labels -->
|
||||
<div class="detail-section" *ngIf="item.labels">
|
||||
<div class="section-title">{{ 'alert.center.labels' | i18n }}</div>
|
||||
<div class="alert-labels">
|
||||
<nz-tag *ngFor="let label of recordEntries(item.labels)">
|
||||
{{ label[0] + ':' + label[1] }}
|
||||
</nz-tag>
|
||||
<nz-tag *ngFor="let label of item.labels | keyvalue">{{ label.key }}:{{ label.value }}</nz-tag>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -147,9 +148,9 @@
|
||||
<div class="detail-section" *ngIf="item.annotations">
|
||||
<div class="section-title">{{ 'annotation' | i18n }}</div>
|
||||
<div class="alert-annotations">
|
||||
<div *ngFor="let anno of recordEntries(item.annotations)" class="annotation-item">
|
||||
<span class="annotation-key">{{ anno[0] }}:</span>
|
||||
<span class="annotation-value">{{ anno[1] }}</span>
|
||||
<div *ngFor="let anno of item.annotations | keyvalue" class="annotation-item">
|
||||
<span class="annotation-key">{{ anno.key }}:</span>
|
||||
<span class="annotation-value">{{ anno.value }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -162,10 +163,14 @@
|
||||
<span class="time-label">{{ 'alert.center.first-time' | i18n }}:</span>
|
||||
<span class="time-value">{{ item.startAt | date : 'yyyy-MM-dd HH:mm:ss' }}</span>
|
||||
</div>
|
||||
<div class="time-item">
|
||||
<div *ngIf="item.activeAt" class="time-item">
|
||||
<span class="time-label">{{ 'alert.center.last-time' | i18n }}:</span>
|
||||
<span class="time-value">{{ item.activeAt | date : 'yyyy-MM-dd HH:mm:ss' }}</span>
|
||||
</div>
|
||||
<div *ngIf="item.endAt" class="time-item">
|
||||
<span class="time-label">{{ 'alert.center.end-time' | i18n }}:</span>
|
||||
<span class="time-value">{{ item.endAt | date : 'yyyy-MM-dd HH:mm:ss' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nz-collapse-panel>
|
||||
|
||||
@@ -1,3 +1,68 @@
|
||||
/* 调整工具栏布局 */
|
||||
:host ::ng-deep app-toolbar {
|
||||
.center-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
width: 100%;
|
||||
padding: 0 16px;
|
||||
|
||||
button {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
nz-select {
|
||||
min-width: 120px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 100%;
|
||||
|
||||
:global {
|
||||
.ant-input {
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
border-radius: 6px;
|
||||
padding: 4px 11px 4px 40px;
|
||||
}
|
||||
|
||||
.ant-input-prefix {
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
font-size: 16px;
|
||||
margin-right: 8px;
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.ant-input-affix-wrapper {
|
||||
border-radius: 6px;
|
||||
|
||||
&:hover, &:focus {
|
||||
border-color: #40a9ff;
|
||||
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.search-wrapper {
|
||||
max-width: 100%;
|
||||
padding: 12px 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.alert-cards {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -29,7 +94,7 @@
|
||||
|
||||
.alert-info {
|
||||
flex: 1;
|
||||
|
||||
|
||||
.alert-labels {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -40,7 +105,7 @@
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.alert-meta-info {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
@@ -52,7 +117,7 @@
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.alert-time, .alert-count {
|
||||
.alert-time {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
@@ -97,7 +162,7 @@
|
||||
padding: 8px 12px;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
|
||||
&:hover {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
@@ -121,7 +186,7 @@
|
||||
|
||||
.ant-collapse-content {
|
||||
border-top: 1px solid #f0f0f0;
|
||||
|
||||
|
||||
.ant-collapse-content-box {
|
||||
padding: 12px;
|
||||
}
|
||||
@@ -143,6 +208,13 @@
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.alert-count {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #8c8c8c;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.alert-annotations {
|
||||
@@ -201,11 +273,11 @@
|
||||
&.status-firing {
|
||||
border-left-color: #ff4d4f;
|
||||
}
|
||||
|
||||
|
||||
&.status-resolved {
|
||||
border-left-color: #52c41a;
|
||||
}
|
||||
|
||||
|
||||
&.status-pending {
|
||||
border-left-color: #faad14;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import { I18NService } from '@core';
|
||||
import { ALAIN_I18N_TOKEN } from '@delon/theme';
|
||||
import { NzModalService } from 'ng-zorro-antd/modal';
|
||||
import { NzNotificationService } from 'ng-zorro-antd/notification';
|
||||
import { NzTableQueryParams } from 'ng-zorro-antd/table';
|
||||
|
||||
import { GroupAlert } from '../../../pojo/GroupAlert';
|
||||
import { AlertService } from '../../../service/alert.service';
|
||||
@@ -46,8 +45,7 @@ export class AlertCenterComponent implements OnInit {
|
||||
groupAlerts!: GroupAlert[];
|
||||
tableLoading: boolean = false;
|
||||
checkedAlertIds = new Set<number>();
|
||||
filterStatus: string = 'firing';
|
||||
filterPriority: number = 9;
|
||||
filterStatus!: string;
|
||||
filterContent: string | undefined;
|
||||
|
||||
ngOnInit(): void {
|
||||
@@ -62,7 +60,6 @@ export class AlertCenterComponent implements OnInit {
|
||||
this.tableLoading = true;
|
||||
let alertsInit$ = this.alertSvc.loadGroupAlerts(this.filterStatus, this.filterContent, this.pageIndex - 1, this.pageSize).subscribe(
|
||||
message => {
|
||||
this.tableLoading = false;
|
||||
if (message.code === 0) {
|
||||
let page = message.data;
|
||||
this.groupAlerts = page.content;
|
||||
@@ -76,6 +73,7 @@ export class AlertCenterComponent implements OnInit {
|
||||
} else {
|
||||
console.warn(message.msg);
|
||||
}
|
||||
this.tableLoading = false;
|
||||
alertsInit$.unsubscribe();
|
||||
},
|
||||
error => {
|
||||
@@ -206,26 +204,4 @@ export class AlertCenterComponent implements OnInit {
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// begin: List multiple choice paging
|
||||
checkedAll: boolean = false;
|
||||
onAllChecked(checked: boolean) {
|
||||
if (checked) {
|
||||
this.groupAlerts.forEach(monitor => this.checkedAlertIds.add(monitor.id));
|
||||
} else {
|
||||
this.checkedAlertIds.clear();
|
||||
}
|
||||
}
|
||||
onItemChecked(monitorId: number, checked: boolean) {
|
||||
if (checked) {
|
||||
this.checkedAlertIds.add(monitorId);
|
||||
} else {
|
||||
this.checkedAlertIds.delete(monitorId);
|
||||
}
|
||||
}
|
||||
// end: List multiple choice paging
|
||||
|
||||
recordEntries(record: Record<any, any>) {
|
||||
return Object.entries(record);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@
|
||||
required
|
||||
>
|
||||
</nz-input-number>
|
||||
<span class="ant-form-text">{{ 'alert.group-converge.seconds' | i18n }}</span>
|
||||
<span class="ant-form-text">{{ 'common.time.unit.second' | i18n }}</span>
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
groupStyle="width: 250px;"
|
||||
[placeholder]="'alert.setting.search' | i18n"
|
||||
[(value)]="search"
|
||||
(valueChange)="loadAlertDefineTable()"
|
||||
(keydown.enter)="loadAlertDefineTable()"
|
||||
/>
|
||||
</ng-template>
|
||||
</app-toolbar>
|
||||
@@ -96,7 +96,7 @@
|
||||
<th nzAlign="center" nzWidth="8%">{{ 'alert.setting.type' | i18n }}</th>
|
||||
<th nzAlign="center" nzWidth="24%">{{ 'alert.setting.expr' | i18n }}</th>
|
||||
<th nzAlign="center" nzWidth="20%">{{ 'alert.setting.template' | i18n }}</th>
|
||||
<th nzAlign="center" nzWidth="8%">{{ 'alert.severity' | i18n }}</th>
|
||||
<th nzAlign="center" nzWidth="8%">{{ 'label.bind' | i18n }}</th>
|
||||
<th nzAlign="center" nzWidth="8%">{{ 'alert.setting.enable' | i18n }}</th>
|
||||
<th nzAlign="center" nzWidth="8%">{{ 'common.edit' | i18n }}</th>
|
||||
</tr>
|
||||
@@ -120,18 +120,7 @@
|
||||
</td>
|
||||
<td nzAlign="center">{{ data.template }}</td>
|
||||
<td nzAlign="center">
|
||||
<nz-tag *ngIf="data.labels?.severity == 'emergency'" nzColor="red">
|
||||
<i nz-icon nzType="bell" nzTheme="outline"></i>
|
||||
<span>{{ 'alert.severity.0' | i18n }}</span>
|
||||
</nz-tag>
|
||||
<nz-tag *ngIf="data.labels?.severity == 'critical'" nzColor="orange">
|
||||
<i nz-icon nzType="bell" nzTheme="outline"></i>
|
||||
<span>{{ 'alert.severity.1' | i18n }}</span>
|
||||
</nz-tag>
|
||||
<nz-tag *ngIf="data.labels?.severity == 'warning'" nzColor="yellow">
|
||||
<i nz-icon nzType="bell" nzTheme="outline"></i>
|
||||
<span>{{ 'alert.severity.2' | i18n }}</span>
|
||||
</nz-tag>
|
||||
<nz-tag *ngFor="let item of data.labels | keyvalue">{{ item.key }}:{{ item.value }}</nz-tag>
|
||||
</td>
|
||||
<td nzAlign="center">
|
||||
<nz-switch [(ngModel)]="data.enable" (ngModelChange)="updateAlertDefine(data)" name="enable"></nz-switch>
|
||||
@@ -463,21 +452,17 @@
|
||||
{{ 'alert.setting.period' | i18n }}
|
||||
</nz-form-label>
|
||||
<nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.required' | i18n">
|
||||
<nz-input-group nzCompact>
|
||||
<nz-input-number
|
||||
[(ngModel)]="define.period"
|
||||
required
|
||||
[nzMin]="60"
|
||||
[nzStep]="60"
|
||||
name="period"
|
||||
id="period"
|
||||
[nzPlaceHolder]="'alert.setting.period.placeholder' | i18n"
|
||||
>
|
||||
</nz-input-number>
|
||||
<div class="ant-input-group-addon" style="width: 40px; text-align: center">
|
||||
{{ 'common.time.unit.second' | i18n }}
|
||||
</div>
|
||||
</nz-input-group>
|
||||
<nz-input-number
|
||||
[(ngModel)]="define.period"
|
||||
required
|
||||
[nzMin]="60"
|
||||
[nzStep]="60"
|
||||
name="period"
|
||||
id="period"
|
||||
[nzPlaceHolder]="'alert.setting.period.placeholder' | i18n"
|
||||
>
|
||||
</nz-input-number>
|
||||
<span class="ant-form-text">{{ 'common.time.unit.second' | i18n }}</span>
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
<nz-form-item>
|
||||
|
||||
@@ -294,7 +294,7 @@
|
||||
<angular-tag-cloud
|
||||
class="br-4"
|
||||
*ngIf="!wordCloudDataLoading"
|
||||
(clicked)="onTagCloudClick($event)"
|
||||
(clicked)="onLabelCloudClick($event)"
|
||||
[font]="'italic bold 6px monospace'"
|
||||
[data]="wordCloudData"
|
||||
[width]="1"
|
||||
|
||||
@@ -113,8 +113,8 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
||||
);
|
||||
}
|
||||
|
||||
onTagCloudClick(data: CloudData): void {
|
||||
this.router.navigate(['/monitors'], { queryParams: { tag: data.text } });
|
||||
onLabelCloudClick(data: CloudData): void {
|
||||
this.router.navigate(['/monitors'], { queryParams: { labels: data.text } });
|
||||
}
|
||||
|
||||
// start -- quantitative information summary
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
groupStyle="width: 120px;"
|
||||
class="mobile-hide"
|
||||
[placeholder]="'monitors.search.tag' | i18n"
|
||||
[(value)]="tag"
|
||||
[(value)]="labels"
|
||||
(valueChange)="onTagChanged()"
|
||||
/>
|
||||
<app-multi-func-input
|
||||
|
||||
@@ -21,7 +21,6 @@ import { Component, Inject, OnDestroy, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { I18NService } from '@core';
|
||||
import { ALAIN_I18N_TOKEN, MenuService } from '@delon/theme';
|
||||
import { NzMessageService } from 'ng-zorro-antd/message';
|
||||
import { NzModalService } from 'ng-zorro-antd/modal';
|
||||
import { ModalButtonOptions } from 'ng-zorro-antd/modal/modal-types';
|
||||
import { NzNotificationService } from 'ng-zorro-antd/notification';
|
||||
@@ -33,7 +32,7 @@ import { Monitor } from '../../../pojo/Monitor';
|
||||
import { AppDefineService } from '../../../service/app-define.service';
|
||||
import { MemoryStorageService } from '../../../service/memory-storage.service';
|
||||
import { MonitorService } from '../../../service/monitor.service';
|
||||
import { formatTagName, findDeepestSelected } from '../../../shared/utils/common-util';
|
||||
import { findDeepestSelected } from '../../../shared/utils/common-util';
|
||||
|
||||
@Component({
|
||||
selector: 'app-monitor-list',
|
||||
@@ -47,7 +46,6 @@ export class MonitorListComponent implements OnInit, OnDestroy {
|
||||
private modal: NzModalService,
|
||||
private notifySvc: NzNotificationService,
|
||||
private monitorSvc: MonitorService,
|
||||
private messageSvc: NzMessageService,
|
||||
private storageSvc: MemoryStorageService,
|
||||
private appDefineSvc: AppDefineService,
|
||||
private menuService: MenuService,
|
||||
@@ -56,7 +54,7 @@ export class MonitorListComponent implements OnInit, OnDestroy {
|
||||
|
||||
isDefaultListMenu!: boolean;
|
||||
app!: string | undefined;
|
||||
tag!: string | undefined;
|
||||
labels!: string | undefined;
|
||||
pageIndex: number = 1;
|
||||
pageSize: number = 8;
|
||||
total: number = 0;
|
||||
@@ -86,11 +84,11 @@ export class MonitorListComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
this.route.queryParamMap.subscribe(paramMap => {
|
||||
let appStr = paramMap.get('app');
|
||||
let tagStr = paramMap.get('tag');
|
||||
if (tagStr != null) {
|
||||
this.tag = tagStr;
|
||||
let labelsStr = paramMap.get('labels');
|
||||
if (labelsStr != null) {
|
||||
this.labels = labelsStr;
|
||||
} else {
|
||||
this.tag = undefined;
|
||||
this.labels = undefined;
|
||||
}
|
||||
if (appStr != null) {
|
||||
this.app = appStr;
|
||||
@@ -126,7 +124,7 @@ export class MonitorListComponent implements OnInit, OnDestroy {
|
||||
onTagChanged(): void {
|
||||
this.router.navigate([], {
|
||||
relativeTo: this.route,
|
||||
queryParams: { ...this.route.snapshot.queryParams, tag: this.tag },
|
||||
queryParams: { ...this.route.snapshot.queryParams, tag: this.labels },
|
||||
queryParamsHandling: 'merge'
|
||||
});
|
||||
}
|
||||
@@ -134,7 +132,7 @@ export class MonitorListComponent implements OnInit, OnDestroy {
|
||||
onFilterSearchMonitors() {
|
||||
this.tableLoading = true;
|
||||
let filter$ = this.monitorSvc
|
||||
.searchMonitors(this.app, this.tag, this.filterContent, this.filterStatus, this.pageIndex - 1, this.pageSize)
|
||||
.searchMonitors(this.app, this.labels, this.filterContent, this.filterStatus, this.pageIndex - 1, this.pageSize)
|
||||
.subscribe(
|
||||
message => {
|
||||
filter$.unsubscribe();
|
||||
@@ -180,7 +178,7 @@ export class MonitorListComponent implements OnInit, OnDestroy {
|
||||
loadMonitorTable(sortField?: string | null, sortOrder?: string | null) {
|
||||
this.tableLoading = true;
|
||||
let monitorInit$ = this.monitorSvc
|
||||
.searchMonitors(this.app, this.tag, this.filterContent, this.filterStatus, this.pageIndex - 1, this.pageSize, sortField, sortOrder)
|
||||
.searchMonitors(this.app, this.labels, this.filterContent, this.filterStatus, this.pageIndex - 1, this.pageSize, sortField, sortOrder)
|
||||
.subscribe(
|
||||
message => {
|
||||
this.tableLoading = false;
|
||||
@@ -205,7 +203,7 @@ export class MonitorListComponent implements OnInit, OnDestroy {
|
||||
changeMonitorTable(sortField?: string | null, sortOrder?: string | null) {
|
||||
this.tableLoading = true;
|
||||
let monitorInit$ = this.monitorSvc
|
||||
.searchMonitors(this.app, this.tag, this.filterContent, this.filterStatus, this.pageIndex - 1, this.pageSize, sortField, sortOrder)
|
||||
.searchMonitors(this.app, this.labels, this.filterContent, this.filterStatus, this.pageIndex - 1, this.pageSize, sortField, sortOrder)
|
||||
.subscribe(
|
||||
message => {
|
||||
this.tableLoading = false;
|
||||
@@ -495,7 +493,7 @@ export class MonitorListComponent implements OnInit, OnDestroy {
|
||||
// end: List multiple choice paging
|
||||
|
||||
notifyCopySuccess() {
|
||||
this.messageSvc.success(this.i18nSvc.fanyi('common.notify.copy-success'), { nzDuration: 800 });
|
||||
this.notifySvc.success(this.i18nSvc.fanyi('common.notify.copy-success'), '');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -53,8 +53,8 @@
|
||||
<nz-card [nzActions]="[copyAction, editAction, deleteAction]" [nzBorderless]="true" class="tag-card" [nzSize]="'small'">
|
||||
<div class="tag-content">
|
||||
<div class="tag-header">
|
||||
<a routerLink="/monitors" [queryParams]="{ tag: formatTagName(data) }">
|
||||
<nz-tag [nzColor]="data.color" class="tag-name" style="font-size: 14px; padding: 4px 8px">
|
||||
<a routerLink="/monitors" [queryParams]="{ labels: formatTagName(data) }">
|
||||
<nz-tag [nzColor]="data.color" class="tag-name">
|
||||
{{ formatTagName(data) }}
|
||||
</nz-tag>
|
||||
</a>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
transition: all 0.3s;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
@@ -26,13 +26,13 @@
|
||||
background: #fafafa;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
min-height: 32px;
|
||||
|
||||
|
||||
> li {
|
||||
margin: 0;
|
||||
|
||||
|
||||
> span {
|
||||
padding: 4px 0;
|
||||
|
||||
|
||||
&:hover {
|
||||
color: #1890ff;
|
||||
}
|
||||
@@ -53,8 +53,8 @@
|
||||
margin-bottom: 8px;
|
||||
|
||||
.tag-name {
|
||||
font-size: 16px;
|
||||
padding: 4px 16px;
|
||||
font-size: 18px;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
margin: 0;
|
||||
font-weight: 500;
|
||||
@@ -64,11 +64,9 @@
|
||||
}
|
||||
|
||||
.tag-description {
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
color: rgba(35, 34, 34, 0.65);
|
||||
font-size: 12px;
|
||||
margin: 0;
|
||||
min-height: 32px;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
@@ -106,4 +104,4 @@
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ export class AlertService {
|
||||
httpParams = httpParams.append('status', status);
|
||||
}
|
||||
if (search != undefined && search != '' && search.trim() != '') {
|
||||
httpParams = httpParams.append('content', search.trim());
|
||||
httpParams = httpParams.append('search', search.trim());
|
||||
}
|
||||
const options = { params: httpParams };
|
||||
return this.http.get<Message<Page<SingleAlert>>>(alerts_uri, options);
|
||||
@@ -83,7 +83,7 @@ export class AlertService {
|
||||
httpParams = httpParams.append('status', status);
|
||||
}
|
||||
if (search != undefined && search != '' && search.trim() != '') {
|
||||
httpParams = httpParams.append('content', search.trim());
|
||||
httpParams = httpParams.append('search', search.trim());
|
||||
}
|
||||
const options = { params: httpParams };
|
||||
return this.http.get<Message<Page<GroupAlert>>>(alerts_group_uri, options);
|
||||
|
||||
@@ -109,8 +109,8 @@ export class MonitorService {
|
||||
|
||||
public searchMonitors(
|
||||
app: string | undefined,
|
||||
tag: string | undefined,
|
||||
searchValue: string,
|
||||
labels: string | undefined,
|
||||
search: string,
|
||||
status: number,
|
||||
pageIndex: number,
|
||||
pageSize: number,
|
||||
@@ -125,8 +125,8 @@ export class MonitorService {
|
||||
pageIndex: pageIndex,
|
||||
pageSize: pageSize
|
||||
});
|
||||
if (tag != undefined) {
|
||||
httpParams = httpParams.append('tag', tag);
|
||||
if (labels != undefined) {
|
||||
httpParams = httpParams.append('labels', labels);
|
||||
}
|
||||
if (status != undefined && status != 9) {
|
||||
httpParams = httpParams.append('status', status);
|
||||
@@ -140,9 +140,8 @@ export class MonitorService {
|
||||
order: sortOrder == 'ascend' ? 'asc' : 'desc'
|
||||
});
|
||||
}
|
||||
if (searchValue != undefined && searchValue != '' && searchValue.trim() != '') {
|
||||
httpParams = httpParams.append('name', searchValue);
|
||||
httpParams = httpParams.append('host', searchValue);
|
||||
if (search != undefined && search != '' && search.trim() != '') {
|
||||
httpParams = httpParams.append('search', search);
|
||||
}
|
||||
const options = { params: httpParams };
|
||||
return this.http.get<Message<Page<Monitor>>>(monitors_uri, options);
|
||||
|
||||
@@ -127,9 +127,8 @@
|
||||
"status": {
|
||||
"": "Alert Status",
|
||||
"all": "All Status",
|
||||
"0": "Pending",
|
||||
"2": "Restored",
|
||||
"3": "Processed"
|
||||
"firing": "Firing",
|
||||
"resolved": "Resolved"
|
||||
},
|
||||
"severity": {
|
||||
"": "Alarm Severity",
|
||||
@@ -244,7 +243,7 @@
|
||||
"alert.center.clear": "Clear All",
|
||||
"alert.center.deal": "Mark Processed",
|
||||
"alert.center.no-deal": "Mark Pending",
|
||||
"alert.center.search": "Search Alert Content",
|
||||
"alert.center.search": "Search Alert",
|
||||
"alert.center.filter-status": "Alert Status",
|
||||
"alert.center.filter-priority": "Alert Priority",
|
||||
"alert.center.target": "Metric Target",
|
||||
@@ -257,6 +256,7 @@
|
||||
"alert.center.time.tip": "Alerts were triggered {{times}} times during this alert period",
|
||||
"alert.center.first-time": "Start Time",
|
||||
"alert.center.last-time": "Latest Time",
|
||||
"alert.center.end-time": "End Time",
|
||||
"alert.center.confirm.delete": "Please confirm whether to delete!",
|
||||
"alert.center.confirm.clear-all": "Please confirm whether to clear all alerts!",
|
||||
"alert.center.notify.no-mark": "No items selected for mark!",
|
||||
|
||||
@@ -126,9 +126,8 @@
|
||||
"status": {
|
||||
"": "告警状态",
|
||||
"all": "全部状态",
|
||||
"0": "未处理",
|
||||
"2": "已恢复",
|
||||
"3": "已处理"
|
||||
"firing": "告警中",
|
||||
"resolved": "已恢复"
|
||||
},
|
||||
"severity": {
|
||||
"": "告警级别",
|
||||
@@ -245,7 +244,7 @@
|
||||
"alert.center.clear": "一键清空",
|
||||
"alert.center.deal": "标记已处理",
|
||||
"alert.center.no-deal": "标记未处理",
|
||||
"alert.center.search": "搜索告警内容",
|
||||
"alert.center.search": "搜索告警",
|
||||
"alert.center.filter-status": "告警状态",
|
||||
"alert.center.filter-priority": "告警级别",
|
||||
"alert.center.target": "告警对象",
|
||||
@@ -258,6 +257,7 @@
|
||||
"alert.center.time.tip": "此告警期间累计触发 {{times}} 次告警",
|
||||
"alert.center.first-time": "开始",
|
||||
"alert.center.last-time": "最新",
|
||||
"alert.center.end-time": "结束",
|
||||
"alert.center.confirm.delete": "请确认是否删除!",
|
||||
"alert.center.confirm.clear-all": "请确认是否清空所有告警记录!",
|
||||
"alert.center.notify.no-mark": "未选中任何待标记项!",
|
||||
@@ -851,5 +851,6 @@
|
||||
"alert.inhibit.edit": "编辑抑制规则",
|
||||
"alert.inhibit.delete": "删除抑制规则",
|
||||
"alert.help.inhibit": "告警抑制用于配置告警之间的抑制关系。当某个告警发生时,可以抑制其他告警的产生。例如,当服务器宕机时,可以抑制该服务器上的所有告警。",
|
||||
"alert.help.inhibit.link": "https://hertzbeat.apache.org/zh-cn/docs/help/alert_inhibit"
|
||||
"alert.help.inhibit.link": "https://hertzbeat.apache.org/zh-cn/docs/help/alert_inhibit",
|
||||
"alert.center.tag.search.placeholder": "搜索标签..."
|
||||
}
|
||||
|
||||
@@ -141,9 +141,8 @@
|
||||
"status": {
|
||||
"": "告警狀態",
|
||||
"all": "全部狀態",
|
||||
"0": "未處理",
|
||||
"2": "已恢複",
|
||||
"3": "已處理"
|
||||
"firing": "告警中",
|
||||
"resolved": "已恢复"
|
||||
},
|
||||
"severity": {
|
||||
"": "告警級別",
|
||||
@@ -257,7 +256,7 @@
|
||||
"alert.center.clear": "一鍵清空",
|
||||
"alert.center.deal": "標記已處理",
|
||||
"alert.center.no-deal": "標記未處理",
|
||||
"alert.center.search": "搜索告警內容",
|
||||
"alert.center.search": "搜索告警",
|
||||
"alert.center.filter-status": "告警狀態",
|
||||
"alert.center.filter-priority": "告警級別",
|
||||
"alert.center.target": "告警對象",
|
||||
@@ -270,6 +269,7 @@
|
||||
"alert.center.time.tip": "此告警期間累計觸發 {{times}} 次告警",
|
||||
"alert.center.first-time": "開始",
|
||||
"alert.center.last-time": "最新",
|
||||
"alert.center.end-time": "结束",
|
||||
"alert.center.confirm.delete": "請確認是否刪除!",
|
||||
"alert.center.confirm.clear-all": "請確認是否清空所有告警記錄!",
|
||||
"alert.center.notify.no-mark": "未選中任何待標記項!",
|
||||
|
||||
Reference in New Issue
Block a user