diff --git a/application/src/main/java/org/thingsboard/server/controller/AdminController.java b/application/src/main/java/org/thingsboard/server/controller/AdminController.java index d2e1123d04..c3078e7f83 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AdminController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AdminController.java @@ -21,29 +21,38 @@ import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; -import org.springframework.beans.factory.annotation.Autowired; +import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Lazy; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.async.DeferredResult; import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.rule.engine.api.SmsService; import org.thingsboard.server.common.data.AdminSettings; +import org.thingsboard.server.common.data.SystemInfo; import org.thingsboard.server.common.data.UpdateMessage; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.security.model.JwtPair; +import org.thingsboard.server.common.data.security.model.JwtSettings; import org.thingsboard.server.common.data.security.model.SecuritySettings; import org.thingsboard.server.common.data.sms.config.TestSmsRequest; import org.thingsboard.server.common.data.sync.vc.AutoCommitSettings; import org.thingsboard.server.common.data.sync.vc.RepositorySettings; import org.thingsboard.server.common.data.sync.vc.RepositorySettingsInfo; -import org.thingsboard.server.common.data.security.model.JwtSettings; -import org.thingsboard.server.service.security.auth.jwt.settings.JwtSettingsService; import org.thingsboard.server.dao.settings.AdminSettingsService; import org.thingsboard.server.queue.util.TbCoreComponent; -import org.thingsboard.server.common.data.security.model.JwtPair; +import org.thingsboard.server.service.security.auth.jwt.settings.JwtSettingsService; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.token.JwtTokenFactory; import org.thingsboard.server.service.security.permission.Operation; @@ -51,43 +60,30 @@ import org.thingsboard.server.service.security.permission.Resource; import org.thingsboard.server.service.security.system.SystemSecurityService; import org.thingsboard.server.service.sync.vc.EntitiesVersionControlService; import org.thingsboard.server.service.sync.vc.autocommit.TbAutoCommitSettingsService; +import org.thingsboard.server.service.system.SystemInfoService; import org.thingsboard.server.service.update.UpdateService; -import static org.thingsboard.server.controller.ControllerConstants.*; +import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_AUTHORITY_PARAGRAPH; +import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH; @RestController @TbCoreComponent @RequestMapping("/api/admin") +@RequiredArgsConstructor public class AdminController extends BaseController { - @Autowired - private MailService mailService; - - @Autowired - private SmsService smsService; - - @Autowired - private AdminSettingsService adminSettingsService; - - @Autowired - private SystemSecurityService systemSecurityService; - + private final MailService mailService; + private final SmsService smsService; + private final AdminSettingsService adminSettingsService; + private final SystemSecurityService systemSecurityService; @Lazy - @Autowired - private JwtSettingsService jwtSettingsService; - + private final JwtSettingsService jwtSettingsService; @Lazy - @Autowired - private JwtTokenFactory tokenFactory; - - @Autowired - private EntitiesVersionControlService versionControlService; - - @Autowired - private TbAutoCommitSettingsService autoCommitSettingsService; - - @Autowired - private UpdateService updateService; + private final JwtTokenFactory tokenFactory; + private final EntitiesVersionControlService versionControlService; + private final TbAutoCommitSettingsService autoCommitSettingsService; + private final UpdateService updateService; + private final SystemInfoService systemInfoService; @ApiOperation(value = "Get the Administration Settings object using key (getAdminSettings)", notes = "Get the Administration Settings object using specified string key. Referencing non-existing key will cause an error." + SYSTEM_AUTHORITY_PARAGRAPH) @@ -109,7 +105,6 @@ public class AdminController extends BaseController { } } - @ApiOperation(value = "Get the Administration Settings object using key (getAdminSettings)", notes = "Creates or Updates the Administration Settings. Platform generates random Administration Settings Id during settings creation. " + "The Administration Settings Id will be present in the response. Specify the Administration Settings Id when you would like to update the Administration Settings. " + @@ -318,7 +313,6 @@ public class AdminController extends BaseController { } } - @ApiOperation(value = "Check repository access (checkRepositoryAccess)", notes = "Attempts to check repository access. " + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @@ -399,4 +393,15 @@ public class AdminController extends BaseController { } } + @ApiOperation(value = "Get system info (getSystemInfo)", + notes = "Get main information about system. " + + SYSTEM_AUTHORITY_PARAGRAPH) + @PreAuthorize("hasAuthority('SYS_ADMIN')") + @RequestMapping(value = "/systemInfo", method = RequestMethod.GET) + @ResponseBody + public SystemInfo getSystemInfo() throws ThingsboardException { + return systemInfoService.getSystemInfo(); + + } + } diff --git a/application/src/main/java/org/thingsboard/server/service/system/DefaultSystemInfoService.java b/application/src/main/java/org/thingsboard/server/service/system/DefaultSystemInfoService.java new file mode 100644 index 0000000000..3e9b778a5d --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/system/DefaultSystemInfoService.java @@ -0,0 +1,91 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed 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.thingsboard.server.service.system; + +import com.google.protobuf.ProtocolStringList; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.SystemInfo; +import org.thingsboard.server.gen.transport.TransportProtos; +import org.thingsboard.server.queue.discovery.PartitionService; +import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; +import org.thingsboard.server.queue.util.TbCoreComponent; + +import java.io.File; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryMXBean; +import java.lang.management.OperatingSystemMXBean; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@TbCoreComponent +@Service +@RequiredArgsConstructor +public class DefaultSystemInfoService implements SystemInfoService { + + private final TbServiceInfoProvider serviceInfoProvider; + private final PartitionService partitionService; + + @Value("${zk.enabled:false}") + private boolean zkEnabled; + + @Override + @SneakyThrows + public SystemInfo getSystemInfo() { + SystemInfo systemInfo = new SystemInfo(); + + TransportProtos.ServiceInfo serviceInfo = serviceInfoProvider.getServiceInfo(); + List currentOtherServices = partitionService.getCurrentOtherServices(); + + if (zkEnabled) { + Map serviceInfos = new HashMap<>(); + addServiceInfo(serviceInfos, serviceInfo); + currentOtherServices.forEach(otherInfo -> addServiceInfo(serviceInfos, otherInfo)); + systemInfo.setServiceInfos(serviceInfos); + } else { + systemInfo.setMonolith(true); + systemInfo.setMemUsage(getMemoryUsage()); + + systemInfo.setCpuUsage((int) (getCpuUsage() * 100) / 100.0); + systemInfo.setFreeDiscSpace(getFreeDiscSpace()); + } + + return systemInfo; + } + + private void addServiceInfo(Map serviceInfos, TransportProtos.ServiceInfo serviceInfo) { + ProtocolStringList serviceTypes = serviceInfo.getServiceTypesList(); + serviceInfos.put(serviceInfo.getServiceId(), serviceTypes.size() > 1 ? "MONOLITH" : serviceTypes.get(0)); + } + + private long getMemoryUsage() { + MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); + return memoryMXBean.getHeapMemoryUsage().getUsed(); + } + + private double getCpuUsage() { + OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean(); + return osBean.getSystemLoadAverage(); + } + + private long getFreeDiscSpace() { + File file = new File("/"); + return file.getFreeSpace(); + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/system/SystemInfoService.java b/application/src/main/java/org/thingsboard/server/service/system/SystemInfoService.java new file mode 100644 index 0000000000..3b48d809b2 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/system/SystemInfoService.java @@ -0,0 +1,22 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed 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.thingsboard.server.service.system; + +import org.thingsboard.server.common.data.SystemInfo; + +public interface SystemInfoService { + SystemInfo getSystemInfo(); +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/SystemInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/SystemInfo.java new file mode 100644 index 0000000000..f1aa8b4abe --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/SystemInfo.java @@ -0,0 +1,35 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed 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.thingsboard.server.common.data; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.Map; + +@Data +public class SystemInfo { + @ApiModelProperty(position = 1, value = "Is monolith.") + private boolean isMonolith; + @ApiModelProperty(position = 2, value = "CPU usage.") + private Double cpuUsage; + @ApiModelProperty(position = 3, value = "Memory usage.") + private Long memUsage; + @ApiModelProperty(position = 4, value = "Free disc space.") + private Long freeDiscSpace; + @ApiModelProperty(position = 5, value = "Json object with info about services.") + private Map serviceInfos; +} diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java index 3fc1626f52..6888b9ad8c 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java @@ -17,6 +17,7 @@ package org.thingsboard.server.queue.discovery; import com.google.common.hash.HashFunction; import com.google.common.hash.Hashing; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationEventPublisher; @@ -76,6 +77,7 @@ public class HashPartitionService implements PartitionService { private final ConcurrentMap tenantRoutingInfoMap = new ConcurrentHashMap<>(); private Map> tbTransportServicesByType = new HashMap<>(); + @Getter private List currentOtherServices; private HashFunction hashFunction; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/PartitionService.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/PartitionService.java index f19375984e..3806c59a68 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/PartitionService.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/PartitionService.java @@ -63,4 +63,6 @@ public interface PartitionService { void updateQueue(TransportProtos.QueueUpdateMsg queueUpdateMsg); void removeQueue(TransportProtos.QueueDeleteMsg queueDeleteMsg); + + List getCurrentOtherServices(); }