[improve]Improve issues related to tag conflicts (#3889)

This commit is contained in:
Duansg
2025-12-05 22:02:43 +08:00
committed by GitHub
parent 4ae6ba9a3c
commit 3e567e5be6
7 changed files with 200 additions and 17 deletions
@@ -205,7 +205,6 @@ public class MetricsRealTimeAlertCalculator {
}
Long defineId = define.getId();
Map<String, String> commonFingerPrints = new HashMap<>(8);
commonFingerPrints.put(CommonConstants.LABEL_INSTANCE, instance);
// here use the alert name as finger, not care the alert name may be changed
commonFingerPrints.put(CommonConstants.LABEL_DEFINE_ID, String.valueOf(define.getId()));
commonFingerPrints.put(CommonConstants.LABEL_ALERT_NAME, define.getName());
@@ -0,0 +1,43 @@
/*
* 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.constants;
/**
* HertzBeat Reserved Keywords Enum
*/
public enum HertzBeatKeywordsEnum {
INSTANCE("instance", "metric_instance");
private final String keyword;
private final String alias;
HertzBeatKeywordsEnum(String keyword, String alias) {
this.keyword = keyword;
this.alias = alias;
}
public String getKeyword() {
return keyword;
}
public String getAlias() {
return alias;
}
}
@@ -0,0 +1,51 @@
/*
* 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.util;
import org.apache.hertzbeat.common.constants.HertzBeatKeywordsEnum;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Validate JEXL rules
*/
public class HertzBeatKeywordsUtil {
private static final Map<String, HertzBeatKeywordsEnum> KEYWORDS =
Arrays.stream(HertzBeatKeywordsEnum.values())
.collect(Collectors.toMap(HertzBeatKeywordsEnum::getKeyword, e -> e));
/**
* Verify if the field matches any reserved keywords
*
* @param field Field name to verify
*/
public static void verifyKeywords(String field) {
HertzBeatKeywordsEnum keyword = KEYWORDS.get(field);
if (null == keyword) {
return;
}
throw new IllegalArgumentException(
String.format("Field matches keyword `%s`, please set alias `%s`.",
keyword.getKeyword(), keyword.getAlias()));
}
}
@@ -0,0 +1,54 @@
/*
* 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.util;
import org.apache.hertzbeat.common.constants.HertzBeatKeywordsEnum;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
/**
* Test case for {@link HertzBeatKeywordsUtil}
*/
class HertzBeatKeywordsUtilTest {
@Test
void testVerifyKeywords_WithReservedKeyword_Instance() {
IllegalArgumentException exception = assertThrows(
IllegalArgumentException.class,
() -> HertzBeatKeywordsUtil.verifyKeywords("instance")
);
String expectedMessage = String.format(
"Field matches keyword `%s`, please set alias `%s`.",
HertzBeatKeywordsEnum.INSTANCE.getKeyword(),
HertzBeatKeywordsEnum.INSTANCE.getAlias()
);
assertEquals(expectedMessage, exception.getMessage());
}
@Test
void testVerifyKeywords_WithValidField() {
assertDoesNotThrow(() -> HertzBeatKeywordsUtil.verifyKeywords("cpu_usage"));
assertDoesNotThrow(() -> HertzBeatKeywordsUtil.verifyKeywords("memory_used"));
assertDoesNotThrow(() -> HertzBeatKeywordsUtil.verifyKeywords("response_time"));
assertDoesNotThrow(() -> HertzBeatKeywordsUtil.verifyKeywords("metric_instance"));
assertDoesNotThrow(() -> HertzBeatKeywordsUtil.verifyKeywords(HertzBeatKeywordsEnum.INSTANCE.getAlias()));
}
}
@@ -34,6 +34,7 @@ import org.apache.hertzbeat.common.entity.message.CollectRep;
import org.apache.hertzbeat.common.support.SpringContextHolder;
import org.apache.hertzbeat.common.support.exception.CommonException;
import org.apache.hertzbeat.common.util.CommonUtil;
import org.apache.hertzbeat.common.util.HertzBeatKeywordsUtil;
import org.apache.hertzbeat.common.util.JexlCheckerUtil;
import org.apache.hertzbeat.manager.dao.DefineDao;
import org.apache.hertzbeat.manager.dao.MonitorDao;
@@ -439,24 +440,18 @@ public class AppServiceImpl implements AppService, InitializingBean {
for (ParamDefine param : app.getParams()) {
CommonUtil.validDefineI18n(param.getName(), param.getField() + " param");
}
for (Metrics metric : app.getMetrics()) {
CommonUtil.validDefineI18n(metric.getI18n(), metric.getName() + " metric");
if (metric.getFields() == null){
continue;
}
for (Metrics.Field field : metric.getFields()) {
CommonUtil.validDefineI18n(field.getI18n(), metric.getName() + " metric " + field.getField() + " field");
}
}
if (!isModify) {
Assert.isNull(appDefines.get(app.getApp().toLowerCase()),
"monitoring template name " + app.getApp() + " already exists.");
}
Set<String> fieldsSet = new HashSet<>(16);
for (Metrics metrics : app.getMetrics()) {
CommonUtil.validDefineI18n(metrics.getI18n(), metrics.getName() + " metric");
Assert.notEmpty(metrics.getFields(), "monitoring template metrics fields can not null");
fieldsSet.clear();
for (Metrics.Field field : metrics.getFields()) {
CommonUtil.validDefineI18n(field.getI18n(), metrics.getName() + " metric " + field.getField() + " field");
HertzBeatKeywordsUtil.verifyKeywords(field.getField());
if (fieldsSet.contains(field.getField())) {
throw new IllegalArgumentException(app.getApp() + " " + metrics.getName() + " "
+ field.getField() + " can not duplicated.");
@@ -162,7 +162,7 @@ metrics:
# metrics fields list.
fields:
# Metric information includes the following: Field name, Type: 0-number, 1-string, instance: indicates whether the metric is the primary key, unit: the unit of the metric
- field: instance
- field: metric_instance
type: 1
i18n:
zh-CN: 实例
@@ -180,6 +180,12 @@ metrics:
zh-CN:
en-US: Value
ja-JP:
aliasFields:
- instance
- timestamp
- value
calculates:
- metric_instance=instance
# Monitoring protocol used for data collection, e.g. sql, ssh, http, telnet, wmi, snmp, sdk.
protocol: http
# When the protocol is HTTP, the specific collection configuration is as follows
@@ -201,7 +207,7 @@ metrics:
^_^headers^_^: ^_^headers^_^
# Request parameter content
params:
^_^params^_^: ^_^params^_^
query: basic_influxdb_memstats_alloc
# authorization
authorization:
# Authentication method: Basic Auth, Digest Auth, Bearer Token
@@ -231,7 +237,7 @@ metrics:
zh-CN: 任务
en-US: Job
ja-JP: タスク
- field: instance
- field: metric_instance
type: 1
i18n:
zh-CN: 实例
@@ -255,6 +261,14 @@ metrics:
zh-CN:
en-US: Value
ja-JP:
aliasFields:
- job
- instance
- database
- timestamp
- value
calculates:
- metric_instance=instance
# Monitoring protocol used for data collection, e.g. sql, ssh, http, telnet, wmi, snmp, sdk.
protocol: http
# When the protocol is HTTP, the specific collection configuration is as follows
@@ -300,7 +314,7 @@ metrics:
# metrics fields list.
fields:
# Metric information includes the following: Field name, Type: 0-number, 1-string, instance: indicates whether the metric is the primary key, unit: the unit of the metric
- field: instance
- field: metric_instance
type: 1
i18n:
zh-CN: 实例
@@ -318,6 +332,12 @@ metrics:
zh-CN:
en-US: Value
ja-JP:
aliasFields:
- instance
- timestamp
- value
calculates:
- metric_instance=instance
# Monitoring protocol used for data collection, e.g. sql, ssh, http, telnet, wmi, snmp, sdk.
protocol: http
# When the protocol is HTTP, the specific collection configuration is as follows
@@ -364,7 +384,7 @@ metrics:
# metrics fields list.
fields:
# Metric information includes the following: Field name, Type: 0-number, 1-string, instance: indicates whether the metric is the primary key, unit: the unit of the metric
- field: instance
- field: metric_instance
type: 1
i18n:
zh-CN: 实例
@@ -382,6 +402,12 @@ metrics:
zh-CN:
en-US: Value
ja-JP:
aliasFields:
- instance
- timestamp
- value
calculates:
- metric_instance=instance
# Monitoring protocol used for data collection, e.g. sql, ssh, http, telnet, wmi, snmp, sdk.
protocol: http
# When the protocol is HTTP, the specific collection configuration is as follows
@@ -166,7 +166,7 @@ metrics:
zh-CN: 名称
en-US: Name
ja-JP: 名前
- field: instance
- field: metric_instance
type: 1
i18n:
zh-CN: 实例
@@ -184,6 +184,13 @@ metrics:
zh-CN: 数值
en-US: Value
ja-JP:
aliasFields:
- __name__
- instance
- timestamp
- value
calculates:
- metric_instance=instance
# The protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: http
# The config content when protocol is http
@@ -295,7 +302,7 @@ metrics:
# collect metrics content
fields:
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: instance
- field: metric_instance
type: 1
i18n:
zh-CN: 实例
@@ -325,6 +332,14 @@ metrics:
zh-CN: 数值
en-US: Value
ja-JP:
aliasFields:
- instance
- job
- topic
- timestamp
- value
calculates:
- metric_instance=instance
# The protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: http
# The specific collection configuration when the protocol is http