This is an automated email from the ASF dual-hosted git repository. gongchao 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 f05e91247a [refactor] refactor auto discovery http sd (#3300) f05e91247a is described below commit f05e91247ae115742dfe681f4a7a870d606befe4 Author: tomsun28 <tomsu...@outlook.com> AuthorDate: Sun May 4 00:07:06 2025 +0800 [refactor] refactor auto discovery http sd (#3300) Signed-off-by: tomsun28 <tomsu...@outlook.com> --- .../collector/collect/sd/HttpSdCollectImpl.java | 2 +- .../collector/dispatch/CommonDispatcher.java | 3 +- .../collector/dispatch/DispatchConstants.java | 2 +- .../common/constants/CommonConstants.java | 111 +---- .../hertzbeat/common/entity/job/Metrics.java | 7 +- .../entity/job/protocol/CommonRequestProtocol.java | 3 +- .../protocol/HttpSdProtocol.java} | 14 +- .../hertzbeat/common/entity/manager/Monitor.java | 4 + .../common/entity/manager/MonitorBind.java | 15 +- .../common/entity/sd/ServiceDiscoveryProtocol.java | 67 --- .../common/support/valid/HostParamValidator.java | 8 +- .../hertzbeat/common/util/SdMonitorOperator.java | 151 ------- .../support/vaild/HostParamValidatorTest.java | 6 +- .../component/sd/ServiceDiscoveryWorker.java | 118 +++--- .../manager/controller/MonitorsController.java | 12 - .../hertzbeat/manager/dao/MonitorBindDao.java | 16 +- .../hertzbeat/manager/pojo/dto/MonitorDto.java | 4 +- .../hertzbeat/manager/scheduler/SchedulerInit.java | 25 +- .../hertzbeat/manager/service/MonitorService.java | 17 +- .../manager/service/impl/AppServiceImpl.java | 4 - .../manager/service/impl/MonitorServiceImpl.java | 455 ++++++--------------- .../define/{app-push.yml => app-http_sd.yml} | 74 ++-- .../src/main/resources/define/app-push.yml | 2 +- .../manager/controller/MonitorsControllerTest.java | 11 - .../manager/service/MonitorServiceTest.java | 2 +- web-app/src/app/pojo/Monitor.ts | 1 + .../monitor-detail/monitor-detail.component.ts | 3 + .../monitor-edit/monitor-edit.component.html | 3 + .../monitor/monitor-edit/monitor-edit.component.ts | 129 +++++- .../monitor-form/monitor-form.component.html | 41 ++ .../monitor/monitor-form/monitor-form.component.ts | 39 +- .../monitor-list/monitor-list.component.html | 5 + .../monitor/monitor-list/monitor-list.component.ts | 62 ++- .../monitor/monitor-new/monitor-new.component.html | 3 + .../monitor/monitor-new/monitor-new.component.ts | 118 +++++- .../app/routes/setting/define/define.component.ts | 3 + web-app/src/assets/i18n/en-US.json | 8 +- web-app/src/assets/i18n/ja-JP.json | 2 + web-app/src/assets/i18n/pt-BR.json | 2 + web-app/src/assets/i18n/zh-CN.json | 2 + web-app/src/assets/i18n/zh-TW.json | 2 + 41 files changed, 642 insertions(+), 914 deletions(-) diff --git a/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/sd/HttpSdCollectImpl.java b/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/sd/HttpSdCollectImpl.java index 0935b9fddc..0de9598c97 100644 --- a/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/sd/HttpSdCollectImpl.java +++ b/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/sd/HttpSdCollectImpl.java @@ -52,7 +52,7 @@ public class HttpSdCollectImpl extends AbstractCollect { @Override public void collect(CollectRep.MetricsData.Builder builder, Metrics metrics) { List<ConnectionConfig> configList = Lists.newArrayList(); - HttpUriRequest request = RequestBuilder.get().setUri(metrics.getSdProtocol().getSdSource()).build(); + HttpUriRequest request = RequestBuilder.get().setUri(metrics.getHttp_sd().getUrl()).build(); try (CloseableHttpResponse response = CommonHttpClient.getHttpClient().execute(request)) { int statusCode = response.getStatusLine().getStatusCode(); diff --git a/hertzbeat-collector/hertzbeat-collector-collector/src/main/java/org/apache/hertzbeat/collector/dispatch/CommonDispatcher.java b/hertzbeat-collector/hertzbeat-collector-collector/src/main/java/org/apache/hertzbeat/collector/dispatch/CommonDispatcher.java index b592ea0e1f..1262e57967 100644 --- a/hertzbeat-collector/hertzbeat-collector-collector/src/main/java/org/apache/hertzbeat/collector/dispatch/CommonDispatcher.java +++ b/hertzbeat-collector/hertzbeat-collector-collector/src/main/java/org/apache/hertzbeat/collector/dispatch/CommonDispatcher.java @@ -281,7 +281,8 @@ public class CommonDispatcher implements MetricsTaskDispatch, CollectDataDispatc } // If it is an asynchronous periodic cyclic task, directly response the collected data if (job.isSd()) { - commonDataQueue.sendServiceDiscoveryData(metricsData); + CollectRep.MetricsData sdMetricsData = CollectRep.MetricsData.newBuilder(metricsData).build(); + commonDataQueue.sendServiceDiscoveryData(sdMetricsData); } commonDataQueue.sendMetricsData(metricsData); } else { diff --git a/hertzbeat-collector/hertzbeat-collector-common/src/main/java/org/apache/hertzbeat/collector/dispatch/DispatchConstants.java b/hertzbeat-collector/hertzbeat-collector-common/src/main/java/org/apache/hertzbeat/collector/dispatch/DispatchConstants.java index eea60acebf..b8ee6d11fc 100644 --- a/hertzbeat-collector/hertzbeat-collector-common/src/main/java/org/apache/hertzbeat/collector/dispatch/DispatchConstants.java +++ b/hertzbeat-collector/hertzbeat-collector-common/src/main/java/org/apache/hertzbeat/collector/dispatch/DispatchConstants.java @@ -126,7 +126,7 @@ public interface DispatchConstants { /** * protocol http sd */ - String PROTOCOL_HTTP_SD = "httpsd"; + String PROTOCOL_HTTP_SD = "http_sd"; /** * protocol redfish */ 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 24e1d15433..0e036d3010 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 @@ -73,14 +73,14 @@ public interface CommonConstants { byte MONITOR_DOWN_CODE = 0x02; /** - * Monitor bind type, 0: monitor that auto-created by sd + * scrape type static */ - byte MONITOR_BIND_TYPE_SD_SUB_MONITOR = 0x00; + String SCRAPE_STATIC = "static"; /** - * Monitor bind type, 1: the main monitor of sd + * scrape type */ - byte MONITOR_BIND_TYPE_SD_MAIN_MONITOR = 0x01; + String SCRAPE_HTTP_SD = "http_sd"; /** * label key: instance @@ -192,11 +192,6 @@ public interface CommonConstants { */ String PROM_VALUE = "value"; - /** - * Monitor total availability metrics - */ - String AVAILABILITY = "availability"; - /** * Parameter Type Number */ @@ -222,104 +217,6 @@ public interface CommonConstants { */ byte PARAM_TYPE_ARRAY = 4; - /** - * Authentication type Account password - */ - byte AUTH_TYPE_PASSWORD = 1; - - /** - * Authentication type GitHub three-party login - */ - byte AUTH_TYPE_GITHUB = 2; - - /** - * Authentication type WeChat three-party login - */ - byte AUTH_TYPE_WEIXIN = 3; - - /** - * Authentication type GITEE three-party login - */ - byte AUTH_TYPE_GITEE = 5; - - /** - * inner default label key __instance__ - */ - String LABEL_INNER_KEY_INSTANCE = "__instance__"; - - /** - * Inside the tag: monitorId Monitor task ID - */ - String TAG_MONITOR_ID = "monitorId"; - - /** - * Inside the tag: monitorName Task name - */ - String TAG_MONITOR_NAME = "monitorName"; - - /** - * Inside the tag: indicate that this monitor is auto-created by main monitor - */ - String TAG_AUTO_CREATED = "autoCreated"; - - /** - * Inside the tag: indicate that this monitor is a main monitor which provides service discovery - */ - String TAG_SD_MAIN_MONITOR = "sdMainMonitor"; - - /** - * Inside the tag: monitorHost Task host - */ - String TAG_MONITOR_HOST = "monitorHost"; - - /** - * Inside the tag: policyId Alarm threshold rule ID - */ - String TAG_THRESHOLD_ID = "thresholdId"; - - /** - * Inside the tag: app Type of monitoring - */ - String TAG_MONITOR_APP = "app"; - - /** - * Inside the tag: metrics - */ - String TAG_METRICS = "metrics"; - - /** - * Inside the tag: metric - */ - String TAG_METRIC = "metric"; - - /** - * Inside the tag: code - */ - String TAG_CODE = "code"; - - /** - * Tag Type: Auto-generated - */ - byte TAG_TYPE_AUTO_GENERATE = 0; - /** - * Tag Type: User-generated - */ - byte TAG_TYPE_USER_GENERATE = 1; - /** - * Tag Type: System preset - */ - byte TAG_TYPE_SYSTEM_PRESET = 2; - - /** - * notice_period type Type field, daily type - */ - int NOTICE_PERIOD_DAILY = 0; - - /** - * key is receiver.id, value is noticePeriod cache key prefix - */ - String RECEIVER_NOTICE_PERIOD_CACHE_PREFIX = "receiver_notice_period:"; - /** * cache key notice_rule */ diff --git a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/job/Metrics.java b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/job/Metrics.java index e56bbf93b6..49eafe3ae4 100644 --- a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/job/Metrics.java +++ b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/job/Metrics.java @@ -32,6 +32,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.hertzbeat.common.entity.job.protocol.DnsProtocol; import org.apache.hertzbeat.common.entity.job.protocol.FtpProtocol; import org.apache.hertzbeat.common.entity.job.protocol.HttpProtocol; +import org.apache.hertzbeat.common.entity.job.protocol.HttpSdProtocol; import org.apache.hertzbeat.common.entity.job.protocol.ModbusProtocol; import org.apache.hertzbeat.common.entity.job.protocol.PlcProtocol; import org.apache.hertzbeat.common.entity.job.protocol.RegistryProtocol; @@ -63,7 +64,6 @@ import org.apache.hertzbeat.common.entity.job.protocol.TelnetProtocol; import org.apache.hertzbeat.common.entity.job.protocol.UdpProtocol; import org.apache.hertzbeat.common.entity.job.protocol.WebsocketProtocol; import org.apache.hertzbeat.common.entity.message.CollectRep; -import org.apache.hertzbeat.common.entity.sd.ServiceDiscoveryProtocol; /** * Details of the monitoring metrics collected @@ -74,6 +74,7 @@ import org.apache.hertzbeat.common.entity.sd.ServiceDiscoveryProtocol; @NoArgsConstructor @Builder @Slf4j +@SuppressWarnings("checkstyle:MemberName") public class Metrics { /** @@ -260,9 +261,9 @@ public class Metrics { */ private KafkaProtocol kclient; /** - * Collect sd data protocol + * http sd protocol */ - private ServiceDiscoveryProtocol sdProtocol; + private HttpSdProtocol http_sd; /** * Monitoring configuration information using the public plc protocol */ diff --git a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/job/protocol/CommonRequestProtocol.java b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/job/protocol/CommonRequestProtocol.java index eb1c0d5c9e..b5e0edd6ef 100644 --- a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/job/protocol/CommonRequestProtocol.java +++ b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/job/protocol/CommonRequestProtocol.java @@ -21,7 +21,8 @@ package org.apache.hertzbeat.common.entity.job.protocol; * Define common field method for each protocol in {@link org.apache.hertzbeat.common.entity.job.Metrics} */ public interface CommonRequestProtocol { + void setHost(String host); void setPort(String port); -} \ No newline at end of file +} diff --git a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/SdMonitorParam.java b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/job/protocol/HttpSdProtocol.java similarity index 81% rename from hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/SdMonitorParam.java rename to hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/job/protocol/HttpSdProtocol.java index 33ceb7dbf5..67d50fa6e5 100644 --- a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/SdMonitorParam.java +++ b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/job/protocol/HttpSdProtocol.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.hertzbeat.common.entity.manager; +package org.apache.hertzbeat.common.entity.job.protocol; import lombok.AllArgsConstructor; import lombok.Builder; @@ -23,15 +23,13 @@ import lombok.Data; import lombok.NoArgsConstructor; /** - * sd monitor param + * Dns protocol */ @Data @Builder @AllArgsConstructor @NoArgsConstructor -public class SdMonitorParam { - private String detectedHost; - private String detectedPort; - private Param sdParam; - private Long bizId; -} \ No newline at end of file +public class HttpSdProtocol implements Protocol { + + private String url; +} diff --git a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/Monitor.java b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/Monitor.java index 7133f87d85..31cc545853 100644 --- a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/Monitor.java +++ b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/Monitor.java @@ -77,6 +77,10 @@ public class Monitor { @Size(max = 100) private String app; + @Schema(title = "Scrape type: static | http_sd", example = "static", accessMode = READ_WRITE) + @Size(max = 100) + private String scrape; + @Schema(title = "peer host: ipv4, ipv6, domain name", example = "192.167.25.11", accessMode = READ_WRITE) @Size(max = 100) @HostValid diff --git a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/MonitorBind.java b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/MonitorBind.java index 38ea1d4833..9161447696 100644 --- a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/MonitorBind.java +++ b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/MonitorBind.java @@ -17,7 +17,6 @@ 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.Entity; @@ -27,8 +26,6 @@ import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.Index; import jakarta.persistence.Table; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; import java.time.LocalDateTime; import lombok.AllArgsConstructor; import lombok.Builder; @@ -60,18 +57,16 @@ public class MonitorBind { @Schema(title = "primary id", example = "23") private Long id; - @Schema(title = "collector name", example = "87432674384") + @Schema(title = "key string: ip:port") + private String keyStr; + + @Schema(title = "connect bind id", example = "87432674384") private Long bizId; @Schema(title = "monitor ID", example = "87432674336") @Column(name = "monitor_id") private Long monitorId; - @Schema(title = "Bind type 0: sd", accessMode = READ_WRITE) - @Min(0) - @Max(3) - private byte type; - @Schema(title = "The creator of this record", example = "tom") @CreatedBy private String creator; @@ -87,4 +82,4 @@ public class MonitorBind { @Schema(title = "Record the latest modification time (timestamp in milliseconds)") @LastModifiedDate private LocalDateTime gmtUpdate; -} \ No newline at end of file +} diff --git a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/sd/ServiceDiscoveryProtocol.java b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/sd/ServiceDiscoveryProtocol.java deleted file mode 100644 index 42ef97316c..0000000000 --- a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/sd/ServiceDiscoveryProtocol.java +++ /dev/null @@ -1,67 +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.sd; - -import java.util.Arrays; -import java.util.List; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * service discovery common field - */ -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class ServiceDiscoveryProtocol { - private Long id; - private List<Long> jobIdList; - /** - * sd type - */ - private Type type; - /** - * Target sd sources by which collector updates SDCache. - */ - private String sdSource; - - /** - * sd Type - */ - public enum Type { - HTTP_SD("httpsd"), - ; - - private final String protocolName; - - Type(String protocolName) { - this.protocolName = protocolName; - } - - public static Type getType(String str) { - return Arrays.stream(Type.values()).filter(t -> t.toString().equalsIgnoreCase(str)).findFirst().orElse(null); - } - - public String getProtocolName() { - return protocolName; - } - } -} \ No newline at end of file diff --git a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/support/valid/HostParamValidator.java b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/support/valid/HostParamValidator.java index a30e1c26a8..7462d8c85d 100644 --- a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/support/valid/HostParamValidator.java +++ b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/support/valid/HostParamValidator.java @@ -20,6 +20,7 @@ package org.apache.hertzbeat.common.support.valid; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; import org.apache.hertzbeat.common.util.IpDomainUtil; +import org.springframework.util.StringUtils; /** * Host Param Validator @@ -33,10 +34,13 @@ public class HostParamValidator implements ConstraintValidator<HostValid, String @Override public boolean isValid(String value, ConstraintValidatorContext context) { - if (value != null && value.toLowerCase().contains(HTTP)){ + if (!StringUtils.hasText(value)) { + return true; + } + if (value.toLowerCase().contains(HTTP)){ value = value.replaceFirst(PATTERN_HTTP, BLANK); } - if (value != null && value.toLowerCase().contains(HTTPS)){ + if (value.toLowerCase().contains(HTTPS)){ value = value.replaceFirst(PATTERN_HTTPS, BLANK); } diff --git a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/util/SdMonitorOperator.java b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/util/SdMonitorOperator.java deleted file mode 100644 index ed528584b3..0000000000 --- a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/util/SdMonitorOperator.java +++ /dev/null @@ -1,151 +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.util; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.stream.Collectors; -import org.apache.commons.lang3.StringUtils; -import org.apache.hertzbeat.common.constants.CommonConstants; -import org.apache.hertzbeat.common.entity.job.Configmap; -import org.apache.hertzbeat.common.entity.job.Job; -import org.apache.hertzbeat.common.entity.job.Metrics; -import org.apache.hertzbeat.common.entity.manager.MonitorBind; -import org.apache.hertzbeat.common.entity.manager.Param; -import org.apache.hertzbeat.common.entity.manager.SdMonitorParam; -import org.apache.hertzbeat.common.entity.manager.Label; -import org.apache.hertzbeat.common.entity.sd.ServiceDiscoveryProtocol; - -/** - * Operator for service discovery - */ -public class SdMonitorOperator { - public static Optional<Param> getSdParam(List<Param> params) { - return params.stream() - .filter(param -> StringUtils.isNoneBlank(param.getField(), param.getParamValue())) - .filter(param -> Objects.nonNull(ServiceDiscoveryProtocol.Type.getType(param.getField()))) - .findFirst(); - } - - public static List<Param> removeSdParam(List<Param> params) { - return params.stream() - .filter(param -> Objects.isNull(ServiceDiscoveryProtocol.Type.getType(param.getField()))) - .collect(Collectors.toList()); - } - - public static List<Param> cloneParamList(List<Param> params) { - return params.stream() - .map(Param::clone) - .peek(param -> param.setId(null)) - .collect(Collectors.toList()); - } - - public static MonitorBind buildSdSubMonitorBind(SdMonitorParam sdMonitorParam, long monitorId, Map<String, String> labels) { - if (Objects.isNull(sdMonitorParam.getBizId())) { - return null; - } - labels.put(CommonConstants.TAG_AUTO_CREATED, String.valueOf(sdMonitorParam.getBizId())); - return MonitorBind.builder() - .id(SnowFlakeIdGenerator.generateId()) - .bizId(sdMonitorParam.getBizId()) - .monitorId(monitorId) - .type(CommonConstants.MONITOR_BIND_TYPE_SD_SUB_MONITOR) - .build(); - } - - public static MonitorBind buildSdMainMonitorBind(SdMonitorParam sdMonitorParam, long monitorId) { - if (Objects.isNull(sdMonitorParam.getSdParam())) { - return null; - } - - return MonitorBind.builder() - .id(SnowFlakeIdGenerator.generateId()) - .bizId(sdMonitorParam.getBizId()) - .monitorId(monitorId) - .type(CommonConstants.MONITOR_BIND_TYPE_SD_MAIN_MONITOR) - .build(); - } - - public static Job constructSdJobAndTag(SdMonitorParam sdMonitorParam, Map<String, String> labels, Job appDefine) { - if (Objects.isNull(sdMonitorParam.getSdParam())) { - return appDefine; - } - labels.put(CommonConstants.TAG_SD_MAIN_MONITOR, ServiceDiscoveryProtocol.Type.getType(sdMonitorParam.getSdParam().getField()).name()); - return constructSdJob(appDefine, sdMonitorParam.getSdParam()); - } - - public static Job constructSdJob(Job appDefine, Param sdParam) { - final Job sdJob = appDefine.clone(); - final ServiceDiscoveryProtocol.Type sdType = ServiceDiscoveryProtocol.Type.getType(sdParam.getField()); - List<Metrics> metricsList = Lists.newArrayList(); - Map<String, String> i18n = Maps.newHashMap(); - i18n.put("zh-CN", "监控目标"); - i18n.put("en-US", "Monitor Target"); - List<Metrics.Field> fields = Lists.newArrayList(); - fields.add(Metrics.Field.builder() - .field("host") - .type(CommonConstants.TYPE_STRING) - .i18n(constructSdFieldI18n("主机", "host")) - .build()); - fields.add(Metrics.Field.builder() - .field("port") - .type(CommonConstants.TYPE_STRING) - .i18n(constructSdFieldI18n("端口", "port")) - .build()); - metricsList.add(Metrics.builder() - .name("target") - .fields(fields) - .i18n(i18n) - .protocol(sdType.getProtocolName()) - .sdProtocol(ServiceDiscoveryProtocol.builder() - .sdSource(sdParam.getParamValue()) - .type(sdType) - .build()) - .build()); - - sdJob.setSd(Boolean.TRUE); - sdJob.setMetrics(metricsList); - sdJob.setConfigmap(Lists.newArrayList(new Configmap(sdParam.getField(), sdParam.getParamValue(), sdParam.getType()))); - return sdJob; - } - - public static List<Label> addMainMonitorTag(List<Label> tagList, Param sdParam) { - tagList = tagList.stream() - .filter(tag -> !StringUtils.equals(tag.getName(), CommonConstants.TAG_SD_MAIN_MONITOR)) - .filter(tag -> !StringUtils.equals(tag.getName(), CommonConstants.TAG_AUTO_CREATED)) - .collect(Collectors.toList()); - - tagList.add(Label.builder().name(CommonConstants.TAG_SD_MAIN_MONITOR) - .tagValue(ServiceDiscoveryProtocol.Type.getType(sdParam.getField()).name()) - .type(CommonConstants.TAG_TYPE_AUTO_GENERATE) - .build()); - - return tagList; - } - - private static Map<String, String> constructSdFieldI18n(String zh, String en) { - Map<String, String> i18n = Maps.newHashMap(); - i18n.put("zh-CN", zh); - i18n.put("en-US", en); - return i18n; - } -} diff --git a/hertzbeat-common/src/test/java/org/apache/hertzbeat/common/support/vaild/HostParamValidatorTest.java b/hertzbeat-common/src/test/java/org/apache/hertzbeat/common/support/vaild/HostParamValidatorTest.java index 5b5669d986..b60f77a5b6 100644 --- a/hertzbeat-common/src/test/java/org/apache/hertzbeat/common/support/vaild/HostParamValidatorTest.java +++ b/hertzbeat-common/src/test/java/org/apache/hertzbeat/common/support/vaild/HostParamValidatorTest.java @@ -53,13 +53,13 @@ class HostParamValidatorTest { @Test public void testIsValid() { boolean result = hostParamValidator.isValid(null, context); - assertFalse(result); + assertTrue(result); result = hostParamValidator.isValid("", context); - assertFalse(result); + assertTrue(result); result = hostParamValidator.isValid(" ", context); - assertFalse(result); + assertTrue(result); result = hostParamValidator.isValid("192.168.1.1", context); assertTrue(result); diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/component/sd/ServiceDiscoveryWorker.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/component/sd/ServiceDiscoveryWorker.java index 12c258d29f..f783d34b22 100644 --- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/component/sd/ServiceDiscoveryWorker.java +++ b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/component/sd/ServiceDiscoveryWorker.java @@ -18,25 +18,22 @@ package org.apache.hertzbeat.manager.component.sd; import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import java.util.HashSet; +import java.time.LocalDateTime; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.apache.hertzbeat.common.constants.CommonConstants; import org.apache.hertzbeat.common.entity.arrow.RowWrapper; import org.apache.hertzbeat.common.entity.manager.CollectorMonitorBind; import org.apache.hertzbeat.common.entity.manager.Monitor; import org.apache.hertzbeat.common.entity.manager.MonitorBind; import org.apache.hertzbeat.common.entity.manager.Param; -import org.apache.hertzbeat.common.entity.manager.SdMonitorParam; import org.apache.hertzbeat.common.entity.message.CollectRep; import org.apache.hertzbeat.common.queue.CommonDataQueue; -import org.apache.hertzbeat.common.util.SdMonitorOperator; import org.apache.hertzbeat.manager.dao.CollectorMonitorBindDao; import org.apache.hertzbeat.manager.dao.MonitorBindDao; import org.apache.hertzbeat.manager.dao.MonitorDao; @@ -45,7 +42,6 @@ import org.apache.hertzbeat.manager.scheduler.ManagerWorkerPool; import org.apache.hertzbeat.manager.service.MonitorService; import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Component; -import org.springframework.util.CollectionUtils; /** * Service Discovery Worker @@ -53,6 +49,9 @@ import org.springframework.util.CollectionUtils; @Slf4j @Component public class ServiceDiscoveryWorker implements InitializingBean { + + private static final String FILED_HOST = "host"; + private static final String FILED_PORT = "port"; private final MonitorService monitorService; private final ParamDao paramDao; private final MonitorDao monitorDao; @@ -83,74 +82,73 @@ public class ServiceDiscoveryWorker implements InitializingBean { public void run() { while (!Thread.currentThread().isInterrupted()) { try (final CollectRep.MetricsData metricsData = dataQueue.pollServiceDiscoveryData()) { - Long monitorId = metricsData.getId(); - final Monitor mainMonitor = monitorDao.findMonitorsByIdIn(Sets.newHashSet(monitorId)).get(0); - mainMonitor.getLabels().remove(CommonConstants.TAG_SD_MAIN_MONITOR); + final Monitor mainMonitor = monitorDao.findById(monitorId).orElse(null); + if (mainMonitor == null) { + log.warn("No monitor found for id {}", monitorId); + continue; + } // collector - final Optional<CollectorMonitorBind> collectorBind = collectorMonitorBindDao.findCollectorMonitorBindByMonitorId(mainMonitor.getId()); + final Optional<CollectorMonitorBind> collectorBind = collectorMonitorBindDao.findCollectorMonitorBindByMonitorId(monitorId); String collector = collectorBind.map(CollectorMonitorBind::getCollector).orElse(null); - // param - List<Param> mainMonitorParamList = paramDao.findParamsByMonitorId(mainMonitor.getId()); - mainMonitorParamList = SdMonitorOperator.removeSdParam(mainMonitorParamList); - - final Set<Long> subMonitorIdSet = monitorBindDao.findMonitorBindByBizIdAndType(monitorId, CommonConstants.MONITOR_BIND_TYPE_SD_SUB_MONITOR) - .stream() - .map(MonitorBind::getMonitorId) - .collect(Collectors.toSet()); - final Map<String, List<Monitor>> hostMonitorMap = CollectionUtils.isEmpty(subMonitorIdSet) - ? Maps.newHashMap() - : monitorDao.findMonitorsByIdIn(subMonitorIdSet).stream().collect(Collectors.groupingBy(Monitor::getHost)); - + // params + List<Param> mainMonitorParams = paramDao.findParamsByMonitorId(monitorId); + final Map<String, MonitorBind> subMonitorBindMap = monitorBindDao.findMonitorBindsByBizId(monitorId) + .stream().collect(Collectors.toMap(MonitorBind::getKeyStr, item -> item)); RowWrapper rowWrapper = metricsData.readRow(); - + Map<String, String> fieldsValue = Maps.newHashMapWithExpectedSize(8); while (rowWrapper.hasNextRow()) { rowWrapper = rowWrapper.nextRow(); - - - final String host = rowWrapper.nextCell().getValue(); - final String port = rowWrapper.nextCell().getValue(); - final List<Monitor> monitorList = hostMonitorMap.get(host); - if (CollectionUtils.isEmpty(monitorList)) { - monitorService.addAndSaveMonitorJob(mainMonitor.clone(), SdMonitorOperator.cloneParamList(mainMonitorParamList), collector, - SdMonitorParam.builder() - .detectedHost(host) - .detectedPort(port) - .bizId(mainMonitor.getId()) - .build(), null); - return; + fieldsValue.clear(); + rowWrapper.cellStream().forEach(cell -> { + String value = cell.getValue(); + fieldsValue.put(cell.getField().getName(), value); + }); + final String host = fieldsValue.get(FILED_HOST); + final String port = fieldsValue.get(FILED_PORT); + final String keyStr = host + ":" + port; + if (subMonitorBindMap.containsKey(keyStr)) { + subMonitorBindMap.remove(keyStr); + continue; } - - for (Monitor monitor : monitorList) { - // make sure monitor that has the same host and port is not existed. - final Optional<Param> samePortParam = paramDao.findParamsByMonitorId(monitor.getId()).stream() - .filter(param -> StringUtils.equals(param.getField(), "port")) - .filter(param -> StringUtils.equals(param.getParamValue(), port)) - .findFirst(); - if (samePortParam.isEmpty()) { - monitorService.addAndSaveMonitorJob(mainMonitor.clone(), SdMonitorOperator.cloneParamList(mainMonitorParamList), collector, - SdMonitorParam.builder() - .detectedHost(host) - .detectedPort(port) - .bizId(mainMonitor.getId()) - .build(), null); - } else { - monitorService.enableManageMonitors(Sets.newHashSet(monitor.getId())); + Monitor newMonitor = mainMonitor.clone(); + newMonitor.setId(null); + newMonitor.setHost(host); + newMonitor.setName(newMonitor.getName() + "-" + host + ":" + port); + newMonitor.setScrape(CommonConstants.SCRAPE_STATIC); + newMonitor.setGmtCreate(LocalDateTime.now()); + newMonitor.setGmtUpdate(LocalDateTime.now()); + // replace host port + List<Param> newParams = new LinkedList<>(); + for (Param param : mainMonitorParams) { + Param newParam = param.clone(); + newParam.setId(null); + newParam.setGmtUpdate(null); + newParam.setGmtCreate(null); + if (FILED_HOST.equals(newParam.getField())) { + newParam.setParamValue(host); + } else if (FILED_PORT.equals(newParam.getField())) { + newParam.setParamValue(port); } + newParams.add(newParam); } - - // make sure hostMonitorMap contains monitors that have not judged yet. - hostMonitorMap.remove(host); + monitorService.addMonitor(newMonitor, newParams, collector, null); + MonitorBind monitorBind = MonitorBind.builder() + .bizId(monitorId) + .monitorId(newMonitor.getId()) + .keyStr(keyStr) + .build(); + monitorBindDao.save(monitorBind); } - // hostMonitorMap only contains monitors which are already existed but not in service discovery data // due to monitors that coincide with service discovery data are removed. // Thus, all monitors still in hostMonitorMap need to be cancelled. - final HashSet<Long> needCancelMonitorIdSet = Sets.newHashSet(); - hostMonitorMap.forEach((key, value) -> needCancelMonitorIdSet.addAll(value.stream() - .map(Monitor::getId) - .collect(Collectors.toSet()))); + final Set<Long> needCancelMonitorIdSet = subMonitorBindMap.values().stream() + .map(MonitorBind::getMonitorId).collect(Collectors.toSet()); monitorService.cancelManageMonitors(needCancelMonitorIdSet); + for (Long id : needCancelMonitorIdSet) { + monitorBindDao.deleteMonitorBindByBizIdAndMonitorId(monitorId, id); + } } catch (Exception exception) { log.error(exception.getMessage(), exception); } diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/controller/MonitorsController.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/controller/MonitorsController.java index 73e926c8a4..7ecf8354b2 100644 --- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/controller/MonitorsController.java +++ b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/controller/MonitorsController.java @@ -127,16 +127,4 @@ public class MonitorsController { monitorService.importConfig(file); return ResponseEntity.ok(Message.success("Import success")); } - - - @PostMapping("/copy") - @Operation(summary = "copy monitors by ids", description = "copy monitors by ids") - public ResponseEntity<Message<Void>> duplicateMonitors( - @Parameter(description = "Monitor ID List", example = "6565463543") @RequestParam List<Long> ids - ) { - if (ids != null && !ids.isEmpty()) { - monitorService.copyMonitors(ids); - } - return ResponseEntity.ok(Message.success("copy success")); - } } diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/dao/MonitorBindDao.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/dao/MonitorBindDao.java index bc7d6d877d..82eb54d4ed 100644 --- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/dao/MonitorBindDao.java +++ b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/dao/MonitorBindDao.java @@ -18,22 +18,20 @@ package org.apache.hertzbeat.manager.dao; import java.util.List; -import java.util.Set; import org.apache.hertzbeat.common.entity.manager.MonitorBind; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Modifying; /** - * AuthResources database operation + * MonitorBind database operation */ public interface MonitorBindDao extends JpaRepository<MonitorBind, Long>, JpaSpecificationExecutor<MonitorBind> { - List<MonitorBind> findAllByBizIdInAndType(Set<Long> bizIdList, byte type); - List<MonitorBind> findMonitorBindByBizIdAndType(Long bizId, byte type); - - MonitorBind findMonitorBindByBizIdAndMonitorIdAndType(Long bizId, Long monitorId, byte type); - - List<MonitorBind> findAllByType(byte type); + List<MonitorBind> findMonitorBindsByBizId(Long bizId); void deleteByMonitorId(Long monitorId); -} \ No newline at end of file + + @Modifying + void deleteMonitorBindByBizIdAndMonitorId(Long bizId, Long monitorId); +} diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/MonitorDto.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/MonitorDto.java index fbae3f7bda..be292fb393 100644 --- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/MonitorDto.java +++ b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/MonitorDto.java @@ -36,12 +36,12 @@ import org.apache.hertzbeat.common.entity.manager.Param; @Schema(description = "Monitoring information entities") public class MonitorDto { - @Schema(description = "Monitor Content", accessMode = READ_WRITE) + @Schema(description = "monitor content", accessMode = READ_WRITE) @NotNull @Valid private Monitor monitor; - @Schema(description = "Monitor Params", accessMode = READ_WRITE) + @Schema(description = "monitor params", accessMode = READ_WRITE) @NotEmpty @Valid private List<Param> params; diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/scheduler/SchedulerInit.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/scheduler/SchedulerInit.java index 756b08fa0a..592d913f58 100644 --- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/scheduler/SchedulerInit.java +++ b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/scheduler/SchedulerInit.java @@ -19,10 +19,8 @@ package org.apache.hertzbeat.manager.scheduler; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.apache.hertzbeat.common.constants.CommonConstants; import org.apache.hertzbeat.common.entity.dto.CollectorInfo; import org.apache.hertzbeat.common.entity.job.Configmap; @@ -30,13 +28,10 @@ import org.apache.hertzbeat.common.entity.job.Job; import org.apache.hertzbeat.common.entity.manager.Collector; import org.apache.hertzbeat.common.entity.manager.CollectorMonitorBind; import org.apache.hertzbeat.common.entity.manager.Monitor; -import org.apache.hertzbeat.common.entity.manager.MonitorBind; import org.apache.hertzbeat.common.entity.manager.Param; import org.apache.hertzbeat.common.entity.manager.ParamDefine; -import org.apache.hertzbeat.common.util.SdMonitorOperator; import org.apache.hertzbeat.manager.dao.CollectorDao; import org.apache.hertzbeat.manager.dao.CollectorMonitorBindDao; -import org.apache.hertzbeat.manager.dao.MonitorBindDao; import org.apache.hertzbeat.manager.dao.MonitorDao; import org.apache.hertzbeat.manager.dao.ParamDao; import org.apache.hertzbeat.manager.service.AppService; @@ -45,6 +40,7 @@ import org.springframework.boot.CommandLineRunner; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; +import org.springframework.util.StringUtils; /** * scheduler init @@ -77,9 +73,6 @@ public class SchedulerInit implements CommandLineRunner { @Autowired private CollectorMonitorBindDao collectorMonitorBindDao; - - @Autowired - private MonitorBindDao monitorBindDao; @Override public void run(String... args) throws Exception { @@ -98,20 +91,18 @@ public class SchedulerInit implements CommandLineRunner { // init jobs List<Monitor> monitors = monitorDao.findMonitorsByStatusNotInAndJobIdNotNull(List.of(CommonConstants.MONITOR_PAUSED_CODE)); List<CollectorMonitorBind> monitorBinds = collectorMonitorBindDao.findAll(); - final Set<Long> sdMonitorIds = monitorBindDao.findAllByType(CommonConstants.MONITOR_BIND_TYPE_SD_SUB_MONITOR).stream() - .map(MonitorBind::getBizId) - .collect(Collectors.toSet()); Map<Long, String> monitorIdCollectorMap = monitorBinds.stream().collect( Collectors.toMap(CollectorMonitorBind::getMonitorId, CollectorMonitorBind::getCollector)); for (Monitor monitor : monitors) { try { // build collect job entity - Job appDefine = appService.getAppDefine(monitor.getApp()); - List<Param> params = paramDao.findParamsByMonitorId(monitor.getId()); - if (sdMonitorIds.contains(monitor.getId())) { - appDefine = SdMonitorOperator.constructSdJob(appDefine, SdMonitorOperator.getSdParam(params).get()); + boolean isStatic = CommonConstants.SCRAPE_STATIC.equals(monitor.getScrape()) || !StringUtils.hasText(monitor.getScrape()); + String app = isStatic ? monitor.getApp() : monitor.getScrape(); + Job appDefine = appService.getAppDefine(app); + if (!isStatic) { + appDefine.setSd(true); } - + List<Param> params = paramDao.findParamsByMonitorId(monitor.getId()); if (CommonConstants.PROMETHEUS.equals(monitor.getApp())) { appDefine.setApp(CommonConstants.PROMETHEUS_APP_PREFIX + monitor.getName()); } @@ -129,7 +120,7 @@ public class SchedulerInit implements CommandLineRunner { .map(param -> new Configmap(param.getField(), param.getParamValue(), param.getType())).collect(Collectors.toList()); List<ParamDefine> paramDefaultValue = appDefine.getParams().stream() - .filter(item -> StringUtils.isNotBlank(item.getDefaultValue())) + .filter(item -> StringUtils.hasText(item.getDefaultValue())) .toList(); paramDefaultValue.forEach(defaultVar -> { if (configmaps.stream().noneMatch(item -> item.getKey().equals(defaultVar.getField()))) { diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/MonitorService.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/MonitorService.java index ff173393fa..dbc5307404 100644 --- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/MonitorService.java +++ b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/MonitorService.java @@ -22,14 +22,12 @@ import org.apache.hertzbeat.common.entity.grafana.GrafanaDashboard; import org.apache.hertzbeat.common.entity.job.Job; import org.apache.hertzbeat.common.entity.manager.Monitor; import org.apache.hertzbeat.common.entity.manager.Param; -import org.apache.hertzbeat.common.entity.manager.SdMonitorParam; import org.apache.hertzbeat.manager.pojo.dto.AppCount; import org.apache.hertzbeat.manager.pojo.dto.MonitorDto; import org.apache.hertzbeat.manager.support.exception.MonitorDetectException; import org.springframework.data.domain.Page; import org.springframework.web.multipart.MultipartFile; -import java.util.HashSet; import java.util.List; import java.util.Set; @@ -125,14 +123,14 @@ public interface MonitorService { * * @param ids Monitoring ID List */ - void cancelManageMonitors(HashSet<Long> ids); + void cancelManageMonitors(Set<Long> ids); /** * Start the managed monitoring items in batches according to the monitoring ID list * * @param ids Monitoring ID List */ - void enableManageMonitors(HashSet<Long> ids); + void enableManageMonitors(Set<Long> ids); /** * Query the monitoring category and its corresponding monitoring quantity @@ -183,22 +181,13 @@ public interface MonitorService { */ void importConfig(MultipartFile file) throws Exception; - /** - * Copy monitor in batches based on the id - * - * @param ids monitor id - */ - void copyMonitors(List<Long> ids); - /** * update app collect job by app * * @param job job content */ void updateAppCollectJob(Job job); - - void addAndSaveMonitorJob(Monitor monitor, List<Param> params, String collector, SdMonitorParam sdMonitorParam, GrafanaDashboard grafanaDashboard); - + /** * Copy monitor by id * diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/AppServiceImpl.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/AppServiceImpl.java index 5e0be4bc98..b8f62e4235 100644 --- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/AppServiceImpl.java +++ b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/AppServiceImpl.java @@ -270,10 +270,6 @@ public class AppServiceImpl implements AppService, InitializingBean { public List<Hierarchy> getAllAppHierarchy(String lang) { LinkedList<Hierarchy> hierarchies = new LinkedList<>(); for (var job : appDefines.values()) { - // TODO temporarily filter out push to solve the front-end problem, and open it after the subsequent design optimization - if (DispatchConstants.PROTOCOL_PUSH.equalsIgnoreCase(job.getApp())) { - continue; - } queryAppHierarchy(lang, hierarchies, job); } return hierarchies; 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 a74b1af6ea..3e21dfaa4f 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 @@ -23,7 +23,6 @@ import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.Predicate; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.apache.hertzbeat.alert.dao.AlertDefineBindDao; import org.apache.hertzbeat.collector.dispatch.DispatchConstants; import org.apache.hertzbeat.common.constants.CommonConstants; @@ -34,23 +33,19 @@ import org.apache.hertzbeat.common.entity.grafana.GrafanaDashboard; import org.apache.hertzbeat.common.entity.job.Configmap; import org.apache.hertzbeat.common.entity.job.Job; import org.apache.hertzbeat.common.entity.job.Metrics; -import org.apache.hertzbeat.common.entity.job.protocol.CommonRequestProtocol; import org.apache.hertzbeat.common.entity.manager.Collector; import org.apache.hertzbeat.common.entity.manager.CollectorMonitorBind; import org.apache.hertzbeat.common.entity.manager.Monitor; -import org.apache.hertzbeat.common.entity.manager.MonitorBind; import org.apache.hertzbeat.common.entity.manager.Param; import org.apache.hertzbeat.common.entity.manager.ParamDefine; -import org.apache.hertzbeat.common.entity.manager.SdMonitorParam; import org.apache.hertzbeat.common.entity.message.CollectRep; -import org.apache.hertzbeat.common.entity.sd.ServiceDiscoveryProtocol; import org.apache.hertzbeat.common.support.event.MonitorDeletedEvent; import org.apache.hertzbeat.common.util.AesUtil; +import org.apache.hertzbeat.common.util.CommonUtil; import org.apache.hertzbeat.common.util.FileUtil; import org.apache.hertzbeat.common.util.IntervalExpressionUtil; import org.apache.hertzbeat.common.util.IpDomainUtil; import org.apache.hertzbeat.common.util.JsonUtil; -import org.apache.hertzbeat.common.util.SdMonitorOperator; import org.apache.hertzbeat.common.util.SnowFlakeIdGenerator; import org.apache.hertzbeat.grafana.service.DashboardService; import org.apache.hertzbeat.manager.config.ManagerSseManager; @@ -65,7 +60,6 @@ import org.apache.hertzbeat.manager.scheduler.CollectJobScheduling; import org.apache.hertzbeat.manager.service.AppService; import org.apache.hertzbeat.manager.service.ImExportService; import org.apache.hertzbeat.manager.service.MonitorService; -import org.apache.hertzbeat.manager.service.LabelService; import org.apache.hertzbeat.manager.support.exception.MonitorDatabaseException; import org.apache.hertzbeat.manager.support.exception.MonitorDetectException; import org.apache.hertzbeat.warehouse.service.WarehouseService; @@ -81,15 +75,14 @@ import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -109,15 +102,11 @@ public class MonitorServiceImpl implements MonitorService { private static final Long MONITOR_ID_TMP = 1000000000L; private static final byte ALL_MONITOR_STATUS = 9; - private static final int TAG_LENGTH = 2; - private static final String CONTENT_VALUE = MediaType.APPLICATION_OCTET_STREAM_VALUE + SignConstants.SINGLE_MARK + "charset=" + StandardCharsets.UTF_8; private final Map<String, ImExportService> imExportServiceMap = new HashMap<>(); @Autowired private AppService appService; @Autowired - private LabelService tagService; - @Autowired private CollectJobScheduling collectJobScheduling; @Autowired private MonitorDao monitorDao; @@ -147,25 +136,74 @@ public class MonitorServiceImpl implements MonitorService { @Override @Transactional(readOnly = true) public void detectMonitor(Monitor monitor, List<Param> params, String collector) throws MonitorDetectException { - final Optional<Param> sdParam = SdMonitorOperator.getSdParam(params); - - if (sdParam.isPresent()) { - collectOneTimeSdData(monitor, collector, sdParam.get()); - } else { + if (CommonConstants.SCRAPE_STATIC.equals(monitor.getScrape()) || !StringUtils.hasText(monitor.getScrape())) { detectMonitorDirectly(monitor, params, collector); + } else { + detectSdMonitor(monitor, params, collector); } } @Override @Transactional(rollbackFor = Exception.class) public void addMonitor(Monitor monitor, List<Param> params, String collector, GrafanaDashboard grafanaDashboard) throws RuntimeException { - final Optional<Param> sdParam = SdMonitorOperator.getSdParam(params); - if (sdParam.isPresent()) { - addAndSaveMonitorJob(monitor.clone(), params, collector, SdMonitorParam.builder().sdParam(sdParam.get()).build(), grafanaDashboard); - return; + // Apply for monitor id + long monitorId = SnowFlakeIdGenerator.generateId(); + Map<String, String> labels = monitor.getLabels(); + if (labels == null) { + labels = new HashMap<>(8); + monitor.setLabels(labels); + } + // Construct the collection task Job entity + boolean isStatic = CommonConstants.SCRAPE_STATIC.equals(monitor.getScrape()) || !StringUtils.hasText(monitor.getScrape()); + String app = isStatic ? monitor.getApp() : monitor.getScrape(); + Job appDefine = appService.getAppDefine(app); + if (!isStatic) { + appDefine.setSd(true); + } + if (CommonConstants.PROMETHEUS.equals(monitor.getApp())) { + appDefine.setApp(CommonConstants.PROMETHEUS_APP_PREFIX + monitor.getName()); } + appDefine.setMonitorId(monitorId); + appDefine.setDefaultInterval(monitor.getIntervals()); + appDefine.setCyclic(true); + appDefine.setTimestamp(System.currentTimeMillis()); + Map<String, String> metadata = Map.of(CommonConstants.LABEL_INSTANCE_NAME, monitor.getName(), + CommonConstants.LABEL_INSTANCE_HOST, monitor.getHost()); + appDefine.setMetadata(metadata); + appDefine.setLabels(monitor.getLabels()); + appDefine.setAnnotations(monitor.getAnnotations()); + List<Configmap> configmaps = params.stream().map(param -> { + param.setMonitorId(monitorId); + return new Configmap(param.getField(), param.getParamValue(), param.getType()); + }).collect(Collectors.toList()); + appDefine.setConfigmap(configmaps); + long jobId = collector == null ? collectJobScheduling.addAsyncCollectJob(appDefine, null) : + collectJobScheduling.addAsyncCollectJob(appDefine, collector); + try { + detectMonitor(monitor, params, collector); + } catch (Exception ignored) {} - addAndSaveMonitorJob(monitor, params, collector, null, grafanaDashboard); + try { + if (collector != null) { + CollectorMonitorBind collectorMonitorBind = CollectorMonitorBind.builder() + .collector(collector) + .monitorId(monitorId) + .build(); + collectorMonitorBindDao.save(collectorMonitorBind); + } + monitor.setId(monitorId); + monitor.setJobId(jobId); + // create grafana dashboard + if (monitor.getApp().equals(CommonConstants.PROMETHEUS) && grafanaDashboard != null && grafanaDashboard.isEnabled()) { + dashboardService.createOrUpdateDashboard(grafanaDashboard.getTemplate(), monitorId); + } + monitorDao.save(monitor); + paramDao.saveAll(params); + } catch (Exception e) { + log.error("Error while adding monitor: {}", e.getMessage(), e); + collectJobScheduling.cancelAsyncCollectJob(jobId); + throw new MonitorDatabaseException(e.getMessage()); + } } @Override @@ -233,7 +271,7 @@ public class MonitorServiceImpl implements MonitorService { } } // the dispatch collector must exist if pin - if (StringUtils.isNotBlank(monitorDto.getCollector())) { + if (StringUtils.hasText(monitorDto.getCollector())) { Optional<Collector> optionalCollector = collectorDao.findCollectorByName(monitorDto.getCollector()); if (optionalCollector.isEmpty()) { throw new IllegalArgumentException("The pinned collector does not exist."); @@ -250,7 +288,7 @@ public class MonitorServiceImpl implements MonitorService { if (paramDefine.isRequired() && (param == null || param.getParamValue() == null)) { throw new IllegalArgumentException("Params field " + field + " is required."); } - if (param != null && param.getParamValue() != null && StringUtils.isNotBlank(param.getParamValue())) { + if (param != null && StringUtils.hasText(param.getParamValue())) { switch (paramDefine.getType()) { case "number": double doubleValue; @@ -376,7 +414,6 @@ public class MonitorServiceImpl implements MonitorService { @Override @Transactional(rollbackFor = Exception.class) public void modifyMonitor(Monitor monitor, List<Param> params, String collector, GrafanaDashboard grafanaDashboard) throws RuntimeException { - final Optional<Param> sdParam = SdMonitorOperator.getSdParam(params); long monitorId = monitor.getId(); // Check to determine whether the monitor corresponding to the monitor id exists Optional<Monitor> queryOption = monitorDao.findById(monitorId); @@ -393,36 +430,14 @@ public class MonitorServiceImpl implements MonitorService { labels = new HashMap<>(8); monitor.setLabels(labels); } - + boolean isStatic = CommonConstants.SCRAPE_STATIC.equals(monitor.getScrape()) || !StringUtils.hasText(monitor.getScrape()); if (preMonitor.getStatus() != CommonConstants.MONITOR_PAUSED_CODE) { // Construct the collection task Job entity - Job appDefine = appService.getAppDefine(monitor.getApp()); - if (sdParam.isPresent()) { - // not allow to modify a sub monitor to main monitor - labels.entrySet() - .stream() - .filter(label -> org.apache.commons.lang3.StringUtils.equals(label.getKey(), CommonConstants.TAG_AUTO_CREATED)) - .findFirst() - .ifPresent(label -> { - final MonitorBind isSubMonitorBefore = monitorBindDao.findMonitorBindByBizIdAndMonitorIdAndType(Long.valueOf(label.getValue()), - monitorId, CommonConstants.MONITOR_BIND_TYPE_SD_SUB_MONITOR); - if (Objects.nonNull(isSubMonitorBefore)) { - throw new UnsupportedOperationException("Can not change a auto-created monitor to sd! "); - } - }); - // create main monitor bind - final List<MonitorBind> mainMonitorBind = monitorBindDao.findMonitorBindByBizIdAndType(monitorId, CommonConstants.MONITOR_BIND_TYPE_SD_MAIN_MONITOR); - if (CollectionUtils.isEmpty(mainMonitorBind)) { - monitorBindDao.save(Objects.requireNonNull( - SdMonitorOperator.buildSdMainMonitorBind( - SdMonitorParam.builder().sdParam(sdParam.get()).build(), monitorId - ))); - } - - appDefine = SdMonitorOperator.constructSdJob(appDefine, sdParam.get()); - labels.put(CommonConstants.TAG_SD_MAIN_MONITOR, ServiceDiscoveryProtocol.Type.getType(sdParam.get().getField()).name()); + String app = isStatic ? monitor.getApp() : monitor.getScrape(); + Job appDefine = appService.getAppDefine(app); + if (!isStatic) { + appDefine.setSd(true); } - if (CommonConstants.PROMETHEUS.equals(monitor.getApp())) { appDefine.setApp(CommonConstants.PROMETHEUS_APP_PREFIX + monitor.getName()); } @@ -450,8 +465,7 @@ public class MonitorServiceImpl implements MonitorService { // execute only in non paused status try { detectMonitor(monitor, params, collector); - } catch (Exception ignored) { - } + } catch (Exception ignored) {} } // After the update is successfully released, refresh the database @@ -474,12 +488,6 @@ public class MonitorServiceImpl implements MonitorService { } } monitorDao.save(monitor); - - // delete all sub monitor if sd param is removed - final List<MonitorBind> subMonitorBindList = monitorBindDao.findMonitorBindByBizIdAndType(monitorId, CommonConstants.MONITOR_BIND_TYPE_SD_SUB_MONITOR); - if (!CollectionUtils.isEmpty(subMonitorBindList) && sdParam.isEmpty()) { - deleteMonitors(subMonitorBindList.stream().map(MonitorBind::getMonitorId).collect(Collectors.toSet())); - } paramDao.saveAll(params); } catch (Exception e) { log.error(e.getMessage(), e); @@ -501,12 +509,6 @@ public class MonitorServiceImpl implements MonitorService { if (CollectionUtils.isEmpty(ids)) { return; } - - final List<MonitorBind> allSubMonitorBind = monitorBindDao.findAllByBizIdInAndType(ids, CommonConstants.MONITOR_BIND_TYPE_SD_SUB_MONITOR); - if (!CollectionUtils.isEmpty(allSubMonitorBind)) { - ids.addAll(allSubMonitorBind.stream().map(MonitorBind::getMonitorId).collect(Collectors.toSet())); - } - List<Monitor> monitors = monitorDao.findMonitorsByIdIn(ids); if (!monitors.isEmpty()) { monitorDao.deleteAll(monitors); @@ -537,7 +539,9 @@ public class MonitorServiceImpl implements MonitorService { monitorDto.setMetrics(metrics); monitorDto.setGrafanaDashboard(dashboardService.getDashboardByMonitorId(id)); } else { - Job job = appService.getAppDefine(monitor.getApp()); + boolean isStatic = CommonConstants.SCRAPE_STATIC.equals(monitor.getScrape()) || !StringUtils.hasText(monitor.getScrape()); + String type = isStatic ? monitor.getApp() : monitor.getScrape(); + Job job = appService.getAppDefine(type); List<String> metrics = job.getMetrics().stream() .filter(Metrics::isVisible) .map(Metrics::getName).collect(Collectors.toList()); @@ -563,7 +567,7 @@ public class MonitorServiceImpl implements MonitorService { } andList.add(inPredicate); } - if (StringUtils.isNotBlank(app)) { + if (StringUtils.hasText(app)) { Predicate predicateApp = criteriaBuilder.equal(root.get("app"), app); andList.add(predicateApp); } @@ -575,17 +579,17 @@ public class MonitorServiceImpl implements MonitorService { Predicate andPredicate = criteriaBuilder.and(andList.toArray(andPredicates)); List<Predicate> orList = new ArrayList<>(); - if (StringUtils.isNotBlank(search)) { + if (StringUtils.hasText(search)) { Predicate predicateHost = criteriaBuilder.like(root.get("host"), "%" + search + "%"); Predicate predicateName = criteriaBuilder.like(criteriaBuilder.lower(root.get("name")), "%" + search.toLowerCase() + "%"); - if (StringUtils.isNumeric(search)){ + if (CommonUtil.isNumeric(search)){ Predicate predicateId = criteriaBuilder.equal(root.get("id"), Long.parseLong(search)); orList.add(predicateId); } orList.add(predicateHost); orList.add(predicateName); } - if (StringUtils.isNotBlank(labels)) { + if (StringUtils.hasText(labels)) { String[] labelAres = labels.split(","); for (String label : labelAres) { String[] labelArr = label.split(":"); @@ -620,18 +624,10 @@ public class MonitorServiceImpl implements MonitorService { } @Override - public void cancelManageMonitors(HashSet<Long> ids) { + public void cancelManageMonitors(Set<Long> ids) { if (CollectionUtils.isEmpty(ids)) { return; } - - final Set<Long> subMonitorIds = monitorBindDao.findAllByBizIdInAndType(ids, CommonConstants.MONITOR_BIND_TYPE_SD_SUB_MONITOR).stream() - .map(MonitorBind::getMonitorId) - .collect(Collectors.toSet()); - if (!CollectionUtils.isEmpty(subMonitorIds)) { - ids.addAll(subMonitorIds); - } - // Update monitoring status Delete corresponding monitoring periodic task // The jobId is not deleted, and the jobId is reused again after the management is started. List<Monitor> managedMonitors = monitorDao.findMonitorsByIdIn(ids) @@ -648,7 +644,7 @@ public class MonitorServiceImpl implements MonitorService { } @Override - public void enableManageMonitors(HashSet<Long> ids) { + public void enableManageMonitors(Set<Long> ids) { // Update monitoring status Add corresponding monitoring periodic task List<Monitor> unManagedMonitors = monitorDao.findMonitorsByIdIn(ids) .stream().filter(monitor -> @@ -662,20 +658,12 @@ public class MonitorServiceImpl implements MonitorService { for (Monitor monitor : unManagedMonitors) { // Construct the collection task Job entity List<Param> params = paramDao.findParamsByMonitorId(monitor.getId()); - final Optional<Param> sdParam = SdMonitorOperator.getSdParam(params); - Job appDefine = appService.getAppDefine(monitor.getApp()); - if (sdParam.isPresent()) { - final List<MonitorBind> mainMonitorBind = monitorBindDao.findMonitorBindByBizIdAndType(monitor.getId(), CommonConstants.MONITOR_BIND_TYPE_SD_MAIN_MONITOR); - if (CollectionUtils.isEmpty(mainMonitorBind)) { - monitorBindDao.save(Objects.requireNonNull( - SdMonitorOperator.buildSdMainMonitorBind( - SdMonitorParam.builder().sdParam(sdParam.get()).build(), monitor.getId() - ))); - } - - appDefine = SdMonitorOperator.constructSdJob(appDefine, sdParam.get()); + boolean isStatic = CommonConstants.SCRAPE_STATIC.equals(monitor.getScrape()) || !StringUtils.hasText(monitor.getScrape()); + String app = isStatic ? monitor.getApp() : monitor.getScrape(); + Job appDefine = appService.getAppDefine(app); + if (!isStatic) { + appDefine.setSd(true); } - if (CommonConstants.PROMETHEUS.equals(monitor.getApp())) { appDefine.setApp(CommonConstants.PROMETHEUS_APP_PREFIX + monitor.getName()); } @@ -691,7 +679,7 @@ public class MonitorServiceImpl implements MonitorService { List<Configmap> configmaps = params.stream().map(param -> new Configmap(param.getField(), param.getParamValue(), param.getType())).collect(Collectors.toList()); List<ParamDefine> paramDefaultValue = appDefine.getParams().stream() - .filter(item -> StringUtils.isNotBlank(item.getDefaultValue())) + .filter(item -> StringUtils.hasText(item.getDefaultValue())) .toList(); paramDefaultValue.forEach(defaultVar -> { if (configmaps.stream().noneMatch(item -> item.getKey().equals(defaultVar.getField()))) { @@ -752,25 +740,6 @@ public class MonitorServiceImpl implements MonitorService { }).filter(Objects::nonNull).collect(Collectors.toList()); } - @Override - @Transactional(rollbackFor = Exception.class) - public void copyMonitors(List<Long> ids) { - - ids.stream().parallel().forEach(id -> { - // get monitor and Params according id - Optional<Monitor> monitorOpt = monitorDao.findById(id); - List<Param> params = paramDao.findParamsByMonitorId(id); - - monitorOpt.ifPresentOrElse(monitor -> { - // deep copy original monitor to achieve persist in JPA - Monitor newMonitor = JsonUtil.fromJson(JsonUtil.toJson(monitor), Monitor.class); - if (newMonitor != null) { - copyMonitor(newMonitor, params); - } - }, () -> log.warn("can not find the monitor for id :{}", id)); - }); - } - @Override public void updateAppCollectJob(Job job) { List<Monitor> monitors = monitorDao.findMonitorsByAppEquals(job.getApp()) @@ -807,7 +776,7 @@ public class MonitorServiceImpl implements MonitorService { List<Configmap> configmaps = params.stream().map(param -> new Configmap(param.getField(), param.getParamValue(), param.getType())).collect(Collectors.toList()); List<ParamDefine> paramDefaultValue = appDefine.getParams().stream() - .filter(item -> StringUtils.isNotBlank(item.getDefaultValue())) + .filter(item -> StringUtils.hasText(item.getDefaultValue())) .toList(); paramDefaultValue.forEach(defaultVar -> { if (configmaps.stream().noneMatch(item -> item.getKey().equals(defaultVar.getField()))) { @@ -827,80 +796,7 @@ public class MonitorServiceImpl implements MonitorService { } } } - - @Override - public void addAndSaveMonitorJob(Monitor monitor, List<Param> params, String collector, SdMonitorParam sdMonitorParam, GrafanaDashboard grafanaDashboard) { - // Apply for monitor id - long monitorId = SnowFlakeIdGenerator.generateId(); - Map<String, String> labels = monitor.getLabels(); - if (labels == null) { - labels = new HashMap<>(8); - monitor.setLabels(labels); - } - MonitorBind monitorBind = null; - // Construct the collection task Job entity - Job appDefine = appService.getAppDefine(monitor.getApp()); - if (Objects.nonNull(sdMonitorParam)) { - monitorBind = Objects.isNull(sdMonitorParam.getSdParam()) - ? SdMonitorOperator.buildSdSubMonitorBind(sdMonitorParam, monitorId, labels) - : SdMonitorOperator.buildSdMainMonitorBind(sdMonitorParam, monitorId); - - appDefine = SdMonitorOperator.constructSdJobAndTag(sdMonitorParam, labels, appDefine); - } - if (CommonConstants.PROMETHEUS.equals(monitor.getApp())) { - appDefine.setApp(CommonConstants.PROMETHEUS_APP_PREFIX + monitor.getName()); - } - appDefine.setMonitorId(monitorId); - appDefine.setDefaultInterval(monitor.getIntervals()); - appDefine.setCyclic(true); - appDefine.setTimestamp(System.currentTimeMillis()); - Map<String, String> metadata = Map.of(CommonConstants.LABEL_INSTANCE_NAME, monitor.getName(), - CommonConstants.LABEL_INSTANCE_HOST, monitor.getHost()); - appDefine.setMetadata(metadata); - appDefine.setLabels(monitor.getLabels()); - appDefine.setAnnotations(monitor.getAnnotations()); - resetMetricsCommonField(monitor, appDefine, sdMonitorParam); - - List<Configmap> configmaps = params.stream().map(param -> { - param.setMonitorId(monitorId); - return new Configmap(param.getField(), param.getParamValue(), param.getType()); - }).collect(Collectors.toList()); - appDefine.setConfigmap(configmaps); - - long jobId = collector == null ? collectJobScheduling.addAsyncCollectJob(appDefine, null) : - collectJobScheduling.addAsyncCollectJob(appDefine, collector); - - try { - detectMonitor(monitor, params, collector); - } catch (Exception ignored) { - } - - try { - if (collector != null) { - CollectorMonitorBind collectorMonitorBind = CollectorMonitorBind.builder() - .collector(collector) - .monitorId(monitorId) - .build(); - collectorMonitorBindDao.save(collectorMonitorBind); - } - monitor.setId(monitorId); - monitor.setJobId(jobId); - // create grafana dashboard - if (monitor.getApp().equals(CommonConstants.PROMETHEUS) && grafanaDashboard != null && grafanaDashboard.isEnabled()) { - dashboardService.createOrUpdateDashboard(grafanaDashboard.getTemplate(), monitorId); - } - monitorDao.save(monitor); - if (Objects.nonNull(monitorBind)) { - monitorBindDao.save(monitorBind); - } - paramDao.saveAll(params); - } catch (Exception e) { - log.error("Error while adding monitor: {}", e.getMessage(), e); - collectJobScheduling.cancelAsyncCollectJob(jobId); - throw new MonitorDatabaseException(e.getMessage()); - } - } - + @Override public Monitor getMonitor(Long monitorId) { return monitorDao.findById(monitorId).orElse(null); @@ -916,73 +812,69 @@ public class MonitorServiceImpl implements MonitorService { return monitorDao.findMonitorsByAppEquals(app); } - private void resetMetricsCommonField(Monitor monitor, Job appDefine, SdMonitorParam sdMonitorParam) { - if (Objects.isNull(sdMonitorParam) - || org.apache.commons.lang3.StringUtils.isAnyBlank(sdMonitorParam.getDetectedHost(), sdMonitorParam.getDetectedPort())) { - return; - } - - for (Metrics metric : appDefine.getMetrics()) { - Arrays.stream(metric.getClass().getDeclaredFields()) - .filter(field -> metric.getProtocol().equalsIgnoreCase(field.getName())) - .findFirst() - .ifPresent(field -> { - field.setAccessible(true); - final Object obj; - try { - obj = field.get(metric); - if (obj instanceof CommonRequestProtocol protocol) { - protocol.setHost(sdMonitorParam.getDetectedHost()); - protocol.setPort(sdMonitorParam.getDetectedPort()); - } - } catch (IllegalAccessException exception) { - log.warn("Not such field {}", field.getName()); - } - }); + @Override + @Transactional(rollbackFor = Exception.class) + public void copyMonitor(Long id) { + // Get the source monitor information + Optional<Monitor> monitorOptional = monitorDao.findById(id); + if (monitorOptional.isEmpty()) { + throw new IllegalArgumentException("Monitor not found: " + id); } - - monitor.setHost(sdMonitorParam.getDetectedHost()); - Map<String, String> labels = monitor.getLabels(); - if (labels == null) { - labels = new HashMap<>(8); - monitor.setLabels(labels); + Monitor sourceMonitor = monitorOptional.get(); + // Get the parameters of source monitor + List<Param> sourceParams = paramDao.findParamsByMonitorId(id); + // Create new monitor object + Monitor newMonitor = new Monitor(); + // Copy basic properties, exclude ID, jobId and status + BeanUtils.copyProperties(sourceMonitor, newMonitor, "id", "jobId", "status"); + // Set new name + newMonitor.setName(sourceMonitor.getName() + "_copy"); + // Set initial status + newMonitor.setStatus(CommonConstants.MONITOR_UP_CODE); + // Set create and update time + newMonitor.setGmtCreate(LocalDateTime.now()); + newMonitor.setGmtUpdate(LocalDateTime.now()); + // Copy parameters + List<Param> newParams = new ArrayList<>(); + if (!sourceParams.isEmpty()) { + for (Param sourceParam : sourceParams) { + Param newParam = new Param(); + BeanUtils.copyProperties(sourceParam, newParam, "id"); + newParam.setMonitorId(newMonitor.getId()); + newParams.add(newParam); + } } - labels.put(CommonConstants.TAG_MONITOR_HOST, sdMonitorParam.getDetectedHost()); - monitor.setName(monitor.getApp().toUpperCase() + CommonConstants.LOCALE_SEPARATOR + sdMonitorParam.getDetectedHost() - + CommonConstants.LOCALE_SEPARATOR + SnowFlakeIdGenerator.generateId()); + addMonitor(newMonitor, newParams, null, null); } - private void copyMonitor(Monitor monitor, List<Param> params) { - monitor.setName(String.format("%s - copy", monitor.getName())); - addMonitor(monitor, params, null, null); - } - private void collectOneTimeSdData(Monitor monitor, String collector, Param sdParam) { + private void detectSdMonitor(Monitor monitor, List<Param> params, String collector) { Long monitorId = monitor.getId(); if (monitorId == null || monitorId == 0) { monitorId = MONITOR_ID_TMP; } - Job appDefine = appService.getAppDefine(monitor.getApp()); - if (CommonConstants.PROMETHEUS.equals(monitor.getApp())) { - appDefine.setApp(CommonConstants.PROMETHEUS_APP_PREFIX + monitor.getName()); + if (monitor.getScrape() == null || params == null || params.isEmpty()) { + throw new IllegalArgumentException("scrape params is null or empty!"); } + Job appDefine = appService.getAppDefine(monitor.getScrape()); appDefine.setMonitorId(monitorId); appDefine.setCyclic(false); appDefine.setTimestamp(System.currentTimeMillis()); - Map<String, String> metadata = Map.of(CommonConstants.LABEL_INSTANCE_NAME, monitor.getName(), - CommonConstants.LABEL_INSTANCE_HOST, monitor.getHost()); + Map<String, String> metadata = Map.of(CommonConstants.LABEL_INSTANCE_NAME, monitor.getName()); appDefine.setMetadata(metadata); appDefine.setLabels(monitor.getLabels()); appDefine.setAnnotations(monitor.getAnnotations()); - final Job sdJob = SdMonitorOperator.constructSdJob(appDefine, sdParam); + List<Configmap> configmaps = params.stream().map(param -> + new Configmap(param.getField(), param.getParamValue(), param.getType())).collect(Collectors.toList()); + appDefine.setConfigmap(configmaps); + appDefine.setSd(true); List<CollectRep.MetricsData> collectRep; if (collector != null) { - collectRep = collectJobScheduling.collectSyncJobData(sdJob, collector); + collectRep = collectJobScheduling.collectSyncJobData(appDefine, collector); } else { - collectRep = collectJobScheduling.collectSyncJobData(sdJob); + collectRep = collectJobScheduling.collectSyncJobData(appDefine); } monitor.setStatus(CommonConstants.MONITOR_UP_CODE); - // If the detection result fails, a detection exception is thrown if (collectRep == null || collectRep.isEmpty()) { monitor.setStatus(CommonConstants.MONITOR_DOWN_CODE); @@ -1038,95 +930,4 @@ public class MonitorServiceImpl implements MonitorService { } collectRep.forEach(CollectRep.MetricsData::close); } - - @Override - @Transactional(rollbackFor = Exception.class) - public void copyMonitor(Long id) { - // Get the source monitor information - Optional<Monitor> monitorOptional = monitorDao.findById(id); - if (monitorOptional.isEmpty()) { - throw new IllegalArgumentException("Monitor not found: " + id); - } - Monitor sourceMonitor = monitorOptional.get(); - - // Get the parameters of source monitor - List<Param> sourceParams = paramDao.findParamsByMonitorId(id); - - // Create new monitor object - Monitor newMonitor = new Monitor(); - // Copy basic properties, exclude ID, jobId and status - BeanUtils.copyProperties(sourceMonitor, newMonitor, "id", "jobId", "status"); - // Set new name - newMonitor.setName(sourceMonitor.getName() + "_copy"); - // Set initial status - newMonitor.setStatus(CommonConstants.MONITOR_UP_CODE); - // Set create and update time - newMonitor.setGmtCreate(LocalDateTime.now()); - newMonitor.setGmtUpdate(LocalDateTime.now()); - // Generate new ID using snowflake algorithm - newMonitor.setId(SnowFlakeIdGenerator.generateId()); - // Save new monitor - newMonitor = monitorDao.save(newMonitor); - - // Ensure ID is set - if (newMonitor.getId() == null) { - throw new RuntimeException("Failed to generate monitor ID"); - } - - // Copy parameters - if (!sourceParams.isEmpty()) { - List<Param> newParams = new ArrayList<>(); - for (Param sourceParam : sourceParams) { - Param newParam = new Param(); - BeanUtils.copyProperties(sourceParam, newParam, "id"); - newParam.setMonitorId(newMonitor.getId()); - newParams.add(newParam); - } - paramDao.saveAll(newParams); - } - - try { - // Build collect job - Job appDefine = appService.getAppDefine(newMonitor.getApp()); - if (CommonConstants.PROMETHEUS.equals(newMonitor.getApp())) { - appDefine.setApp(CommonConstants.PROMETHEUS_APP_PREFIX + newMonitor.getName()); - } - // Ensure using correct monitor ID - appDefine.setMonitorId(newMonitor.getId()); - appDefine.setDefaultInterval(newMonitor.getIntervals()); - appDefine.setCyclic(true); - appDefine.setTimestamp(System.currentTimeMillis()); - Map<String, String> metadata = Map.of(CommonConstants.LABEL_INSTANCE_NAME, newMonitor.getName(), - CommonConstants.LABEL_INSTANCE_HOST, newMonitor.getHost()); - appDefine.setMetadata(metadata); - appDefine.setLabels(newMonitor.getLabels()); - appDefine.setAnnotations(newMonitor.getAnnotations()); - List<Configmap> configmaps = sourceParams.stream() - .map(param -> new Configmap(param.getField(), param.getParamValue(), param.getType())) - .collect(Collectors.toList()); - appDefine.setConfigmap(configmaps); - - // Get collector configuration from source monitor - Optional<CollectorMonitorBind> bindOptional = - collectorMonitorBindDao.findCollectorMonitorBindByMonitorId(sourceMonitor.getId()); - String collector = bindOptional.map(CollectorMonitorBind::getCollector).orElse(null); - - // Dispatch collect job - long jobId = collectJobScheduling.addAsyncCollectJob(appDefine, collector); - newMonitor.setJobId(jobId); - monitorDao.save(newMonitor); - - // Copy collector binding if exists - if (collector != null) { - CollectorMonitorBind newBind = CollectorMonitorBind.builder() - .collector(collector) - .monitorId(newMonitor.getId()) - .build(); - collectorMonitorBindDao.save(newBind); - } - } catch (Exception e) { - log.error("Create collect job error: {}", e.getMessage(), e); - throw new RuntimeException("Create collect job failed: " + e.getMessage()); - } - } } diff --git a/hertzbeat-manager/src/main/resources/define/app-push.yml b/hertzbeat-manager/src/main/resources/define/app-http_sd.yml similarity index 59% copy from hertzbeat-manager/src/main/resources/define/app-push.yml copy to hertzbeat-manager/src/main/resources/define/app-http_sd.yml index 91bcd15ba7..77b2fbd483 100644 --- a/hertzbeat-manager/src/main/resources/define/app-push.yml +++ b/hertzbeat-manager/src/main/resources/define/app-http_sd.yml @@ -14,67 +14,49 @@ # limitations under the License. # The monitoring type category:service-application service monitoring db-database monitoring custom-custom monitoring os-operating system monitoring -category: service +category: __system__ # Monitoring application type name (consistent with file name) eg: linux windows tomcat mysql aws... -app: push +app: http_sd # The app api i18n name name: - zh-CN: 推送方式监控 - en-US: Push Style Monitor + zh-CN: Http Service Discovery + en-US: Http Service Discovery # Input params define for app api(render web ui by the definition) params: # field-param field key - - field: host + - field: __sd_url__ # name-param field display i18n name name: - zh-CN: 推送模块Host - en-US: Push Module Host + zh-CN: 服务发现地址 + en-US: Service Discovery Url # type-param field type(most mapping the html input type) - type: host - # required-true or false - required: true - # field-param field key - defaultValue: 127.0.0.1 - - field: port - # name-param field display i18n name - name: - zh-CN: 端口 - en-US: Port - # type-param field type(most mapping the html input type) - type: number - # when type is number, range is required - range: '[0,65535]' - # required-true or false - required: true - # default value - defaultValue: 1157 - - field: fields - # name-param field display i18n name - name: - zh-CN: 监控数据字段 - en-US: Metrics fields - # type-param field type(most mapping the html input type) - type: metrics-field + type: text # required-true or false required: true -# collect metrics config list metrics: - # metrics - all - - name: metrics + - name: target i18n: - zh-CN: 指标 - en-US: Metrics + zh-CN: 监控目标 + en-US: Monitor Target # metrics scheduling priority(0->127)->(high->low), metrics with the same priority will be scheduled in parallel # priority 0's metrics is availability metrics, it will be scheduled first, only availability metrics collect success will the scheduling continue priority: 0 + # 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: host + type: 1 + i18n: + zh-CN: Host + en-US: Host + - field: port + type: 1 + i18n: + zh-CN: Port + en-US: Port # the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk - protocol: push - # the config content when protocol is http - push: - # http host: ipv4 ipv6 domain - host: ^_^host^_^ - # http port - port: ^_^port^_^ - # http uri - uri: /api/push + protocol: http_sd + # the config content when protocol is http_sd + http_sd: + url: ^_^__sd_url__^_^ diff --git a/hertzbeat-manager/src/main/resources/define/app-push.yml b/hertzbeat-manager/src/main/resources/define/app-push.yml index 91bcd15ba7..447f101eeb 100644 --- a/hertzbeat-manager/src/main/resources/define/app-push.yml +++ b/hertzbeat-manager/src/main/resources/define/app-push.yml @@ -14,7 +14,7 @@ # limitations under the License. # The monitoring type category:service-application service monitoring db-database monitoring custom-custom monitoring os-operating system monitoring -category: service +category: __system__ # Monitoring application type name (consistent with file name) eg: linux windows tomcat mysql aws... app: push # The app api i18n name diff --git a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/controller/MonitorsControllerTest.java b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/controller/MonitorsControllerTest.java index 5ace90bec7..1ef34b819f 100644 --- a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/controller/MonitorsControllerTest.java +++ b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/controller/MonitorsControllerTest.java @@ -145,15 +145,4 @@ class MonitorsControllerTest { .andExpect(jsonPath("$.code").value("0")) .andExpect(jsonPath("$.msg").value("Import success")); } - - @Test - void duplicateMonitors() throws Exception { - // Mock the behavior of monitorService.copyMonitors - doNothing().when(monitorService).copyMonitors(List.of(6565463543L)); - - // Perform the POST request and verify the response - this.mockMvc.perform(MockMvcRequestBuilders.post("/api/monitors/copy") - .param("ids", "6565463543")) - .andExpect(status().isOk()); - } } 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 07b04305cc..e79a3886aa 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 @@ -744,7 +744,7 @@ class MonitorServiceTest { List<Param> params = Collections.singletonList(new Param()); when(monitorDao.findById(1L)).thenReturn(Optional.of(monitor)); when(paramDao.findParamsByMonitorId(1L)).thenReturn(params); - assertDoesNotThrow(() -> monitorService.copyMonitors(List.of(1L))); + assertDoesNotThrow(() -> monitorService.copyMonitor(1L)); } } diff --git a/web-app/src/app/pojo/Monitor.ts b/web-app/src/app/pojo/Monitor.ts index e84c67831c..5093887d80 100644 --- a/web-app/src/app/pojo/Monitor.ts +++ b/web-app/src/app/pojo/Monitor.ts @@ -21,6 +21,7 @@ export class Monitor { id!: number; name!: string; app!: string; + scrape!: string; host!: string; intervals: number = 60; // Monitoring status 0: Paused, 1: Up, 2: Down diff --git a/web-app/src/app/routes/monitor/monitor-detail/monitor-detail.component.ts b/web-app/src/app/routes/monitor/monitor-detail/monitor-detail.component.ts index eb50e417b3..2362eb547a 100644 --- a/web-app/src/app/routes/monitor/monitor-detail/monitor-detail.component.ts +++ b/web-app/src/app/routes/monitor/monitor-detail/monitor-detail.component.ts @@ -145,6 +145,9 @@ export class MonitorDetailComponent implements OnInit, OnDestroy { if (message.code === 0) { this.monitor = message.data.monitor; this.app = this.monitor?.app; + if (this.monitor.scrape && this.monitor.scrape != 'static') { + this.app = this.monitor.scrape; + } let params: Param[] = message.data.params; params.forEach(param => { if (param.field === 'port') { diff --git a/web-app/src/app/routes/monitor/monitor-edit/monitor-edit.component.html b/web-app/src/app/routes/monitor/monitor-edit/monitor-edit.component.html index 896a201497..32892a6932 100644 --- a/web-app/src/app/routes/monitor/monitor-edit/monitor-edit.component.html +++ b/web-app/src/app/routes/monitor/monitor-edit/monitor-edit.component.html @@ -39,6 +39,9 @@ [paramValueMap]="paramValueMap" [collector]="collector" [collectors]="collectors" + [sdParams]="sdParams" + [sdDefines]="sdDefines" + (scrapeChange)="onScrapeChange($event)" (formCancel)="onCancel()" (formSubmit)="onSubmit($event)" (formDetect)="onDetect($event)" 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 cc92099ddb..26b0f0e9c8 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 @@ -24,8 +24,8 @@ import { I18NService } from '@core'; import { ALAIN_I18N_TOKEN, TitleService } from '@delon/theme'; import { NzNotificationService } from 'ng-zorro-antd/notification'; import { NzUploadFile } from 'ng-zorro-antd/upload'; -import { throwError } from 'rxjs'; -import { switchMap } from 'rxjs/operators'; +import { of, throwError } from 'rxjs'; +import { finalize, switchMap } from 'rxjs/operators'; import { Collector } from '../../../pojo/Collector'; import { GrafanaDashboard } from '../../../pojo/GrafanaDashboard'; @@ -54,6 +54,8 @@ export class MonitorEditComponent implements OnInit { @Inject(ALAIN_I18N_TOKEN) private i18nSvc: I18NService ) {} + sdDefines: ParamDefine[] = []; + sdParams: Param[] = []; paramDefines!: ParamDefine[]; hostName!: string; params!: Param[]; @@ -172,27 +174,142 @@ export class MonitorEditComponent implements OnInit { return this.collectorSvc.getCollectors(); }) ) + .pipe( + switchMap((message: any) => { + if (message.code === 0) { + this.collectors = message.data.content?.map((item: { collector: any }) => item.collector); + } else { + console.warn(message.msg); + } + if (this.monitor.scrape == 'static') { + return of({ code: 0, data: [], msg: '' }); + } else { + return this.appDefineSvc.getAppParamsDefine(this.monitor.scrape); + } + }) + ) .subscribe( message => { if (message.code === 0) { - this.collectors = message.data.content?.map(item => item.collector); + if (message.data.length > 0) { + let params: Param[] = []; + let paramDefines: ParamDefine[] = []; + message.data.forEach(define => { + let param = this.paramValueMap.get(define.field); + if (param === undefined) { + param = new Param(); + param.field = define.field; + if (define.type === 'number') { + param.type = 0; + } else if (define.type === 'key-value') { + param.type = 3; + } else if (define.type === 'array') { + param.type = 4; + } else { + param.type = 1; + } + if (define.type === 'boolean') { + param.paramValue = define.defaultValue == 'true'; + } else if (param.field === 'host') { + param.paramValue = this.monitor.host; + } else if (define.defaultValue != undefined) { + if (define.type === 'number') { + param.paramValue = Number(define.defaultValue); + } else if (define.type === 'boolean') { + param.paramValue = define.defaultValue.toLowerCase() == 'true'; + } else { + param.paramValue = define.defaultValue; + } + } + } else { + if (define.type === 'boolean') { + if (param.paramValue != null) { + param.paramValue = param.paramValue.toLowerCase() == 'true'; + } else { + param.paramValue = false; + } + } + } + define.name = this.i18nSvc.fanyi(`monitor.app.${this.monitor.scrape}.param.${define.field}`); + if (define.placeholder == null && this.i18nSvc.fanyi(`monitor.${define.field}.tip`) != `monitor.${define.field}.tip`) { + define.placeholder = this.i18nSvc.fanyi(`monitor.${define.field}.tip`); + } + params.push(param); + paramDefines.push(define); + }); + this.sdParams = [...params]; + this.sdDefines = [...paramDefines]; + } } else { console.warn(message.msg); } this.isSpinning = false; }, error => { - console.error(error); this.isSpinning = false; } ); } + onScrapeChange(scrapeValue: string) { + this.monitor.scrape = scrapeValue; + if (this.monitor.scrape !== 'static') { + this.isSpinning = true; + let queryScrapeDefine$ = this.appDefineSvc + .getAppParamsDefine(this.monitor.scrape) + .pipe( + finalize(() => { + queryScrapeDefine$.unsubscribe(); + this.isSpinning = false; + }) + ) + .subscribe(message => { + if (message.code === 0) { + let params: Param[] = []; + let paramDefines: ParamDefine[] = []; + message.data.forEach(define => { + let param = new Param(); + param.field = define.field; + if (define.type === 'number') { + param.type = 0; + } else if (define.type === 'key-value') { + param.type = 3; + } else if (define.type === 'array') { + param.type = 4; + } else { + param.type = 1; + } + if (define.type === 'boolean') { + param.paramValue = false; + } + if (define.defaultValue != undefined) { + if (define.type === 'number') { + param.paramValue = Number(define.defaultValue); + } else if (define.type === 'boolean') { + param.paramValue = define.defaultValue.toLowerCase() == 'true'; + } else { + param.paramValue = define.defaultValue; + } + } + define.name = this.i18nSvc.fanyi(`monitor.app.${this.monitor.scrape}.param.${define.field}`); + if (define.placeholder == null && this.i18nSvc.fanyi(`monitor.${define.field}.tip`) != `monitor.${define.field}.tip`) { + define.placeholder = this.i18nSvc.fanyi(`monitor.${define.field}.tip`); + } + params.push(param); + paramDefines.push(define); + }); + this.sdParams = [...params]; + this.sdDefines = [...paramDefines]; + } + }); + } + } + onSubmit(info: any) { let addMonitor = { monitor: info.monitor, collector: info.collector, - params: info.params.concat(info.advancedParams), + params: info.params.concat(info.advancedParams).concat(info.sdParams), grafanaDashboard: info.grafanaDashboard }; this.spinningTip = 'Loading...'; @@ -218,7 +335,7 @@ export class MonitorEditComponent implements OnInit { let detectMonitor = { monitor: info.monitor, collector: info.collector, - params: info.params.concat(info.advancedParams) + params: info.params.concat(info.advancedParams).concat(info.sdParams) }; this.spinningTip = this.i18nSvc.fanyi('monitor.spinning-tip.detecting'); this.isSpinning = true; 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 383c84961c..ce12b5b82b 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 @@ -21,6 +21,45 @@ <div class="-inner-content"> <form nz-form #form="ngForm"> <nz-form-item> + <nz-form-control nzSpan="4" nzOffset="9" [nzErrorTip]="'validation.required' | i18n"> + <nz-select + style="text-align: center" + [nzDropdownStyle]="{ textAlign: 'center' }" + [(ngModel)]="monitor.scrape" + name="scrape" + (ngModelChange)="onScrapeChange($event)" + > + <nz-option nzValue="static" [nzLabel]="'monitor.scrape.type.static' | i18n"></nz-option> + <nz-option nzValue="http_sd" [nzLabel]="'monitor.scrape.type.http_sd' | i18n"></nz-option> + </nz-select> + </nz-form-control> + </nz-form-item> + + <ng-container *ngIf="monitor.scrape != 'static'"> + <ng-container *ngFor="let sdPramDefine of sdDefines; let i = index"> + <nz-form-item *ngIf="sdParams[i].display !== false"> + <nz-form-label nzSpan="7" [nzRequired]="sdPramDefine.required" [nzFor]="sdPramDefine.field" + >{{ sdPramDefine.name }} + </nz-form-label> + <nz-form-control nzSpan="8" [nzErrorTip]="'validation.required' | i18n"> + <app-form-field + [item]="sdPramDefine" + [name]="sdPramDefine.field" + [(ngModel)]="sdParams[i].paramValue" + (ngModelChange)=" + sdPramDefine.type === 'boolean' + ? onParamBooleanChanged($event, sdPramDefine.field) + : sdPramDefine.type === 'radio' + ? onDependChanged($event, sdPramDefine.field) + : null + " + /> + </nz-form-control> + </nz-form-item> + </ng-container> + </ng-container> + + <nz-form-item *ngIf="monitor.scrape == 'static'"> <nz-form-label nzSpan="7" [nzRequired]="true" [nzFor]="'host'">{{ hostName ? hostName : ('monitor.host' | i18n) }} </nz-form-label> <nz-form-control nzSpan="8" [nzErrorTip]="'validation.required' | i18n"> <app-form-field @@ -53,6 +92,8 @@ </nz-form-control> </nz-form-item> + <nz-divider></nz-divider> + <ng-container *ngFor="let paramDefine of paramDefines; let i = index"> <nz-form-item *ngIf="params[i].display !== false && paramDefine.field !== 'host'"> <nz-form-label nzSpan="7" [nzRequired]="paramDefine.required" [nzFor]="paramDefine.field">{{ paramDefine.name }} </nz-form-label> 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 f8403a6b3b..97e888974a 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 @@ -46,11 +46,14 @@ export class MonitorFormComponent implements OnChanges { @Input() paramDefines!: ParamDefine[]; @Input() advancedParamDefines!: ParamDefine[]; @Input() paramValueMap!: Map<String, Param>; + @Input() sdDefines!: ParamDefine[]; + @Input() sdParams!: Param[]; @Output() readonly formSubmit = new EventEmitter<any>(); @Output() readonly formCancel = new EventEmitter<any>(); @Output() readonly formDetect = new EventEmitter<any>(); @Output() readonly hostChange = new EventEmitter<string>(); + @Output() readonly scrapeChange = new EventEmitter<string>(); @Output() readonly collectorChange = new EventEmitter<string>(); hasAdvancedParams: boolean = false; @@ -87,7 +90,7 @@ export class MonitorFormComponent implements OnChanges { }); return; } - this.monitor.host = this.monitor.host.trim(); + this.monitor.host = this.monitor.host ? this.monitor.host.trim() : ''; this.monitor.name = this.monitor.name.trim(); // todo Set the host property value separately for now this.params.forEach(param => { @@ -103,7 +106,18 @@ export class MonitorFormComponent implements OnChanges { param.paramValue = (param.paramValue as string).trim(); } }); - this.formDetect.emit({ monitor: this.monitor, params: this.params, advancedParams: this.advancedParams, collector: this.collector }); + this.sdParams.forEach(param => { + if (param.paramValue != null && typeof param.paramValue == 'string') { + param.paramValue = (param.paramValue as string).trim(); + } + }); + this.formDetect.emit({ + monitor: this.monitor, + sdParams: this.sdParams, + params: this.params, + advancedParams: this.advancedParams, + collector: this.collector + }); } onSubmit(formGroup: FormGroup) { @@ -132,8 +146,14 @@ export class MonitorFormComponent implements OnChanges { param.paramValue = (param.paramValue as string).trim(); } }); + this.sdParams.forEach(param => { + if (param.paramValue != null && typeof param.paramValue == 'string') { + param.paramValue = (param.paramValue as string).trim(); + } + }); this.formSubmit.emit({ monitor: this.monitor, + sdParams: this.sdParams, params: this.params, advancedParams: this.advancedParams, collector: this.collector, @@ -145,6 +165,10 @@ export class MonitorFormComponent implements OnChanges { this.formCancel.emit(); } + onScrapeChange(scrape: string) { + this.scrapeChange.emit(scrape); + } + onHostChange(host: string) { this.hostChange.emit(host); } @@ -193,6 +217,17 @@ export class MonitorFormComponent implements OnChanges { } } }); + this.sdDefines.forEach((paramDefine, index) => { + if (paramDefine.depend) { + let fieldValues = new Map(Object.entries(paramDefine.depend)).get(dependField); + if (fieldValues) { + this.sdParams[index].display = false; + if (fieldValues.map(String).includes(dependValue)) { + this.sdParams[index].display = true; + } + } + } + }); this.advancedParamDefines.forEach((advancedParamDefine, index) => { if (advancedParamDefine.depend) { let fieldValues = new Map(Object.entries(advancedParamDefine.depend)).get(dependField); 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 b8f6fdf5b3..23438d721a 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 @@ -174,6 +174,7 @@ <div class="monitor-card-info"> <div class="monitor-card-info-item host-item"> <button + *ngIf="data.scrape == 'static' || !data.scrape" nz-button nzType="text" [cdkCopyToClipboard]="data.host" @@ -184,6 +185,10 @@ <i nz-icon nzType="global"></i> {{ data.host }} </button> + <button nz-button nzType="text" *ngIf="data.scrape && data.scrape != 'static'"> + <i nz-icon nzType="partition"></i> + {{ 'monitor.scrape.type.' + data.scrape | i18n }} + </button> <button nz-button nz-dropdown [nzDropdownMenu]="actionMenu" class="action-button"> <span nz-icon nzType="ellipsis"></span> 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 9302e780c8..83caede859 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 @@ -28,7 +28,6 @@ import { NzUploadChangeParam } from 'ng-zorro-antd/upload'; import { finalize } from 'rxjs/operators'; import { Monitor } from '../../../pojo/Monitor'; -import { AppDefineService } from '../../../service/app-define.service'; import { MemoryStorageService } from '../../../service/memory-storage.service'; import { MonitorService } from '../../../service/monitor.service'; import { findDeepestSelected, renderLabelColor } from '../../../shared/utils/common-util'; @@ -46,7 +45,6 @@ export class MonitorListComponent implements OnInit, OnDestroy { private notifySvc: NzNotificationService, private monitorSvc: MonitorService, private storageSvc: MemoryStorageService, - private appDefineSvc: AppDefineService, private menuService: MenuService, @Inject(ALAIN_I18N_TOKEN) private i18nSvc: I18NService ) {} @@ -506,43 +504,29 @@ export class MonitorListComponent implements OnInit, OnDestroy { onAppSwitchModalOpen() { this.appSwitchModalVisible = true; this.appSearchLoading = true; - const getHierarchy$ = this.appDefineSvc - .getAppHierarchy(this.i18nSvc.defaultLang) - .pipe( - finalize(() => { - getHierarchy$.unsubscribe(); - this.appSearchLoading = false; - }) - ) - .subscribe( - message => { - if (message.code === 0) { - let appMenus: Record<string, any> = {}; - message.data.forEach((app: any) => { - let menus = appMenus[app.category]; - app.categoryLabel = this.i18nSvc.fanyi(`menu.monitor.${app.category}`); - if (app.categoryLabel == `menu.monitor.${app.category}`) { - app.categoryLabel = app.category.toUpperCase(); - } - if (menus == undefined) { - menus = { label: app.categoryLabel, child: [app] }; - } else { - menus.child.push(app); - } - appMenus[app.category] = menus; - }); - this.appSearchOrigin = Object.entries(appMenus); - this.appSearchOrigin.sort((a, b) => { - return b[1].length - a[1].length; - }); - } else { - console.warn(message.msg); - } - }, - error => { - console.warn(error.msg); - } - ); + let appMenus: Record<string, any> = {}; + let hierarchy: any[] = this.storageSvc.getData('hierarchy'); + hierarchy.forEach((app: any) => { + if (app.category == '__system__') { + return; + } + let menus = appMenus[app.category]; + app.categoryLabel = this.i18nSvc.fanyi(`menu.monitor.${app.category}`); + if (app.categoryLabel == `menu.monitor.${app.category}`) { + app.categoryLabel = app.category.toUpperCase(); + } + if (menus == undefined) { + menus = { label: app.categoryLabel, child: [app] }; + } else { + menus.child.push(app); + } + appMenus[app.category] = menus; + }); + this.appSearchOrigin = Object.entries(appMenus); + this.appSearchOrigin.sort((a, b) => { + return b[1].length - a[1].length; + }); + this.appSearchLoading = false; } onAppSwitchModalCancel() { diff --git a/web-app/src/app/routes/monitor/monitor-new/monitor-new.component.html b/web-app/src/app/routes/monitor/monitor-new/monitor-new.component.html index 8978a7ef46..4511bf0ed1 100644 --- a/web-app/src/app/routes/monitor/monitor-new/monitor-new.component.html +++ b/web-app/src/app/routes/monitor/monitor-new/monitor-new.component.html @@ -38,6 +38,9 @@ [advancedParamDefines]="advancedParamDefines" [collector]="collector" [collectors]="collectors" + [sdParams]="sdParams" + [sdDefines]="sdDefines" + (scrapeChange)="onScrapeChange($event)" (hostChange)="onHostChange($event)" (formCancel)="onCancel()" (formSubmit)="onSubmit($event)" 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 ad4e18dc7a..ff700dd452 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 @@ -22,7 +22,8 @@ import { ActivatedRoute, ParamMap, Router } from '@angular/router'; import { I18NService } from '@core'; import { ALAIN_I18N_TOKEN, TitleService } from '@delon/theme'; import { NzNotificationService } from 'ng-zorro-antd/notification'; -import { switchMap } from 'rxjs/operators'; +import { of } from 'rxjs'; +import { finalize, switchMap } from 'rxjs/operators'; import { Collector } from '../../../pojo/Collector'; import { GrafanaDashboard } from '../../../pojo/GrafanaDashboard'; @@ -41,6 +42,8 @@ import { generateReadableRandomString } from '../../../shared/utils/common-util' styles: [] }) export class MonitorNewComponent implements OnInit { + sdDefines: ParamDefine[] = []; + sdParams: Param[] = []; paramDefines!: ParamDefine[]; hostName!: string; params!: Param[]; @@ -75,6 +78,7 @@ export class MonitorNewComponent implements OnInit { if (this.monitor.app == '') { this.router.navigateByUrl('/monitors/new?app=website'); } + this.monitor.scrape = paramMap.get('scrape') || 'static'; this.titleSvc.setTitleByI18n(`monitor.app.${this.monitor.app}`); this.isSpinning = true; return this.appDefineSvc.getAppParamsDefine(this.monitor.app); @@ -140,21 +144,125 @@ export class MonitorNewComponent implements OnInit { return this.collectorSvc.getCollectors(); }) ) + .pipe( + switchMap((message: any) => { + if (message.code === 0) { + this.collectors = message.data.content?.map((item: { collector: any }) => item.collector); + } else { + console.warn(message.msg); + } + if (this.monitor.scrape == 'static') { + return of({ code: 0, data: [], msg: '' }); + } else { + return this.appDefineSvc.getAppParamsDefine(this.monitor.scrape); + } + }) + ) .subscribe( message => { if (message.code === 0) { - this.collectors = message.data.content?.map(item => item.collector); + if (message.data.length > 0) { + let params: Param[] = []; + let paramDefines: ParamDefine[] = []; + message.data.forEach(define => { + let param = new Param(); + param.field = define.field; + if (define.type === 'number') { + param.type = 0; + } else if (define.type === 'key-value') { + param.type = 3; + } else if (define.type === 'array') { + param.type = 4; + } else { + param.type = 1; + } + if (define.type === 'boolean') { + param.paramValue = false; + } + if (define.defaultValue != undefined) { + if (define.type === 'number') { + param.paramValue = Number(define.defaultValue); + } else if (define.type === 'boolean') { + param.paramValue = define.defaultValue.toLowerCase() == 'true'; + } else { + param.paramValue = define.defaultValue; + } + } + define.name = this.i18nSvc.fanyi(`monitor.app.${this.monitor.scrape}.param.${define.field}`); + if (define.placeholder == null && this.i18nSvc.fanyi(`monitor.${define.field}.tip`) != `monitor.${define.field}.tip`) { + define.placeholder = this.i18nSvc.fanyi(`monitor.${define.field}.tip`); + } + params.push(param); + paramDefines.push(define); + }); + this.sdParams = [...params]; + this.sdDefines = [...paramDefines]; + } } else { console.warn(message.msg); } this.isSpinning = false; }, error => { - this.isSpinning = true; + this.isSpinning = false; } ); } + onScrapeChange(scrapeValue: string) { + this.monitor.scrape = scrapeValue; + if (this.monitor.scrape !== 'static') { + this.isSpinning = true; + let queryScrapeDefine$ = this.appDefineSvc + .getAppParamsDefine(this.monitor.scrape) + .pipe( + finalize(() => { + queryScrapeDefine$.unsubscribe(); + this.isSpinning = false; + }) + ) + .subscribe(message => { + if (message.code === 0) { + let params: Param[] = []; + let paramDefines: ParamDefine[] = []; + message.data.forEach(define => { + let param = new Param(); + param.field = define.field; + if (define.type === 'number') { + param.type = 0; + } else if (define.type === 'key-value') { + param.type = 3; + } else if (define.type === 'array') { + param.type = 4; + } else { + param.type = 1; + } + if (define.type === 'boolean') { + param.paramValue = false; + } + if (define.defaultValue != undefined) { + if (define.type === 'number') { + param.paramValue = Number(define.defaultValue); + } else if (define.type === 'boolean') { + param.paramValue = define.defaultValue.toLowerCase() == 'true'; + } else { + param.paramValue = define.defaultValue; + } + } + define.name = this.i18nSvc.fanyi(`monitor.app.${this.monitor.scrape}.param.${define.field}`); + if (define.placeholder == null && this.i18nSvc.fanyi(`monitor.${define.field}.tip`) != `monitor.${define.field}.tip`) { + define.placeholder = this.i18nSvc.fanyi(`monitor.${define.field}.tip`); + } + params.push(param); + paramDefines.push(define); + }); + this.sdParams = [...params]; + this.sdDefines = [...paramDefines]; + } + }); + } + } + onHostChange(hostValue: string) { if (this.monitor.name == undefined || this.monitor.name == '') { this.monitor.name = generateReadableRandomString(); @@ -165,7 +273,7 @@ export class MonitorNewComponent implements OnInit { let addMonitor = { monitor: info.monitor, collector: info.collector, - params: info.params.concat(info.advancedParams), + params: info.params.concat(info.advancedParams).concat(info.sdParams), grafanaDashboard: info.grafanaDashboard }; this.spinningTip = 'Loading...'; @@ -191,7 +299,7 @@ export class MonitorNewComponent implements OnInit { let detectMonitor = { monitor: info.monitor, collector: info.collector, - params: info.params.concat(info.advancedParams) + params: info.params.concat(info.advancedParams).concat(info.sdParams) }; this.spinningTip = this.i18nSvc.fanyi('monitor.spinning-tip.detecting'); this.isSpinning = true; diff --git a/web-app/src/app/routes/setting/define/define.component.ts b/web-app/src/app/routes/setting/define/define.component.ts index 7246826f8c..063f05e6e0 100644 --- a/web-app/src/app/routes/setting/define/define.component.ts +++ b/web-app/src/app/routes/setting/define/define.component.ts @@ -94,6 +94,9 @@ export class DefineComponent implements OnInit { if (app.value == 'prometheus') { return; } + if (app.category == '__system__') { + return; + } this.appLabel[app.value] = app.label; let menus = appMenus[app.category]; if (menus == undefined) { diff --git a/web-app/src/assets/i18n/en-US.json b/web-app/src/assets/i18n/en-US.json index b3b778e066..c6b209bcf5 100644 --- a/web-app/src/assets/i18n/en-US.json +++ b/web-app/src/assets/i18n/en-US.json @@ -612,7 +612,7 @@ "menu.monitor.service": "Service Monitor", "menu.monitor.webserver": "Webserver Monitor", "menu.more": "More", - "menu.search.placeholder": "Search Monitoring Task Name、Host etc", + "menu.search.placeholder": "Search Task Name、Host etc", "monitor": "Monitor", "monitor.advanced": "Advanced", "monitor.advanced.tip": "Advanced Setting Params", @@ -709,7 +709,7 @@ "monitor.headerValue.tip": "Header Value", "monitor.holdingRegisterAddresses.tip": "Input RegisterAddress", "monitor.host": "Target Host", - "monitor.host.tip": "The monitored peer ip or domain name", + "monitor.host.tip": "The target peer ip or domain name", "monitor.icon.bigdata": "dot-chart", "monitor.icon.cache": "group", "monitor.icon.center": "laptop", @@ -728,7 +728,7 @@ "monitor.keyword.tip": "Enter keyword which occurrences need to be monitored", "monitor.list": "Monitor List", "monitor.name": "Task Name", - "monitor.name.tip": "Monitoring task name", + "monitor.name.tip": "The unique name that identifies the task", "monitor.new": "New", "monitor.new-monitor": "New Monitor", "monitor.new.failed": "New Monitor Failed", @@ -759,6 +759,8 @@ "monitor.sshPort.tip": "Required When Enabling SSH Tunnel", "monitor.sshUsername.tip": "Required When Enabling SSH Tunnel", "monitor.sshPrivateKey.tip": "BEGIN RSA PRIVATE KEY", + "monitor.scrape.type.static": "Static Scrape", + "monitor.scrape.type.http_sd": "Http Service Discovery", "placeholder.key": "Key", "placeholder.value": "Value", "plugin.delete": "Delete Plugin", diff --git a/web-app/src/assets/i18n/ja-JP.json b/web-app/src/assets/i18n/ja-JP.json index 2354b80ea7..3e93acda1d 100644 --- a/web-app/src/assets/i18n/ja-JP.json +++ b/web-app/src/assets/i18n/ja-JP.json @@ -759,6 +759,8 @@ "monitor.sshPort.tip": "SSHトンネルオープン時に必要", "monitor.sshUsername.tip": "SSHトンネルオープン時に必要", "monitor.sshPrivateKey.tip": "RSA秘密鍵の起動", + "monitor.scrape.type.static": "静的", + "monitor.scrape.type.http_sd": "Http Service Discovery", "placeholder.key": "キー", "placeholder.value": "値", "plugin.delete": "プラグインを削除", diff --git a/web-app/src/assets/i18n/pt-BR.json b/web-app/src/assets/i18n/pt-BR.json index 51e8811e0e..accdda3f03 100644 --- a/web-app/src/assets/i18n/pt-BR.json +++ b/web-app/src/assets/i18n/pt-BR.json @@ -571,6 +571,8 @@ "monitor.sshPort.tip": "Obrigatório quando túnel SSH está ativo", "monitor.sshUsername.tip": "Obrigatório quando túnel SSH está ativo", "monitor.sshPrivateKey.tip": "Chave privada RSA", + "monitor.scrape.type.static": "Estatico", + "monitor.scrape.type.http_sd": "Http Service Discovery", "common.name": "Nome da Métrica", "common.value": "Valor da Métrica", "common.search": "Pesquisar", diff --git a/web-app/src/assets/i18n/zh-CN.json b/web-app/src/assets/i18n/zh-CN.json index 95431dbf07..e62856b83c 100644 --- a/web-app/src/assets/i18n/zh-CN.json +++ b/web-app/src/assets/i18n/zh-CN.json @@ -759,6 +759,8 @@ "monitor.sshPort.tip": "SSH隧道开启时必填", "monitor.sshUsername.tip": "SSH隧道开启时必填", "monitor.sshPrivateKey.tip": "启动RSA私钥", + "monitor.scrape.type.static": "静态配置", + "monitor.scrape.type.http_sd": "Http 服务发现", "placeholder.key": "键", "placeholder.value": "值", "plugin.delete": "刪除插件", diff --git a/web-app/src/assets/i18n/zh-TW.json b/web-app/src/assets/i18n/zh-TW.json index 421e19384c..a9eef93d07 100644 --- a/web-app/src/assets/i18n/zh-TW.json +++ b/web-app/src/assets/i18n/zh-TW.json @@ -758,6 +758,8 @@ "monitor.sshPort.tip": "SSH隧道開啓時必填", "monitor.sshUsername.tip": "SSH隧道開啓時必填", "monitor.sshPrivateKey.tip": "啟動RSA私鑰", + "monitor.scrape.type.static": "靜態配置", + "monitor.scrape.type.http_sd": "Http 服務發現", "placeholder.key": "鍵", "placeholder.value": "值", "plugin.delete": "刪除插件", --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@hertzbeat.apache.org For additional commands, e-mail: notifications-h...@hertzbeat.apache.org