This is an automated email from the ASF dual-hosted git repository.
gongchao pushed a commit to branch new-alarm
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git
The following commit(s) were added to refs/heads/new-alarm by this push:
new 9224d3160 [alarm] combine common labels and update ui (#2944)
9224d3160 is described below
commit 9224d31604b7566966ecccc819eb632f3c44adf3
Author: tomsun28 <[email protected]>
AuthorDate: Fri Jan 3 17:18:21 2025 +0800
[alarm] combine common labels and update ui (#2944)
Signed-off-by: tomsun28 <[email protected]>
---
.../apache/hertzbeat/alert/dto/AlertDefineDTO.java | 4 -
.../impl/AlertDefineExcelImExportServiceImpl.java | 21 +----
.../controller/NoticeConfigControllerTest.java | 5 --
.../AlertDefineExcelImExportServiceTest.java | 10 ---
.../common/constants/CommonConstants.java | 5 ++
.../hertzbeat/common/entity/manager/Bulletin.java | 6 --
.../entity/manager/JsonTagAttributeConverter.java | 43 ----------
.../manager/JsonTagListAttributeConverter.java | 58 -------------
.../common/entity/manager/StatusPageComponent.java | 13 ++-
.../hertzbeat/common/entity/manager/TagItem.java | 41 ----------
.../apache/hertzbeat/common/util/JsonUtilTest.java | 21 ++---
.../manager/component/status/CalculateStatus.java | 58 ++++++-------
.../app/layout/basic/widgets/notify.component.ts | 2 +-
web-app/src/app/pojo/Alert.ts | 38 ---------
web-app/src/app/pojo/AlertDefine.ts | 6 +-
web-app/src/app/pojo/AlertSilence.ts | 5 +-
web-app/src/app/pojo/Monitor.ts | 3 -
web-app/src/app/pojo/NoticeRule.ts | 1 +
web-app/src/app/pojo/StatusPageComponent.ts | 2 +-
.../alert/alert-center/alert-center.component.html | 8 +-
.../alert/alert-notice/alert-notice.component.html | 40 +--------
.../alert-setting/alert-setting.component.html | 53 ++++++------
.../alert/alert-setting/alert-setting.component.ts | 16 ++--
.../alert-silence/alert-silence.component.html | 52 +-----------
.../alert/alert-silence/alert-silence.component.ts | 85 -------------------
.../app/routes/dashboard/dashboard.component.html | 12 +--
.../app/routes/dashboard/dashboard.component.ts | 3 +-
.../monitor/monitor-edit/monitor-edit.component.ts | 3 -
.../monitor-form/monitor-form.component.html | 20 +++--
.../monitor/monitor-form/monitor-form.component.ts | 3 +-
.../monitor-list/monitor-list.component.html | 10 +--
.../monitor/monitor-list/monitor-list.component.ts | 16 +++-
.../monitor/monitor-new/monitor-new.component.ts | 1 -
web-app/src/app/routes/setting/setting.module.ts | 6 +-
.../routes/setting/status/status.component.html | 22 +----
.../app/routes/setting/status/status.component.ts | 75 +++--------------
.../app/routes/setting/tags/tags.component.html | 95 +++++++---------------
.../app/routes/setting/tags/tags.component.less | 80 ++++++++++++++++++
.../src/app/routes/setting/tags/tags.component.ts | 13 ++-
.../key-value-input/key-value-input.component.html | 6 +-
.../key-value-input/key-value-input.component.less | 2 +-
.../labels-input/labels-input.component.html | 7 +-
.../labels-input/labels-input.component.less | 2 +-
.../labels-input/labels-input.component.ts | 12 ++-
.../tags-select/tags-select.component.html | 2 +-
web-app/src/assets/i18n/en-US.json | 6 +-
web-app/src/assets/i18n/zh-CN.json | 16 ++--
web-app/src/assets/i18n/zh-TW.json | 6 +-
48 files changed, 318 insertions(+), 696 deletions(-)
diff --git
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/AlertDefineDTO.java
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/AlertDefineDTO.java
index 0cf72feda..290f3781f 100644
---
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/AlertDefineDTO.java
+++
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/AlertDefineDTO.java
@@ -21,9 +21,7 @@ import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
-import java.util.List;
import lombok.Data;
-import org.apache.hertzbeat.common.entity.manager.TagItem;
/**
* Data transfer object for alert configuration
@@ -48,8 +46,6 @@ public class AlertDefineDTO {
private Byte priority;
@Excel(name = "Times")
private Integer times;
- @Excel(name = "Tags")
- private List<TagItem> tags;
@Excel(name = "Enable")
private Boolean enable;
@Excel(name = "RecoverNotice")
diff --git
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlertDefineExcelImExportServiceImpl.java
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlertDefineExcelImExportServiceImpl.java
index 50540042e..4c2ba2e6f 100644
---
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlertDefineExcelImExportServiceImpl.java
+++
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlertDefineExcelImExportServiceImpl.java
@@ -19,7 +19,6 @@ package org.apache.hertzbeat.alert.service.impl;
import static
org.apache.hertzbeat.common.constants.ExportFileConstants.ExcelFile.FILE_SUFFIX;
import static
org.apache.hertzbeat.common.constants.ExportFileConstants.ExcelFile.TYPE;
-import com.fasterxml.jackson.core.type.TypeReference;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -29,8 +28,6 @@ import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.apache.hertzbeat.alert.dto.AlertDefineDTO;
import org.apache.hertzbeat.alert.dto.ExportAlertDefineDTO;
-import org.apache.hertzbeat.common.entity.manager.TagItem;
-import org.apache.hertzbeat.common.util.JsonUtil;
import org.apache.hertzbeat.common.util.export.ExcelExportUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
@@ -97,15 +94,6 @@ public class AlertDefineExcelImExportServiceImpl extends
AlertDefineAbstractImEx
}
}
- private List<TagItem> extractTagDataFromRow(Cell cell) {
- String jsonStr = getCellValueAsString(cell);
- if (StringUtils.hasText(jsonStr)) {
- return JsonUtil.fromJson(jsonStr, new TypeReference<>() {
- });
- }
- return null;
- }
-
private String getCellValueAsString(Cell cell) {
if (cell == null) {
@@ -161,7 +149,7 @@ public class AlertDefineExcelImExportServiceImpl extends
AlertDefineAbstractImEx
alertDefineDTO.setExpr(getCellValueAsString(row.getCell(4)));
alertDefineDTO.setPriority(getCellValueAsByte(row.getCell(5)));
alertDefineDTO.setTimes(getCellValueAsInteger(row.getCell(6)));
- alertDefineDTO.setTags(extractTagDataFromRow(row.getCell(7)));
+ // todo labels
alertDefineDTO.setEnable(getCellValueAsBoolean(row.getCell(8)));
alertDefineDTO.setRecoverNotice(getCellValueAsBoolean(row.getCell(9)));
alertDefineDTO.setTemplate(getCellValueAsString(row.getCell(10)));
@@ -211,12 +199,7 @@ public class AlertDefineExcelImExportServiceImpl extends
AlertDefineAbstractImEx
priorityCell.setCellStyle(cellStyle);
Cell timesCell = row.createCell(6);
timesCell.setCellValue(alertDefineDTO.getTimes());
- Cell tagCell = row.createCell(7);
- // get tags
- List<TagItem> tagList = alertDefineDTO.getTags();
- String tagValue = tagList == null || tagList.isEmpty() ? "" :
JsonUtil.toJson(tagList);
- tagCell.setCellValue(tagValue);
- tagCell.setCellStyle(cellStyle);
+ // todo labels
Cell enableCell = row.createCell(8);
enableCell.setCellValue(alertDefineDTO.getEnable() != null
&& alertDefineDTO.getEnable());
diff --git
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/controller/NoticeConfigControllerTest.java
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/controller/NoticeConfigControllerTest.java
index 59001a5fb..5ced52af7 100644
---
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/controller/NoticeConfigControllerTest.java
+++
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/controller/NoticeConfigControllerTest.java
@@ -36,7 +36,6 @@ import org.apache.hertzbeat.common.constants.CommonConstants;
import org.apache.hertzbeat.common.entity.alerter.NoticeReceiver;
import org.apache.hertzbeat.common.entity.alerter.NoticeRule;
import org.apache.hertzbeat.common.entity.alerter.NoticeTemplate;
-import org.apache.hertzbeat.common.entity.manager.TagItem;
import org.apache.hertzbeat.common.util.JsonUtil;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -66,10 +65,6 @@ class NoticeConfigControllerTest {
public NoticeRule getNoticeRule() {
- TagItem tagItem = new TagItem();
- tagItem.setName("key1");
- tagItem.setValue("value1");
-
NoticeRule noticeRule = new NoticeRule();
noticeRule.setId(87584674384L);
noticeRule.setName("dispatch-1");
diff --git
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AlertDefineExcelImExportServiceTest.java
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AlertDefineExcelImExportServiceTest.java
index dd46b3e22..e775baea7 100644
---
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AlertDefineExcelImExportServiceTest.java
+++
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AlertDefineExcelImExportServiceTest.java
@@ -27,7 +27,6 @@ import java.util.List;
import org.apache.hertzbeat.alert.dto.AlertDefineDTO;
import org.apache.hertzbeat.alert.dto.ExportAlertDefineDTO;
import
org.apache.hertzbeat.alert.service.impl.AlertDefineExcelImExportServiceImpl;
-import org.apache.hertzbeat.common.entity.manager.TagItem;
import org.apache.hertzbeat.common.util.export.ExcelExportUtils;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
@@ -91,9 +90,6 @@ public class AlertDefineExcelImExportServiceTest {
assertTrue(alertDefineDTO.getPreset());
assertEquals("expr1", alertDefineDTO.getExpr());
assertEquals(10, alertDefineDTO.getTimes());
- assertEquals(1, alertDefineDTO.getTags().size());
- assertEquals("tag1", alertDefineDTO.getTags().get(0).getName());
- assertEquals("value1", alertDefineDTO.getTags().get(0).getValue());
assertTrue(alertDefineDTO.getEnable());
assertTrue(alertDefineDTO.getRecoverNotice());
assertEquals("template1", alertDefineDTO.getTemplate());
@@ -113,12 +109,6 @@ public class AlertDefineExcelImExportServiceTest {
alertDefineDTO.setExpr("expr1");
alertDefineDTO.setPriority((byte) 1);
alertDefineDTO.setTimes(10);
- List<TagItem> tags = new ArrayList<>();
- TagItem tagItem = new TagItem();
- tagItem.setName("tag1");
- tagItem.setValue("value1");
- tags.add(tagItem);
- alertDefineDTO.setTags(tags);
alertDefineDTO.setEnable(true);
alertDefineDTO.setRecoverNotice(true);
alertDefineDTO.setTemplate("template1");
diff --git
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/constants/CommonConstants.java
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/constants/CommonConstants.java
index 062adacb4..f4bdb3cbe 100644
---
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/constants/CommonConstants.java
+++
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/constants/CommonConstants.java
@@ -101,6 +101,11 @@ public interface CommonConstants {
* Alarm severity label key
*/
String LABEL_ALERT_SEVERITY = "severity";
+
+ /**
+ * Alarm severity fatal level
+ */
+ String LABEL_ALERT_FATAL = "fatal";
/**
* alarm severity emergency level
diff --git
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/Bulletin.java
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/Bulletin.java
index b0d724dd8..b98082296 100644
---
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/Bulletin.java
+++
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/Bulletin.java
@@ -74,12 +74,6 @@ public class Bulletin {
@Convert(converter = JsonMapListAttributeConverter.class)
private Map<String, List<String>> fields;
- @Schema(description = "Tags(status:success,env:prod)", example = "{name:
key1, value: value1}",
- accessMode = READ_WRITE)
- @Convert(converter = JsonTagListAttributeConverter.class)
- @Column(length = 2048)
- private List<TagItem> tags;
-
@Schema(title = "The creator of this record", example = "tom", accessMode
= READ_WRITE)
@CreatedBy
private String creator;
diff --git
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/JsonTagAttributeConverter.java
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/JsonTagAttributeConverter.java
deleted file mode 100644
index b3e21460a..000000000
---
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/JsonTagAttributeConverter.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.hertzbeat.common.entity.manager;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import jakarta.persistence.AttributeConverter;
-import jakarta.persistence.Converter;
-import org.apache.hertzbeat.common.util.JsonUtil;
-import org.springframework.stereotype.Component;
-
-/**
- * json str to tag item
- */
-@Converter
-@Component
-public class JsonTagAttributeConverter implements AttributeConverter<TagItem,
String> {
-
- @Override
- public String convertToDatabaseColumn(TagItem attribute) {
- return JsonUtil.toJson(attribute);
- }
-
- @Override
- public TagItem convertToEntityAttribute(String dbData) {
- TypeReference<TagItem> typeReference = new TypeReference<>() {};
- return JsonUtil.fromJson(dbData, typeReference);
- }
-}
diff --git
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/JsonTagListAttributeConverter.java
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/JsonTagListAttributeConverter.java
deleted file mode 100644
index 50ea299ff..000000000
---
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/JsonTagListAttributeConverter.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.hertzbeat.common.entity.manager;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import jakarta.persistence.AttributeConverter;
-import jakarta.persistence.Converter;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-import org.apache.hertzbeat.common.util.JsonUtil;
-import org.springframework.stereotype.Component;
-
-/**
- * json str to tag list
- */
-@Converter
-@Component
-public class JsonTagListAttributeConverter implements
AttributeConverter<List<TagItem>, String> {
-
- @Override
- public String convertToDatabaseColumn(List<TagItem> attribute) {
- return JsonUtil.toJson(attribute);
- }
-
- @Override
- public List<TagItem> convertToEntityAttribute(String dbData) {
- TypeReference<List<TagItem>> typeReference = new TypeReference<>() {};
- List<TagItem> tagItems = JsonUtil.fromJson(dbData, typeReference);
- if (tagItems == null) {
- TypeReference<Map<String, String>> mapTypeReference = new
TypeReference<>() {};
- Map<String, String> map = JsonUtil.fromJson(dbData,
mapTypeReference);
- if (map != null) {
- return map.entrySet().stream().map(entry -> new
TagItem(entry.getKey(), entry.getValue())).collect(Collectors.toList());
- } else {
- return null;
- }
- } else {
- return tagItems;
- }
-
- }
-}
diff --git
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/StatusPageComponent.java
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/StatusPageComponent.java
index 5fe82560c..0bf6d57dd 100644
---
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/StatusPageComponent.java
+++
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/StatusPageComponent.java
@@ -17,7 +17,9 @@
package org.apache.hertzbeat.common.entity.manager;
+import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_WRITE;
import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.persistence.Column;
import jakarta.persistence.Convert;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
@@ -27,10 +29,12 @@ import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotBlank;
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.entity.alerter.JsonMapAttributeConverter;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
@@ -64,10 +68,11 @@ public class StatusPageComponent {
@Schema(title = "component desc", example = "TanCloud Gateway")
private String description;
-
- @Schema(title = "component match single tag", example =
"{labelName:labelValue}")
- @Convert(converter = JsonTagAttributeConverter.class)
- private TagItem tag;
+
+ @Schema(title = "component label", example = "{env:test}", accessMode =
READ_WRITE)
+ @Convert(converter = JsonMapAttributeConverter.class)
+ @Column(length = 4096)
+ private Map<String, String> labels;
@Schema(title = "calculate status method: 0-auto 1-manual", example = "0")
private byte method;
diff --git
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/TagItem.java
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/TagItem.java
deleted file mode 100644
index dbd9c8a4a..000000000
---
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/TagItem.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.hertzbeat.common.entity.manager;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotBlank;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * tag item
- */
-@AllArgsConstructor
-@NoArgsConstructor
-@Data
-public class TagItem {
-
- @Schema(title = "Tag Name")
- @NotBlank
- private String name;
-
- @Schema(title = "Tag Value")
- private String value;
-
-}
diff --git
a/hertzbeat-common/src/test/java/org/apache/hertzbeat/common/util/JsonUtilTest.java
b/hertzbeat-common/src/test/java/org/apache/hertzbeat/common/util/JsonUtilTest.java
index a43989b2c..8908485ca 100644
---
a/hertzbeat-common/src/test/java/org/apache/hertzbeat/common/util/JsonUtilTest.java
+++
b/hertzbeat-common/src/test/java/org/apache/hertzbeat/common/util/JsonUtilTest.java
@@ -20,13 +20,10 @@ package org.apache.hertzbeat.common.util;
import static org.apache.hertzbeat.common.util.JsonUtil.isJsonStr;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.fasterxml.jackson.core.type.TypeReference;
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.hertzbeat.common.entity.manager.TagItem;
+import java.util.Map;
import org.junit.jupiter.api.Test;
/**
@@ -36,23 +33,16 @@ class JsonUtilTest {
@Test
void toJson() {
- List<TagItem> tagList = new ArrayList<>(4);
- TagItem proTag = new TagItem("test", "pro");
- tagList.add(proTag);
- tagList.add(new TagItem("test", "dev"));
-
-
assertEquals("[{\"name\":\"test\",\"value\":\"pro\"},{\"name\":\"test\",\"value\":\"dev\"}]",
- JsonUtil.toJson(tagList));
+ Map<String, String> map = Map.of("test", "pro");
+
+ assertEquals("{\"test\":\"pro\"}",
+ JsonUtil.toJson(map));
assertNull(JsonUtil.toJson(null));
}
@Test
void testFromJson() {
- String jsonStr =
"[{\"name\":\"test\",\"value\":\"pro\"},{\"name\":\"test\",\"value\":\"dev\"}]";
- List<TagItem> tagItems = JsonUtil.fromJson(jsonStr, new
TypeReference<>() {
- });
- assertEquals("[TagItem(name=test, value=pro), TagItem(name=test,
value=dev)]", tagItems.toString());
assertNull(JsonUtil.fromJson("", new TypeReference<>() {
}));
assertNull(JsonUtil.fromJson(null, new TypeReference<>() {
@@ -62,7 +52,6 @@ class JsonUtilTest {
assertNull(JsonUtil.fromJson(" ", String.class));
assertNull(JsonUtil.fromJson(" "));
assertNull(JsonUtil.fromJson(null));
- assertNotNull(JsonUtil.fromJson(jsonStr));
assertNull(JsonUtil.fromJson("invalid"));
}
diff --git
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/component/status/CalculateStatus.java
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/component/status/CalculateStatus.java
index ec37ea966..94a0d7ca0 100644
---
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/component/status/CalculateStatus.java
+++
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/component/status/CalculateStatus.java
@@ -18,8 +18,6 @@
package org.apache.hertzbeat.manager.component.status;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
-import jakarta.persistence.criteria.JoinType;
-import jakarta.persistence.criteria.ListJoin;
import jakarta.persistence.criteria.Predicate;
import java.time.Duration;
import java.time.Instant;
@@ -37,14 +35,11 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
import org.apache.hertzbeat.common.constants.CommonConstants;
import org.apache.hertzbeat.common.entity.manager.Monitor;
import org.apache.hertzbeat.common.entity.manager.StatusPageComponent;
import org.apache.hertzbeat.common.entity.manager.StatusPageHistory;
import org.apache.hertzbeat.common.entity.manager.StatusPageOrg;
-import org.apache.hertzbeat.common.entity.manager.Tag;
-import org.apache.hertzbeat.common.entity.manager.TagItem;
import org.apache.hertzbeat.manager.config.StatusProperties;
import org.apache.hertzbeat.manager.dao.MonitorDao;
import org.apache.hertzbeat.manager.dao.StatusPageComponentDao;
@@ -104,37 +99,34 @@ public class CalculateStatus {
List<StatusPageComponent> pageComponentList =
statusPageComponentDao.findByOrgId(orgId);
Set<Byte> stateSet = new HashSet<>(8);
for (StatusPageComponent component : pageComponentList) {
- byte state =
CommonConstants.STATUS_PAGE_COMPONENT_STATE_NORMAL;
+ byte state;
if (component.getMethod() ==
CommonConstants.STATUS_PAGE_CALCULATE_METHOD_MANUAL) {
state = component.getConfigState();
} else {
- TagItem tagItem = component.getTag();
- if (tagItem != null) {
- Specification<Monitor> specification = (root,
query, criteriaBuilder) -> {
- List<Predicate> andList = new
ArrayList<>();
- ListJoin<Monitor, Tag> tagJoin = root
- .join(root.getModel()
- .getList("tags",
Tag.class), JoinType.LEFT);
- if
(StringUtils.isNotBlank(tagItem.getValue())) {
-
andList.add(criteriaBuilder.equal(tagJoin.get("name"), tagItem.getName()));
-
andList.add(criteriaBuilder.equal(tagJoin.get("tagValue"), tagItem.getValue()));
- } else {
-
andList.add(criteriaBuilder.equal(tagJoin.get("name"), tagItem.getName()));
- }
- Predicate[] andPredicates = new
Predicate[andList.size()];
- Predicate andPredicate =
criteriaBuilder.and(andList.toArray(andPredicates));
- return
query.where(andPredicate).getRestriction();
- };
- List<Monitor> monitorList =
monitorDao.findAll(specification);
- state =
CommonConstants.STATUS_PAGE_COMPONENT_STATE_UNKNOWN;
- for (Monitor monitor : monitorList) {
- if (monitor.getStatus() ==
CommonConstants.MONITOR_DOWN_CODE) {
- state =
CommonConstants.STATUS_PAGE_COMPONENT_STATE_ABNORMAL;
- break;
- } else if (monitor.getStatus() ==
CommonConstants.MONITOR_UP_CODE) {
- state =
CommonConstants.STATUS_PAGE_COMPONENT_STATE_NORMAL;
- }
- }
+ Map<String, String> labels = component.getLabels();
+ if (labels == null || labels.isEmpty()) {
+ continue;
+ }
+ Specification<Monitor> specification = (root,
query, criteriaBuilder) -> {
+ List<Predicate> predicates = new ArrayList<>();
+ // create every label condition
+ labels.forEach((key, value) -> {
+ String pattern =
String.format("%%\"%s\":\"%s\"%%", key, value);
+
predicates.add(criteriaBuilder.like(root.get("labels"), pattern));
+ });
+
+ // use or connect them
+ return
criteriaBuilder.or(predicates.toArray(new Predicate[0]));
+ };
+ List<Monitor> monitorList =
monitorDao.findAll(specification);
+ state =
CommonConstants.STATUS_PAGE_COMPONENT_STATE_UNKNOWN;
+ for (Monitor monitor : monitorList) {
+ if (monitor.getStatus() ==
CommonConstants.MONITOR_DOWN_CODE) {
+ state =
CommonConstants.STATUS_PAGE_COMPONENT_STATE_ABNORMAL;
+ break;
+ } else if (monitor.getStatus() ==
CommonConstants.MONITOR_UP_CODE) {
+ state =
CommonConstants.STATUS_PAGE_COMPONENT_STATE_NORMAL;
+ }
}
}
stateSet.add(state);
diff --git a/web-app/src/app/layout/basic/widgets/notify.component.ts
b/web-app/src/app/layout/basic/widgets/notify.component.ts
index 2a45af50a..b65ee7662 100644
--- a/web-app/src/app/layout/basic/widgets/notify.component.ts
+++ b/web-app/src/app/layout/basic/widgets/notify.component.ts
@@ -206,7 +206,7 @@ export class HeaderNotifyComponent implements OnInit,
OnDestroy {
let item = {
id: alert.id,
avatar: '/assets/img/notification.svg',
- // title:
`${alert.tags?.monitorName}--${this.i18nSvc.fanyi(`alert.priority.${alert.priority}`)}`,
+ // title:
`${alert.tags?.monitorName}--${this.i18nSvc.fanyi(`alert.severity.${alert.severity}`)}`,
title: alert.content,
datetime: new Date(alert.activeAt).toLocaleString(),
color: 'blue',
diff --git a/web-app/src/app/pojo/Alert.ts b/web-app/src/app/pojo/Alert.ts
deleted file mode 100644
index b342ce8e7..000000000
--- a/web-app/src/app/pojo/Alert.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export class Alert {
- id!: number;
- target!: string;
- monitorId!: number;
- monitorName!: string;
- // alert level -- 0:high-emergency-red 1:medium-critical-orange
2:low-warning-yellow
- priority: number = 2;
- // alert status-- 0-to be processed 1-not reached the threshold 2-recover
3-processed
- status!: number;
- content!: string;
- // alarm times
- times!: number;
- firstAlarmTime!: number;
- lastAlarmTime!: number;
- tags!: Record<string, string>;
- gmtCreate!: number;
- gmtUpdate!: number;
- tmp!: any;
-}
diff --git a/web-app/src/app/pojo/AlertDefine.ts
b/web-app/src/app/pojo/AlertDefine.ts
index 93b0021b8..bfaf6dbf0 100644
--- a/web-app/src/app/pojo/AlertDefine.ts
+++ b/web-app/src/app/pojo/AlertDefine.ts
@@ -17,8 +17,6 @@
* under the License.
*/
-import { TagItem } from './NoticeRule';
-
export class AlertDefine {
id!: number;
name!: string;
@@ -30,7 +28,9 @@ export class AlertDefine {
// unit second
period: number = 300;
times: number = 3;
- tags!: TagItem[];
+ // severity: info, warning, critical, emergency, fatal
+ labels!: Record<string, string>;
+ annotations!: Record<string, string>;
enable: boolean = true;
template!: string;
creator!: string;
diff --git a/web-app/src/app/pojo/AlertSilence.ts
b/web-app/src/app/pojo/AlertSilence.ts
index d5d75dce3..444f4f180 100644
--- a/web-app/src/app/pojo/AlertSilence.ts
+++ b/web-app/src/app/pojo/AlertSilence.ts
@@ -17,8 +17,6 @@
* under the License.
*/
-import { TagItem } from './NoticeRule';
-
export class AlertSilence {
id!: number;
name!: string;
@@ -26,8 +24,7 @@ export class AlertSilence {
matchAll: boolean = true;
type: number = 0;
times!: number;
- priorities!: number[];
- tags!: TagItem[];
+ labels!: Record<string, string>;
days!: number[];
periodStart: Date = new Date();
periodEnd: Date = new Date();
diff --git a/web-app/src/app/pojo/Monitor.ts b/web-app/src/app/pojo/Monitor.ts
index 649bb67e8..2f42c7053 100644
--- a/web-app/src/app/pojo/Monitor.ts
+++ b/web-app/src/app/pojo/Monitor.ts
@@ -17,8 +17,6 @@
* under the License.
*/
-import { Tag } from './Tag';
-
export class Monitor {
id!: number;
name!: string;
@@ -34,5 +32,4 @@ export class Monitor {
modifier!: string;
gmtCreate!: number;
gmtUpdate!: number;
- tags!: Tag[];
}
diff --git a/web-app/src/app/pojo/NoticeRule.ts
b/web-app/src/app/pojo/NoticeRule.ts
index 65585b7cc..efdf73831 100644
--- a/web-app/src/app/pojo/NoticeRule.ts
+++ b/web-app/src/app/pojo/NoticeRule.ts
@@ -27,6 +27,7 @@ export class NoticeRule {
enable: boolean = true;
// forward all or not
filterAll: boolean = true;
+ labels!: Record<string, string>;
// filter alert level
priorities!: number[];
tags!: TagItem[];
diff --git a/web-app/src/app/pojo/StatusPageComponent.ts
b/web-app/src/app/pojo/StatusPageComponent.ts
index ac5552958..6afe004cb 100644
--- a/web-app/src/app/pojo/StatusPageComponent.ts
+++ b/web-app/src/app/pojo/StatusPageComponent.ts
@@ -24,7 +24,7 @@ export class StatusPageComponent {
orgId!: number;
name!: string;
description!: string;
- tag!: TagItem;
+ labels!: Record<string, string>;
// calculate status method: 0-auto 1-manual
method: number = 0;
// config state when use manual method: 0-Normal 1-Abnormal 2-unknown
diff --git
a/web-app/src/app/routes/alert/alert-center/alert-center.component.html
b/web-app/src/app/routes/alert/alert-center/alert-center.component.html
index 8870e4e26..c141e8c60 100644
--- a/web-app/src/app/routes/alert/alert-center/alert-center.component.html
+++ b/web-app/src/app/routes/alert/alert-center/alert-center.component.html
@@ -40,10 +40,10 @@
[(ngModel)]="filterPriority"
(ngModelChange)="loadAlertsTable()"
>
- <nz-option [nzLabel]="'alert.priority.all' | i18n"
[nzValue]="9"></nz-option>
- <nz-option [nzLabel]="'alert.priority.2' | i18n"
[nzValue]="2"></nz-option>
- <nz-option [nzLabel]="'alert.priority.1' | i18n"
[nzValue]="1"></nz-option>
- <nz-option [nzLabel]="'alert.priority.0' | i18n"
[nzValue]="0"></nz-option>
+ <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"
diff --git
a/web-app/src/app/routes/alert/alert-notice/alert-notice.component.html
b/web-app/src/app/routes/alert/alert-notice/alert-notice.component.html
index f81609c4e..436b7a37d 100644
--- a/web-app/src/app/routes/alert/alert-notice/alert-notice.component.html
+++ b/web-app/src/app/routes/alert/alert-notice/alert-notice.component.html
@@ -436,45 +436,9 @@
</nz-form-control>
</nz-form-item>
<nz-form-item *ngIf="!rule.filterAll">
- <nz-form-label nzFor="tags" nzSpan="7">{{ 'alert.notice.rule.tag' |
i18n }}</nz-form-label>
+ <nz-form-label nzFor="labels" nzSpan="7">{{ 'alert.notice.rule.tag' |
i18n }}</nz-form-label>
<nz-form-control nzSpan="12">
- <nz-select
- (nzOpenChange)="loadTagsOption()"
- [(ngModel)]="filterTags"
- [nzDisabled]="rule.filterAll"
- [nzMaxTagCount]="5"
- [nzOptions]="tagsOption"
- id="tags"
- name="tags"
- nzAllowClear
- nzMode="multiple"
- [nzPlaceHolder]="'alert.notice.rule.tag.placeholder' | i18n"
- nzShowSearch
- required
- >
- </nz-select>
- </nz-form-control>
- </nz-form-item>
- <nz-form-item *ngIf="!rule.filterAll">
- <nz-form-label nzFor="priorities" nzSpan="7">{{
'alert.notice.rule.priority' | i18n }}</nz-form-label>
- <nz-form-control nzSpan="12">
- <nz-select
- (ngModelChange)="onPrioritiesChange()"
- [(ngModel)]="rule.priorities"
- [nzDisabled]="rule.filterAll"
- id="priorities"
- name="priorities"
- nzAllowClear
- nzMode="multiple"
- [nzPlaceHolder]="'alert.notice.rule.priority.placeholder' | i18n"
- nzShowSearch
- required
- >
- <nz-option [nzLabel]="'alert.priority.all' | i18n"
[nzValue]="9"></nz-option>
- <nz-option [nzLabel]="'alert.priority.0' | i18n"
[nzValue]="0"></nz-option>
- <nz-option [nzLabel]="'alert.priority.1' | i18n"
[nzValue]="1"></nz-option>
- <nz-option [nzLabel]="'alert.priority.2' | i18n"
[nzValue]="2"></nz-option>
- </nz-select>
+ <app-labels-input [(ngModel)]="rule.labels" name="labels"
required></app-labels-input>
</nz-form-control>
</nz-form-item>
<nz-form-item>
diff --git
a/web-app/src/app/routes/alert/alert-setting/alert-setting.component.html
b/web-app/src/app/routes/alert/alert-setting/alert-setting.component.html
index 8b51f5bca..a0ed89183 100644
--- a/web-app/src/app/routes/alert/alert-setting/alert-setting.component.html
+++ b/web-app/src/app/routes/alert/alert-setting/alert-setting.component.html
@@ -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.priority' | i18n }}</th>
+ <th nzAlign="center" nzWidth="8%">{{ 'alert.severity' | i18n }}</th>
<th nzAlign="center" nzWidth="8%">{{ 'alert.setting.enable' | i18n
}}</th>
<th nzAlign="center" nzWidth="8%">{{ 'common.edit' | i18n }}</th>
</tr>
@@ -120,17 +120,17 @@
</td>
<td nzAlign="center">{{ data.template }}</td>
<td nzAlign="center">
- <nz-tag *ngIf="data.priority == 0" nzColor="red">
+ <nz-tag *ngIf="severity == 'emergency'" nzColor="red">
<i nz-icon nzType="bell" nzTheme="outline"></i>
- <span>{{ 'alert.priority.0' | i18n }}</span>
+ <span>{{ 'alert.severity.0' | i18n }}</span>
</nz-tag>
- <nz-tag *ngIf="data.priority == 1" nzColor="orange">
+ <nz-tag *ngIf="severity == 'critical'" nzColor="orange">
<i nz-icon nzType="bell" nzTheme="outline"></i>
- <span>{{ 'alert.priority.1' | i18n }}</span>
+ <span>{{ 'alert.severity.1' | i18n }}</span>
</nz-tag>
- <nz-tag *ngIf="data.priority == 2" nzColor="yellow">
+ <nz-tag *ngIf="severity == 'warning'" nzColor="yellow">
<i nz-icon nzType="bell" nzTheme="outline"></i>
- <span>{{ 'alert.priority.2' | i18n }}</span>
+ <span>{{ 'alert.severity.2' | i18n }}</span>
</nz-tag>
</td>
<td nzAlign="center">
@@ -481,19 +481,20 @@
</nz-form-control>
</nz-form-item>
<nz-form-item>
- <nz-form-label nzSpan="7" nzRequired="true" nzFor="priority"
[nzTooltipTitle]="'alert.setting.priority.tip' | i18n">
- {{ 'alert.priority' | i18n }}
+ <nz-form-label nzSpan="7" nzRequired="true" nzFor="severity"
[nzTooltipTitle]="'alert.setting.priority.tip' | i18n">
+ {{ 'alert.severity' | i18n }}
</nz-form-label>
<nz-form-control nzSpan="12" [nzErrorTip]="'validation.required' |
i18n">
<nz-select
- [(ngModel)]="define.priority"
+ [(ngModel)]="severity"
+ (ngModelChange)="onSeverityChange()"
[nzPlaceHolder]="'alert.notice.rule.priority.placeholder' | i18n"
- name="priority"
- id="priority"
+ name="severity"
+ id="severity"
>
- <nz-option [nzValue]="0" [nzLabel]="'alert.priority.0' |
i18n"></nz-option>
- <nz-option [nzValue]="1" [nzLabel]="'alert.priority.1' |
i18n"></nz-option>
- <nz-option [nzValue]="2" [nzLabel]="'alert.priority.2' |
i18n"></nz-option>
+ <nz-option [nzValue]="'emergency'" [nzLabel]="'alert.severity.0' |
i18n"></nz-option>
+ <nz-option [nzValue]="'critical'" [nzLabel]="'alert.severity.1' |
i18n"></nz-option>
+ <nz-option [nzValue]="'warning'" [nzLabel]="'alert.severity.2' |
i18n"></nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
@@ -542,17 +543,17 @@
</nz-form-control>
</nz-form-item>
<nz-form-item>
- <nz-form-label nzSpan="7" [nzFor]="'tags'"
[nzTooltipTitle]="'tag.bind.tip' | i18n">{{ 'tag.bind' | i18n }}
</nz-form-label>
- <nz-form-control nzSpan="8" [nzErrorTip]="'validation.required' |
i18n">
- <app-form-field
- [item]="{
- field: 'tags',
- type: 'tags-selection'
- }"
- [extra]="{ tag_mode: 'closeable' }"
- [name]="'tags'"
- [(ngModel)]="define.tags"
- />
+ <nz-form-label nzSpan="7" [nzFor]="'labels'"
[nzTooltipTitle]="'label.bind.tip' | i18n">{{ 'label.bind' | i18n }}
</nz-form-label>
+ <nz-form-control nzSpan="12">
+ <app-labels-input [(ngModel)]="define.labels"
name="labels"></app-labels-input>
+ </nz-form-control>
+ </nz-form-item>
+ <nz-form-item>
+ <nz-form-label nzSpan="7" [nzFor]="'annotations'"
[nzTooltipTitle]="'annotation.bind.tip' | i18n"
+ >{{ 'annotation.bind' | i18n }}
+ </nz-form-label>
+ <nz-form-control nzSpan="12">
+ <app-labels-input [(ngModel)]="define.annotations"
name="annotations"></app-labels-input>
</nz-form-control>
</nz-form-item>
<nz-form-item>
diff --git
a/web-app/src/app/routes/alert/alert-setting/alert-setting.component.ts
b/web-app/src/app/routes/alert/alert-setting/alert-setting.component.ts
index 41f69ea16..b6b3cb1d7 100644
--- a/web-app/src/app/routes/alert/alert-setting/alert-setting.component.ts
+++ b/web-app/src/app/routes/alert/alert-setting/alert-setting.component.ts
@@ -247,7 +247,6 @@ export class AlertSettingComponent implements OnInit {
this.isSelectTypeModalVisible = false;
this.define = new AlertDefine();
this.define.type = type;
- this.define.tags = [];
this.userExpr = '';
this.selectedMonitorIds = new Set<number>();
// Set default period for periodic alert
@@ -469,6 +468,7 @@ export class AlertSettingComponent implements OnInit {
currentMetrics: any[] = [];
isExpr = false;
userExpr!: string;
+ severity!: string;
editAlertDefine(alertDefineId: number) {
if (this.isLoadingEdit !== -1) return;
@@ -489,6 +489,9 @@ export class AlertSettingComponent implements OnInit {
message => {
if (message.code === 0) {
this.define = message.data;
+ if (this.define.labels && this.define.labels['severity']) {
+ this.severity = this.define.labels['severity'];
+ }
// Set default period for periodic alert if not set
if (this.define.type === 'periodic' && !this.define.period) {
this.define.period = 300;
@@ -512,10 +515,6 @@ export class AlertSettingComponent implements OnInit {
}
});
}
- // Initialize tags array if undefined
- if (this.define.tags == undefined) {
- this.define.tags = [];
- }
} else {
this.notifySvc.error(this.i18nSvc.fanyi('common.notify.monitor-fail'),
message.msg);
}
@@ -853,6 +852,13 @@ export class AlertSettingComponent implements OnInit {
}
}
+ onSeverityChange() {
+ if (!this.define.labels) {
+ this.define.labels = {};
+ }
+ this.define.labels['severity'] = this.severity;
+ }
+
onManageModalCancel() {
this.cascadeValues = [];
this.isExpr = false;
diff --git
a/web-app/src/app/routes/alert/alert-silence/alert-silence.component.html
b/web-app/src/app/routes/alert/alert-silence/alert-silence.component.html
index c57f5e7d0..68ccef7a7 100755
--- a/web-app/src/app/routes/alert/alert-silence/alert-silence.component.html
+++ b/web-app/src/app/routes/alert/alert-silence/alert-silence.component.html
@@ -79,7 +79,6 @@
<th nzAlign="center" nzLeft nzWidth="3%" [(nzChecked)]="checkedAll"
(nzCheckedChange)="onAllChecked($event)"></th>
<th nzAlign="center" nzWidth="8%">{{ 'alert.silence.name' | i18n }}</th>
<th nzAlign="center" nzWidth="14%">{{ 'alert.silence.type' | i18n }}</th>
- <th nzAlign="center" nzWidth="14%">{{ 'alert.silence.tags' | i18n }}</th>
<th nzAlign="center" nzWidth="8%">{{ 'alert.silence.times' | i18n }}</th>
<th nzAlign="center" nzWidth="8%">{{ 'alert.silence.enable' | i18n
}}</th>
<th nzAlign="center" nzWidth="15%">{{ 'common.edit' | i18n }}</th>
@@ -101,16 +100,6 @@
<span>{{ 'alert.silence.type.cyc' | i18n }}</span>
</nz-tag>
</td>
- <td nzAlign="center" *ngIf="!data.matchAll">
- <nz-tag nzColor="processing" style="margin-top: 2px" *ngFor="let tag
of data.tags; let i = index">
- {{ sliceTagName(tag) }}
- </nz-tag>
- </td>
- <td nzAlign="center" *ngIf="data.matchAll">
- <nz-tag nzColor="warning">
- {{ 'alert.silence.match-all' | i18n }}
- </nz-tag>
- </td>
<td nzAlign="center">
<nz-tag nzColor="processing">
<i nz-icon nzType="audio-muted" nzTheme="outline"></i>
@@ -182,46 +171,9 @@
</nz-form-control>
</nz-form-item>
<nz-form-item *ngIf="!silence.matchAll">
- <nz-form-label nzSpan="7" nzFor="tags" nzRequired="true">{{
'alert.silence.tags' | i18n }}</nz-form-label>
- <nz-form-control nzSpan="12" [nzErrorTip]="'validation.required' |
i18n">
- <nz-select
- [(ngModel)]="matchTags"
- [nzDisabled]="silence.matchAll"
- (nzOpenChange)="loadTagsOption()"
- [nzOptions]="tagsOption"
- [nzMaxTagCount]="5"
- [nzDropdownMatchSelectWidth]="false"
- nzShowSearch
- nzMode="multiple"
- nzAllowClear
- [nzPlaceHolder]="'alert.notice.rule.tag.placeholder' | i18n"
- required
- name="tags"
- id="tags"
- >
- </nz-select>
- </nz-form-control>
- </nz-form-item>
- <nz-form-item *ngIf="!silence.matchAll">
- <nz-form-label nzSpan="7" nzFor="priorities" nzRequired="true">{{
'alert.silence.priority' | i18n }}</nz-form-label>
+ <nz-form-label nzSpan="7" nzFor="labels" nzRequired="true">{{
'alert.silence.labels' | i18n }}</nz-form-label>
<nz-form-control nzSpan="12" [nzErrorTip]="'validation.required' |
i18n">
- <nz-select
- [(ngModel)]="silence.priorities"
- [nzDisabled]="silence.matchAll"
- (ngModelChange)="onPrioritiesChange()"
- nzShowSearch
- nzMode="multiple"
- nzAllowClear
- [nzPlaceHolder]="'alert.notice.rule.priority.placeholder' | i18n"
- required
- name="priorities"
- id="priorities"
- >
- <nz-option [nzLabel]="'alert.priority.all' | i18n"
[nzValue]="9"></nz-option>
- <nz-option [nzLabel]="'alert.priority.0' | i18n"
[nzValue]="0"></nz-option>
- <nz-option [nzLabel]="'alert.priority.1' | i18n"
[nzValue]="1"></nz-option>
- <nz-option [nzLabel]="'alert.priority.2' | i18n"
[nzValue]="2"></nz-option>
- </nz-select>
+ <app-labels-input [(ngModel)]="silence.labels" name="labels"
required></app-labels-input>
</nz-form-control>
</nz-form-item>
<nz-form-item>
diff --git
a/web-app/src/app/routes/alert/alert-silence/alert-silence.component.ts
b/web-app/src/app/routes/alert/alert-silence/alert-silence.component.ts
index b25f33577..baf32d84d 100644
--- a/web-app/src/app/routes/alert/alert-silence/alert-silence.component.ts
+++ b/web-app/src/app/routes/alert/alert-silence/alert-silence.component.ts
@@ -29,7 +29,6 @@ import { finalize } from 'rxjs/operators';
import { AlertSilence } from '../../../pojo/AlertSilence';
import { TagItem } from '../../../pojo/NoticeRule';
import { AlertSilenceService } from '../../../service/alert-silence.service';
-import { TagService } from '../../../service/tag.service';
@Component({
selector: 'app-alert-silence',
@@ -41,7 +40,6 @@ export class AlertSilenceComponent implements OnInit {
private modal: NzModalService,
private notifySvc: NzNotificationService,
private alertSilenceService: AlertSilenceService,
- private tagService: TagService,
@Inject(ALAIN_I18N_TOKEN) private i18nSvc: I18NService
) {}
@@ -208,8 +206,6 @@ export class AlertSilenceComponent implements OnInit {
isManageModalOkLoading = false;
isManageModalAdd = true;
silence: AlertSilence = new AlertSilence();
- searchTag!: string;
- tagsOption: any[] = [];
matchTags: string[] = [];
silenceDates!: Date[];
dayCheckOptions = [
@@ -269,19 +265,6 @@ export class AlertSilenceComponent implements OnInit {
this.isManageModalVisible = true;
this.isManageModalAdd = false;
this.matchTags = [];
- if (this.silence.tags != undefined) {
- this.silence.tags.forEach(item => {
- let tag = `${item.name}`;
- if (item.value != undefined) {
- tag = `${tag}:${item.value}`;
- }
- this.matchTags.push(tag);
- this.tagsOption.push({
- value: tag,
- label: tag
- });
- });
- }
} else {
this.notifySvc.error(this.i18nSvc.fanyi('common.notify.edit-fail'),
message.msg);
}
@@ -301,22 +284,6 @@ export class AlertSilenceComponent implements OnInit {
});
return;
}
- this.silence.tags = [];
- this.matchTags.forEach(tag => {
- let tmp: string[] = tag.split(':');
- let tagItem = new TagItem();
- if (tmp.length == 1) {
- tagItem.name = tmp[0];
- this.silence.tags.push(tagItem);
- } else if (tmp.length == 2) {
- tagItem.name = tmp[0];
- tagItem.value = tmp[1];
- this.silence.tags.push(tagItem);
- }
- });
- if (this.silence.priorities != undefined) {
- this.silence.priorities = this.silence.priorities.filter(item => item !=
null && item != 9);
- }
if (this.silence.type === 0) {
this.silence.periodStart = this.silenceDates[0];
this.silence.periodEnd = this.silenceDates[1];
@@ -375,56 +342,4 @@ export class AlertSilenceComponent implements OnInit {
);
}
}
-
- onPrioritiesChange() {
- if (this.silence.priorities != undefined) {
- let isAll = false;
- this.silence.priorities.forEach(item => {
- if (item == 9) {
- isAll = true;
- }
- });
- if (isAll) {
- this.silence.priorities = [9, 0, 1, 2];
- }
- }
- }
-
- loadTagsOption() {
- let tagsInit$ = this.tagService.loadTags(this.searchTag, undefined, 0,
1000).subscribe(
- message => {
- if (message.code === 0) {
- let page = message.data;
- this.tagsOption = [];
- if (page.content != undefined) {
- page.content.forEach(item => {
- let tag = `${item.name}`;
- if (item.tagValue != undefined) {
- tag = `${tag}:${item.tagValue}`;
- }
- this.tagsOption.push({
- value: tag,
- label: tag
- });
- });
- }
- } else {
- console.warn(message.msg);
- }
- tagsInit$.unsubscribe();
- },
- error => {
- tagsInit$.unsubscribe();
- console.error(error.msg);
- }
- );
- }
-
- sliceTagName(tag: any): string {
- if (tag.value != undefined && tag.value.trim() != '') {
- return `${tag.name}:${tag.value}`;
- } else {
- return tag.name;
- }
- }
}
diff --git a/web-app/src/app/routes/dashboard/dashboard.component.html
b/web-app/src/app/routes/dashboard/dashboard.component.html
index a6e226f64..59e37eddd 100644
--- a/web-app/src/app/routes/dashboard/dashboard.component.html
+++ b/web-app/src/app/routes/dashboard/dashboard.component.html
@@ -398,17 +398,17 @@
<nz-timeline nzMode="left">
<nz-timeline-item *ngFor="let alert of alerts; let i = index"
[nzLabel]="(alert.activeAt | date : 'YYYY-MM-dd HH:mm:ss')?.trim()">
<p style="font-weight: 400">
- <!-- <nz-tag *ngIf="alert.priority == 0"
nzColor="red">-->
+ <!-- <nz-tag *ngIf="alert.severity == 0"
nzColor="red">-->
<!-- <i nz-icon nzType="bell"
nzTheme="outline"></i>-->
- <!-- <span>{{ 'alert.priority.0' | i18n
}}</span>-->
+ <!-- <span>{{ 'alert.severity.0' | i18n
}}</span>-->
<!-- </nz-tag>-->
- <!-- <nz-tag *ngIf="alert.priority == 1"
nzColor="orange">-->
+ <!-- <nz-tag *ngIf="alert.severity == 1"
nzColor="orange">-->
<!-- <i nz-icon nzType="bell"
nzTheme="outline"></i>-->
- <!-- <span>{{ 'alert.priority.1' | i18n
}}</span>-->
+ <!-- <span>{{ 'alert.severity.1' | i18n
}}</span>-->
<!-- </nz-tag>-->
- <!-- <nz-tag *ngIf="alert.priority == 2"
nzColor="yellow">-->
+ <!-- <nz-tag *ngIf="alert.severity == 2"
nzColor="yellow">-->
<!-- <i nz-icon nzType="bell"
nzTheme="outline"></i>-->
- <!-- <span>{{ 'alert.priority.2' | i18n
}}</span>-->
+ <!-- <span>{{ 'alert.severity.2' | i18n
}}</span>-->
<!-- </nz-tag>-->
<!-- <span>[{{ alert.tags.monitorName }}] </span>-->
{{ alert.content }}
diff --git a/web-app/src/app/routes/dashboard/dashboard.component.ts
b/web-app/src/app/routes/dashboard/dashboard.component.ts
index 575fc6503..0c60e8688 100644
--- a/web-app/src/app/routes/dashboard/dashboard.component.ts
+++ b/web-app/src/app/routes/dashboard/dashboard.component.ts
@@ -27,7 +27,6 @@ import { NzMessageService } from 'ng-zorro-antd/message';
import { fromEvent } from 'rxjs';
import { finalize } from 'rxjs/operators';
-import { Alert } from '../../pojo/Alert';
import { AppCount } from '../../pojo/AppCount';
import { CollectorSummary } from '../../pojo/CollectorSummary';
import { SingleAlert } from '../../pojo/SingleAlert';
@@ -299,7 +298,7 @@ export class DashboardComponent implements OnInit,
OnDestroy {
},
xAxis: {
type: 'category',
- data: [this.i18nSvc.fanyi('alert.priority.2'),
this.i18nSvc.fanyi('alert.priority.1'), this.i18nSvc.fanyi('alert.priority.0')]
+ data: [this.i18nSvc.fanyi('alert.severity.2'),
this.i18nSvc.fanyi('alert.severity.1'), this.i18nSvc.fanyi('alert.severity.0')]
},
yAxis: {
type: 'value'
diff --git
a/web-app/src/app/routes/monitor/monitor-edit/monitor-edit.component.ts
b/web-app/src/app/routes/monitor/monitor-edit/monitor-edit.component.ts
index bd313128f..5eae28f83 100644
--- a/web-app/src/app/routes/monitor/monitor-edit/monitor-edit.component.ts
+++ b/web-app/src/app/routes/monitor/monitor-edit/monitor-edit.component.ts
@@ -92,9 +92,6 @@ export class MonitorEditComponent implements OnInit {
});
this.paramValueMap = paramValueMap;
}
- if (this.monitor.tags == undefined) {
- this.monitor.tags = [];
- }
} else {
console.warn(message.msg);
this.notifySvc.error(this.i18nSvc.fanyi('monitors.not-found'),
message.msg);
diff --git
a/web-app/src/app/routes/monitor/monitor-form/monitor-form.component.html
b/web-app/src/app/routes/monitor/monitor-form/monitor-form.component.html
index d721ff16d..601688714 100644
--- a/web-app/src/app/routes/monitor/monitor-form/monitor-form.component.html
+++ b/web-app/src/app/routes/monitor/monitor-form/monitor-form.component.html
@@ -129,16 +129,18 @@
</nz-form-item>
<nz-form-item>
- <nz-form-label nzSpan="7" [nzFor]="'tags'"
[nzTooltipTitle]="'tag.bind.tip' | i18n">{{ 'tag.bind' | i18n }}
</nz-form-label>
+ <nz-form-label nzSpan="7" [nzFor]="'labels'"
[nzTooltipTitle]="'label.bind.tip' | i18n">{{ 'label.bind' | i18n }}
</nz-form-label>
<nz-form-control nzSpan="8" [nzErrorTip]="'validation.required' |
i18n">
- <app-form-field
- [item]="{
- field: 'tags',
- type: 'tags-selection'
- }"
- [name]="'tags'"
- [(ngModel)]="monitor.tags"
- />
+ <app-labels-input [(ngModel)]="monitor.labels"
name="labels"></app-labels-input>
+ </nz-form-control>
+ </nz-form-item>
+
+ <nz-form-item>
+ <nz-form-label nzSpan="7" [nzFor]="'annotation'"
[nzTooltipTitle]="'annotation.bind.tip' | i18n"
+ >{{ 'annotation.bind' | i18n }}
+ </nz-form-label>
+ <nz-form-control nzSpan="8" [nzErrorTip]="'validation.required' |
i18n">
+ <app-labels-input [(ngModel)]="monitor.annotations"
name="annotation"></app-labels-input>
</nz-form-control>
</nz-form-item>
diff --git
a/web-app/src/app/routes/monitor/monitor-form/monitor-form.component.ts
b/web-app/src/app/routes/monitor/monitor-form/monitor-form.component.ts
index e08653f57..b301f713d 100644
--- a/web-app/src/app/routes/monitor/monitor-form/monitor-form.component.ts
+++ b/web-app/src/app/routes/monitor/monitor-form/monitor-form.component.ts
@@ -24,6 +24,7 @@ import { ALAIN_I18N_TOKEN } from '@delon/theme';
import { NzNotificationService } from 'ng-zorro-antd/notification';
import { Collector } from '../../../pojo/Collector';
+import { Monitor } from '../../../pojo/Monitor';
import { Param } from '../../../pojo/Param';
import { ParamDefine } from '../../../pojo/ParamDefine';
@@ -33,7 +34,7 @@ import { ParamDefine } from '../../../pojo/ParamDefine';
styleUrls: ['./monitor-form.component.less']
})
export class MonitorFormComponent implements OnChanges {
- @Input() monitor!: any;
+ @Input() monitor!: Monitor;
@Input() grafanaDashboard!: any;
@Input() loading!: boolean;
@Input() loadingTip!: string;
diff --git
a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html
b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html
index 35cba1480..84620da17 100644
--- a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html
+++ b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html
@@ -150,7 +150,7 @@
<th nzAlign="center" nzWidth="10%" nzColumnKey="status"
[nzSortFn]="true">{{ 'monitor.status' | i18n }}</th>
<th nzAlign="center" nzWidth="12%">{{ 'monitor.host' | i18n }}</th>
<th nzAlign="center" nzWidth="10%">{{ 'monitor.app' | i18n }}</th>
- <th nzAlign="center" nzWidth="21%">{{ 'tag' | i18n }}</th>
+ <th nzAlign="center" nzWidth="21%">{{ 'label' | i18n }}</th>
<th nzAlign="center" nzWidth="14%" nzColumnKey="gmtUpdate"
[nzSortFn]="true">{{ 'common.edit-time' | i18n }}</th>
<th nzAlign="center" nzWidth="10%">{{ 'common.edit' | i18n }}</th>
</tr>
@@ -201,11 +201,9 @@
</a>
</td>
<td nzAlign="left">
- <a *ngFor="let tag of data?.tags; let i = index"
routerLink="/monitors" [queryParams]="{ tag: sliceTagName(tag) }">
- <nz-tag style="margin-top: 2px" [nzColor]="tag?.color"
class="hoverClass">
- {{ sliceTagName(tag) }}
- </nz-tag>
- </a>
+ <nz-tag *ngFor="let label of data.labels | keyvalue"
style="margin-top: 2px" [nzColor]="getLabelColor(label.key)">
+ {{ label.key }}:{{ label.value }}
+ </nz-tag>
</td>
<td nzAlign="center">{{ (data.gmtUpdate ? data.gmtUpdate :
data.gmtCreate) | date : 'YYYY-MM-dd HH:mm:ss' }}</td>
<td nzAlign="center">
diff --git
a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.ts
b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.ts
index 1184a6bbd..79781adb7 100644
--- a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.ts
+++ b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.ts
@@ -594,5 +594,19 @@ export class MonitorListComponent implements OnInit,
OnDestroy {
);
}
- protected readonly sliceTagName = formatTagName;
+ getLabelColor(key: string): string {
+ const colors = ['blue', 'green', 'orange', 'purple', 'cyan'];
+ const index = Math.abs(this.hashString(key)) % colors.length;
+ return colors[index];
+ }
+
+ private hashString(str: string): number {
+ let hash = 0;
+ for (let i = 0; i < str.length; i++) {
+ const char = str.charCodeAt(i);
+ hash = (hash << 5) - hash + char;
+ hash = hash & hash;
+ }
+ return hash;
+ }
}
diff --git
a/web-app/src/app/routes/monitor/monitor-new/monitor-new.component.ts
b/web-app/src/app/routes/monitor/monitor-new/monitor-new.component.ts
index 03a20449a..e626afa4d 100644
--- a/web-app/src/app/routes/monitor/monitor-new/monitor-new.component.ts
+++ b/web-app/src/app/routes/monitor/monitor-new/monitor-new.component.ts
@@ -64,7 +64,6 @@ export class MonitorNewComponent implements OnInit {
private collectorSvc: CollectorService
) {
this.monitor = new Monitor();
- this.monitor.tags = [];
this.grafanaDashboard = new GrafanaDashboard();
}
diff --git a/web-app/src/app/routes/setting/setting.module.ts
b/web-app/src/app/routes/setting/setting.module.ts
index 08d23546e..108221d3b 100644
--- a/web-app/src/app/routes/setting/setting.module.ts
+++ b/web-app/src/app/routes/setting/setting.module.ts
@@ -26,8 +26,10 @@ import { NzCascaderModule } from 'ng-zorro-antd/cascader';
import { NzCodeEditorModule } from 'ng-zorro-antd/code-editor';
import { NzCollapseModule } from 'ng-zorro-antd/collapse';
import { NzDividerModule } from 'ng-zorro-antd/divider';
+import { NzDropDownModule } from 'ng-zorro-antd/dropdown';
import { NzLayoutModule } from 'ng-zorro-antd/layout';
import { NzListModule } from 'ng-zorro-antd/list';
+import { NzPaginationComponent } from 'ng-zorro-antd/pagination';
import { NzRadioModule } from 'ng-zorro-antd/radio';
import { NzSwitchModule } from 'ng-zorro-antd/switch';
import { NzTagModule } from 'ng-zorro-antd/tag';
@@ -74,7 +76,9 @@ const COMPONENTS: Array<Type<void>> = [
ClipboardModule,
NzBadgeModule,
NzRadioModule,
- NzUploadComponent
+ NzUploadComponent,
+ NzPaginationComponent,
+ NzDropDownModule
],
declarations: COMPONENTS
})
diff --git a/web-app/src/app/routes/setting/status/status.component.html
b/web-app/src/app/routes/setting/status/status.component.html
index 06962fd73..5aee1e288 100644
--- a/web-app/src/app/routes/setting/status/status.component.html
+++ b/web-app/src/app/routes/setting/status/status.component.html
@@ -194,11 +194,9 @@
</nz-tag>
</td>
<td nzAlign="center">
- <a routerLink="/monitors" [queryParams]="{ tag:
sliceTagName(data.tag) }">
- <nz-tag class="hoverClass">
- {{ sliceTagName(data.tag) }}
- </nz-tag>
- </a>
+ <nz-tag *ngFor="let label of data.labels | keyvalue"
style="margin-top: 2px" [nzColor]="getLabelColor(label.key)">
+ {{ label.key }}:{{ label.value }}
+ </nz-tag>
</td>
<td nzAlign="center">{{ data.gmtUpdate | date : 'YYYY-MM-dd
HH:mm:ss' }}</td>
<td nzAlign="center">
@@ -375,19 +373,7 @@
'status.component.tag' | i18n
}}</nz-form-label>
<nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.required' |
i18n">
- <nz-select
- [(ngModel)]="matchTag"
- (nzOpenChange)="loadTagsOption()"
- [nzOptions]="tagsOption"
- [nzMaxTagCount]="5"
- [nzDropdownMatchSelectWidth]="false"
- nzShowSearch
- [nzPlaceHolder]="'alert.notice.rule.tag.placeholder' | i18n"
- required
- name="tag"
- id="tag"
- >
- </nz-select>
+ <app-labels-input [(ngModel)]="currentStatusComponent.labels"
name="sourceLabels" required></app-labels-input>
</nz-form-control>
</nz-form-item>
<nz-form-item *ngIf="currentStatusComponent.method == 1">
diff --git a/web-app/src/app/routes/setting/status/status.component.ts
b/web-app/src/app/routes/setting/status/status.component.ts
index 1258c2c00..d7128996b 100644
--- a/web-app/src/app/routes/setting/status/status.component.ts
+++ b/web-app/src/app/routes/setting/status/status.component.ts
@@ -26,13 +26,11 @@ import { NzNotificationService } from
'ng-zorro-antd/notification';
import { switchMap } from 'rxjs';
import { Message } from '../../../pojo/Message';
-import { TagItem } from '../../../pojo/NoticeRule';
import { StatusPageComponent } from '../../../pojo/StatusPageComponent';
import { StatusPageIncident } from '../../../pojo/StatusPageIncident';
import { StatusPageIncidentContent } from
'../../../pojo/StatusPageIncidentContent';
import { StatusPageOrg } from '../../../pojo/StatusPageOrg';
import { StatusPageService } from '../../../service/status-page.service';
-import { TagService } from '../../../service/tag.service';
@Component({
selector: 'app-status',
@@ -44,7 +42,6 @@ export class StatusComponent implements OnInit {
private notifySvc: NzNotificationService,
private modal: NzModalService,
private statusPageService: StatusPageService,
- private tagService: TagService,
@Inject(ALAIN_I18N_TOKEN) private i18nSvc: I18NService
) {}
@@ -70,8 +67,6 @@ export class StatusComponent implements OnInit {
isIncidentModalAdd: boolean = true;
search!: string;
- tagsOption: any[] = [];
- matchTag: string = '';
ngOnInit(): void {
this.loadStatusPageConfig();
@@ -182,7 +177,6 @@ export class StatusComponent implements OnInit {
onNewStatusComponent() {
this.isComponentModalAdd = true;
this.currentStatusComponent = new StatusPageComponent();
- this.matchTag = '';
this.currentComponentVisible = true;
}
@@ -220,13 +214,6 @@ export class StatusComponent implements OnInit {
onEditOneComponent(data: StatusPageComponent) {
this.isComponentModalAdd = false;
this.currentStatusComponent = { ...data };
- if (this.currentStatusComponent.tag != undefined) {
- this.matchTag = this.sliceTagName(this.currentStatusComponent.tag);
- this.tagsOption.push({
- value: this.matchTag,
- label: this.matchTag
- });
- }
this.currentComponentVisible = true;
}
@@ -304,17 +291,6 @@ export class StatusComponent implements OnInit {
});
return;
}
- if (this.matchTag != undefined && this.matchTag.trim() != '') {
- let tmp: string[] = this.matchTag.split(':');
- let tagItem = new TagItem();
- if (tmp.length == 1) {
- tagItem.name = tmp[0];
- } else if (tmp.length == 2) {
- tagItem.name = tmp[0];
- tagItem.value = tmp[1];
- }
- this.currentStatusComponent.tag = tagItem;
- }
if (this.statusOrg.id == undefined) {
this.notifySvc.warning(this.i18nSvc.fanyi('status.component.notify.need-org'),
'');
return;
@@ -479,36 +455,6 @@ export class StatusComponent implements OnInit {
});
}
- loadTagsOption() {
- let tagsInit$ = this.tagService.loadTags(undefined, undefined, 0,
1000).subscribe(
- message => {
- if (message.code === 0) {
- let page = message.data;
- this.tagsOption = [];
- if (page.content != undefined) {
- page.content.forEach(item => {
- let tag = `${item.name}`;
- if (item.tagValue != undefined) {
- tag = `${tag}:${item.tagValue}`;
- }
- this.tagsOption.push({
- value: tag,
- label: tag
- });
- });
- }
- } else {
- console.warn(message.msg);
- }
- tagsInit$.unsubscribe();
- },
- error => {
- tagsInit$.unsubscribe();
- console.error(error.msg);
- }
- );
- }
-
getLatestIncidentContentMsg(incidents: StatusPageIncidentContent[]): string {
if (incidents == undefined || incidents.length == 0) {
return '';
@@ -533,14 +479,19 @@ export class StatusComponent implements OnInit {
}
}
- sliceTagName(tag: TagItem): string {
- if (tag == undefined) {
- return '';
- }
- if (tag.value != undefined && tag.value.trim() != '') {
- return `${tag.name}:${tag.value}`;
- } else {
- return tag.name;
+ getLabelColor(key: string): string {
+ const colors = ['blue', 'green', 'orange', 'purple', 'cyan'];
+ const index = Math.abs(this.hashString(key)) % colors.length;
+ return colors[index];
+ }
+
+ private hashString(str: string): number {
+ let hash = 0;
+ for (let i = 0; i < str.length; i++) {
+ const char = str.charCodeAt(i);
+ hash = (hash << 5) - hash + char;
+ hash = hash & hash;
}
+ return hash;
}
}
diff --git a/web-app/src/app/routes/setting/tags/tags.component.html
b/web-app/src/app/routes/setting/tags/tags.component.html
index 75683c288..9de6b5ca5 100644
--- a/web-app/src/app/routes/setting/tags/tags.component.html
+++ b/web-app/src/app/routes/setting/tags/tags.component.html
@@ -60,73 +60,38 @@
</ng-template>
</app-toolbar>
-<nz-table
- #fixedTable
- [nzData]="tags"
- [nzPageIndex]="pageIndex"
- [nzPageSize]="pageSize"
- [nzTotal]="total"
- nzFrontPagination="false"
- [nzLoading]="tableLoading"
- nzShowSizeChanger
- [nzShowTotal]="rangeTemplate"
- [nzPageSizeOptions]="[8, 15, 25]"
- (nzQueryParams)="onTablePageChange($event)"
- nzShowPagination="true"
- [nzScroll]="{ x: '1240px' }"
->
- <thead>
- <tr>
- <th nzAlign="center" nzLeft nzWidth="3%" [(nzChecked)]="checkedAll"
(nzCheckedChange)="onAllChecked($event)"></th>
- <th nzAlign="center" nzWidth="15%">{{ 'tag' | i18n }}</th>
- <th nzAlign="center" nzWidth="15%">{{ 'tag.name' | i18n }}</th>
- <th nzAlign="center" nzWidth="15%">{{ 'tag.value' | i18n }}</th>
- <th nzAlign="center" nzWidth="15%">{{ 'tag.description' | i18n }}</th>
- <th nzAlign="center" nzWidth="20%">{{ 'tag.update-time' | i18n }}</th>
- <th nzAlign="center" nzWidth="17%">{{ 'common.edit' | i18n }}</th>
- </tr>
- </thead>
- <tbody>
- <tr *ngFor="let data of fixedTable.data">
- <td nzAlign="center" nzLeft [nzChecked]="checkedTagIds.has(data.id)"
(nzCheckedChange)="onItemChecked(data.id, $event)"></td>
- <td nzAlign="center">
- <a routerLink="/monitors" [queryParams]="{ tag: formatTagName(data) }">
- <nz-tag [nzColor]="data.color" style="font-weight: bold; font-size:
larger" class="hoverClass">
- {{ formatTagName(data) }}
- </nz-tag>
- </a>
- </td>
- <td nzAlign="center">{{ data.name }}</td>
- <td nzAlign="center">{{ data.tagValue }}</td>
- <td nzAlign="center">{{ data.description }}</td>
- <td nzAlign="center">{{ data.gmtUpdate | date : 'YYYY-MM-dd HH:mm:ss'
}}</td>
- <td nzAlign="center">
- <div class="actions">
- <button nz-button nzType="primary" (click)="onEditOneTag(data)"
nz-tooltip [nzTooltipTitle]="'tag.edit' | i18n">
- <i nz-icon nzType="edit" nzTheme="outline"></i>
- </button>
- <button nz-button nz-dropdown [nzDropdownMenu]="more_menu">
- <span nz-icon nzType="ellipsis"></span>
- </button>
- <nz-dropdown-menu #more_menu="nzDropdownMenu">
- <ul nz-menu>
- <li nz-menu-item>
- <button nz-button nzDanger (click)="onDeleteOneTag(data.id)">
- <i nz-icon nzType="delete" nzTheme="outline"></i>
- {{ 'common.button.delete' | i18n }}
- </button>
- </li>
- </ul>
- </nz-dropdown-menu>
+<div class="tag-cards-container">
+ <nz-row [nzGutter]="[12, 12]">
+ <nz-col [nzXs]="12" [nzSm]="8" [nzMd]="6" [nzLg]="4" *ngFor="let data of
tags">
+ <nz-card [nzActions]="[editAction, deleteAction]" [nzBorderless]="true"
class="tag-card">
+ <div class="tag-header">
+ <a routerLink="/monitors" [queryParams]="{ tag: formatTagName(data)
}">
+ <nz-tag [nzColor]="data.color" class="tag-name">
+ {{ formatTagName(data) }}
+ </nz-tag>
+ </a>
</div>
- </td>
- </tr>
- </tbody>
-</nz-table>
-<ng-template #rangeTemplate> {{ 'common.total' | i18n }} {{ total }}
</ng-template>
+ <div class="tag-description" *ngIf="data.description">
+ {{ data.description }}
+ </div>
+
+ <ng-template #editAction>
+ <span nz-tooltip [nzTooltipTitle]="'tag.edit' | i18n"
(click)="onEditOneTag(data)">
+ <i nz-icon nzType="edit" nzTheme="outline"></i>
+ </span>
+ </ng-template>
+
+ <ng-template #deleteAction>
+ <span nz-tooltip [nzTooltipTitle]="'common.button.delete' | i18n"
(click)="onDeleteOneTag(data.id)">
+ <i nz-icon nzType="delete" nzTheme="outline"></i>
+ </span>
+ </ng-template>
+ </nz-card>
+ </nz-col>
+ </nz-row>
+</div>
-<!-- new or update TAG pop-up box -->
<nz-modal
[(nzVisible)]="isManageModalVisible"
[nzTitle]="isManageModalAdd ? ('tag.new' | i18n) : ('tag.edit' | i18n)"
@@ -184,3 +149,5 @@
</form>
</div>
</nz-modal>
+
+<ng-template #rangeTemplate> {{ 'common.total' | i18n }} {{ total }}
</ng-template>
diff --git a/web-app/src/app/routes/setting/tags/tags.component.less
b/web-app/src/app/routes/setting/tags/tags.component.less
new file mode 100644
index 000000000..192b580e2
--- /dev/null
+++ b/web-app/src/app/routes/setting/tags/tags.component.less
@@ -0,0 +1,80 @@
+.tag-cards-container {
+ padding: 24px 0;
+
+ .tag-card {
+ transition: all 0.3s;
+ border-radius: 8px;
+ background: #fff;
+
+ &:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+ }
+
+ ::ng-deep {
+ .ant-card-body {
+ padding: 12px;
+ min-height: 80px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .ant-card-actions {
+ border-radius: 0 0 8px 8px;
+ background: #fafafa;
+ border-top: 1px solid #f0f0f0;
+ min-height: 32px;
+
+ > li {
+ margin: 0;
+
+ > span {
+ padding: 4px 0;
+
+ &:hover {
+ color: #1890ff;
+ }
+
+ i {
+ font-size: 14px;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ .tag-header {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-bottom: 8px;
+
+ .tag-name {
+ font-size: 16px;
+ padding: 4px 16px;
+ border-radius: 4px;
+ margin: 0;
+ font-weight: 500;
+ line-height: 1.4;
+ text-align: center;
+ }
+ }
+
+ .tag-description {
+ color: rgba(0, 0, 0, 0.65);
+ font-size: 14px;
+ line-height: 1.5;
+ margin: 0;
+ min-height: 32px;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ text-align: center;
+ width: 100%;
+ }
+}
\ No newline at end of file
diff --git a/web-app/src/app/routes/setting/tags/tags.component.ts
b/web-app/src/app/routes/setting/tags/tags.component.ts
index e3aee2fe4..928d800f7 100644
--- a/web-app/src/app/routes/setting/tags/tags.component.ts
+++ b/web-app/src/app/routes/setting/tags/tags.component.ts
@@ -32,7 +32,8 @@ import { formatTagName } from
'../../../shared/utils/common-util';
@Component({
selector: 'app-setting-tags',
- templateUrl: './tags.component.html'
+ templateUrl: './tags.component.html',
+ styleUrls: ['./tags.component.less']
})
export class SettingTagsComponent implements OnInit {
@ViewChild('tagForm', { static: false }) tagForm: NgForm | undefined;
@@ -253,4 +254,14 @@ export class SettingTagsComponent implements OnInit {
}
// end 新增修改告警定义model
protected readonly formatTagName = formatTagName;
+
+ onPageIndexChange(index: number): void {
+ this.pageIndex = index;
+ this.loadTagsTable();
+ }
+
+ onPageSizeChange(size: number): void {
+ this.pageSize = size;
+ this.loadTagsTable();
+ }
}
diff --git
a/web-app/src/app/shared/components/key-value-input/key-value-input.component.html
b/web-app/src/app/shared/components/key-value-input/key-value-input.component.html
index a366b9f0c..9b5b0823a 100644
---
a/web-app/src/app/shared/components/key-value-input/key-value-input.component.html
+++
b/web-app/src/app/shared/components/key-value-input/key-value-input.component.html
@@ -17,14 +17,14 @@
~ under the License.
-->
-<div *ngFor="let item of keyValues; let i = index" nz-row>
+<div style="margin-bottom: 2px; margin-top: 2px" *ngFor="let item of
keyValues; let i = index" nz-row>
<div nz-col nzSpan="10">
<input nz-input [placeholder]="keyAlias" [(ngModel)]="item.key"
(ngModelChange)="onChange()" />
</div>
- <div nz-col nzSpan="11">
+ <div nz-col nzSpan="10">
<input nz-input [placeholder]="valueAlias" [(ngModel)]="item.value"
(ngModelChange)="onChange()" />
</div>
- <div nz-col nzSpan="3">
+ <div nz-col nzSpan="4">
<i nz-icon nzType="plus-circle" class="dynamic-button" *ngIf="i === 0"
(click)="addNew($event)"></i>
<i nz-icon nzType="minus-circle" class="dynamic-button"
(click)="removeCurrent(i, $event)"></i>
</div>
diff --git
a/web-app/src/app/shared/components/key-value-input/key-value-input.component.less
b/web-app/src/app/shared/components/key-value-input/key-value-input.component.less
index 6d29b59af..953c4f9f9 100644
---
a/web-app/src/app/shared/components/key-value-input/key-value-input.component.less
+++
b/web-app/src/app/shared/components/key-value-input/key-value-input.component.less
@@ -8,5 +8,5 @@
}
.dynamic-button:hover {
- font-size: 26px;
+ font-size: 18px;
}
diff --git
a/web-app/src/app/shared/components/labels-input/labels-input.component.html
b/web-app/src/app/shared/components/labels-input/labels-input.component.html
index d1d0e7fc4..70c842dbd 100644
--- a/web-app/src/app/shared/components/labels-input/labels-input.component.html
+++ b/web-app/src/app/shared/components/labels-input/labels-input.component.html
@@ -17,11 +17,14 @@
~ under the License.
-->
-<div *ngFor="let item of keyValues; let i = index" nz-row>
+<div style="margin-bottom: 2px; margin-top: 2px" *ngFor="let item of
keyValues; let i = index" nz-row>
<div nz-col nzSpan="10">
<input nz-input [placeholder]="keyAlias" [(ngModel)]="item.key"
(ngModelChange)="emitChange()" />
</div>
- <div nz-col nzSpan="11">
+ <div style="text-align: center; font-weight: bolder" nz-col nzSpan="1">
+ <span>:</span>
+ </div>
+ <div nz-col nzSpan="10">
<input nz-input [placeholder]="valueAlias" [(ngModel)]="item.value"
(ngModelChange)="emitChange()" />
</div>
<div nz-col nzSpan="3">
diff --git
a/web-app/src/app/shared/components/labels-input/labels-input.component.less
b/web-app/src/app/shared/components/labels-input/labels-input.component.less
index 6d29b59af..953c4f9f9 100644
--- a/web-app/src/app/shared/components/labels-input/labels-input.component.less
+++ b/web-app/src/app/shared/components/labels-input/labels-input.component.less
@@ -8,5 +8,5 @@
}
.dynamic-button:hover {
- font-size: 26px;
+ font-size: 18px;
}
diff --git
a/web-app/src/app/shared/components/labels-input/labels-input.component.ts
b/web-app/src/app/shared/components/labels-input/labels-input.component.ts
index ce5676af7..e1f88002d 100644
--- a/web-app/src/app/shared/components/labels-input/labels-input.component.ts
+++ b/web-app/src/app/shared/components/labels-input/labels-input.component.ts
@@ -1,4 +1,4 @@
-import { Component, EventEmitter, Input, Output, OnInit, forwardRef } from
'@angular/core';
+import { Component, Input, OnInit, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
interface KeyValuePair {
@@ -26,7 +26,7 @@ export class LabelsInputComponent implements OnInit,
ControlValueAccessor {
keyValues: KeyValuePair[] = [];
- // ControlValueAccessor 接口实现
+ // ControlValueAccessor
private onChange: any = () => {};
private onTouched: any = () => {};
@@ -50,7 +50,7 @@ export class LabelsInputComponent implements OnInit,
ControlValueAccessor {
}
setDisabledState(isDisabled: boolean): void {
- // 如果需要处理禁用状态,可以在这里实现
+ // set disabled state here
}
ngOnInit(): void {
@@ -86,7 +86,11 @@ export class LabelsInputComponent implements OnInit,
ControlValueAccessor {
result[item.key] = item.value || '';
}
});
- this.onChange(result);
+ if (Object.keys(result).length === 0 || Object.values(result).every(v => v
=== '')) {
+ this.onChange(null);
+ } else {
+ this.onChange(result);
+ }
this.onTouched();
}
}
diff --git
a/web-app/src/app/shared/components/tags-select/tags-select.component.html
b/web-app/src/app/shared/components/tags-select/tags-select.component.html
index ff8b3f7c5..c888672d3 100644
--- a/web-app/src/app/shared/components/tags-select/tags-select.component.html
+++ b/web-app/src/app/shared/components/tags-select/tags-select.component.html
@@ -36,7 +36,7 @@
<nz-modal
[(nzVisible)]="isManageModalVisible"
- [nzTitle]="'tag.bind' | i18n"
+ [nzTitle]="'label.bind' | i18n"
(nzOnCancel)="onManageModalCancel()"
(nzOnOk)="onManageModalOk()"
nzMaskClosable="false"
diff --git a/web-app/src/assets/i18n/en-US.json
b/web-app/src/assets/i18n/en-US.json
index 64a7f0ed5..2174fea8e 100644
--- a/web-app/src/assets/i18n/en-US.json
+++ b/web-app/src/assets/i18n/en-US.json
@@ -225,7 +225,7 @@
"alert.silence.type.once": "One Time Silence",
"alert.silence.type.cyc": "Periodic Silence",
"alert.silence.type": "Silence Type",
- "alert.silence.tags": "Tag Match",
+ "alert.silence.labels": "Tag Match",
"alert.silence.time": "Silence Period",
"alert.silence.times": "Silenced Alerts Num",
"alert.silence.enable": "Enable Silence",
@@ -572,8 +572,8 @@
"tag.description": "Description",
"tag.update-time": "Update Time",
"tag.display": "Display",
- "tag.bind": "Bind Tags",
- "tag.bind.tip": "You can use tags for classification management.eg: assign
tags to resources in production environment and test environment.",
+ "label.bind": "Bind Tags",
+ "label.bind.tip": "You can use tags for classification management.eg: assign
tags to resources in production environment and test environment.",
"tag.help": "Tags are everywhere in HertzBeat. We can apply tags in resource
grouping, tag matching under rules and others. [Tag Manage] is used for unified
management of tags, including adding, deleting, editing, etc. <br>You can use
tags to classify and manage monitoring resources, such as binding labels for
production and testing environments separately.",
"tag.help.link": "https://hertzbeat.apache.org/zh-cn/docs/",
"plugin.help": "In HertzBeat, we can use the plugin mechanism to perform
some other operations after the alarm except notification. Plugin management is
used for unified management of plugins, including upload and enable/disable
operations.<br>For example, you can use the plugin mechanism to execute
specific scripts or SQL after the alarm occurs.",
diff --git a/web-app/src/assets/i18n/zh-CN.json
b/web-app/src/assets/i18n/zh-CN.json
index 83098a1dc..7cdda7224 100644
--- a/web-app/src/assets/i18n/zh-CN.json
+++ b/web-app/src/assets/i18n/zh-CN.json
@@ -130,7 +130,7 @@
"2": "已恢复",
"3": "已处理"
},
- "priority": {
+ "severity": {
"": "告警级别",
"all": "全部级别",
"0": "紧急告警",
@@ -226,7 +226,7 @@
"alert.silence.type.once": "一次性静默",
"alert.silence.type.cyc": "周期性静默",
"alert.silence.type": "静默类型",
- "alert.silence.tags": "匹配标签",
+ "alert.silence.labels": "匹配标签",
"alert.silence.time": "静默时段",
"alert.silence.times": "已静默告警数",
"alert.silence.enable": "启用静默策略",
@@ -571,10 +571,14 @@
"tag.description": "标签描述",
"tag.update-time": "更新时间",
"tag.display": "效果",
- "tag.bind": "绑定标签",
- "tag.bind.tip": "您可以使用标签进行监控资源的分类管理, 例如给资源分别绑定生产环境、测试环境的标签。",
+ "label": "标签",
+ "label.bind": "绑定标签",
+ "label.bind.tip": "您可以使用标签进行监控资源的分类管理, 例如给资源分别绑定生产环境、测试环境的标签。",
"tag.help": "标签在 HertzBeat
中无处不在,我们可以应用标签在资源分组,规则下的标签匹配等场景。标签管理用于对标签的统一管理维护,包含新增,删除,编辑等操作。<br>例如:您可以使用标签对监控资源进行分类管理,给资源分别绑定生产环境、测试环境的标签,在告警通知时通过标签匹配不同的通知人。",
"tag.help.link": "https://hertzbeat.apache.org/zh-cn/docs/",
+ "annotation": "注解",
+ "annotation.bind": "绑定注解",
+ "annotation.bind.tip": "您可以使用注解对实体信息进行标记,例如给资源绑定重要事件的注解。",
"plugin.help":
"在HertzBeat中,我们可以通过插件机制在告警后执行一些除通知以外的其他操作。插件管理用于对插件的统一管理,包括上传和,启用禁用等操作。<br>例如:您可以通过插件机制实现在告警出现后,执行特定的脚本或SQL等操作。",
"plugin.help.link": "https://hertzbeat.apache.org/zh-cn/docs/help/plugin",
"plugin.upload": "上传插件",
@@ -824,7 +828,7 @@
"alert.group-converge.group-labels.input": "输入自定义标签后按回车",
"alert.group-converge.group-labels.placeholder": "请输入标签",
"alert.group-converge.name.tip": "标识此分组策略的名称,需要唯一",
- "alert.group-converge.group-labels.tip": "根据告警标签对告警消息进行分组,支持配置多个标签,如
alertname、severity、instance 等",
+ "alert.group-converge.group-labels.tip": "根据告警标签Key对告警消息进行分组,支持配置多个标签Key,如
alertname、severity、instance 等",
"alert.group-converge.group-wait.tip": "新告警产生后等待时间,在此时间内收到的相同告警将被分组,默认30秒",
"alert.group-converge.group-interval.tip":
"发送分组告警通知的最小时间间隔,避免告警通知过于频繁,默认5分钟",
"alert.group-converge.repeat-interval.tip":
"重复告警的最小通知间隔,对于持续触发的告警,避免重复发送通知,默认4小时",
@@ -833,7 +837,7 @@
"alert.inhibit.target_labels": "目标标签",
"alert.inhibit.target_labels.tip": "匹配这些标签的告警将被抑制",
"alert.inhibit.equal_labels": "相等标签",
- "alert.inhibit.equal_labels.tip": "源告警和目标告警这些标签值必须相等,常用标签如
alertname、instance、severity 等",
+ "alert.inhibit.equal_labels.tip": "源告警和目标告警这些标签Key和对应值必须相等,常用标签Key如
alertname、instance、severity 等",
"alert.inhibit.equal_labels.placeholder": "输入标签名称后按回车,或从下拉列表选择",
"alert.inhibit.equal_labels.more": "还有 {{count}} 个标签",
"alert.inhibit.equal_labels.common": "常用标签",
diff --git a/web-app/src/assets/i18n/zh-TW.json
b/web-app/src/assets/i18n/zh-TW.json
index fcf5851de..7c8ac3464 100644
--- a/web-app/src/assets/i18n/zh-TW.json
+++ b/web-app/src/assets/i18n/zh-TW.json
@@ -238,7 +238,7 @@
"alert.silence.type.once": "一次性靜默",
"alert.silence.type.cyc": "週期性靜默",
"alert.silence.type": "靜默類型",
- "alert.silence.tags": "匹配標籤",
+ "alert.silence.labels": "匹配標籤",
"alert.silence.time": "靜默時段",
"alert.silence.times": "已靜默告警數",
"alert.silence.enable": "啟用靜默策略",
@@ -582,8 +582,8 @@
"tag.description": "標簽描述",
"tag.update-time": "更新時間",
"tag.display": "效果",
- "tag.bind": "綁定標簽",
- "tag.bind.tip": "您可以使用標簽進行監控資源的分類管理, 例如給資源分別綁定生産環境、測試環境的標簽。",
+ "label.bind": "綁定標簽",
+ "label.bind.tip": "您可以使用標簽進行監控資源的分類管理, 例如給資源分別綁定生産環境、測試環境的標簽。",
"tag.help": "標簽在 HertzBeat
中無處不在,我們可以應用標簽在資源分組,規則下的標簽匹配等場景。標簽管理用于對標簽的統壹管理維護,包含新增,刪除,編輯等操作。<br>例如:您可以使用標簽對監控資源進行分類管理,給資源分別綁定生産環境、測試環境的標簽,在告警通知時通過標簽匹配不同的通知人。",
"tag.help.link": "https://hertzbeat.apache.org/zh-cn/docs/",
"plugin.help":
"在HertzBeat中,我們可以透過外掛機制在警告後執行一些除通知以外的其他操作。外掛程式管理用於對外掛程式的統一管理,包括上傳和,啟用停用等操作。<br>例如:您可以透過外掛機制實現在警告出現後,執行特定的腳本或SQL等操作。",
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]