From e5d4099641047e49f7b9191c0dbeb13980a981dc Mon Sep 17 00:00:00 2001 From: bsc7 <118875465+bsc7@users.noreply.github.com> Date: Thu, 7 Nov 2024 01:04:03 +0100 Subject: [PATCH 1/3] NodeMonitor: FE: +ReportDiffs, +NodeType/UserName: * Rebase/Merge completed due to REST API reorg * ReportDiffs: Compares reports and highlights deviations based on thresholds. * NodeType/UserName: Displays node type and username alongside the address. * Unified BE/FE naming conventions and API endpoints for consistency. --- ReportDiffs enables comparison across all reports and provides average values. It supports three configurable thresholds, which can be adjusted in the settings. Threshold violations are visually highlighted: for subtables, the background of the button that toggles the detail view is marked based on the highest exceeded threshold. --- apps/rest-api-app/build.gradle.kts | 1 + .../rest_api/RestApiApplicationService.java | 36 +-- .../bisq/rest_api/RestApiResourceConfig.java | 2 +- .../bisq/rest_api/proto/AddressDetails.java | 71 ++++++ .../bisq/rest_api/report/ReportRestApi.java | 51 +++- .../src/main/proto/rest_api.proto | 10 + .../src/main/resources/node-monitor/README.md | 54 +++- .../main/resources/node-monitor/index.html | 107 +++++--- .../src/main/resources/node-monitor/index.js | 29 ++- .../resources/node-monitor/js/Constants.js | 89 +++++++ .../resources/node-monitor/js/constants.js | 15 -- .../js/controllers/AppController.js | 129 ++++++++++ .../js/controllers/ReportController.js | 199 +++++++++++++++ .../js/controllers/ReportDiffsController.js | 181 ++++++++++++++ .../js/controllers/appController.js | 201 --------------- .../main/resources/node-monitor/js/errors.js | 49 ++++ .../node-monitor/js/services/DataService.js | 135 ++++++++++ .../js/services/StorageService.js | 165 +++++++++++++ .../node-monitor/js/services/dataService.js | 60 ----- .../js/services/storageService.js | 137 ---------- .../node-monitor/js/utils/DOMUtils.js | 100 ++++++++ .../node-monitor/js/utils/FormatUtils.js | 29 +++ .../node-monitor/js/utils/KeyUtils.js | 83 +++++++ .../node-monitor/js/views/ReportView.js | 233 ++++++++++++++++++ .../node-monitor/js/views/SettingsView.js | 145 +++++++++++ .../node-monitor/js/views/reportView.js | 146 ----------- .../node-monitor/js/views/settingsView.js | 99 -------- .../node-monitor/resources/Bisq2_icon.svg | 82 ++++++ .../resources/node-monitor/styles/global.css | 9 +- .../node-monitor/styles/page-layout.css | 1 + .../node-monitor/styles/reportView.css | 166 ++++++++++++- .../node-monitor/styles/settingsView.css | 92 ++++++- 32 files changed, 2128 insertions(+), 778 deletions(-) create mode 100644 apps/rest-api-app/src/main/java/bisq/rest_api/proto/AddressDetails.java create mode 100644 apps/rest-api-app/src/main/proto/rest_api.proto create mode 100644 apps/rest-api-app/src/main/resources/node-monitor/js/Constants.js delete mode 100644 apps/rest-api-app/src/main/resources/node-monitor/js/constants.js create mode 100644 apps/rest-api-app/src/main/resources/node-monitor/js/controllers/AppController.js create mode 100644 apps/rest-api-app/src/main/resources/node-monitor/js/controllers/ReportController.js create mode 100644 apps/rest-api-app/src/main/resources/node-monitor/js/controllers/ReportDiffsController.js delete mode 100644 apps/rest-api-app/src/main/resources/node-monitor/js/controllers/appController.js create mode 100644 apps/rest-api-app/src/main/resources/node-monitor/js/errors.js create mode 100644 apps/rest-api-app/src/main/resources/node-monitor/js/services/DataService.js create mode 100644 apps/rest-api-app/src/main/resources/node-monitor/js/services/StorageService.js delete mode 100644 apps/rest-api-app/src/main/resources/node-monitor/js/services/dataService.js delete mode 100644 apps/rest-api-app/src/main/resources/node-monitor/js/services/storageService.js create mode 100644 apps/rest-api-app/src/main/resources/node-monitor/js/utils/DOMUtils.js create mode 100644 apps/rest-api-app/src/main/resources/node-monitor/js/utils/FormatUtils.js create mode 100644 apps/rest-api-app/src/main/resources/node-monitor/js/utils/KeyUtils.js create mode 100644 apps/rest-api-app/src/main/resources/node-monitor/js/views/ReportView.js create mode 100644 apps/rest-api-app/src/main/resources/node-monitor/js/views/SettingsView.js delete mode 100644 apps/rest-api-app/src/main/resources/node-monitor/js/views/reportView.js delete mode 100644 apps/rest-api-app/src/main/resources/node-monitor/js/views/settingsView.js create mode 100644 apps/rest-api-app/src/main/resources/node-monitor/resources/Bisq2_icon.svg diff --git a/apps/rest-api-app/build.gradle.kts b/apps/rest-api-app/build.gradle.kts index 93dbe2907d..778519bd16 100644 --- a/apps/rest-api-app/build.gradle.kts +++ b/apps/rest-api-app/build.gradle.kts @@ -1,5 +1,6 @@ plugins { id("bisq.java-library") + id("bisq.protobuf") application } diff --git a/apps/rest-api-app/src/main/java/bisq/rest_api/RestApiApplicationService.java b/apps/rest-api-app/src/main/java/bisq/rest_api/RestApiApplicationService.java index 533637b78c..6e14e0752b 100644 --- a/apps/rest-api-app/src/main/java/bisq/rest_api/RestApiApplicationService.java +++ b/apps/rest-api-app/src/main/java/bisq/rest_api/RestApiApplicationService.java @@ -20,12 +20,8 @@ import bisq.account.AccountService; import bisq.bisq_easy.BisqEasyService; import bisq.bonded_roles.BondedRolesService; -import bisq.bonded_roles.bonded_role.AuthorizedBondedRole; -import bisq.bonded_roles.bonded_role.BondedRole; import bisq.chat.ChatService; import bisq.common.application.Service; -import bisq.common.network.Address; -import bisq.common.network.TransportType; import bisq.common.observable.Observable; import bisq.common.platform.OS; import bisq.common.util.CompletableFutureUtils; @@ -51,13 +47,9 @@ import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import java.util.List; -import java.util.Map; import java.util.Optional; -import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkArgument; import static java.util.concurrent.CompletableFuture.supplyAsync; @@ -102,7 +94,7 @@ public enum State { public RestApiApplicationService(String[] args) { super("rest_api", args); - restApiConfig= getConfig("restApi"); + restApiConfig = getConfig("restApi"); securityService = new SecurityService(persistenceService, SecurityService.Config.from(getConfig("security"))); com.typesafe.config.Config bitcoinWalletConfig = getConfig("bitcoinWallet"); @@ -274,7 +266,6 @@ public KeyBundleService getKeyBundleService() { return securityService.getKeyBundleService(); } - private void setState(State newState) { checkArgument(state.get().ordinal() < newState.ordinal(), "New state %s must have a higher ordinal as the current state %s", newState, state.get()); @@ -300,29 +291,4 @@ private Optional findSystemNotificationDelegate() return Optional.empty(); } } - - public List getAddressList() { - Set
bannedAddresses = bondedRolesService.getAuthorizedBondedRolesService().getBondedRoles().stream() - .filter(BondedRole::isBanned) - .map(BondedRole::getAuthorizedBondedRole) - .map(AuthorizedBondedRole::getAddressByTransportTypeMap) - .filter(Optional::isPresent) - .map(Optional::get) - .flatMap(map -> map.values().stream()) - .collect(Collectors.toSet()); - Map> seedAddressesByTransport = networkService.getSeedAddressesByTransportFromConfig(); - Set supportedTransportTypes = networkService.getSupportedTransportTypes(); - List addresslist = seedAddressesByTransport.entrySet().stream() - .filter(entry -> supportedTransportTypes.contains(entry.getKey())) - .flatMap(entry -> entry.getValue().stream()) - .filter(address -> !bannedAddresses.contains(address)) - .map(Address::toString) - .collect(Collectors.toList()); - - // Oracle Nodes - addresslist.add("kr4yvzlhwt5binpw7js2tsfqv6mjd4klmslmcxw3c5izsaqh5vvsp6ad.onion:36185"); - addresslist.add("s2yxxqvyofzud32mxliya3dihj5rdlowagkblqqtntxhi7cbdaufqkid.onion:54467"); - - return addresslist; - } } diff --git a/apps/rest-api-app/src/main/java/bisq/rest_api/RestApiResourceConfig.java b/apps/rest-api-app/src/main/java/bisq/rest_api/RestApiResourceConfig.java index de8757c3c6..7e1cb6ce78 100644 --- a/apps/rest-api-app/src/main/java/bisq/rest_api/RestApiResourceConfig.java +++ b/apps/rest-api-app/src/main/java/bisq/rest_api/RestApiResourceConfig.java @@ -33,7 +33,7 @@ public RestApiResourceConfig(RestApiApplicationService applicationService, Strin protected void configure() { bind(new SwaggerResolution(baseUrl)).to(SwaggerResolution.class); bind(new UserIdentityRestApi(applicationService.getUserService().getUserIdentityService())).to(UserIdentityRestApi.class); - bind(new ReportRestApi(applicationService.getNetworkService(), applicationService.getBondedRolesService())).to(ReportRestApi.class); + bind(new ReportRestApi(applicationService.getNetworkService(), applicationService.getBondedRolesService(), applicationService.getUserService())).to(ReportRestApi.class); } }); } diff --git a/apps/rest-api-app/src/main/java/bisq/rest_api/proto/AddressDetails.java b/apps/rest-api-app/src/main/java/bisq/rest_api/proto/AddressDetails.java new file mode 100644 index 0000000000..d4819884ef --- /dev/null +++ b/apps/rest-api-app/src/main/java/bisq/rest_api/proto/AddressDetails.java @@ -0,0 +1,71 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.rest_api.proto; + +import bisq.common.proto.NetworkProto; +import bisq.common.proto.Proto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; + +import static com.google.common.base.Preconditions.checkArgument; + +@Slf4j +@Getter +@EqualsAndHashCode +@ToString +@Schema(name = "AddressDetails") +public final class AddressDetails implements NetworkProto { + private final String address; + private final String bondedRoleType; + private final String nickNameOrBondUserName; + + public AddressDetails(String address, String bondedRoleType, String nickNameOrBondUserName) { + this.address = address; + this.bondedRoleType = bondedRoleType; + this.nickNameOrBondUserName = nickNameOrBondUserName; + } + + @Override + public void verify() { + checkArgument(address != null && address.length() > 0); + checkArgument(bondedRoleType != null && bondedRoleType.length() > 0); + checkArgument(nickNameOrBondUserName != null && nickNameOrBondUserName.length() > 0); + } + + @Override + public bisq.rest_api.protobuf.AddressDetails toProto(boolean serializeForHash) { + return resolveProto(serializeForHash); + } + + @Override + public bisq.rest_api.protobuf.AddressDetails.Builder getBuilder(boolean serializeForHash) { + return bisq.rest_api.protobuf.AddressDetails.newBuilder() + .setAddress(this.address) + .setBondedRoleType(this.bondedRoleType) + .setNickNameOrBondUserName(this.nickNameOrBondUserName); + } + + public static AddressDetails fromProto(bisq.rest_api.protobuf.AddressDetails proto) { + return new AddressDetails(proto.getAddress(), + proto.getBondedRoleType(), + proto.getNickNameOrBondUserName()); + } +} diff --git a/apps/rest-api-app/src/main/java/bisq/rest_api/report/ReportRestApi.java b/apps/rest-api-app/src/main/java/bisq/rest_api/report/ReportRestApi.java index 5b63933d03..fbfc49214a 100644 --- a/apps/rest-api-app/src/main/java/bisq/rest_api/report/ReportRestApi.java +++ b/apps/rest-api-app/src/main/java/bisq/rest_api/report/ReportRestApi.java @@ -27,16 +27,15 @@ import bisq.common.util.CompletableFutureUtils; import bisq.network.NetworkService; import bisq.network.p2p.services.reporting.Report; +import bisq.user.UserService; +import bisq.user.profile.UserProfile; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; +import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import lombok.extern.slf4j.Slf4j; @@ -45,6 +44,7 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; @Slf4j @Path("/report") @@ -53,10 +53,14 @@ public class ReportRestApi { private final NetworkService networkService; private final BondedRolesService bondedRolesService; + private final UserService userService; - public ReportRestApi(NetworkService networkService, BondedRolesService bondedRolesService) { + public ReportRestApi(NetworkService networkService, + BondedRolesService bondedRolesService, + UserService userService) { this.networkService = networkService; this.bondedRolesService = bondedRolesService; + this.userService = userService; } @Operation(description = "Get a address list of seed and oracle nodes") @@ -67,7 +71,7 @@ public ReportRestApi(NetworkService networkService, BondedRolesService bondedRol )} ) @GET - @Path("address-list") + @Path("addresses") public List getAddressList() { try { Set
bannedAddresses = bondedRolesService.getAuthorizedBondedRolesService().getBondedRoles().stream() @@ -145,4 +149,39 @@ public List getReports( throw new RestApiException(e); } } + + @GET + @Path("/addresses/details") + @Operation(description = "Get address info for a set of host:port addresses") + @ApiResponse(responseCode = "200", description = "The set of address info (host, role type, nickname or bond name)", + content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = bisq.rest_api.proto.AddressDetails[].class))) + public List getAddressDetailsDto( + @QueryParam("addresses") String addresses) { // Comma-separated list + try { + log.info("Received request to get address infos for: {}", addresses); + List addressList = CollectionUtil.streamFromCsv(addresses).toList(); + return getAddressDetailsProtobufs(addressList); + } catch (Exception e) { + throw new RestApiException(e); + } + } + + public List getAddressDetailsProtobufs(List addressList) { + Set bondedRoles = bondedRolesService.getAuthorizedBondedRolesService().getBondedRoles(); + return bondedRoles.stream() + .flatMap(bondedRole -> bondedRole.getAuthorizedBondedRole().getAddressByTransportTypeMap() + .map(addressMap -> addressMap.entrySet().stream() + .filter(entry -> addressList.contains(entry.getValue().toString())) // Nutze addressList + .map(entry -> new bisq.rest_api.proto.AddressDetails( + entry.getValue().toString(), + bondedRole.getAuthorizedBondedRole().getBondedRoleType().name(), + userService.getUserProfileService() + .findUserProfile(bondedRole.getAuthorizedBondedRole().getProfileId()) + .map(UserProfile::getNickName) + .orElse(bondedRole.getAuthorizedBondedRole().getBondUserName()) + )) + ).orElse(Stream.empty())) + .collect(Collectors.toList()); + + } } diff --git a/apps/rest-api-app/src/main/proto/rest_api.proto b/apps/rest-api-app/src/main/proto/rest_api.proto new file mode 100644 index 0000000000..d8e613da70 --- /dev/null +++ b/apps/rest-api-app/src/main/proto/rest_api.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; +package rest_api; +option java_package = "bisq.rest_api.protobuf"; +option java_multiple_files = true; + +message AddressDetails { + string address = 1; + string bondedRoleType = 2; + string nickNameOrBondUserName = 3; +} diff --git a/apps/rest-api-app/src/main/resources/node-monitor/README.md b/apps/rest-api-app/src/main/resources/node-monitor/README.md index 83e06de037..8d10fa0c7e 100644 --- a/apps/rest-api-app/src/main/resources/node-monitor/README.md +++ b/apps/rest-api-app/src/main/resources/node-monitor/README.md @@ -11,26 +11,54 @@ The application provides a user interface to input a list of hosts and ports, re The project is organized into different modules to ensure a clear separation of concerns and ease of maintenance. Each part of the application has a dedicated file or directory, as outlined below: ``` -projekt-root/ +project-root/ │ -├── index.html # Main HTML file that defines the application's structure +├── index.html # Main HTML file defining the application's structure ├── index.js # Main JavaScript file for initializing the application -├── README.md # Project README file with documentation +├── README.md # Project documentation │ ├── js/ # JavaScript files organized by functionality -│ ├── constants.js # Global constants used throughout the application -│ ├── controllers/ # Application controllers -│ │ └── appController.js # Main application controller for handling user input and API calls -│ ├── services/ # Application services for data and storage management -│ │ ├── dataService.js # Service handling API requests and data retrieval -│ │ └── storageService.js # Service for handling local storage interactions +│ ├── Constants.js # Global constants used throughout the application +│ ├── controllers/ # Controllers for managing application logic +│ │ ├── AppController.js # Main controller for user interaction and API calls +│ │ ├── ReportController.js # Controller for handling reports +│ │ └── ReportDiffsController.js # Controller for report comparison and analysis +│ ├── errors.js # Error handling logic +│ ├── services/ # Services for data and storage management +│ │ ├── DataService.js # Service for managing API requests and data retrieval +│ │ └── StorageService.js # Service for handling local storage +│ ├── utils/ # Utility functions +│ │ ├── DOMUtils.js # Functions for DOM manipulation +│ │ ├── FormatUtils.js # Formatting utilities +│ │ └── KeyUtils.js # Utilities for key management │ └── views/ # View components for different sections -│ ├── settingsView.js # View handling settings display and input -│ └── reportView.js # View managing the display of node reports +│ ├── ReportView.js # View for displaying reports +│ └── SettingsView.js # View for handling settings │ -└── styles/ # Directory containing CSS files for styling +├── resources/ # Resources such as images and icons +│ └── Bisq2_icon.svg # Application icon +│ +└── styles/ # CSS files for styling ├── global.css # Global styles, typography, colors, and basic element styling - ├── page-layout.css # Layout and positioning of main areas, responsive styling + ├── page-layout.css # Layout and positioning of main areas, responsive styles ├── reportView.css # Styling for the report view section └── settingsView.css # Styling for the settings view section ``` + +## Description + +Here’s a revised version integrating your requirements: + +ReportDiffs enables comparison across all reports and highlights deviations. +It provides average values and supports three configurable thresholds, which +can be adjusted in the settings. Threshold violations are visually marked, +with a hover showing the specific average value and the extent of the deviation. +For subtables, the background of the button toggling the detail view is marked +based on the highest exceeded threshold. + +For certain metrics, deviations are highlighted based on fixed reference values +rather than averages: + numConnections: Marked as critical if below 10, highlighting downward deviations. + memoryUsed: Marked as critical if exceeding 500 MB, highlighting upward deviations. + numThreads: Marked as critical if exceeding 70, highlighting upward deviations. + nodeLoad: Marked as critical if exceeding 0.4, highlighting upward deviations. diff --git a/apps/rest-api-app/src/main/resources/node-monitor/index.html b/apps/rest-api-app/src/main/resources/node-monitor/index.html index d5b82b191a..ce445d0eb0 100644 --- a/apps/rest-api-app/src/main/resources/node-monitor/index.html +++ b/apps/rest-api-app/src/main/resources/node-monitor/index.html @@ -1,8 +1,10 @@ + + Bisq Node Monitor @@ -10,52 +12,75 @@ + -

Bisq Node Monitor

+

Bisq Node Monitor

-
- ☰ -
+
+ ☰ +
-