This is an automated email from the ASF dual-hosted git repository.
Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git
The following commit(s) were added to refs/heads/master by this push:
new 589e64414e [fix] keep monitor instance identity stable across edits
(#4329)
589e64414e is described below
commit 589e64414e5f1dd9169360dc7b1e270a4a9a91e2
Author: NekoPunch <[email protected]>
AuthorDate: Mon Aug 17 21:21:50 2026 -0700
[fix] keep monitor instance identity stable across edits (#4329)
---
.../manager/service/impl/MonitorServiceImpl.java | 54 ++++++++++++----------
.../manager/service/MonitorServiceTest.java | 53 +++++++++++++++++++++
2 files changed, 83 insertions(+), 24 deletions(-)
diff --git
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/MonitorServiceImpl.java
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/MonitorServiceImpl.java
index 63ed4fb68d..9b061731e4 100644
---
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/MonitorServiceImpl.java
+++
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/MonitorServiceImpl.java
@@ -138,6 +138,34 @@ public class MonitorServiceImpl implements MonitorService {
@Autowired
private MetricsFavoriteService metricsFavoriteService;
+ /**
+ * Idempotent: an instance already carrying a port is left untouched, so
repeated
+ * edits cannot grow it (host:443:443...). A missing instance falls back
to the
+ * host param - never concatenated onto null, which produced "null:443"
identities.
+ */
+ private void resolveMonitorInstance(Monitor monitor, List<Param> params) {
+ String instance = monitor.getInstance();
+ if (!StringUtils.hasText(instance)) {
+ instance = params.stream()
+ .filter(param -> "host".equals(param.getField()))
+ .map(Param::getParamValue)
+ .filter(StringUtils::hasText)
+ .findFirst()
+ .orElse(StringUtils.hasText(monitor.getName()) ?
monitor.getName() : "unknown");
+ }
+ Param portParam = params.stream()
+ .filter(param -> PARAM_FIELD_PORT.equals(param.getField()))
+ .findFirst()
+ .orElse(null);
+ String portWithMark = (Objects.isNull(portParam) ||
!StringUtils.hasText(portParam.getParamValue()))
+ ? ""
+ : SignConstants.DOUBLE_MARK + portParam.getParamValue();
+ if (!IpDomainUtil.isHasPortWithMark(instance)) {
+ instance = instance + portWithMark;
+ }
+ monitor.setInstance(instance);
+ }
+
@Override
@Transactional(readOnly = true)
public void detectMonitor(Monitor monitor, List<Param> params, String
collector) throws MonitorDetectException {
@@ -184,19 +212,8 @@ public class MonitorServiceImpl implements MonitorService {
appDefine.setScheduleType(monitor.getScheduleType());
appDefine.setCronExpression(monitor.getCronExpression());
+ resolveMonitorInstance(monitor, params);
String instance = monitor.getInstance();
- // The port field may be null
- Param portParam = params.stream()
- .filter(param -> PARAM_FIELD_PORT.equals(param.getField()))
- .findFirst()
- .orElse(null);
- String portWithMark = (Objects.isNull(portParam) ||
!StringUtils.hasText(portParam.getParamValue()))
- ? ""
- : SignConstants.DOUBLE_MARK + portParam.getParamValue();
- if (!IpDomainUtil.isHasPortWithMark(instance)) {
- instance = instance + portWithMark;
- }
- monitor.setInstance(instance);
Map<String, String> metadata =
Map.of(CommonConstants.LABEL_INSTANCE_NAME, monitor.getName(),
CommonConstants.LABEL_INSTANCE, instance);
@@ -384,19 +401,8 @@ public class MonitorServiceImpl implements MonitorService {
labelDao.saveAll(addLabels);
}
+ resolveMonitorInstance(monitor, params);
String instance = monitor.getInstance();
- // The port field may be null
- Param portParam = params.stream()
- .filter(param -> PARAM_FIELD_PORT.equals(param.getField()))
- .findFirst()
- .orElse(null);
- String portWithMark = (Objects.isNull(portParam) ||
!StringUtils.hasText(portParam.getParamValue()))
- ? ""
- : SignConstants.DOUBLE_MARK + portParam.getParamValue();
- if (Objects.nonNull(instance)) {
- instance = instance + portWithMark;
- }
- monitor.setInstance(instance);
boolean isStatic =
CommonConstants.SCRAPE_STATIC.equals(monitor.getScrape())
|| !StringUtils.hasText(monitor.getScrape());
diff --git
a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/MonitorServiceTest.java
b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/MonitorServiceTest.java
index 3f682f933d..6b3b5c502d 100644
---
a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/MonitorServiceTest.java
+++
b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/MonitorServiceTest.java
@@ -225,6 +225,59 @@ class MonitorServiceTest {
assertDoesNotThrow(() -> monitorService.addMonitor(monitor, params,
null, null));
}
+ @Test
+ void addMonitorWithoutInstanceFallsBackToHostParam() {
+ Monitor monitor = Monitor.builder()
+ .intervals(1)
+ .name("memory")
+ .app("demoApp")
+ .build();
+ Job job = new Job();
+ when(appService.getAppDefine(monitor.getApp())).thenReturn(job);
+ when(collectJobScheduling.addAsyncCollectJob(job,
null)).thenReturn(1L);
+ when(monitorDao.save(monitor)).thenReturn(monitor);
+ List<Param> params = List.of(
+
Param.builder().field("host").paramValue("www.example.com").build(),
+ Param.builder().field("port").paramValue("443").build());
+ when(paramDao.saveAll(params)).thenReturn(params);
+ assertDoesNotThrow(() -> monitorService.addMonitor(monitor, params,
null, null));
+ assertEquals("www.example.com:443", monitor.getInstance());
+ }
+
+ @Test
+ void addMonitorInstanceStaysStableAcrossRepeatedResolution() {
+ Monitor monitor = Monitor.builder()
+ .intervals(1)
+ .name("memory")
+ .app("demoApp")
+ .instance("www.example.com:443")
+ .build();
+ Job job = new Job();
+ when(appService.getAppDefine(monitor.getApp())).thenReturn(job);
+ when(collectJobScheduling.addAsyncCollectJob(job,
null)).thenReturn(1L);
+ when(monitorDao.save(monitor)).thenReturn(monitor);
+ List<Param> params =
List.of(Param.builder().field("port").paramValue("443").build());
+ when(paramDao.saveAll(params)).thenReturn(params);
+ assertDoesNotThrow(() -> monitorService.addMonitor(monitor, params,
null, null));
+ assertEquals("www.example.com:443", monitor.getInstance());
+ }
+
+ @Test
+ void modifyMonitorKeepsInstanceStableAcrossEdits() {
+ long monitorId = 7L;
+ Monitor stored =
Monitor.builder().jobId(1L).intervals(1).app("demoApp").name("ssl")
+ .instance("www.example.com:443").id(monitorId).build();
+ when(monitorDao.findById(monitorId)).thenReturn(Optional.of(stored));
+ List<Param> params =
List.of(Param.builder().field("port").paramValue("443").build());
+
+ for (int edit = 0; edit < 2; edit++) {
+ Monitor dto =
Monitor.builder().jobId(1L).intervals(1).app("demoApp").name("ssl")
+ .instance("www.example.com:443").id(monitorId).build();
+ assertDoesNotThrow(() -> monitorService.modifyMonitor(dto, params,
null, null));
+ assertEquals("www.example.com:443", dto.getInstance());
+ }
+ }
+
@Test
void addMonitorException() {
Monitor monitor = Monitor.builder()
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]