perf(X-Pack): 阈值告警支持设置告警数据 #17526

This commit is contained in:
fit2cloud-chenyw
2025-12-17 13:35:24 +08:00
committed by fit2cloud-chenyw
parent 12f438d6c4
commit e4af7e0784
11 changed files with 142 additions and 17 deletions

View File

@@ -35,6 +35,7 @@ public class ChartViewThresholdManage {
@Resource
private ChartViewManege chartViewManege;
public String convertThresholdRules(Long chartId, String thresholdRules, String resourceTable) {
ChartViewDTO details = chartViewManege.getDetails(chartId, resourceTable);
return convertThresholdRules(details, thresholdRules);
@@ -277,30 +278,103 @@ public class ChartViewThresholdManage {
Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
Matcher matcher = pattern.matcher(thresholdTemplate);
StringBuilder sb = new StringBuilder();
boolean withThresholdData = false;
int thresholdRecordCount = request.getThresholdLimit();
while (matcher.find()) {
long id = Long.parseLong(matcher.group(1));
if (id == 2L) {
withThresholdData = true;
}
// 根据id从map中获取替换文本
DatasetTableFieldDTO fieldDTO = fieldMap.get(id);
if (ObjectUtils.isEmpty(fieldDTO)) continue;
String dataeaseName = fieldDTO.getDataeaseName();
String fieldDTOName = fieldDTO.getName();
/*String dataeaseName = fieldDTO.getDataeaseName();
String replacement = null;
if (fieldDTO.getDeType().equals(DeTypeConstants.DE_FLOAT) || fieldDTO.getDeType().equals(DeTypeConstants.DE_INT)) {
List<String> valueList = rows.stream().map(row -> ObjectUtils.isEmpty(row.get(dataeaseName)) ? null : stripTrailingZeros2String(row.get(dataeaseName))).collect(Collectors.toList());
replacement = fieldDTOName + ": " + JsonUtil.toJSONString(valueList);
} else {
List<String> valueList = rows.stream().map(row -> ObjectUtils.isEmpty(row.get(dataeaseName)) ? null : row.get(dataeaseName).toString()).collect(Collectors.toList());
replacement = fieldDTOName + ": " + JsonUtil.toJSONString(valueList);
if (rows.size() > thresholdRecordCount) {
rows = rows.subList(0, thresholdRecordCount);
}
if (request.isShowFieldValue()) {
String replacement = null;
if (fieldDTO.getDeType().equals(DeTypeConstants.DE_FLOAT) || fieldDTO.getDeType().equals(DeTypeConstants.DE_INT)) {
List<String> valueList = rows.stream().map(row -> ObjectUtils.isEmpty(row.get(dataeaseName)) ? null : stripTrailingZeros2String(row.get(dataeaseName))).collect(Collectors.toList());
replacement = fieldDTOName + ": " + JsonUtil.toJSONString(valueList);
} else {
List<String> valueList = rows.stream().map(row -> ObjectUtils.isEmpty(row.get(dataeaseName)) ? null : row.get(dataeaseName).toString()).collect(Collectors.toList());
replacement = fieldDTOName + ": " + JsonUtil.toJSONString(valueList);
}
matcher.appendReplacement(sb, replacement);
} else {
matcher.appendReplacement(sb, fieldDTOName);
}
// 替换文本
matcher.appendReplacement(sb, replacement);*/
matcher.appendReplacement(sb, fieldDTOName);
}
matcher.appendTail(sb);
matcher.appendTail(sb);
// 输出替换后的HTML内容
String result = sb.toString();
if (withThresholdData) {
Set<Long> thresholdFieldIdSet = new HashSet<>();
getThresholdFieldIdList(filterTreeObj, thresholdFieldIdSet);
List<List<String>> thresholdTableList = rows.stream().map(row -> thresholdFieldIdSet.stream().map(fieldId -> {
DatasetTableFieldDTO fieldDTO = fieldMap.get(fieldId);
if (ObjectUtils.isEmpty(fieldDTO)) return "";
String dataeaseName = fieldDTO.getDataeaseName();
Integer deType = fieldDTO.getDeType();
String value = null;
if (deType.equals(DeTypeConstants.DE_FLOAT) || deType.equals(DeTypeConstants.DE_INT)) {
value = ObjectUtils.isEmpty(row.get(dataeaseName)) ? null : stripTrailingZeros2String(row.get(dataeaseName));
} else {
value = ObjectUtils.isEmpty(row.get(dataeaseName)) ? null : row.get(dataeaseName).toString();
}
return value;
}).collect(Collectors.toList())).collect(Collectors.toList());
List<String> tableHeadList = thresholdFieldIdSet.stream().map(i -> fieldMap.get(i).getName()).collect(Collectors.toList());
tableHeadList.addFirst("NO");
thresholdTableList.addFirst(tableHeadList);
StringBuilder tableHtml = new StringBuilder("<table style=\"min-width:35%;border-collapse:collapse;font-family:'Segoe UI',Arial,sans-serif;font-size:14px;border:1px solid;border-radius:8px;overflow:hidden;border-spacing:0\">");
for (int i = 0; i < thresholdTableList.size(); i++) {
List<String> row = thresholdTableList.get(i);
if (i == 0) {
StringBuilder theadHtmlBuild = new StringBuilder("<thead><tr style=\"border-bottom:2px double;border-color: inherit;\">");
row.forEach(item -> {
theadHtmlBuild.append("<th style=\"border: 1px dashed;border-color: inherit;padding:12px;text-align:left;font-weight:bold;letter-spacing:1px;text-transform:uppercase;\">").append(item).append("</th>");
});
theadHtmlBuild.append("</tr></thead>");
tableHtml.append(theadHtmlBuild);
continue;
}
row.addFirst(String.valueOf(i));
if (i == 1) {
tableHtml.append("<tbody>");
}
StringBuilder trHtmlBuild = new StringBuilder("<tr style=\"border-bottom:1px dashed;border-color: inherit;\">");
row.forEach(item -> {
trHtmlBuild.append("<td style=\"border: 1px dashed;border-color: inherit;padding:12px\">").append(item).append("</td>");
});
trHtmlBuild.append("</tr>");
tableHtml.append(trHtmlBuild);
if (i == thresholdTableList.size() - 1) {
tableHtml.append("</tbody></table>");
}
}
String thresholdDataRex = "<span id=\"changeText-(\\d+)\"[^>]*?style=\"([^\"]*?)\"[^>]*?>\\s*<span[^>]*?data-mce-content=\"\\[告警数据\\]\"[^>]*?>\\[告警数据\\]</span>\\s*</span>";
Pattern thresholdDataPattern = Pattern.compile(thresholdDataRex, Pattern.DOTALL);
Matcher thresholdDataMatcher = thresholdDataPattern.matcher(result);
if (thresholdDataMatcher.find()) {
String originStyle = thresholdDataMatcher.group(2);
String tableStyleHtml = tableHtml.toString().replace("min-width:35%;", originStyle + "min-width:35%;");
result = thresholdDataMatcher.replaceAll(tableStyleHtml);
}
}
return new ThresholdCheckVO(true, result, null, null);
} catch (Exception e) {
LogUtil.error(e.getMessage(), new Throwable(e));
@@ -316,6 +390,18 @@ public class ChartViewThresholdManage {
return ((BigDecimal) value).stripTrailingZeros().toPlainString();
}
private void getThresholdFieldIdList(FilterTreeObj conditionTree, Set<Long> fieldIdSet) {
List<FilterTreeItem> items = conditionTree.getItems();
items.forEach(item -> {
if (!StringUtils.equals("item", item.getType())) {
getThresholdFieldIdList(item.getSubTree(), fieldIdSet);
} else {
Long fieldId = item.getFieldId();
fieldIdSet.add(fieldId);
}
});
}
private void chartDynamicMap(List<Map<String, Object>> rows, FilterTreeObj conditionTree, Map<Long, DatasetTableFieldDTO> fieldMap) {
List<FilterTreeItem> items = conditionTree.getItems();
items.forEach(item -> {
@@ -603,4 +689,5 @@ public class ChartViewThresholdManage {
return valueLong == targetLong;
}
}
}

View File

@@ -0,0 +1,6 @@
ALTER TABLE `xpack_threshold_info`
ADD COLUMN `show_field_value` tinyint(1) NOT NULL DEFAULT 0 COMMENT '显示字段值' AFTER `repeat_send`;
ALTER TABLE `xpack_threshold_info_snapshot`
ADD COLUMN `show_field_value` tinyint(1) NOT NULL DEFAULT 0 COMMENT '显示字段值' AFTER `repeat_send`;

View File

@@ -3845,7 +3845,8 @@ export default {
loginLimit: 'Limit login',
loginLimitRate: 'Limit login failure times (times)',
loginLimitTime: 'Limit login failure time (minutes)',
share_disable_tips: 'Dashboard and data screen sharing are invalid after turning on'
share_disable_tips: 'Dashboard and data screen sharing are invalid after turning on',
thresholdLimit: 'Alarm data limitation'
},
resource_sort: {
time_asc: 'In ascending order by creation time',
@@ -4628,6 +4629,7 @@ export default {
msg_title: 'Message title',
msg_content: 'Message content',
repeat_send: 'Repeat send',
show_field_value: 'Show field value',
recipient: 'Recipient',
choose_recipient: 'Select recipient',
trigger_alarm: 'Trigger alarm',
@@ -4637,6 +4639,7 @@ export default {
recipient_setting: 'Recipient setting',
attention_quota_tip: 'The indicators you are following',
pay_attention_in_time: '. Please pay attention in time.',
threshold_record: 'Alert Data',
msg_preview: 'Message preview',
average: 'Average value',
next_time: 'Next ',

View File

@@ -3734,7 +3734,8 @@ export default {
loginLimit: '限制登入',
loginLimitRate: '限制登入失敗次數 (次)',
loginLimitTime: '限制登入失敗時間 (分)',
share_disable_tips: '開啟後儀表板以及大屏分享無效'
share_disable_tips: '開啟後儀表板以及大屏分享無效',
thresholdLimit: '告警數據限製'
},
resource_sort: {
time_asc: '按建立時間升序',
@@ -4497,6 +4498,7 @@ export default {
msg_title: '消息標題',
msg_content: '消息正文',
repeat_send: '是否重複發送',
show_field_value: '顯示字段值',
recipient: '接收人',
choose_recipient: '選擇接收人',
trigger_alarm: '觸發告警',
@@ -4506,6 +4508,7 @@ export default {
recipient_setting: '設置接收人',
attention_quota_tip: '您關注的指標',
pay_attention_in_time: '。請及時關注。',
threshold_record: '告警數據',
msg_preview: '消息預覽',
average: '平均值',
next_time: '下一',

View File

@@ -3740,7 +3740,8 @@ export default {
loginLimit: '限制登录',
loginLimitRate: '限制登录失败次数 (次)',
loginLimitTime: '限制登录失败时间 (分)',
share_disable_tips: '开启后仪表板以及大屏分享无效'
share_disable_tips: '开启后仪表板以及大屏分享无效',
thresholdLimit: '告警数据限制'
},
resource_sort: {
time_asc: '按创建时间升序',
@@ -4502,6 +4503,7 @@ export default {
msg_title: '消息标题',
msg_content: '消息正文',
repeat_send: '是否重复发送',
show_field_value: '显示字段值',
recipient: '接收人',
choose_recipient: '选择接收人',
trigger_alarm: '触发告警',
@@ -4511,6 +4513,7 @@ export default {
recipient_setting: '设置接收人',
attention_quota_tip: '您关注的指标',
pay_attention_in_time: '。请及时关注。',
threshold_record: '告警数据',
msg_preview: '消息预览',
average: '平均值',
next_time: '下一',

View File

@@ -337,6 +337,19 @@ defineExpose({
type="number"
/>
</div>
<div v-else-if="item.pkey === 'thresholdLimit'">
<el-input-number
v-model="state.form.thresholdLimit"
autocomplete="off"
step-strictly
class="text-left edit-all-line"
:min="1"
:max="50"
:placeholder="t('common.inputText')"
controls-position="right"
type="number"
/>
</div>
<div
v-else-if="
item.pkey === 'logLiveTime' ||

View File

@@ -17,4 +17,8 @@ public class ThresholdCheckRequest implements Serializable {
private String thresholdTemplate;
private String resourceTable;
private boolean showFieldValue;
private Integer thresholdLimit = 5;
}

View File

@@ -26,4 +26,6 @@ public class MessageDTO implements Serializable {
private MessageEnum messageEnum;
private Long messageId;
List<List<String>> gridData;
}

View File

@@ -46,5 +46,7 @@ public class ThresholdCreator extends BaseReciDTO implements Serializable {
private Boolean repeatSend = true;
private Boolean showFieldValue = false;
private String resourceTable = CommonConstants.RESOURCE_TABLE.CORE;
}

View File

@@ -17,4 +17,5 @@ public class XpackSettingConstants {
public static final String LOGIN_LIMIT = "basic.loginLimit";
public static final String LOGIN_LIMIT_RATE = "basic.loginLimitRate";
public static final String LOGIN_LIMIT_TIME = "basic.loginLimitTime";
public static final String THRESHOLD_LIMIT = "basic.thresholdLimit";
}

View File

@@ -19,7 +19,8 @@ public class SystemSettingUtils {
XpackSettingConstants.DATA_FILLING_LOG_LIVE_TIME,
XpackSettingConstants.LOGIN_LIMIT,
XpackSettingConstants.LOGIN_LIMIT_RATE,
XpackSettingConstants.LOGIN_LIMIT_TIME);
XpackSettingConstants.LOGIN_LIMIT_TIME,
XpackSettingConstants.THRESHOLD_LIMIT);
return xpackSettingList.contains(pkey);
}
}