diff --git a/common/src/main/java/org/dromara/hertzbeat/common/entity/dto/CollectorSummary.java b/common/src/main/java/org/dromara/hertzbeat/common/entity/dto/CollectorSummary.java new file mode 100644 index 00000000000..ece2351fac3 --- /dev/null +++ b/common/src/main/java/org/dromara/hertzbeat/common/entity/dto/CollectorSummary.java @@ -0,0 +1,29 @@ +package org.dromara.hertzbeat.common.entity.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.dromara.hertzbeat.common.entity.manager.Collector; + +/** + * collector summary + * @author tom + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Schema(description = "collector summary") +public class CollectorSummary { + + @Schema(description = "the collector info") + private Collector collector; + + @Schema(description = "the number of monitors pinned in this collector") + private int pinMonitorNum; + + @Schema(description = "the number of monitors dispatched in this collector") + private int dispatchMonitorNum; +} diff --git a/home/static/img/home/1.png b/home/static/img/home/1.png index edc50ed8bd1..e2ab8191505 100644 Binary files a/home/static/img/home/1.png and b/home/static/img/home/1.png differ diff --git a/home/static/img/home/9.png b/home/static/img/home/9.png index 8e3d87fdd98..4af89c580af 100644 Binary files a/home/static/img/home/9.png and b/home/static/img/home/9.png differ diff --git a/manager/src/main/java/org/dromara/hertzbeat/manager/controller/CollectorController.java b/manager/src/main/java/org/dromara/hertzbeat/manager/controller/CollectorController.java index 849287f2c1e..d75315c8af7 100644 --- a/manager/src/main/java/org/dromara/hertzbeat/manager/controller/CollectorController.java +++ b/manager/src/main/java/org/dromara/hertzbeat/manager/controller/CollectorController.java @@ -20,10 +20,13 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import org.dromara.hertzbeat.common.entity.dto.CollectorSummary; import org.dromara.hertzbeat.common.entity.dto.Message; import org.dromara.hertzbeat.common.entity.manager.Collector; import org.dromara.hertzbeat.manager.service.CollectorService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.domain.Specification; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -32,7 +35,6 @@ import org.springframework.web.bind.annotation.RestController; import javax.persistence.criteria.Predicate; -import java.util.List; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; @@ -51,8 +53,13 @@ public class CollectorController { @GetMapping @Operation(summary = "Get a list of collectors based on query filter items", description = "根据查询过滤项获取采集器列表") - public ResponseEntity>> getCollectors( - @Parameter(description = "collector name", example = "tom") @RequestParam(required = false) final String name) { + public ResponseEntity>> getCollectors( + @Parameter(description = "collector name", example = "tom") @RequestParam(required = false) final String name, + @Parameter(description = "List current page | 列表当前分页", example = "0") @RequestParam(defaultValue = "0") int pageIndex, + @Parameter(description = "Number of list pagination | 列表分页数量", example = "8") @RequestParam(required = false) Integer pageSize) { + if (pageSize == null) { + pageSize = Integer.MAX_VALUE; + } Specification specification = (root, query, criteriaBuilder) -> { Predicate predicate = criteriaBuilder.conjunction(); if (name != null && !"".equals(name)) { @@ -61,8 +68,9 @@ public ResponseEntity>> getCollectors( } return predicate; }; - List receivers = collectorService.getCollectors(specification); - Message> message = new Message<>(receivers); + PageRequest pageRequest = PageRequest.of(pageIndex, pageSize); + Page receivers = collectorService.getCollectors(specification, pageRequest); + Message> message = new Message<>(receivers); return ResponseEntity.ok(message); } } diff --git a/manager/src/main/java/org/dromara/hertzbeat/manager/service/CollectorService.java b/manager/src/main/java/org/dromara/hertzbeat/manager/service/CollectorService.java index 4c7c4ee5b66..4b38e0d23be 100644 --- a/manager/src/main/java/org/dromara/hertzbeat/manager/service/CollectorService.java +++ b/manager/src/main/java/org/dromara/hertzbeat/manager/service/CollectorService.java @@ -1,10 +1,11 @@ package org.dromara.hertzbeat.manager.service; +import org.dromara.hertzbeat.common.entity.dto.CollectorSummary; import org.dromara.hertzbeat.common.entity.manager.Collector; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.domain.Specification; -import java.util.List; - /** * collector service * @author tom @@ -13,9 +14,11 @@ public interface CollectorService { /** * Dynamic conditional query - * @param specification Query conditions - * @return Search result + * + * @param specification Query conditions + * @param pageRequest pageIndex pageSize + * @return Search result */ - List getCollectors(Specification specification); + Page getCollectors(Specification specification, PageRequest pageRequest); } diff --git a/manager/src/main/java/org/dromara/hertzbeat/manager/service/impl/CollectorServiceImpl.java b/manager/src/main/java/org/dromara/hertzbeat/manager/service/impl/CollectorServiceImpl.java index b7cc111e8a0..b71dd554144 100644 --- a/manager/src/main/java/org/dromara/hertzbeat/manager/service/impl/CollectorServiceImpl.java +++ b/manager/src/main/java/org/dromara/hertzbeat/manager/service/impl/CollectorServiceImpl.java @@ -1,12 +1,19 @@ package org.dromara.hertzbeat.manager.service.impl; +import org.dromara.hertzbeat.common.entity.dto.CollectorSummary; import org.dromara.hertzbeat.common.entity.manager.Collector; import org.dromara.hertzbeat.manager.dao.CollectorDao; +import org.dromara.hertzbeat.manager.scheduler.AssignJobs; +import org.dromara.hertzbeat.manager.scheduler.ConsistentHash; import org.dromara.hertzbeat.manager.service.CollectorService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; +import java.util.LinkedList; import java.util.List; /** @@ -19,8 +26,23 @@ public class CollectorServiceImpl implements CollectorService { @Autowired private CollectorDao collectorDao; + @Autowired + private ConsistentHash consistentHash; + @Override - public List getCollectors(Specification specification) { - return collectorDao.findAll(specification); + public Page getCollectors(Specification specification, PageRequest pageRequest) { + Page collectors = collectorDao.findAll(specification, pageRequest); + List collectorSummaryList = new LinkedList<>(); + for (Collector collector : collectors.getContent()) { + CollectorSummary.CollectorSummaryBuilder summaryBuilder = CollectorSummary.builder().collector(collector); + ConsistentHash.Node node = consistentHash.getNode(collector.getName()); + if (node != null && node.getAssignJobs() != null) { + AssignJobs assignJobs = node.getAssignJobs(); + summaryBuilder.pinMonitorNum(assignJobs.getPinnedJobs().size()); + summaryBuilder.dispatchMonitorNum(assignJobs.getJobs().size()); + } + collectorSummaryList.add(summaryBuilder.build()); + } + return new PageImpl<>(collectorSummaryList, pageRequest, collectors.getTotalElements()); } } diff --git a/manager/src/main/resources/sureness.yml b/manager/src/main/resources/sureness.yml index a3efe2b9a90..f4da6b7aec2 100644 --- a/manager/src/main/resources/sureness.yml +++ b/manager/src/main/resources/sureness.yml @@ -50,6 +50,7 @@ resourceRole: - /api/summary/**===post===[admin,user] - /api/summary/**===put===[admin,user] - /api/summary/**===delete===[admin] + - /api/collector/**===get===[admin,user,guest] # 需要被过滤保护的资源,不认证鉴权直接访问 # /api/v1/source3===get 表示 /api/v1/source3===get 可以被任何人访问 无需登录认证鉴权 diff --git a/web-app/src/app/pojo/CollectorSummary.ts b/web-app/src/app/pojo/CollectorSummary.ts new file mode 100644 index 00000000000..6eb289d63e1 --- /dev/null +++ b/web-app/src/app/pojo/CollectorSummary.ts @@ -0,0 +1,7 @@ +import { Collector } from './Collector'; + +export class CollectorSummary { + collector!: Collector; + pinMonitorNum!: number; + dispatchMonitorNum!: number; +} diff --git a/web-app/src/app/routes/dashboard/dashboard.component.html b/web-app/src/app/routes/dashboard/dashboard.component.html index 5172c01cc62..6e7d33fa84d 100644 --- a/web-app/src/app/routes/dashboard/dashboard.component.html +++ b/web-app/src/app/routes/dashboard/dashboard.component.html @@ -1,5 +1,5 @@
-
+
-
+
-
+
-
+
@@ -100,19 +100,77 @@
-
+
+
+
+
+
+
+ + + + +
+ + {{ + item.collector.status == 0 ? ('monitor.collector.status.online' | i18n) : ('monitor.collector.status.offline' | i18n) + }} + +
+
+ +
+ + {{ item.pinMonitorNum + item.dispatchMonitorNum }} + +
+ {{ 'collector.pinned' | i18n }}: {{ item.pinMonitorNum }} + {{ 'collector.dispatched' | i18n }}: {{ item.dispatchMonitorNum }} +
+
+ +
+ {{ + (item.collector.gmtUpdate | date : 'YYYY-MM-dd HH:mm:ss')?.trim() + }} +
+
+ +
+ {{ item.collector.ip }} +
+
+ +
+ {{ item.collector.name }} +
+
+
+
+ + + + {{ 'collector' | i18n }} : {{ item.collector.name }} + + +
+
+
+
-
+
-
+
-
+
{ dashboard$.unsubscribe(); @@ -288,37 +295,42 @@ export class DashboardComponent implements OnInit, OnDestroy { total = total + (app.size ? app.size : 0); switch (app.category) { case 'service': - this.appCountService.size += app.size; - this.appCountService.availableSize += app.availableSize; - this.appCountService.unAvailableSize += app.unAvailableSize; - this.appCountService.unManageSize += app.unManageSize; + appCountService.size += app.size; + appCountService.availableSize += app.availableSize; + appCountService.unAvailableSize += app.unAvailableSize; + appCountService.unManageSize += app.unManageSize; break; case 'db': - this.appCountDb.size += app.size; - this.appCountDb.availableSize += app.availableSize; - this.appCountDb.unAvailableSize += app.unAvailableSize; - this.appCountDb.unManageSize += app.unManageSize; + appCountDb.size += app.size; + appCountDb.availableSize += app.availableSize; + appCountDb.unAvailableSize += app.unAvailableSize; + appCountDb.unManageSize += app.unManageSize; break; case 'os': - this.appCountOs.size += app.size; - this.appCountOs.availableSize += app.availableSize; - this.appCountOs.unAvailableSize += app.unAvailableSize; - this.appCountOs.unManageSize += app.unManageSize; + appCountOs.size += app.size; + appCountOs.availableSize += app.availableSize; + appCountOs.unAvailableSize += app.unAvailableSize; + appCountOs.unManageSize += app.unManageSize; break; case 'mid': - this.appCountMid.size += app.size; - this.appCountMid.availableSize += app.availableSize; - this.appCountMid.unAvailableSize += app.unAvailableSize; - this.appCountMid.unManageSize += app.unManageSize; + appCountMid.size += app.size; + appCountMid.availableSize += app.availableSize; + appCountMid.unAvailableSize += app.unAvailableSize; + appCountMid.unManageSize += app.unManageSize; break; case 'custom': - this.appCountCustom.size += app.size; - this.appCountCustom.availableSize += app.availableSize; - this.appCountCustom.unAvailableSize += app.unAvailableSize; - this.appCountCustom.unManageSize += app.unManageSize; + appCountCustom.size += app.size; + appCountCustom.availableSize += app.availableSize; + appCountCustom.unAvailableSize += app.unAvailableSize; + appCountCustom.unManageSize += app.unManageSize; break; } }); + this.appCountService = appCountService; + this.appCountOs = appCountOs; + this.appCountDb = appCountDb; + this.appCountMid = appCountMid; + this.appCountCustom = appCountCustom; // @ts-ignore this.appsCountTheme.series[0].data = [{ value: total, name: this.i18nSvc.fanyi('dashboard.monitors.total') }]; // @ts-ignore @@ -406,6 +418,24 @@ export class DashboardComponent implements OnInit, OnDestroy { ); } + refreshCollectorContentList(): void { + let collectorInit$ = this.collectorSvc.getCollectors().subscribe( + message => { + if (message.code === 0) { + this.collectors = message.data.content; + this.cdr.detectChanges(); + } else { + console.warn(message.msg); + } + collectorInit$.unsubscribe(); + }, + error => { + collectorInit$.unsubscribe(); + console.error(error.msg); + } + ); + } + refreshAlertSummary(): void { let alertSummaryInit$ = this.alertSvc.getAlertsSummary().subscribe( message => { 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 65d8a82920c..ca01f2f64a6 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 @@ -319,7 +319,13 @@ {{ 'monitor.collector' | i18n }} - + {{ 'monitor.collector.system.default' | i18n }} 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 03968431b53..3abcecf3cb1 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 @@ -154,7 +154,7 @@ export class MonitorEditComponent implements OnInit { .subscribe( message => { if (message.code === 0) { - this.collectors = message.data; + this.collectors = message.data.content.map(item => item.collector); } else { console.warn(message.msg); } 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 527d7cbb047..1ba91194135 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 @@ -328,7 +328,13 @@ {{ 'monitor.collector' | i18n }} - + {{ 'monitor.collector.system.default' | i18n }} 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 8e77fe4fe8e..fa0f239748c 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 @@ -124,7 +124,7 @@ export class MonitorNewComponent implements OnInit { .subscribe( message => { if (message.code === 0) { - this.collectors = message.data; + this.collectors = message.data.content.map(item => item.collector); } else { console.warn(message.msg); } diff --git a/web-app/src/app/service/collector.service.ts b/web-app/src/app/service/collector.service.ts index 410453b0209..3820e288926 100644 --- a/web-app/src/app/service/collector.service.ts +++ b/web-app/src/app/service/collector.service.ts @@ -3,7 +3,9 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { Collector } from '../pojo/Collector'; +import { CollectorSummary } from '../pojo/CollectorSummary'; import { Message } from '../pojo/Message'; +import { Page } from '../pojo/Page'; const collector_uri = '/collector'; @@ -13,7 +15,7 @@ const collector_uri = '/collector'; export class CollectorService { constructor(private http: HttpClient) {} - public getCollectors(): Observable> { - return this.http.get>(collector_uri); + public getCollectors(): Observable>> { + return this.http.get>>(collector_uri); } } diff --git a/web-app/src/assets/i18n/en-US.json b/web-app/src/assets/i18n/en-US.json index 0c76c49ea25..88de8f546ce 100644 --- a/web-app/src/assets/i18n/en-US.json +++ b/web-app/src/assets/i18n/en-US.json @@ -446,6 +446,14 @@ "settings.server.email.setting": "Configure Email Server", "settings.server.sms": "SMS Server", "settings.server.sms.setting": "Configure SMS Server", + "collector": "Collector", + "collector.status": "Online Status", + "collector.task": "Number of Tasks", + "collector.start-time": "Start Time", + "collector.ip": "IP Address", + "collector.node": "Node Name", + "collector.pinned": "Pinned", + "collector.dispatched": "Dispatched", "validation.email.required": "Please enter your email!", "validation.email.wrong-format": "The email address is in the wrong format!", "validation.password.required": "Please enter your password!", diff --git a/web-app/src/assets/i18n/zh-CN.json b/web-app/src/assets/i18n/zh-CN.json index bf5e6d0a5a4..4310548d7eb 100644 --- a/web-app/src/assets/i18n/zh-CN.json +++ b/web-app/src/assets/i18n/zh-CN.json @@ -444,6 +444,14 @@ "settings.server.email.setting": "配置邮件服务器", "settings.server.sms": "短信服务器", "settings.server.sms.setting": "配置短信服务器", + "collector": "采集器", + "collector.status": "运行状态", + "collector.task": "任务数量", + "collector.start-time": "启动时间", + "collector.ip": "IP地址", + "collector.node": "节点名称", + "collector.pinned": "固定任务", + "collector.dispatched": "调度任务", "validation.email.required": "请输入邮箱地址!", "validation.email.wrong-format": "邮箱地址格式错误!", "validation.email.invalid": "无效的邮箱地址!", diff --git a/web-app/src/assets/i18n/zh-TW.json b/web-app/src/assets/i18n/zh-TW.json index d126558053f..a694281011f 100644 --- a/web-app/src/assets/i18n/zh-TW.json +++ b/web-app/src/assets/i18n/zh-TW.json @@ -442,6 +442,14 @@ "settings.server.email.setting": "配置郵件服務器", "settings.server.sms": "短信服務器", "settings.server.sms.setting": "配置短信服務器", + "collector": "採集器", + "collector.status": "運行狀態", + "collector.task": "任務數量", + "collector.start-time": "啟動時間", + "collector.ip": "IP地址", + "collector.node": "節點名稱", + "collector.pinned": "固定任務", + "collector.dispatched": "調度任務", "validation.email.required": "請輸入郵箱地址!", "validation.email.wrong-format": "郵箱地址格式錯誤!", "validation.email.invalid": "無效的郵箱地址!",