diff --git a/.github/workflows/test-against-released.yml b/.github/workflows/test-against-released.yml index 61c72f0..8997537 100644 --- a/.github/workflows/test-against-released.yml +++ b/.github/workflows/test-against-released.yml @@ -44,25 +44,15 @@ jobs: version: - 14.1.1-0-9 - 14.1.1-0-8 - - 20.06.1 - 20.12.2 - 21.06.1 - - 21.12.3 - 21.12.4 - - 21.12.2 + - 22.06 steps: - name: Checkout uses: actions/checkout@v2 - - name: Set up JDK 1.8 for NetBeans Dependencies build - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - - name: Print Versions - run: mvn -version && ant -version - - name: Cache Maven packages uses: actions/cache@v1 with: @@ -70,16 +60,14 @@ jobs: key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-m2 - - name: Generate NetBeans Dependencies - shell: bash - run: | - bin/install-artifacts.sh /tmp/install/${{ matrix.version }} - - name: Set up JDK 11 for Build uses: actions/setup-java@v1 with: java-version: '11' + - name: Print Versions + run: mvn -version && ant -version + - name: Build shell: bash run: | diff --git a/.github/workflows/test-against-snapshot.yml b/.github/workflows/test-against-snapshot.yml index 3d621e4..d2fe1ce 100644 --- a/.github/workflows/test-against-snapshot.yml +++ b/.github/workflows/test-against-snapshot.yml @@ -52,14 +52,6 @@ jobs: - name: Checkout uses: actions/checkout@v2 - - name: Set up JDK 1.8 for NetBeans Dependencies build - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - - name: Print Versions - run: mvn -version && ant -version - - name: Cache Maven packages uses: actions/cache@v1 with: @@ -67,16 +59,14 @@ jobs: key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-m2-snapshots - - name: Generate NetBeans Dependencies - shell: bash - run: | - bin/install-artifacts.sh /tmp/install/${{ matrix.branch }} - - name: Set up JDK 11 for Build uses: actions/setup-java@v1 with: java-version: '11' + - name: Print Versions + run: mvn -version && ant -version + - name: Build Coherence Snapshot shell: bash env: diff --git a/README.adoc b/README.adoc index c685d7a..0cdd6ca 100644 --- a/README.adoc +++ b/README.adoc @@ -27,17 +27,19 @@ questions. image::https://oracle.github.io/coherence/assets/images/logo-red.png[Coherence CE] image:https://github.com/oracle/coherence-visualvm/workflows/Java%20CI%20-%20Released%20versions/badge.svg[CI Build] +image:https://img.shields.io/github/v/release/oracle/coherence-visualvm[Release] +image:https://sonarcloud.io/api/project_badges/measure?project=oracle_coherence-visualvm&metric=alert_status[Sonarcloud] The Coherence-VisualVM Plugin (the Plugin) provides management and monitoring of a single Coherence cluster using the VisualVM management utility. The Plugin aggregates Coherence MBean data and shows a concise operational view of a single Coherence cluster. Some management information is presented over time, which allows real-time analysis and troubleshooting. -You can connect to clusters via JMX or via management over REST with Coherence versions 14.1.1 or above. +You can connect to clusters via JMX or via management over REST with Coherence versions 12.2.1.4 or above. The Plugin is an ideal tool for monitoring and managing Coherence clusters during the development and testing lifecycle and supports connecting to both Community Edition and Commercial versions of Coherence. -NOTE: This version of the Plugin requires VisualVM release 2.0.6 or later which is available from https://visualvm.github.io/. +NOTE: This version of the Plugin requires VisualVM release 2.1 or later which is available from https://visualvm.github.io/. image::assets/coherence-visualvm.png[Coherence VisualVM Plugin,800,479] @@ -56,9 +58,9 @@ image::assets/coherence-visualvm.png[Coherence VisualVM Plugin,800,479] The Plugin will connect to and display data for the following Coherence versions: -**Community Editions**: 14.1.1.0.x, 20.06.x, 20.12.x, 21.06.x and 21.12.x +**Community Editions**: 14.1.1.0.x, 20.06.x, 20.12.x, 21.06.x, 21.12.x and 22.06.x -**Commercial Editions**: 14.1.1.0.x, 12.2.1.5.x, 12.2.1.4.x, 12.1.3.x, 12.1.2.x and 3.7.1.x +**Commercial Editions**: 14.1.1.0.x, 12.2.1.5.x, 12.2.1.4.x, 12.1.3.x, 12.1.2.x and 3.7.1.x (Support will be dropped for versions 12.1.3.x and older in an upcoming release) NOTE: If you wish to connect to Coherence version 12.2.1.4.x via REST you should have Coherence version 12.2.1.4.7 or greater. @@ -85,7 +87,7 @@ Other useful resources: * https://coherence.community/[The Coherence Community - All things Coherence] * https://visualvm.github.io/[VisualVM Home Page] * https://github.com/oracle/coherence[Coherence Community Edition on GitHub] -* https://github.com/oracle/coherence/tree/master/examples[Various Coherence Examples] +* https://coherence.community/latest/22.06/docs/#/examples/README[Various Coherence Examples] * https://github.com/oracle/coherence-operator[The Coherence Operator - Run your clusters in Kubernetes] [#connect] @@ -186,7 +188,7 @@ There are tool tips for each of the preferences, but a summary is shown below. | Enable Zoom on Graphs | false | Enables additional zoom function for all graphs. | Enable Cluster Snapshot tab | false | Enables experimental Cluster Snapshot tab. This tab is useful for seeing all the relevant cluster information on one pae in a text format. | Enable Cluster Heap Dump | false | Enables the cluster heap dump button on the Cluster Overview tab. -| Analyze Unavailable Time in LogFile| | Provides the ability to analyze log files where Partition Events Logging has been enabled for logs generated from Coherence versions 21.06 and above. See https://coherence.community/21.06/docs/#/docs/core/07_partition_events_logging[here] for more details. Note: You select a Coherence log file to analyze and don't need to be connected to a running cluster. +| Analyze Unavailable Time in LogFile| | Provides the ability to analyze log files where Partition Events Logging has been enabled for logs generated from Coherence versions 21.06 and above. See https://docs.oracle.com/pls/topic/lookup?ctx=en/middleware/standalone/coherence/14.1.1.2206/release-notes&id=COHDG-GUID-41F5341C-0318-41B2-AEBF-B9DB7FBF25E7[here] for more details. Note: You select a Coherence log file to analyze and don't need to be connected to a running cluster. !=== [#capabilities] @@ -213,26 +215,21 @@ Depending upon the edition and functionality you are using, the following option * **Elastic Data** - If your cluster is configured with Elastic Data, this tab displays graphs and information about RAM Journal and Flash Journal usage. You can click on each of the usage bars to show detailed node information * **JCache** - If your cluster is being used to store JCache caches, this tab displays JCache "Management" and "Statistics" MBean information regarding the configured caches. * **HotCache** - If your cluster contains HotCache node(s), then this tab lists the running HotCache instances. If you select an instance, on the next data refresh the console will display statistics and graphs for the operations performed. You may click on tabs and cache-ops to see further fine-grained information. -* **gRPC Proxies** – If you cluster is configured with gRPC Proxies, this tab displays information about the requests sent and received as well as successful and failed requests. A Graph of message rates and durations is also displayed. This tab will only show when connected via JMX and is not supported for REST connections. +* **gRPC Proxies** – If your cluster is configured with gRPC Proxies, this tab displays information about the requests sent and received as well as successful and failed requests. A Graph of message rates and durations is also displayed. This tab will only show when connected via JMX and is not supported for REST connections. +* **Health** – If your cluster supports the Health Check API, this tab displays information regarding the status of all health endpoints. [#build] == Building the Plugin -If you wish to build the Plugin from scratch you need to build the VisualVM dependencies first. -To build the plugin is a two-step process: - -1. Generate the VisualVM dependencies -2. Build the Coherence VisualVM Plugin +If you wish to build the Plugin from scratch please follow the instructions below. === Pre-requisites You must have the following: -1. Java JDK 1.8 - To build VisualVM dependencies -2. Java JDK 11+ - To build and test the plugin -3. Ant version >= 1.9.9 -4. Maven 3.6.3+ -5. Git +1. Java JDK 11+ - To build and test the plugin +2. Maven 3.6.3+ +3. Git === Clone the Repository @@ -243,81 +240,6 @@ You must have the following: $ git clone https://github.com/oracle/coherence-visualvm.git ---- -=== Generate the VisualVM dependencies - -NOTE: These instructions have been summarized from https://github.com/oracle/visualvm/blob/release204/README.md. - -NOTE: A Script `install-artifacts.sh` is available in the `bin` directory to run this for a Linux/Mac environment. - -1. Ensure you have JDK8 in you PATH. - -2. Checkout the VisualVM repository -+ -[source,shell] ----- -$ git clone https://github.com/oracle/visualvm.git - -Cloning into 'visualvm'... ----- - -3. Checkout the `release204` branch -+ -[source,shell] ----- -$ cd visualvm - -$ git checkout release204 - -Switched to a new branch 'release204' ----- - -4. Unzip the NetBeans Platform 11.3 -+ -[source,shell] ----- -$ cd visualvm - -$ unzip nb113_platform_19062020.zip ----- - -5. Build the Plugins -+ -[source,shell] ----- -$ ant build-zip ----- - -6. Unzip the artefacts -+ -[source,shell] ----- -$ cd dist - -$ unzip visualvm.zip - -$ cd .. ----- - -7. Generate the NBM's -+ -[source,shell] ----- -$ ant nbms ----- - -8. Install into the local repository -+ -[source,shell] ----- -$ mvn -DnetbeansInstallDirectory=dist/visualvm \ - -DnetbeansNbmDirectory=build/updates \ - -DgroupIdPrefix=org.graalvm.visualvm \ - -DforcedVersion=RELEASE204 org.apache.netbeans.utilities:nb-repository-plugin:populate ----- - -NOTE: See https://github.com/oracle/visualvm/blob/release204/README.md[here] for instructions on how to -push the artefacts to a remote Maven repository. - ==== Build the VisualVM Plugin 1. Ensure you have JDK11 or above in your PATH. @@ -335,7 +257,7 @@ If you wish to run the Community Edition tests then leave out the `-DskipTests`. 3. Install the Plugin + -The plugin will be available in the location `coherence-visualvm-plugin/target/coherence-visualvm-plugin-{version}` +The plugin will be available in the location `coherence-visualvm-plugin/target/coherence-visualvm-plugin-{version}.nbm` Follow the instructions https://docs.oracle.com/en/middleware/standalone/coherence/14.1.1.0/manage/using-jmx-manage-oracle-coherence.html[here] to install the plugin manually. diff --git a/assets/coherence-visualvm-health.png b/assets/coherence-visualvm-health.png new file mode 100644 index 0000000..4f742cd Binary files /dev/null and b/assets/coherence-visualvm-health.png differ diff --git a/coherence-visualvm-plugin/pom.xml b/coherence-visualvm-plugin/pom.xml index 04d4e51..9b9de69 100644 --- a/coherence-visualvm-plugin/pom.xml +++ b/coherence-visualvm-plugin/pom.xml @@ -33,7 +33,7 @@ com.oracle.coherence.plugin.visualvm coherence-visualvm-main - 1.3.1-SNAPSHOT + 1.4.0-SNAPSHOT ../pom.xml @@ -55,7 +55,7 @@ org-graalvm-visualvm-uisupport - org.graalvm.visualvm.api + org.netbeans.api org-openide-awt @@ -79,23 +79,23 @@ org-graalvm-visualvm-tools - org.graalvm.visualvm.api + org.netbeans.api org-openide-modules - org.graalvm.visualvm.api + org.netbeans.api org-openide-util - org.graalvm.visualvm.api + org.netbeans.api org-openide-dialogs - org.graalvm.visualvm.api + org.netbeans.api org-openide-windows - org.graalvm.visualvm.api + org.netbeans.api org-netbeans-modules-options-api diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/VisualVMModel.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/VisualVMModel.java index 08103b8..5c5697a 100644 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/VisualVMModel.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/VisualVMModel.java @@ -40,6 +40,7 @@ import com.oracle.coherence.plugin.visualvm.tablemodel.model.FederationOriginDetailsData; import com.oracle.coherence.plugin.visualvm.tablemodel.model.FlashJournalData; import com.oracle.coherence.plugin.visualvm.tablemodel.model.GrpcProxyData; +import com.oracle.coherence.plugin.visualvm.tablemodel.model.HealthData; import com.oracle.coherence.plugin.visualvm.tablemodel.model.HotCacheData; import com.oracle.coherence.plugin.visualvm.tablemodel.model.HotCachePerCacheData; import com.oracle.coherence.plugin.visualvm.tablemodel.model.HttpProxyData; @@ -163,6 +164,7 @@ private void init() f_mapDataRetrievers.put(NodeStorageData.class, new NodeStorageData()); f_mapDataRetrievers.put(ExecutorData.class, new ExecutorData()); f_mapDataRetrievers.put(GrpcProxyData.class, new GrpcProxyData()); + f_mapDataRetrievers.put(HealthData.class, new HealthData()); // Loop through each data retriever and initialize the map of // report XML. Doing it this way we load it only once @@ -351,6 +353,22 @@ private boolean shouldRetrieveData(DataType type) return false; } + if (!isHealthConfigured() && + ( + clazz.equals(DataType.HEALTH.getClassName()) + )) + { + return false; + } + + if (!isExecutorConfigured() && + ( + clazz.equals(DataType.EXECUTOR.getClassName()) + )) + { + return false; + } + return true; } @@ -991,9 +1009,9 @@ public boolean isFederationCongfigured() public boolean isElasticDataConfigured() { return (m_mapCollectedData.get(DataType.RAMJOURNAL) != null - && m_mapCollectedData.get(DataType.RAMJOURNAL).size() != 0) || + && !m_mapCollectedData.get(DataType.RAMJOURNAL).isEmpty()) || (m_mapCollectedData.get(DataType.FLASHJOURNAL) != null - && m_mapCollectedData.get(DataType.FLASHJOURNAL).size() != 0); + && !m_mapCollectedData.get(DataType.FLASHJOURNAL).isEmpty()); } /** @@ -1004,7 +1022,7 @@ public boolean isElasticDataConfigured() public boolean isExecutorConfigured() { return (m_mapCollectedData.get(DataType.EXECUTOR) != null - && m_mapCollectedData.get(DataType.EXECUTOR).size() != 0); + && !m_mapCollectedData.get(DataType.EXECUTOR).isEmpty()); } /** @@ -1015,7 +1033,18 @@ public boolean isExecutorConfigured() public boolean isGrpcProxyConfigured() { return (m_mapCollectedData.get(DataType.GRPC_PROXY) != null - && m_mapCollectedData.get(DataType.GRPC_PROXY).size() != 0); + && !m_mapCollectedData.get(DataType.GRPC_PROXY).isEmpty()); + } + + /** + * Returns if Health is configured. + * + * @return true if Health is configured. + */ + public boolean isHealthConfigured() + { + return (m_mapCollectedData.get(DataType.HEALTH) != null + && !m_mapCollectedData.get(DataType.HEALTH).isEmpty()); } /** @@ -1026,9 +1055,9 @@ public boolean isGrpcProxyConfigured() public boolean isJCacheConfigured() { return (m_mapCollectedData.get(DataType.JCACHE_CONFIG) != null - && m_mapCollectedData.get(DataType.JCACHE_CONFIG).size() != 0) || + && !m_mapCollectedData.get(DataType.JCACHE_CONFIG).isEmpty()) || (m_mapCollectedData.get(DataType.JCACHE_STATS) != null - && m_mapCollectedData.get(DataType.JCACHE_STATS).size() != 0); + && !m_mapCollectedData.get(DataType.JCACHE_STATS).isEmpty()); } /** @@ -1039,7 +1068,7 @@ public boolean isJCacheConfigured() public boolean isHttpProxyConfigured() { return (m_mapCollectedData.get(DataType.HTTP_PROXY) != null - && m_mapCollectedData.get(DataType.HTTP_PROXY).size() != 0); + && !m_mapCollectedData.get(DataType.HTTP_PROXY).isEmpty()); } /** @@ -1237,7 +1266,8 @@ public enum DataType HOTCACHE(HotCacheData.class, HOTCACHE_LABELS), HOTCACHE_PERCACHE(HotCachePerCacheData.class, HOTCACHE_PERCACHE_LABELS), EXECUTOR(ExecutorData.class, EXECUTOR_LABELS), - GRPC_PROXY(GrpcProxyData.class, GRPC_PROXY_LABELS); + GRPC_PROXY(GrpcProxyData.class, GRPC_PROXY_LABELS), + HEALTH(HealthData.class, HEALTH_LABELS); private DataType(Class clz, String[] asMeta) { @@ -1434,6 +1464,17 @@ public String[] getMetadata() Localization.getLocalText("LBL_message_duration_mean") }; + /** + * Labels for Health table. + */ + private static final String[] HEALTH_LABELS = new String[] + { + Localization.getLocalText("LBL_health_name"), Localization.getLocalText("LBL_health_subtype"), + Localization.getLocalText("LBL_members"), Localization.getLocalText("LBL_started"), + Localization.getLocalText("LBL_live"), Localization.getLocalText("LBL_ready"), + Localization.getLocalText("LBL_safe"), Localization.getLocalText("LBL_health_class") + }; + /** * Labels for persistence table. */ @@ -1441,8 +1482,9 @@ public String[] getMetadata() { Localization.getLocalText("LBL_service_name"), Localization.getLocalText("LBL_persistence_mode"), Localization.getLocalText("LBL_active_space_bytes"), Localization.getLocalText("LBL_active_space_mb"), - Localization.getLocalText("LBL_avge_persistence"), Localization.getLocalText("LBL_max_persistence"), - Localization.getLocalText("LBL_snapshot_count"), Localization.getLocalText("LBL_status") + Localization.getLocalText("LBL_backup_space_mb"), Localization.getLocalText("LBL_avge_persistence"), + Localization.getLocalText("LBL_max_persistence"), Localization.getLocalText("LBL_snapshot_count"), + Localization.getLocalText("LBL_status") }; /** diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/VisualVMView.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/VisualVMView.java index 498d993..608721d 100644 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/VisualVMView.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/VisualVMView.java @@ -35,6 +35,7 @@ import com.oracle.coherence.plugin.visualvm.panel.CoherenceClusterSnapshotPanel; import com.oracle.coherence.plugin.visualvm.panel.CoherenceExecutorPanel; import com.oracle.coherence.plugin.visualvm.panel.CoherenceGrpcProxyPanel; +import com.oracle.coherence.plugin.visualvm.panel.CoherenceHealthPanel; import com.oracle.coherence.plugin.visualvm.panel.CoherenceTopicPanel; import com.oracle.coherence.plugin.visualvm.tablemodel.model.Data; import com.oracle.coherence.plugin.visualvm.panel.CoherenceHttpProxyPanel; @@ -69,6 +70,7 @@ import javax.swing.Timer; import org.graalvm.visualvm.application.Application; +import org.graalvm.visualvm.core.datasupport.Stateful; import org.graalvm.visualvm.core.ui.DataSourceView; import org.graalvm.visualvm.core.ui.components.DataViewComponent; import org.graalvm.visualvm.tools.jmx.JmxModel; @@ -190,6 +192,7 @@ protected DataViewComponent createComponent() final CoherenceHttpProxyPanel pnlHttpProxy = new CoherenceHttpProxyPanel(model); final CoherenceExecutorPanel pnlExecutor = new CoherenceExecutorPanel(model); final CoherenceGrpcProxyPanel pnlGrpcProxy = new CoherenceGrpcProxyPanel(model); + final CoherenceHealthPanel pnlHealth = new CoherenceHealthPanel(model); String sClusterVersion = model.getClusterVersion(); String sClusterName = null; @@ -325,6 +328,13 @@ protected DataViewComponent createComponent() f_setPanels.add(pnlGrpcProxy); } + if (model.isHealthConfigured()) + { + m_dvc.addDetailsView(new DataViewComponent.DetailsView(Localization.getLocalText("LBL_health"), + null, 10, pnlHealth, null), DataViewComponent.TOP_RIGHT); + f_setPanels.add(pnlHealth); + } + // update the request sender pnlClusterOverview.setRequestSender(requestSender); pnlMachine.setRequestSender(requestSender); @@ -341,6 +351,7 @@ protected DataViewComponent createComponent() pnlJCache.setRequestSender(requestSender); pnlExecutor.setRequestSender(requestSender); pnlGrpcProxy.setRequestSender(requestSender); + pnlHealth.setRequestSender(requestSender); // display a warning if we are connected to a WLS domain and we can // see more that 1 domainPartition key. This code relies on us @@ -372,7 +383,7 @@ public void run() try { // application may be null inside the constructor - if (m_application == null || m_application.getState() == Application.STATE_AVAILABLE) + if (m_application == null || m_application.getState() == Stateful.STATE_AVAILABLE) { // Schedule the SwingWorker to update the GUI model.refreshStatistics(requestSender); diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/GraphHelper.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/GraphHelper.java index b417fd0..265b013 100755 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/GraphHelper.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/GraphHelper.java @@ -589,7 +589,8 @@ public static SimpleXYChartSupport createPersistenceActiveTotalGraph() VALUES_LIMIT); sxycd.setChartTitle(getLocalText("GRPH_total_active_space")); - sxycd.addLineFillItems(getLocalText("GRPH_total_space")); + sxycd.addLineItems(getLocalText("GRPH_total_space")); + sxycd.addLineItems(getLocalText("GRPH_backup_space")); return createChart(sxycd); } @@ -598,11 +599,12 @@ public static SimpleXYChartSupport createPersistenceActiveTotalGraph() * Add values to the total active persistence space used. * * @param graph {@link SimpleXYChartSupport} to add values to - * @param cTotalPersistenceSpace total persistence size of all caches + * @param cTotalPersistenceSpace total persistence active size of all caches + * @param cTotalBackupSpace total persistence backup size of all caches */ - public static void addValuesToPersistenceActiveTotalGraph(SimpleXYChartSupport graph, long cTotalPersistenceSpace) + public static void addValuesToPersistenceActiveTotalGraph(SimpleXYChartSupport graph, long cTotalPersistenceSpace, long cTotalBackupSpace) { - graph.addValues(System.currentTimeMillis(), new long[] {cTotalPersistenceSpace}); + graph.addValues(System.currentTimeMillis(), new long[] {cTotalPersistenceSpace, cTotalBackupSpace}); } /** diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/HttpRequestSender.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/HttpRequestSender.java index 9dc7581..2d6160f 100644 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/HttpRequestSender.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/HttpRequestSender.java @@ -163,7 +163,7 @@ public String getAttribute(ObjectName objectName, String attribute) String restName = getRestName(attribute); URLBuilder urlBuilder = getBasePath(); - modifyTarget(objectName, urlBuilder).addQueryParameter("fields", restName); + modifyTarget(objectName, urlBuilder).addQueryParameter(FIELDS, restName); JsonNode rootNode = getResponseJson(sendGetRequest(urlBuilder)); @@ -197,7 +197,7 @@ public AttributeList getAttributes(ObjectName objectName, String[] asAttribute) URLBuilder urlBuilder = getBasePath(); - modifyTarget(objectName, urlBuilder).addQueryParameter("fields", attributes); + modifyTarget(objectName, urlBuilder).addQueryParameter(FIELDS, attributes); JsonNode rootNode = getResponseJson(sendGetRequest(urlBuilder)); @@ -234,8 +234,8 @@ public Set getAllCacheMembers() throws Exception { URLBuilder urlBuilder = getBasePath(); - urlBuilder.addPathSegment("caches").addPathSegment("members") - .addQueryParameter("fields", "name,service,domainPartition"); + urlBuilder.addPathSegment(CACHES).addPathSegment(MEMBERS) + .addQueryParameter(FIELDS, "name,service,domainPartition"); JsonNode rootNode = getResponseJson(sendGetRequest(urlBuilder)); JsonNode nodeCacheItems = rootNode.get("items"); @@ -249,7 +249,7 @@ public Set getAllCacheMembers() Hashtable mapKeysProps = new Hashtable<>(); mapKeysProps.put("name", cacheMember.get("name").asText()); - mapKeysProps.put("service", cacheMember.get("service").asText()); + mapKeysProps.put(SERVICE, cacheMember.get(SERVICE).asText()); JsonNode domainPartition = cacheMember.get("domainPartition"); if (domainPartition != null) @@ -273,8 +273,8 @@ public Set getAllJournalMembers(String sJournalType) URLBuilder urlBuilder = getBasePath(); urlBuilder.addPathSegment("journal") - .addPathSegment(sJournalUrlType).addPathSegment("members") - .addQueryParameter("fields", "nodeId,type,name"); + .addPathSegment(sJournalUrlType).addPathSegment(MEMBERS) + .addQueryParameter(FIELDS, "nodeId,type,name"); JsonNode rootNode = getResponseJson(sendGetRequest(urlBuilder)); JsonNode nodeJournalMemberItems = rootNode.get("items"); @@ -302,16 +302,16 @@ public Set getAllJournalMembers(String sJournalType) public Set getCacheMembers(String sServiceName, String sCacheName, String sDomainPartition) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") - .addPathSegment(encodeServiceName(sServiceName)).addPathSegment("caches") - .addPathSegment(sCacheName).addPathSegment("members"); + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) + .addPathSegment(encodeServiceName(sServiceName)).addPathSegment(CACHES) + .addPathSegment(sCacheName).addPathSegment(MEMBERS); if (sDomainPartition != null) { urlBuilder.addQueryParameter("domainPartition", sDomainPartition); } - urlBuilder.addQueryParameter("fields", "service,name,type,tier,nodeId") - .addQueryParameter("links", ""); + urlBuilder.addQueryParameter(FIELDS, "service,name,type,tier,nodeId") + .addQueryParameter(LINKS, ""); return getSetObjectNamesFromResponse(sendGetRequest(urlBuilder)); } @@ -344,7 +344,7 @@ public Set getAllClusters() } // build the list of clusters - URLBuilder urlBuilder = getBasePath().addQueryParameter("links", ""); + URLBuilder urlBuilder = getBasePath().addQueryParameter(LINKS, ""); JsonNode rootNode = getResponseJson(sendGetRequest(urlBuilder)); JsonNode clusterItems = rootNode.get("items"); Set setObjectNames = new HashSet<>(); @@ -367,8 +367,9 @@ public Set getHotCacheMembers() throws Exception { URLBuilder urlBuilder = getBasePath().addPathSegment("hotcache") - .addPathSegment("members"); - urlBuilder.addQueryParameter("fields", "name,type,nodeId"); + .addPathSegment(MEMBERS); + urlBuilder.addQueryParameter(FIELDS, "name,type,nodeId") + .addQueryParameter(LINKS, ""); return getSetObjectNamesFromResponse(sendGetRequest(urlBuilder)); } @@ -378,10 +379,10 @@ public Set getHotCachePerCacheAdapters(String sMember) throws Exception { URLBuilder urlBuilder = getBasePath().addPathSegment("hotcache") - .addPathSegment("members").addPathSegment(sMember); + .addPathSegment(MEMBERS).addPathSegment(sMember); - urlBuilder.addQueryParameter("fields", "name,type,nodeId") - .addQueryParameter("links", ""); + urlBuilder.addQueryParameter(FIELDS, "name,type,nodeId") + .addQueryParameter(LINKS, ""); return getSetObjectNamesFromResponse(sendGetRequest(urlBuilder)); } @@ -390,8 +391,8 @@ public Set getHotCachePerCacheAdapters(String sMember) public Set getAllCoherenceWebMembers(String sSessionManager) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") - .addPathSegment("proxy").addPathSegment("members").addQueryParameter("fields", "name,type,nodeId"); + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) + .addPathSegment("proxy").addPathSegment(MEMBERS).addQueryParameter(FIELDS, "name,type,nodeId"); JsonNode rootNode = getResponseJson(sendGetRequest(urlBuilder)); JsonNode nodeWebAppItems = (JsonNode) rootNode.get("items"); @@ -419,10 +420,10 @@ public Set getCoherenceWebMembersForApplication(String sSessionManag throws Exception { URLBuilder urlBuilder = getBasePath().addPathSegment("webApplications") - .addPathSegment(sAppId).addPathSegment("members"); + .addPathSegment(sAppId).addPathSegment(MEMBERS); - urlBuilder.addQueryParameter("fields", "name,type,nodeId") - .addQueryParameter("links", ""); + urlBuilder.addQueryParameter(FIELDS, "name,type,nodeId") + .addQueryParameter(LINKS, ""); return getSetObjectNamesFromResponse(sendGetRequest(urlBuilder)); } @@ -440,9 +441,9 @@ public Set getClusterMemberOS(int nodeId) public Set getAllClusterMembers() throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("members"); - urlBuilder.addQueryParameter("fields", "type,nodeId") - .addQueryParameter("links", ""); + URLBuilder urlBuilder = getBasePath().addPathSegment(MEMBERS); + urlBuilder.addQueryParameter(FIELDS, "type,nodeId") + .addQueryParameter(LINKS, ""); return getSetObjectNamesFromResponse(sendGetRequest(urlBuilder)); } @@ -450,8 +451,8 @@ public Set getAllClusterMembers() @Override public Set getAllExecutorMembers() throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("executors").addPathSegment("members"); - urlBuilder.addQueryParameter("links", "").addQueryParameter("fields", "name"); + URLBuilder urlBuilder = getBasePath().addPathSegment("executors").addPathSegment(MEMBERS); + urlBuilder.addQueryParameter(LINKS, "").addQueryParameter(FIELDS, "name"); return getSetObjectNamesFromResponse(sendGetRequest(urlBuilder)); } @@ -469,10 +470,10 @@ public Set getAllGrpcProxyMembers() public Set getAllServiceMembers() throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") - .addPathSegment("members").addQueryParameter("fields", "name,type,domainPartition,nodeId," + + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) + .addPathSegment(MEMBERS).addQueryParameter(FIELDS, "name,type,domainPartition,nodeId," + "storageEnabled,persistenceActiveSpaceUsed,persistenceLatencyMax,persistenceLatencyAverage") - .addQueryParameter("links", ""); + .addQueryParameter(LINKS, ""); JsonNode rootNode = getResponseJson(sendGetRequest(urlBuilder)); JsonNode nodeServiceMembersItems = (JsonNode) rootNode.get("items"); @@ -501,9 +502,9 @@ public Set getAllServiceMembers() public Set getAllProxyServerMembers() throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") - .addPathSegment("proxy").addPathSegment("members") - .addQueryParameter("fields", "name,type,domainPartition,nodeId"); + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) + .addPathSegment("proxy").addPathSegment(MEMBERS) + .addQueryParameter(FIELDS, "name,type,domainPartition,nodeId"); return getSetObjectNamesFromResponse(sendGetRequest(urlBuilder)); } @@ -529,7 +530,7 @@ public Set getPartitionAssignmentObjectName(String sService, String public String getScheduledDistributions(String sService, String sDomainPartition) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) .addPathSegment(encodeServiceName(sService)).addPathSegment("partition").addPathSegment("scheduledDistributions"); if (sDomainPartition != null) { @@ -544,9 +545,9 @@ public String getScheduledDistributions(String sService, String sDomainPartition public Set getPartitionAssignmentAttributes(String sService, String sDomainPartition) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) .addPathSegment(encodeServiceName(sService)).addPathSegment("partition") - .addQueryParameter("fields", "averagePartitionSizeKB,maxPartitionSizeKB,averageStorageSizeKB," + + .addQueryParameter(FIELDS, "averagePartitionSizeKB,maxPartitionSizeKB,averageStorageSizeKB," + "maxStorageSizeKB,maxLoadNodeId"); if (sDomainPartition != null) { @@ -569,7 +570,7 @@ public Set getPartitionAssignmentAttributes(String sService, String sD public void invokeFederationOperation(String sService, String sOperation, String sParticipant) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) .addPathSegment(encodeServiceName(sService)).addPathSegment("federation").addPathSegment("participants") .addPathSegment(sParticipant).addPathSegment(sOperation); sendPostRequest(urlBuilder); @@ -579,7 +580,7 @@ public void invokeFederationOperation(String sService, String sOperation, String public Integer retrievePendingIncomingMessages(String sService) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) .addPathSegment(encodeServiceName(sService)).addPathSegment("federation").addPathSegment("pendingIncomingMessages"); JsonNode rootNode = getResponseJson(sendGetRequest(urlBuilder)); @@ -590,7 +591,7 @@ public Integer retrievePendingIncomingMessages(String sService) public Integer retrievePendingOutgoingMessages(String sService) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) .addPathSegment(encodeServiceName(sService)).addPathSegment("federation").addPathSegment("pendingOutgoingMessages"); JsonNode rootNode = getResponseJson(sendGetRequest(urlBuilder)); @@ -601,13 +602,24 @@ public Integer retrievePendingOutgoingMessages(String sService) public String getNodeState(Integer nNodeId) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("members") + URLBuilder urlBuilder = getBasePath().addPathSegment(MEMBERS) .addPathSegment(nNodeId + "").addPathSegment("state"); JsonNode rootNode = getResponseJson(sendGetRequest(urlBuilder)); return rootNode.get("state").asText(); } + @Override + public String reportEnvironment(Integer nNodeId) + throws Exception + { + URLBuilder urlBuilder = getBasePath().addPathSegment(MEMBERS) + .addPathSegment(nNodeId + "").addPathSegment("environment"); + + JsonNode rootNode = getResponseJson(sendGetRequest(urlBuilder)); + return rootNode.get("environment").asText(); + } + /** * Issue a dump cluster heap request. * @@ -626,15 +638,15 @@ public void dumpClusterHeap(String sRole) throws Exception public String[] getSnapshots(String sService, String sDomainPartition) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") - .addPathSegment(encodeServiceName(sService)).addPathSegment("persistence").addPathSegment("snapshots"); + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) + .addPathSegment(encodeServiceName(sService)).addPathSegment(PERSISTENCE).addPathSegment(SNAPSHOTS); if (sDomainPartition != null) { urlBuilder.addQueryParameter("domainPartition", sDomainPartition); } JsonNode rootNode = getResponseJson(sendGetRequest(urlBuilder)); - JsonNode nodeSnapshots = rootNode.get("snapshots"); + JsonNode nodeSnapshots = rootNode.get(SNAPSHOTS); List listSnapshots = new ArrayList<>(); if (nodeSnapshots != null && nodeSnapshots.isArray()) @@ -652,8 +664,8 @@ public String[] getSnapshots(String sService, String sDomainPartition) public String[] getArchivedSnapshots(String sService, String sDomainPartition) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") - .addPathSegment(encodeServiceName(sService)).addPathSegment("persistence").addPathSegment("archives"); + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) + .addPathSegment(encodeServiceName(sService)).addPathSegment(PERSISTENCE).addPathSegment("archives"); if (sDomainPartition != null) { urlBuilder.addQueryParameter("domainPartition", sDomainPartition); @@ -680,8 +692,8 @@ public void executePersistenceOperation(String sService, String sSnapshotName) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") - .addPathSegment(encodeServiceName(sService)).addPathSegment("persistence"); + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) + .addPathSegment(encodeServiceName(sService)).addPathSegment(PERSISTENCE); switch (sOperationName) { @@ -698,15 +710,15 @@ public void executePersistenceOperation(String sService, sendPostRequest(urlBuilder); break; case CoherencePersistencePanel.CREATE_SNAPSHOT: - urlBuilder.addPathSegment("snapshots").addPathSegment(sSnapshotName); + urlBuilder.addPathSegment(SNAPSHOTS).addPathSegment(sSnapshotName); sendPostRequest(urlBuilder); break; case CoherencePersistencePanel.REMOVE_SNAPSHOT: - urlBuilder.addPathSegment("snapshots").addPathSegment(sSnapshotName); + urlBuilder.addPathSegment(SNAPSHOTS).addPathSegment(sSnapshotName); sendDeleteRequest(urlBuilder); break; case CoherencePersistencePanel.RECOVER_SNAPSHOT: - urlBuilder.addPathSegment("snapshots").addPathSegment(sSnapshotName).addPathSegment("recover"); + urlBuilder.addPathSegment(SNAPSHOTS).addPathSegment(sSnapshotName).addPathSegment("recover"); sendPostRequest(urlBuilder); break; case CoherencePersistencePanel.FORCE_RECOVERY: @@ -729,15 +741,15 @@ public void executePersistenceOperation(String sService, public Set getMembersOfService(String sServiceName, String sDomainPartition) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") - .addPathSegment(encodeServiceName(sServiceName)).addPathSegment("members"); + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) + .addPathSegment(encodeServiceName(sServiceName)).addPathSegment(MEMBERS); if (sDomainPartition != null) { urlBuilder.addQueryParameter("domainPartition", sDomainPartition); } - urlBuilder.addQueryParameter("fields", "name,type,nodeId,domainPartition") - .addQueryParameter("links", ""); + urlBuilder.addQueryParameter(FIELDS, "name,type,nodeId,domainPartition") + .addQueryParameter(LINKS, ""); JsonNode rootNode = getResponseJson(sendGetRequest(urlBuilder)); JsonNode nodeServiceMembers = (JsonNode) rootNode.get("items"); @@ -772,10 +784,10 @@ public Set getMembersOfService(String sServiceName, String sDomainPa public JsonNode getListOfServiceCaches(String sServiceName, String sDomainPartition) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") - .addPathSegment(encodeServiceName(sServiceName)).addPathSegment("caches") - .addQueryParameter("links", "") - .addQueryParameter("fields", "nodeId,name,unitFactor,size,unitsBytes,units,memoryUnits," + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) + .addPathSegment(encodeServiceName(sServiceName)).addPathSegment(CACHES) + .addQueryParameter(LINKS, "") + .addQueryParameter(FIELDS, "nodeId,name,unitFactor,size,unitsBytes,units,memoryUnits," + "averageMissMillis"); if (sDomainPartition != null) @@ -797,9 +809,9 @@ public JsonNode getListOfServiceCaches(String sServiceName, String sDomainPartit public JsonNode getListOfCaches() throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("caches") - .addQueryParameter("links", "") - .addQueryParameter("fields", "nodeId,name,unitFactor,size,unitsBytes,units,memoryUnits," + URLBuilder urlBuilder = getBasePath().addPathSegment(CACHES) + .addQueryParameter(LINKS, "") + .addQueryParameter(FIELDS, "nodeId,name,unitFactor,size,unitsBytes,units,memoryUnits," + "averageMissMillis,service"); return getResponseJson(sendGetRequest(urlBuilder)); @@ -814,10 +826,10 @@ public JsonNode getListOfCaches() public JsonNode getNodeStorage() throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") - .addPathSegment("members") - .addQueryParameter("links", "") - .addQueryParameter("fields", "nodeId,ownedPartitionsPrimary"); + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) + .addPathSegment(MEMBERS) + .addQueryParameter(LINKS, "") + .addQueryParameter(FIELDS, "nodeId,ownedPartitionsPrimary"); return getResponseJson(sendGetRequest(urlBuilder)); } @@ -833,10 +845,10 @@ public JsonNode getNodeStorage() public JsonNode getListOfStorageMembers(String sServiceName, String sDomainPartition) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") - .addPathSegment(encodeServiceName(sServiceName)).addPathSegment("members") - .addQueryParameter("links", "") - .addQueryParameter("fields", "ownedPartitionsPrimary,nodeId"); + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) + .addPathSegment(encodeServiceName(sServiceName)).addPathSegment(MEMBERS) + .addQueryParameter(LINKS, "") + .addQueryParameter(FIELDS, "ownedPartitionsPrimary,nodeId"); if (sDomainPartition != null) { @@ -847,18 +859,32 @@ public JsonNode getListOfStorageMembers(String sServiceName, String sDomainParti } /** - * Get a list of all storage members. + * Get a list of all health members. + * + * @return a list of all storage members + * @throws Exception in case of errors + */ + public JsonNode getAllHealthMembers() throws Exception + { + URLBuilder urlBuilder = getBasePath().addPathSegment("health") + .addPathSegment(MEMBERS) + .addQueryParameter(LINKS, ""); + return getResponseJson(sendGetRequest(urlBuilder)); + } + + /** + * Get a list of all health checks. * * @return a list of all storage members * @throws Exception in case of errors */ public JsonNode getAllStorageMembers() throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") - .addPathSegment("members") - .addQueryParameter("links", "") - .addQueryParameter("fields", "type,name,domainPartition,nodeId,persistenceMode," + - "storageEnabled,persistenceActiveSpaceUsed,persistenceLatencyMax,persistenceLatencyAverage"); + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) + .addPathSegment(MEMBERS) + .addQueryParameter(LINKS, "") + .addQueryParameter(FIELDS, "type,name,domainPartition,nodeId,persistenceMode," + + "storageEnabled,persistenceActiveSpaceUsed,persistenceBackupSpaceUsed,persistenceLatencyMax,persistenceLatencyAverage"); return getResponseJson(sendGetRequest(urlBuilder)); } @@ -875,12 +901,12 @@ public JsonNode getAllStorageMembers() throws Exception public JsonNode getDataForStorageManagerMembers(String sServiceName, String sDomainPartition, String sCacheName) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") - .addPathSegment(encodeServiceName(sServiceName)).addPathSegment("caches").addPathSegment(sCacheName) - .addPathSegment("members").addQueryParameter("fields", + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) + .addPathSegment(encodeServiceName(sServiceName)).addPathSegment(CACHES).addPathSegment(sCacheName) + .addPathSegment(MEMBERS).addQueryParameter(FIELDS, "nodeId,locksGranted,locksPending,listenerRegistrations,maxQueryDurationMillis,maxQueryDescription," + "nonOptimizedQueryAverageMillis,optimizedQueryAverageMillis,indexTotalUnits,indexingTotalMillis") - .addQueryParameter("links", ""); + .addQueryParameter(LINKS, ""); if (sDomainPartition != null) { @@ -904,17 +930,17 @@ public JsonNode getDataForStorageManagerMembers(String sServiceName, String sDom public JsonNode getDataForCacheMembers(String sServiceName, String sCacheName, String sDomainPartition) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") - .addPathSegment(encodeServiceName(sServiceName)).addPathSegment("caches").addPathSegment(sCacheName) - .addPathSegment("members"); + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) + .addPathSegment(encodeServiceName(sServiceName)).addPathSegment(CACHES).addPathSegment(sCacheName) + .addPathSegment(MEMBERS); if (sDomainPartition != null) { urlBuilder.addQueryParameter("domainPartition", sDomainPartition); } - urlBuilder.addQueryParameter("fields", "name,type,size,service,nodeId," + + urlBuilder.addQueryParameter(FIELDS, "name,type,size,service,nodeId," + "domainPartition,tier,units,unitFactor,totalGets,totalPuts,cacheHits,cacheMisses,hitProbability") - .addQueryParameter("links", ""); + .addQueryParameter(LINKS, ""); return getResponseJson(sendGetRequest(urlBuilder)); } @@ -927,13 +953,13 @@ public JsonNode getDataForCacheMembers(String sServiceName, String sCacheName, S */ public JsonNode getListOfClusterMembers() throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("members"); + URLBuilder urlBuilder = getBasePath().addPathSegment(MEMBERS); - urlBuilder = urlBuilder.addQueryParameter("fields", "nodeId," + + urlBuilder = urlBuilder.addQueryParameter(FIELDS, "nodeId," + "publisherSuccessRate,receiverSuccessRate," + "sendQueueSize,memoryMaxMB,memoryAvailableMB,unicastAddress,roleName,unicastPort," + "machineName,rackName,siteName,productEdition") - .addQueryParameter("links", ""); + .addQueryParameter(LINKS, ""); return getResponseJson(sendGetRequest(urlBuilder)); } @@ -946,13 +972,13 @@ public JsonNode getListOfClusterMembers() throws Exception */ public JsonNode getListOfServices() throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") - .addPathSegment("members") - .addQueryParameter("fields", "name,type,domainPartition,nodeId," + + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) + .addPathSegment(MEMBERS) + .addQueryParameter(FIELDS, "name,type,domainPartition,nodeId," + "statusHA,memberCount,partitionsAll,partitionsEndangered," + "partitionsVulnerable,partitionsUnbalanced,requestPendingCount," + "storageEnabledCount,type") - .addQueryParameter("links", ""); + .addQueryParameter(LINKS, ""); return getResponseJson(sendGetRequest(urlBuilder)); } @@ -964,8 +990,8 @@ public JsonNode getListOfServices() throws Exception */ public JsonNode getExecutors() throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("executors").addPathSegment("members") - .addQueryParameter("links", ""); + URLBuilder urlBuilder = getBasePath().addPathSegment("executors").addPathSegment(MEMBERS) + .addQueryParameter(LINKS, ""); return getResponseJson(sendGetRequest(urlBuilder)); } @@ -977,8 +1003,8 @@ public JsonNode getExecutors() throws Exception */ public JsonNode getDataForProxyMembers() throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") - .addPathSegment("proxy").addPathSegment("members").addQueryParameter("fields", "hostIP,name,nodeId," + + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) + .addPathSegment("proxy").addPathSegment(MEMBERS).addQueryParameter(FIELDS, "hostIP,name,nodeId," + "connectionCount,outgoingMessageBacklog,totalBytesReceived,totalBytesSent," + "totalMessagesReceived,totalMessagesSent,protocol," + "domainPartition,httpServerType,totalRequestCount," + @@ -996,8 +1022,8 @@ public JsonNode getDataForProxyMembers() throws Exception */ public JsonNode getDataForServiceMembers() throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") - .addPathSegment("members").addQueryParameter("fields", "name,type,domainPartition,nodeId,taskBacklog," + + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) + .addPathSegment(MEMBERS).addQueryParameter(FIELDS, "name,type,domainPartition,nodeId,taskBacklog," + "threadCount,threadIdleCount,requestAverageDuration,taskAverageDuration"); return getResponseJson(sendGetRequest(urlBuilder)); @@ -1014,10 +1040,10 @@ public JsonNode getDataForServiceMembers() throws Exception public JsonNode getIncomingDataForParticipant(String sServiceName, String sParticipantName) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) .addPathSegment(encodeServiceName(sServiceName)).addPathSegment("federation").addPathSegment("statistics") .addPathSegment("incoming").addPathSegment("participants") - .addPathSegment(sParticipantName).addPathSegment("members"); + .addPathSegment(sParticipantName).addPathSegment(MEMBERS); return getResponseJson(sendGetRequest(urlBuilder)); } @@ -1033,10 +1059,10 @@ public JsonNode getIncomingDataForParticipant(String sServiceName, String sParti public JsonNode getOutgoingDataForParticipant(String sServiceName, String sParticipantName) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) .addPathSegment(encodeServiceName(sServiceName)).addPathSegment("federation").addPathSegment("statistics") .addPathSegment("outgoing").addPathSegment("participants").addPathSegment(sParticipantName) - .addPathSegment("members"); + .addPathSegment(MEMBERS); return getResponseJson(sendGetRequest(urlBuilder)); } @@ -1052,8 +1078,8 @@ public JsonNode getDataForElasticDataMembers(String sElasticDataType) throws Exception { URLBuilder urlBuilder = getBasePath().addPathSegment("journal") - .addPathSegment(sElasticDataType).addPathSegment("members") - .addQueryParameter("fields", "nodeId,fileCount,maxJournalFilesNumber,maxFileSize,totalDataSize," + + .addPathSegment(sElasticDataType).addPathSegment(MEMBERS) + .addQueryParameter(FIELDS, "nodeId,fileCount,maxJournalFilesNumber,maxFileSize,totalDataSize," + "compactionCount,exhaustiveCompactionCount,currentCollectorLoadFactor"); return getResponseJson(sendGetRequest(urlBuilder)); @@ -1071,16 +1097,16 @@ public JsonNode getDataForElasticDataMembers(String sElasticDataType) public JsonNode getAggregatedProxyData(String sServiceName, String sDomainPartition) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) .addPathSegment(encodeServiceName(sServiceName)).addPathSegment("proxy"); if (sDomainPartition != null) { urlBuilder.addQueryParameter("domainPartition", sDomainPartition); } - urlBuilder = urlBuilder.addQueryParameter("fields", "name,type,httpServerType,totalRequestCount," + + urlBuilder = urlBuilder.addQueryParameter(FIELDS, "name,type,httpServerType,totalRequestCount," + "totalErrorCount,requestsPerSecond,averageRequestTime,protocol") - .addQueryParameter("links", ""); + .addQueryParameter(LINKS, ""); return getResponseJson(sendGetRequest(urlBuilder)); } @@ -1097,16 +1123,16 @@ public JsonNode getAggregatedProxyData(String sServiceName, String sDomainPartit public JsonNode getAggregatedServiceData(String sServiceName, String sDomainPartition) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) .addPathSegment(encodeServiceName(sServiceName)); if (sDomainPartition != null) { urlBuilder.addQueryParameter("domainPartition", sDomainPartition); } - urlBuilder = urlBuilder.addQueryParameter("fields", "name,domainPartition,statusHA,partitionsAll," + + urlBuilder = urlBuilder.addQueryParameter(FIELDS, "name,domainPartition,statusHA,partitionsAll," + "partitionsEndangered,partitionsVulnerable,partitionsUnbalanced,requestPendingCount,storageEnabled," + - "memberCount").addQueryParameter("links", ""); + "memberCount").addQueryParameter(LINKS, ""); return getResponseJson(sendGetRequest(urlBuilder)); } @@ -1124,7 +1150,7 @@ public JsonNode getAggregatedServiceData(String sServiceName, String sDomainPart public JsonNode getAggregatedIncomingData(String sServiceName, String sDomainPartition) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) .addPathSegment(encodeServiceName(sServiceName)).addPathSegment("federation").addPathSegment("statistics") .addPathSegment("incoming").addPathSegment("participants"); @@ -1133,8 +1159,8 @@ public JsonNode getAggregatedIncomingData(String sServiceName, String sDomainPar urlBuilder.addQueryParameter("domainPartition", sDomainPartition); } - urlBuilder = urlBuilder.addQueryParameter("fields", "status,bytesReceivedSecs,msgsReceivedSecs") - .addQueryParameter("links", ""); + urlBuilder = urlBuilder.addQueryParameter(FIELDS, "status,bytesReceivedSecs,msgsReceivedSecs") + .addQueryParameter(LINKS, ""); return getResponseJson(sendGetRequest(urlBuilder)); } @@ -1152,7 +1178,7 @@ public JsonNode getAggregatedIncomingData(String sServiceName, String sDomainPar public JsonNode getAggregatedOutgoingData(String sServiceName, String sDomainPartition) throws Exception { - URLBuilder urlBuilder = getBasePath().addPathSegment("services") + URLBuilder urlBuilder = getBasePath().addPathSegment(SERVICES) .addPathSegment(encodeServiceName(sServiceName)) .addPathSegment("federation").addPathSegment("statistics").addPathSegment("outgoing") .addPathSegment("participants"); @@ -1163,8 +1189,8 @@ public JsonNode getAggregatedOutgoingData(String sServiceName, String sDomainPar urlBuilder.addQueryParameter("domainPartition", sDomainPartition); } - urlBuilder = urlBuilder.addQueryParameter("fields", "status,bytesSentSecs,msgsSentSecs") - .addQueryParameter("links", ""); + urlBuilder = urlBuilder.addQueryParameter(FIELDS, "status,bytesSentSecs,msgsSentSecs") + .addQueryParameter(LINKS, ""); return getResponseJson(sendGetRequest(urlBuilder)); } @@ -1382,20 +1408,24 @@ private URLBuilder modifyTarget(ObjectName objectName, URLBuilder urlBuilder) { switch (objectName.getKeyProperty("type")) { + case "CoherenceAdapter": + return urlBuilder.addPathSegment("hotcache").addPathSegment(MEMBERS) + .addPathSegment(getKeyPropertyFromObjName(objectName, "nodeId")) + .addQueryParameter(LINKS, ""); case "Node": - return urlBuilder.addPathSegment("members") + return urlBuilder.addPathSegment(MEMBERS) .addPathSegment(getKeyPropertyFromObjName(objectName, "nodeId")) - .addQueryParameter("links", ""); + .addQueryParameter(LINKS, ""); case "Journal": String sJournalUrlType = objectName.getKeyProperty("name").equals("FlashJournalRM") ? "flash" : "ram"; - return urlBuilder.addPathSegment("journal").addPathSegment(sJournalUrlType).addPathSegment("members") + return urlBuilder.addPathSegment("journal").addPathSegment(sJournalUrlType).addPathSegment(MEMBERS) .addPathSegment(getKeyPropertyFromObjName(objectName, "nodeId")); case "Cache": - urlBuilder = urlBuilder.addPathSegment("services") - .addPathSegment(encodeServiceName(getKeyPropertyFromObjName(objectName, "service"))) - .addPathSegment("caches").addPathSegment(getKeyPropertyFromObjName(objectName, "name")) - .addPathSegment("members") + urlBuilder = urlBuilder.addPathSegment(SERVICES) + .addPathSegment(encodeServiceName(getKeyPropertyFromObjName(objectName, SERVICE))) + .addPathSegment(CACHES).addPathSegment(getKeyPropertyFromObjName(objectName, "name")) + .addPathSegment(MEMBERS) .addPathSegment(getKeyPropertyFromObjName(objectName, "nodeId")) .addQueryParameter("tier", getKeyPropertyFromObjName(objectName, "tier")); String loader = objectName.getKeyProperty("loader"); @@ -1405,28 +1435,28 @@ private URLBuilder modifyTarget(ObjectName objectName, URLBuilder urlBuilder) } return urlBuilder; case "StorageManager": - return urlBuilder.addPathSegment("services") - .addPathSegment(encodeServiceName(getKeyPropertyFromObjName(objectName, "service"))) - .addPathSegment("caches").addPathSegment(objectName.getKeyProperty("cache")) - .addPathSegment("members").addPathSegment(getKeyPropertyFromObjName(objectName, "nodeId")); + return urlBuilder.addPathSegment(SERVICES) + .addPathSegment(encodeServiceName(getKeyPropertyFromObjName(objectName, SERVICE))) + .addPathSegment(CACHES).addPathSegment(objectName.getKeyProperty("cache")) + .addPathSegment(MEMBERS).addPathSegment(getKeyPropertyFromObjName(objectName, "nodeId")); case "Service": - return urlBuilder.addPathSegment("services") + return urlBuilder.addPathSegment(SERVICES) .addPathSegment(encodeServiceName(getKeyPropertyFromObjName(objectName, "name"))) - .addPathSegment("members").addPathSegment(getKeyPropertyFromObjName(objectName, "nodeId")) - .addQueryParameter("links", ""); + .addPathSegment(MEMBERS).addPathSegment(getKeyPropertyFromObjName(objectName, "nodeId")) + .addQueryParameter(LINKS, ""); case "ConnectionManager": - return urlBuilder.addPathSegment("services") + return urlBuilder.addPathSegment(SERVICES) .addPathSegment(encodeServiceName(getKeyPropertyFromObjName(objectName, "name"))) - .addPathSegment("members").addPathSegment(getKeyPropertyFromObjName(objectName, "nodeId")) + .addPathSegment(MEMBERS).addPathSegment(getKeyPropertyFromObjName(objectName, "nodeId")) .addPathSegment("proxy"); case "Cluster": return urlBuilder; case "Persistence": - return urlBuilder.addPathSegment("services") - .addPathSegment(encodeServiceName(getKeyPropertyFromObjName(objectName, "service"))) - .addPathSegment("persistence"); + return urlBuilder.addPathSegment(SERVICES) + .addPathSegment(encodeServiceName(getKeyPropertyFromObjName(objectName, SERVICE))) + .addPathSegment(PERSISTENCE); case "Platform": - urlBuilder = urlBuilder.addPathSegment("members") + urlBuilder = urlBuilder.addPathSegment(MEMBERS) .addPathSegment(getKeyPropertyFromObjName(objectName, "nodeId")) .addPathSegment("platform"); String subType = objectName.getKeyProperty("subType"); @@ -1737,6 +1767,18 @@ private void initSSL() */ public static final String CLUSTER_PREFIX = "Coherence:type=Cluster,cluster="; + /** + * Various constants. + */ + private static final String FIELDS = "fields"; + private static final String LINKS = "links"; + private static final String SERVICES = "services"; + private static final String SERVICE = "service"; + private static final String MEMBERS = "members"; + private static final String CACHES = "caches"; + private static final String PERSISTENCE = "persistence"; + private static final String SNAPSHOTS = "snapshots"; + /** * A trust manager that will trust all certificates. Only used when the preference to ignore SSL certs is chosen. * Should be used with care. diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/JMXRequestSender.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/JMXRequestSender.java index 476ce4b..63601a5 100644 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/JMXRequestSender.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/JMXRequestSender.java @@ -250,13 +250,7 @@ public String getScheduledDistributions(String sService, String sDomainPartition // look up the full name of the MBean in case we are in container Set setResult = getPartitionAssignmentObjectName(sService, sDomainPartition); - String sFQN = null; - - for (Object oResult : setResult) - { - sFQN = oResult.toString(); - break; - } + String sFQN = getFirstResult(setResult); return (String) invoke(new ObjectName(sFQN), "reportScheduledDistributions", new Object[]{true}, new String[]{boolean.class.getName()}); @@ -269,15 +263,8 @@ public Set getPartitionAssignmentAttributes(String sService, String sD // look up the full name of the MBean in case we are in container Set setResult = getPartitionAssignmentObjectName(sService, sDomainPartition); - String sFQN = null; + String sFQN = getFirstResult(setResult); - for (Object oResult : setResult) - { - sFQN = oResult.toString(); - break; - - - } return JMXUtils.runJMXQuery(f_connection, sFQN, new JMXUtils.JMXField[]{ new JMXUtils.Attribute("AveragePartitionSizeKB"), new JMXUtils.Attribute("MaxPartitionSizeKB"), @@ -318,17 +305,24 @@ public String getNodeState(Integer nNodeId) Set setResult = getCompleteObjectName( new ObjectName("Coherence:type=Node,nodeId=" + nNodeId + ",*")); - String sFQN = null; - - for (Object oResult : setResult) - { - sFQN = oResult.toString(); - break; - } + String sFQN = getFirstResult(setResult); return (String) invoke(new ObjectName(sFQN), "reportNodeState", new Object[0], new String[0]); } + @Override + public String reportEnvironment(Integer nNodeId) + throws Exception + { + // look up the full name of the MBean in case we are in container + Set setResult = getCompleteObjectName( + new ObjectName("Coherence:type=Node,nodeId=" + nNodeId + ",*")); + + String sFQN = getFirstResult(setResult); + + return (String) invoke(new ObjectName(sFQN), "reportEnvironment", new Object[0], new String[0]); + } + /** * Issue a dump cluster heap request. * @@ -341,13 +335,8 @@ public void dumpClusterHeap(String sRole) throws Exception Set setResult = getCompleteObjectName( new ObjectName("Coherence:type=Cluster,*")); - String sFQN = null; + String sFQN = getFirstResult(setResult); - for (Object oResult : setResult) - { - sFQN = oResult.toString(); - break; - } invoke(new ObjectName(sFQN), "dumpClusterHeap", new Object[]{sRole}, new String[] {String.class.getName()}); } @@ -361,13 +350,7 @@ public String[] getSnapshots(String sService, String sDomainPartition) : PersistenceData.getFullServiceName(sDomainPartition, sService); Set setResult = getCompleteObjectName(new ObjectName(PersistenceData.getMBeanName(sServiceName))); - String sFQN = null; - - for (Object oResult : setResult) - { - sFQN = oResult.toString(); - break; - } + String sFQN = getFirstResult(setResult); return (String[]) f_connection.getAttribute(new ObjectName(sFQN), "Snapshots"); } @@ -379,13 +362,7 @@ public String[] getArchivedSnapshots(String sService, String sDomainPartition) Set setResult = getCompleteObjectName(new ObjectName(PersistenceData.getMBeanName( PersistenceData.getFullServiceName(sDomainPartition, sService)))); - String sFQN = null; - - for (Object oResult : setResult) - { - sFQN = oResult.toString(); - break; - } + String sFQN = getFirstResult(setResult); return (String[]) invoke(new ObjectName(sFQN), "listArchivedSnapshots", null, null); } @@ -400,13 +377,8 @@ public void executePersistenceOperation(String sService, ObjectName objectName = new ObjectName(PersistenceData.getMBeanName(PersistenceData.getFullServiceName(sDomainPartition, sService))); Set setResult = getCompleteObjectName(objectName); - String sFQN = null; + String sFQN = getFirstResult(setResult); - for (Object oResult : setResult) - { - sFQN = oResult.toString(); - break; - } invoke(new ObjectName(sFQN), sOperationName, new Object[]{sSnapshotName}, new String[]{String.class.getName()}); } @@ -428,17 +400,14 @@ public String getReporterObjectName(MBeanServerConnection server, int nLocalMemb try { Set setResult = server.queryNames(new ObjectName(sQuery), null); - for (Object oResult : setResult) - { - return oResult.toString(); - } + + return getFirstResult(setResult); } catch (Exception e) { throw new RuntimeException("Unable to obtain reporter for nodeId=" + nLocalMemberId + ": " + e.getMessage()); } - return null; } /** @@ -554,6 +523,24 @@ protected String getFederationManagerObjectName(String sService) return null; } + /** + * Returns the first result from a {@link Set} of {@link ObjectName}s. + * + * @param setResult {@link Set} of {@link ObjectName}s + * + * @return result + */ + private String getFirstResult(Set setResult) + { + String sFQN = null; + + if (!setResult.isEmpty()) + { + sFQN = setResult.iterator().next().toString(); + } + return sFQN; + } + // ------ constants ----------------------------------------------------- /** diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/JMXUtils.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/JMXUtils.java index 25d86b1..0767f2a 100644 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/JMXUtils.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/JMXUtils.java @@ -137,7 +137,7 @@ public static String getAttributeValueAsString(AttributeList listAttr, String sN for (int i = 0; i < listAttr.size() ; i++) { javax.management.Attribute attr = (javax.management.Attribute) listAttr.get(i); - if (attr.getName().equals(sName)) + if (sName.equals(attr.getName())) { return (attr.getValue() == null ? "" : attr.getValue().toString()); } @@ -159,7 +159,7 @@ public static Object getAttributeValue(AttributeList listAttr, String sName) for (int i = 0; i < listAttr.size() ; i++) { javax.management.Attribute attr = (javax.management.Attribute) listAttr.get(i); - if (attr.getName().equals(sName)) + if (sName.equals(attr.getName())) { return attr.getValue(); } diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/RenderHelper.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/RenderHelper.java index 5e638bf..a5e532d 100755 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/RenderHelper.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/RenderHelper.java @@ -36,6 +36,7 @@ import javax.swing.JLabel; import javax.swing.JTable; +import javax.swing.SwingConstants; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; @@ -150,7 +151,7 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole boolean hasFocus, int row, int column) { Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - float fValue = Float.valueOf(getText()); + float fValue = Float.parseFloat(getText()); if (fValue <= 0.500) { @@ -173,7 +174,7 @@ else if (fValue <= 0.75) JLabel renderedLabel = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - renderedLabel.setHorizontalAlignment(JLabel.RIGHT); + renderedLabel.setHorizontalAlignment(SwingConstants.RIGHT); String text = MILLIS_FORMAT.format((Number) value); @@ -184,6 +185,56 @@ else if (fValue <= 0.75) } } + /** + * Renderer for health. + */ + @SuppressWarnings("serial") + public static class HealthRenderer + extends DefaultTableCellRenderer + { + /** + * {@inheritDoc} + */ + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, + boolean hasFocus, int row, int column) + { + Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + + String sValue = getText(); + + if (sValue.contains("0/")) + { + // means zero out of n are started so make this red + setBackground(Color.red); + setForeground(Color.black); + } + else if (sValue.contains("/")) + { + // means at least 1 is not ready so make orange + setBackground(Color.orange); + setForeground(Color.black); + } + else + { + // must be ok so make it green + setBackground(Color.green); + setForeground(Color.black); + } + + if (c instanceof JLabel && value instanceof Number) + { + JLabel renderedLabel = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, + row, column); + + renderedLabel.setHorizontalAlignment(SwingConstants.RIGHT); + renderedLabel.setText(sValue); + } + + return c; + } + } + /** * Render for a milliseconds column of type Float. * @@ -199,7 +250,7 @@ public static class DecimalRenderer public DecimalRenderer() { super(); - setHorizontalAlignment(JLabel.RIGHT); + setHorizontalAlignment(SwingConstants.RIGHT); } /** @@ -212,7 +263,7 @@ public DecimalRenderer(NumberFormat sFormat) { super(); this.numberFormat = sFormat; - setHorizontalAlignment(JLabel.RIGHT); + setHorizontalAlignment(SwingConstants.RIGHT); } /** @@ -229,7 +280,7 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole JLabel renderedLabel = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - renderedLabel.setHorizontalAlignment(JLabel.RIGHT); + renderedLabel.setHorizontalAlignment(SwingConstants.RIGHT); String text = numberFormat.format((Number) value); @@ -262,7 +313,7 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole if (!"".equals(getText()) && getText() != null) { - float fValue = Float.valueOf(getText()); + float fValue = Float.parseFloat(getText()); if (fValue < .15) { @@ -288,7 +339,7 @@ else if (fValue < 0.25) JLabel renderedLabel = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - renderedLabel.setHorizontalAlignment(JLabel.RIGHT); + renderedLabel.setHorizontalAlignment(SwingConstants.RIGHT); String text = PERCENT_FORMAT.format((Number) value); @@ -319,7 +370,7 @@ public static class IntegerRenderer public IntegerRenderer() { super(); - setHorizontalAlignment(JLabel.RIGHT); + setHorizontalAlignment(SwingConstants.RIGHT); } /** @@ -335,7 +386,7 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole { JLabel label = (JLabel) c; - label.setHorizontalAlignment(JLabel.RIGHT); + label.setHorizontalAlignment(SwingConstants.RIGHT); String text = INTEGER_FORMAT.format((Number) value); @@ -369,7 +420,7 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole { JLabel label = (JLabel) c; - label.setHorizontalAlignment(JLabel.RIGHT); + label.setHorizontalAlignment(SwingConstants.RIGHT); long nLongValue = value instanceof Integer ? ((Integer)value) * 1L : ((Long)value).longValue(); label.setText(getRenderedBytes(nLongValue)); @@ -522,7 +573,7 @@ else if (fValue <= 0.950) JLabel renderedLabel = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - renderedLabel.setHorizontalAlignment(JLabel.RIGHT); + renderedLabel.setHorizontalAlignment(SwingConstants.RIGHT); String text = MILLIS_FORMAT.format((Number) value); @@ -573,7 +624,7 @@ else if (fValue >= 0.60) JLabel renderedLabel = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - renderedLabel.setHorizontalAlignment(JLabel.RIGHT); + renderedLabel.setHorizontalAlignment(SwingConstants.RIGHT); String text = PERCENT_FORMAT.format((Number) value); diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/RequestSender.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/RequestSender.java index 89bf68a..869229e 100644 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/RequestSender.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/helper/RequestSender.java @@ -358,6 +358,18 @@ Integer retrievePendingOutgoingMessages(String sService) String getNodeState(Integer nNodeId) throws Exception; + /** + * Get the environment of a Cluster member. + * + * @param nNodeId the ID of the cluster member + * + * @return the environment of a cluster member + * + * @throws Exception in case of errors + */ + String reportEnvironment(Integer nNodeId) + throws Exception; + /** * Issue a dump cluster heap request. * diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/AbstractCoherencePanel.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/AbstractCoherencePanel.java index 1cb2aab..490b8ee 100755 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/AbstractCoherencePanel.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/AbstractCoherencePanel.java @@ -28,6 +28,7 @@ import com.oracle.coherence.plugin.visualvm.Localization; import com.oracle.coherence.plugin.visualvm.VisualVMView; +import com.oracle.coherence.plugin.visualvm.helper.GraphHelper; import com.oracle.coherence.plugin.visualvm.helper.RenderHelper; import com.oracle.coherence.plugin.visualvm.helper.RequestSender; import com.oracle.coherence.plugin.visualvm.tablemodel.model.Data; @@ -72,6 +73,7 @@ import javax.swing.JTable; import javax.swing.JTextField; +import javax.swing.SwingConstants; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableModel; @@ -316,7 +318,7 @@ public boolean isCellEditable(int row, int column) } }; m_table = new ExportableJTable(m_tmodel); - RenderHelper.setHeaderAlignment(m_table, JLabel.CENTER); + RenderHelper.setHeaderAlignment(m_table, SwingConstants.CENTER); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); @@ -685,12 +687,14 @@ protected Object[] getStorageDetails(List> memberData) protected Object[] getPersistenceData(List> persistenceData) { Object[] aoResults = new Object[] {}; - // [0] = cTotalMemory (long) - // [1] = cLatencyMax (long) - // [2] = cLatencyTotal(float) - // [3] = count - - long cTotalMemory = 0; + // [0] = cTotalActiveSpace (long) + // [1] = cTotalBackupSpace (long) + // [2] = cLatencyMax (long) + // [3] = cLatencyTotal(float) + // [4] = count + + long cTotalActiveSpace = 0; + long cTotalBackupSpace = 0; long cLatencyMax = 0L; float cLatencyTotal = 0.0f; int count = 0; @@ -698,11 +702,16 @@ protected Object[] getPersistenceData(List> persistenceD for (Map.Entry entry : persistenceData) { // only include services with active persistence - if (entry.getValue().getColumn(PersistenceData.PERSISTENCE_MODE).equals("active")) + String sPersistenceMode = (String) entry.getValue().getColumn(PersistenceData.PERSISTENCE_MODE); + + if (PersistenceData.isActivePersistence(sPersistenceMode)) { - long cTotalMem = (Long) entry.getValue().getColumn(PersistenceData.TOTAL_ACTIVE_SPACE_USED); + long cTotalActive = (Long) entry.getValue().getColumn(PersistenceData.TOTAL_ACTIVE_SPACE_USED); + long cTotalBackup = (Long) entry.getValue().getColumn(PersistenceData.TOTAL_BACKUP_SPACE_USED_MB); + + cTotalActiveSpace += cTotalActive == -1 ? 0 : cTotalActive; + cTotalBackupSpace += cTotalBackup == -1 ? 0 : cTotalBackup * GraphHelper.MB; - cTotalMemory += cTotalMem == -1 ? 0 : cTotalMem; cLatencyTotal += (Float) entry.getValue().getColumn(PersistenceData.AVERAGE_LATENCY); cLatencyMax = (Long) entry.getValue().getColumn(PersistenceData.MAX_LATENCY); @@ -715,7 +724,7 @@ protected Object[] getPersistenceData(List> persistenceD } } - return new Object[] {cTotalMemory, cMaxLatencyMax, cLatencyTotal, count}; + return new Object[] {cTotalActiveSpace, cTotalBackupSpace, cMaxLatencyMax, cLatencyTotal, count}; } /** @@ -729,7 +738,7 @@ protected Object[] getPersistenceData(List> persistenceD */ protected int getNullEntry(Object oValue) { - return (oValue == null ? Integer.valueOf(0) : (Integer) oValue); + return (oValue == null ? 0 : (Integer) oValue); } /** diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceCachePanel.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceCachePanel.java index ea8232f..4198441 100755 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceCachePanel.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceCachePanel.java @@ -83,6 +83,7 @@ import javax.swing.JTextField; import javax.swing.ListSelectionModel; +import javax.swing.SwingConstants; import javax.swing.ToolTipManager; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; @@ -156,10 +157,10 @@ public CoherenceCachePanel(VisualVMModel model) RenderHelper.setColumnRenderer(table, CacheData.MEMORY_USAGE_BYTES, new RenderHelper.IntegerRenderer()); RenderHelper.setColumnRenderer(table, CacheData.UNIT_CALCULATOR, new RenderHelper.UnitCalculatorRenderer()); - RenderHelper.setHeaderAlignment(table, JLabel.CENTER); - RenderHelper.setHeaderAlignment(f_tableDetail, JLabel.CENTER); - RenderHelper.setHeaderAlignment(f_tableFrontDetail, JLabel.CENTER); - RenderHelper.setHeaderAlignment(f_tableStorage, JLabel.CENTER); + RenderHelper.setHeaderAlignment(table, SwingConstants.CENTER); + RenderHelper.setHeaderAlignment(f_tableDetail, SwingConstants.CENTER); + RenderHelper.setHeaderAlignment(f_tableFrontDetail, SwingConstants.CENTER); + RenderHelper.setHeaderAlignment(f_tableStorage, SwingConstants.CENTER); RenderHelper.setColumnRenderer(f_tableDetail, CacheDetailData.CACHE_HITS, new RenderHelper.IntegerRenderer()); RenderHelper.setColumnRenderer(f_tableDetail, CacheDetailData.CACHE_MISSES, new RenderHelper.IntegerRenderer()); diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceClusterSnapshotPanel.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceClusterSnapshotPanel.java index 0b6e142..7a70815 100755 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceClusterSnapshotPanel.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceClusterSnapshotPanel.java @@ -417,11 +417,13 @@ private String persistenceOverview() StringBuilder sb = new StringBuilder(title(getLabel("LBL_persistence"))); Object[] persistenceData = getPersistenceData(m_persistenceData); - long cTotalMemory = (Long) persistenceData[0]; - long cLatencyMax = (Long) persistenceData[1]; + long cTotalActive = (Long) persistenceData[0]; + long cTotalBackup = (Long) persistenceData[1]; + float cLatencyMax = (Float) persistenceData[3]; sb.append(tableStart()) - .append(tableRow(getLabel("LBL_total_active_space"), getMemoryFormat(cTotalMemory))) + .append(tableRow(getLabel("LBL_total_active_space"), getMemoryFormat(cTotalActive))) + .append(tableRow(getLabel("LBL_total_backup_space"), getMemoryFormat(cTotalBackup))) .append(tableRow(getLabel("LBL_max_latency_across_services"), getLatencyValue(Float.toString(cLatencyMax)))) .append(tableEnd()); @@ -437,6 +439,7 @@ private String persistenceOverview() .append(td(entry.getValue().getColumn(PersistenceData.PERSISTENCE_MODE).toString())) .append(td(getMemoryFormat(entry.getValue().getColumn(PersistenceData.TOTAL_ACTIVE_SPACE_USED).toString()))) .append(td(getMemoryFormat(entry.getValue().getColumn(PersistenceData.TOTAL_ACTIVE_SPACE_USED_MB).toString()))) + .append(td(getMemoryFormat(entry.getValue().getColumn(PersistenceData.TOTAL_BACKUP_SPACE_USED_MB).toString()))) .append(td(getLatencyValue(entry.getValue().getColumn(PersistenceData.AVERAGE_LATENCY).toString()))) .append(td(getLatencyValue(entry.getValue().getColumn(PersistenceData.MAX_LATENCY).toString()))) .append(td(getMemoryFormat(entry.getValue().getColumn(PersistenceData.SNAPSHOT_COUNT).toString()))) diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceElasticDataPanel.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceElasticDataPanel.java index edc7468..38c295f 100644 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceElasticDataPanel.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceElasticDataPanel.java @@ -50,6 +50,7 @@ import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JScrollPane; +import javax.swing.SwingConstants; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableModel; @@ -211,10 +212,10 @@ public void updateGUI() int cFlashExhaustiveDelta = cFlashExhaustive - m_cLastFlashExhaustive; GraphHelper.addValuesToRamJournalCompactionGraph(f_ramJournalCompactionGraph, - cRamCompactionDelta < 0 ? 0 : cRamCompactionDelta, cRamExhaustiveDelta < 0 ? 0 : cRamExhaustiveDelta); + Math.max(cRamCompactionDelta, 0), Math.max(cRamExhaustiveDelta, 0)); GraphHelper.addValuesToFlashJournalCompactionGraph(f_flashJournalCompactionGraph, - cFlashCompactionDelta < 0 ? 0 : cFlashCompactionDelta, - cFlashExhaustiveDelta < 0 ? 0 : cFlashExhaustiveDelta); + Math.max(cFlashCompactionDelta, 0), + Math.max(cFlashExhaustiveDelta, 0)); // set the last values to calculate deltas m_cLastFlashCompaction = cFlashCompaction; @@ -297,7 +298,7 @@ public boolean isCellEditable(int row, int column) setColumnRenderer(f_table, 5, null); // load factor RenderHelper.setColumnRenderer(f_table, 6, new RenderHelper.BytesRenderer()); // max file size - RenderHelper.setHeaderAlignment(f_table, JLabel.CENTER); + RenderHelper.setHeaderAlignment(f_table, SwingConstants.CENTER); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); @@ -328,7 +329,7 @@ private void setColumnRenderer(ExportableJTable exportableJTable, int nColumn, S rndRightAlign.setToolTipText(sToolTip); } - rndRightAlign.setHorizontalAlignment(JLabel.RIGHT); + rndRightAlign.setHorizontalAlignment(SwingConstants.RIGHT); exportableJTable.getColumnModel().getColumn(nColumn).setCellRenderer(rndRightAlign); } diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceExecutorPanel.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceExecutorPanel.java index 6800918..ae5545f 100755 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceExecutorPanel.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceExecutorPanel.java @@ -45,6 +45,7 @@ import javax.swing.JSplitPane; import javax.swing.JTextField; +import javax.swing.SwingConstants; import org.graalvm.visualvm.charts.SimpleXYChartSupport; /** @@ -102,7 +103,7 @@ public CoherenceExecutorPanel(VisualVMModel model) RenderHelper.setColumnRenderer(f_table, ExecutorData.TASKS_COMPLETED, new RenderHelper.IntegerRenderer()); RenderHelper.setColumnRenderer(f_table, ExecutorData.TASKS_REJECTED, new RenderHelper.IntegerRenderer()); RenderHelper.setColumnRenderer(f_table, ExecutorData.TASKS_IN_PROGRESS, new RenderHelper.IntegerRenderer()); - RenderHelper.setHeaderAlignment(f_table, JLabel.CENTER); + RenderHelper.setHeaderAlignment(f_table, SwingConstants.CENTER); // Add some space f_table.setIntercellSpacing(new Dimension(6, 3)); diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceFederationPanel.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceFederationPanel.java index 8e1e472..de13005 100644 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceFederationPanel.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceFederationPanel.java @@ -65,6 +65,7 @@ import javax.swing.JTabbedPane; import javax.swing.JTextField; import javax.swing.ListSelectionModel; +import javax.swing.SwingConstants; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; @@ -281,9 +282,9 @@ public CoherenceFederationPanel(VisualVMModel model) RenderHelper.setColumnRenderer(tableInbound, FederationOriginDetailsData.Column.TOTAL_MSG_UNACKED.ordinal(), new RenderHelper.IntegerRenderer()); - RenderHelper.setHeaderAlignment(tableFed, JLabel.CENTER); - RenderHelper.setHeaderAlignment(tableInbound, JLabel.CENTER); - RenderHelper.setHeaderAlignment(tableOutbound, JLabel.CENTER); + RenderHelper.setHeaderAlignment(tableFed, SwingConstants.CENTER); + RenderHelper.setHeaderAlignment(tableInbound, SwingConstants.CENTER); + RenderHelper.setHeaderAlignment(tableOutbound, SwingConstants.CENTER); // set sizes tableFed.setPreferredScrollableViewportSize(new Dimension(500, tableFed.getRowHeight() * 4)); diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceGrpcProxyPanel.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceGrpcProxyPanel.java index 954065f..18c1213 100755 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceGrpcProxyPanel.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceGrpcProxyPanel.java @@ -42,6 +42,7 @@ import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTextField; +import javax.swing.SwingConstants; import org.graalvm.visualvm.charts.SimpleXYChartSupport; /** @@ -102,7 +103,7 @@ public CoherenceGrpcProxyPanel(VisualVMModel model) RenderHelper.setColumnRenderer(f_table, GrpcProxyData.MESSAGES_RECEIVED_COUNT, new RenderHelper.IntegerRenderer()); RenderHelper.setColumnRenderer(f_table, GrpcProxyData.REQUEST_DURATION_MEAN, new RenderHelper.DecimalRenderer()); RenderHelper.setColumnRenderer(f_table, GrpcProxyData.MESSAGE_DURATION_MEAN, new RenderHelper.DecimalRenderer()); - RenderHelper.setHeaderAlignment(f_table, JLabel.CENTER); + RenderHelper.setHeaderAlignment(f_table, SwingConstants.CENTER); // Add some space f_table.setIntercellSpacing(new Dimension(6, 3)); diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceHealthPanel.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceHealthPanel.java new file mode 100755 index 0000000..e077153 --- /dev/null +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceHealthPanel.java @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.coherence.plugin.visualvm.panel; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FlowLayout; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map.Entry; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.concurrent.atomic.AtomicInteger; + +import com.oracle.coherence.plugin.visualvm.Localization; +import com.oracle.coherence.plugin.visualvm.VisualVMModel; +import com.oracle.coherence.plugin.visualvm.helper.RenderHelper; +import com.oracle.coherence.plugin.visualvm.panel.util.ExportableJTable; +import com.oracle.coherence.plugin.visualvm.tablemodel.HealthSummaryTableModel; +import com.oracle.coherence.plugin.visualvm.tablemodel.model.Data; +import com.oracle.coherence.plugin.visualvm.tablemodel.model.HealthData; +import com.oracle.coherence.plugin.visualvm.tablemodel.model.HealthSummaryData; +import com.oracle.coherence.plugin.visualvm.tablemodel.model.Pair; + +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTextField; +import javax.swing.SwingConstants; + +/** + * An implementation of an {@link AbstractCoherencePanel} to view + * summarized health data. + * + * @author tam 2022.06.22 + * @since 1.4.0 + */ +public class CoherenceHealthPanel + extends AbstractCoherencePanel + { + + // ----- constructors --------------------------------------------------- + + /** + * Create the layout for the {@link CoherenceHealthPanel}. + * + * @param model {@link VisualVMModel} to use for this panel + */ + public CoherenceHealthPanel(VisualVMModel model) + { + super(new BorderLayout(), model); + + // create a split pane for resizing + JSplitPane pneSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT); + pneSplit.setOpaque(false); + + // Create the header panel + JPanel pnlHeader = new JPanel(); + pnlHeader.setLayout(new FlowLayout()); + pnlHeader.setOpaque(false); + + f_txtTotalHealthChecks = getTextField(10, SwingConstants.RIGHT); + pnlHeader.add(getLocalizedLabel("LBL_total_health_checks", f_txtTotalHealthChecks)); + pnlHeader.add(f_txtTotalHealthChecks); + + // create the table + f_tmodel = new HealthSummaryTableModel(HEALTH_SUMMARY_LABELS); + + f_table = new ExportableJTable(f_tmodel); + + f_table.setPreferredScrollableViewportSize(new Dimension(500, 150)); + + // define renderers for the columns + RenderHelper.setColumnRenderer(f_table, HealthSummaryData.MEMBERS, new RenderHelper.IntegerRenderer()); + RenderHelper.setColumnRenderer(f_table, HealthSummaryData.STARTED, new RenderHelper.HealthRenderer()); + RenderHelper.setColumnRenderer(f_table, HealthSummaryData.LIVE, new RenderHelper.HealthRenderer()); + RenderHelper.setColumnRenderer(f_table, HealthSummaryData.READY, new RenderHelper.HealthRenderer()); + RenderHelper.setColumnRenderer(f_table, HealthSummaryData.SAFE, new RenderHelper.HealthRenderer()); + + RenderHelper.setHeaderAlignment(f_table, SwingConstants.CENTER); + + // Add some space + f_table.setIntercellSpacing(new Dimension(6, 3)); + f_table.setRowHeight(f_table.getRowHeight() + 4); + + // Create the scroll pane and add the table to it. + JScrollPane pneScroll = new JScrollPane(f_table); + configureScrollPane(pneScroll, f_table); + pneScroll.setOpaque(false); + + JPanel pnlTop = new JPanel(new BorderLayout()); + pnlTop.setOpaque(false); + + pnlTop.add(pnlHeader, BorderLayout.PAGE_START); + pnlTop.add(pneScroll, BorderLayout.CENTER); + + pneSplit.add(pnlTop); + + add(pneSplit); + } + + // ----- AbstractCoherencePanel methods --------------------------------- + + @Override + public void updateGUI() + { + // no-op, done in update data + } + + @Override + public void updateData() + { + List> healthData = f_model.getData(VisualVMModel.DataType.HEALTH); + + SortedMap mapData = new TreeMap<>(); + + // summarise the data by name and sub-type + healthData.forEach(v -> + { + HealthData.HealthKey key = (HealthData.HealthKey) v.getKey(); + HealthData value = (HealthData) v.getValue(); + Pair newKey = new Pair<>(key.getName(), key.getSubType()); + + HealthSummaryData data = (HealthSummaryData) mapData.get(newKey); + if (data == null) + { + data = new HealthSummaryData(); + data.setColumn(HealthSummaryData.HEALTH_NAME, newKey); + data.setColumn(HealthSummaryData.MEMBERS, 0); + data.setColumn(HealthSummaryData.STARTED, 0); + data.setColumn(HealthSummaryData.LIVE, 0); + data.setColumn(HealthSummaryData.READY, 0); + data.setColumn(HealthSummaryData.SAFE, 0); + } + + // increment the values + data.setColumn(HealthSummaryData.MEMBERS, (Integer)data.getColumn(HealthSummaryData.MEMBERS) + 1); + if (Boolean.TRUE.equals(value.getColumn(HealthData.STARTED))) + { + data.setColumn(HealthSummaryData.STARTED, (Integer)data.getColumn(HealthSummaryData.STARTED) + 1); + } + if (Boolean.TRUE.equals(value.getColumn(HealthData.LIVE))) + { + data.setColumn(HealthSummaryData.LIVE, (Integer)data.getColumn(HealthSummaryData.LIVE) + 1); + } + if (Boolean.TRUE.equals(value.getColumn(HealthData.READY))) + { + data.setColumn(HealthSummaryData.READY, (Integer)data.getColumn(HealthSummaryData.READY) + 1); + } + if (Boolean.TRUE.equals(value.getColumn(HealthData.SAFE))) + { + data.setColumn(HealthSummaryData.SAFE, (Integer)data.getColumn(HealthSummaryData.SAFE) + 1); + } + + // update the map + mapData.put(newKey, data); + }); + + AtomicInteger totalChecks = new AtomicInteger(0); + AtomicInteger totalOk = new AtomicInteger(0); + + // process the data and change any values to fractions if they do not equal the member count + mapData.forEach((k,v) -> + { + int cMembers = (Integer) v.getColumn(HealthSummaryData.MEMBERS); + int cStarted = (Integer) v.getColumn(HealthSummaryData.STARTED); + int cLive = (Integer) v.getColumn(HealthSummaryData.LIVE); + int cReady = (Integer) v.getColumn(HealthSummaryData.READY); + int cSafe = (Integer) v.getColumn(HealthSummaryData.SAFE); + + if (cStarted != cMembers) + { + v.setColumn(HealthSummaryData.STARTED, String.format(FORMAT, cStarted, cMembers)); + } + if (cLive != cMembers) + { + v.setColumn(HealthSummaryData.LIVE, String.format(FORMAT, cLive, cMembers)); + } + if (cReady != cMembers) + { + v.setColumn(HealthSummaryData.READY, String.format(FORMAT, cReady, cMembers)); + } + if (cSafe != cMembers) + { + v.setColumn(HealthSummaryData.SAFE, String.format(FORMAT, cSafe, cMembers)); + } + + totalChecks.addAndGet(cMembers * 4); + totalOk.addAndGet(cStarted + cLive + cReady + cSafe); + }); + + // update total health + f_txtTotalHealthChecks.setForeground(Color.black); + String sValue = String.format(FORMAT, totalOk.get(), totalChecks.get()); + + f_txtTotalHealthChecks.setText(sValue); + if (totalOk.get() != totalChecks.get()) + { + // means at least 1 is not ready so make orange + f_txtTotalHealthChecks.setBackground(Color.orange); + } + else + { + // must be ok so make it green + f_txtTotalHealthChecks.setBackground(Color.green); + } + + f_tmodel.setDataList(new ArrayList<>(mapData.entrySet())); + f_tmodel.fireTableDataChanged(); + } + + // ----- constants ------------------------------------------------------ + + private static final long serialVersionUID = -7612569043492412546L; + + private static final String FORMAT = "%d/%d"; + + // ----- data members ---------------------------------------------------- + + /** + * The total number of health checks. + */ + private final JTextField f_txtTotalHealthChecks; + + /** + * The {@link HealthSummaryTableModel} to display proxy data. + */ + protected final HealthSummaryTableModel f_tmodel; + + /** + * the {@link ExportableJTable} to use to display data. + */ + protected final ExportableJTable f_table; + + /** + * Labels for Health table. + */ + private static final String[] HEALTH_SUMMARY_LABELS = new String[] + { + Localization.getLocalText("LBL_health_name"), Localization.getLocalText("LBL_members"), + Localization.getLocalText("LBL_started"), Localization.getLocalText("LBL_live"), + Localization.getLocalText("LBL_ready"), Localization.getLocalText("LBL_safe") + }; + } diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceHotCachePanel.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceHotCachePanel.java index 89103d8..9633fe1 100644 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceHotCachePanel.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceHotCachePanel.java @@ -40,8 +40,8 @@ import javax.swing.JSplitPane; import javax.swing.JTabbedPane; import javax.swing.ListSelectionModel; -import javax.swing.JLabel; +import javax.swing.SwingConstants; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.BorderLayout; @@ -107,8 +107,8 @@ public CoherenceHotCachePanel(VisualVMModel model) RenderHelper.setColumnRenderer(f_percachetable, HotCachePerCacheData.Max, new RenderHelper.IntegerRenderer()); RenderHelper.setColumnRenderer(f_percachetable, HotCachePerCacheData.Min, new RenderHelper.IntegerRenderer()); - RenderHelper.setHeaderAlignment(table, JLabel.CENTER); - RenderHelper.setHeaderAlignment(f_percachetable, JLabel.CENTER); + RenderHelper.setHeaderAlignment(table, SwingConstants.CENTER); + RenderHelper.setHeaderAlignment(f_percachetable, SwingConstants.CENTER); f_percachetable.setIntercellSpacing(new Dimension(6,3)); f_percachetable.setRowHeight(f_percachetable.getRowHeight() + 4); @@ -407,42 +407,42 @@ public void updateRowSelection() /** * The graph of Execution Time Per Operation statistics. */ - private SimpleXYChartSupport m_hotcacheGraph1; + private transient SimpleXYChartSupport m_hotcacheGraph1; /** * The graph of Execution Time Per Transaction Statistics. */ - private SimpleXYChartSupport m_hotcacheGraph2; + private transient SimpleXYChartSupport m_hotcacheGraph2; /** * The graph of Number Of Invocations Per Operation Statistics. */ - private SimpleXYChartSupport m_hotcacheGraph3; + private transient SimpleXYChartSupport m_hotcacheGraph3; /** * The graph of Last ExecutionTime Per Operation Statistics. */ - private SimpleXYChartSupport m_hotcacheGraph4; + private transient SimpleXYChartSupport m_hotcacheGraph4; /** * The graph of Last Operation ReplicationLag Statistics. */ - private SimpleXYChartSupport m_hotcacheGraph5; + private transient SimpleXYChartSupport m_hotcacheGraph5; /** * The graph of Operation ReplicationLag Statistics. */ - private SimpleXYChartSupport m_hotcacheGraph6; + private transient SimpleXYChartSupport m_hotcacheGraph6; /** * The graph of Number Of Operations Per Transaction Statistics. */ - private SimpleXYChartSupport m_hotcacheGraph7; + private transient SimpleXYChartSupport m_hotcacheGraph7; /** * The graph of PerCacheOperation Statistics */ - private SimpleXYChartSupport m_hotcacheGraph8; + private transient SimpleXYChartSupport m_hotcacheGraph8; /** * The tabbed panel. diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceHttpProxyPanel.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceHttpProxyPanel.java index 22fc295..5610399 100644 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceHttpProxyPanel.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceHttpProxyPanel.java @@ -36,13 +36,13 @@ import com.oracle.coherence.plugin.visualvm.VisualVMModel; import com.oracle.coherence.plugin.visualvm.panel.util.ExportableJTable; -import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; import javax.swing.JTextField; import javax.swing.ListSelectionModel; +import javax.swing.SwingConstants; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.BorderLayout; @@ -98,8 +98,8 @@ public CoherenceHttpProxyPanel(VisualVMModel model) RenderHelper.setMillisRenderer(f_tableDetail, HttpProxyMemberData.AVG_REQ_TIME); RenderHelper.setMillisRenderer(f_tableDetail, HttpProxyMemberData.REQ_PER_SECOND); - RenderHelper.setHeaderAlignment(f_table, JLabel.CENTER); - RenderHelper.setHeaderAlignment(f_tableDetail, JLabel.CENTER); + RenderHelper.setHeaderAlignment(f_table, SwingConstants.CENTER); + RenderHelper.setHeaderAlignment(f_tableDetail, SwingConstants.CENTER); f_table.setPreferredScrollableViewportSize(new Dimension(500, f_table.getRowHeight() * 5)); f_tableDetail.setPreferredScrollableViewportSize(new Dimension(500, 125)); @@ -489,22 +489,22 @@ public void updateData() /** * The graph of request time. */ - private SimpleXYChartSupport m_requestTimeGraph; + private transient SimpleXYChartSupport m_requestTimeGraph; /** * The graph of average requests per second time. */ - private SimpleXYChartSupport m_requestsPerSecondGraph; + private transient SimpleXYChartSupport m_requestsPerSecondGraph; /** * The graph of requests and errors */ - private SimpleXYChartSupport m_requestsGraph; + private transient SimpleXYChartSupport m_requestsGraph; /** * The graphs of response codes */ - private SimpleXYChartSupport m_responseGraph; + private transient SimpleXYChartSupport m_responseGraph; /** * Last error count. diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceHttpSessionPanel.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceHttpSessionPanel.java index e9e9332..59574a0 100644 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceHttpSessionPanel.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceHttpSessionPanel.java @@ -42,12 +42,12 @@ import java.util.Map; import java.util.Set; -import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTextField; +import javax.swing.SwingConstants; import org.graalvm.visualvm.charts.SimpleXYChartSupport; /** @@ -105,7 +105,7 @@ public CoherenceHttpSessionPanel(VisualVMModel model) new RenderHelper.IntegerRenderer()); RenderHelper.setColumnRenderer(f_table, HttpSessionData.SESSION_UPDATES, new RenderHelper.IntegerRenderer()); - RenderHelper.setHeaderAlignment(f_table, JLabel.CENTER); + RenderHelper.setHeaderAlignment(f_table, SwingConstants.CENTER); // Add some space f_table.setIntercellSpacing(new Dimension(6, 3)); @@ -250,12 +250,12 @@ public void updateData() /** * The graph of session counts. */ - private final SimpleXYChartSupport f_sessionCountGraph; + private transient final SimpleXYChartSupport f_sessionCountGraph; /** * The graph of overflow session counts. */ - private final SimpleXYChartSupport f_reapDurationGraph; + private transient final SimpleXYChartSupport f_reapDurationGraph; /** * the {@link ExportableJTable} to use to display data. diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceMachinePanel.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceMachinePanel.java index e3a15f3..25855cc 100755 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceMachinePanel.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceMachinePanel.java @@ -41,12 +41,12 @@ import java.util.List; import java.util.Map.Entry; -import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTextField; +import javax.swing.SwingConstants; import org.graalvm.visualvm.charts.SimpleXYChartSupport; /** @@ -100,7 +100,7 @@ public CoherenceMachinePanel(VisualVMModel model) RenderHelper.setColumnRenderer(f_table, MachineData.SYSTEM_LOAD_AVERAGE, new RenderHelper.DecimalRenderer(RenderHelper.LOAD_AVERAGE_FORMAT)); RenderHelper.setColumnRenderer(f_table, MachineData.PERCENT_FREE_MEMORY, new RenderHelper.FreeMemoryRenderer()); - RenderHelper.setHeaderAlignment(f_table, JLabel.CENTER); + RenderHelper.setHeaderAlignment(f_table, SwingConstants.CENTER); // Add some space f_table.setIntercellSpacing(new Dimension(6, 3)); @@ -207,7 +207,7 @@ public void updateData() /** * The graph of machine load averages. */ - private final SimpleXYChartSupport f_machineGraph; + private transient final SimpleXYChartSupport f_machineGraph; /** * The machine statistics data retrieved from the {@link VisualVMModel}. diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceMemberPanel.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceMemberPanel.java index 221d57d..25e1ad6 100755 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceMemberPanel.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceMemberPanel.java @@ -26,7 +26,6 @@ package com.oracle.coherence.plugin.visualvm.panel; -import com.oracle.coherence.plugin.visualvm.Localization; import com.oracle.coherence.plugin.visualvm.helper.GraphHelper; import com.oracle.coherence.plugin.visualvm.helper.RenderHelper; import com.oracle.coherence.plugin.visualvm.helper.RequestSender; @@ -169,7 +168,7 @@ public CoherenceMemberPanel(VisualVMModel model) RenderHelper.setColumnRenderer(f_table, MemberData.RECEIVER_SUCCESS, new RenderHelper.SuccessRateRenderer()); RenderHelper.setColumnRenderer(f_table, MemberData.SENDQ_SIZE, new RenderHelper.IntegerRenderer()); - RenderHelper.setHeaderAlignment(f_table, JLabel.CENTER); + RenderHelper.setHeaderAlignment(f_table, SwingConstants.CENTER); // Add some space f_table.setIntercellSpacing(new Dimension(6, 3)); @@ -182,6 +181,7 @@ public CoherenceMemberPanel(VisualVMModel model) { f_table.setMenuOptions(new MenuOption[] { menuDetail, + new ReportEnvironmentMenuOption(model, m_requestSender, f_table), new ReportNodeStateMenuOption(model, m_requestSender, f_table), new ReportNodeStateMultiMenuOption(model, m_requestSender, f_table)}); } @@ -296,6 +296,62 @@ public void updateData() } + + // ----- inner classes ReportEnvironmentMenuOption ---------------------- + + /** + * A class to call the environment operation on the selected ClusterNode + * MBean and display the details. + */ + private class ReportEnvironmentMenuOption + extends AbstractMenuOption + { + + /** + * {@inheritDoc} + */ + public ReportEnvironmentMenuOption(VisualVMModel model, RequestSender requestSender, + ExportableJTable jtable) + { + super(model, requestSender, jtable); + } + + // ----- MenuOptions methods ---------------------------------------- + + @Override + public String getMenuItem() + { + return getLocalizedText("LBL_report_node_environment"); + } + + @Override + public void actionPerformed(ActionEvent e) + { + int nRow = getSelectedRow(); + Integer nNodeId = null; + + if (nRow == -1) + { + JOptionPane.showMessageDialog(null, getLocalizedText("LBL_must_select_row")); + } + else + { + try + { + nNodeId = (Integer) getJTable().getModel().getValueAt(nRow, 0); + String sResult = generateHeader(nNodeId) + m_requestSender.reportEnvironment(nNodeId); + + showMessageDialog(getLocalizedText("LBL_environment_for_node") + " " + nNodeId, + sResult, JOptionPane.INFORMATION_MESSAGE, 500, 400, true); + } + catch (Exception ee) + { + showMessageDialog("Error running reportEnvironment for Node " + nNodeId, getSanitizedMessage(ee), JOptionPane.ERROR_MESSAGE); + } + } + } + } + // ----- inner classes ReportNodeDetailsMenuOption ---------------------- /** @@ -445,7 +501,7 @@ public void actionPerformed(ActionEvent e) } catch (Exception ee) { - showMessageDialog("Error running reportNodeState for Node " + nNodeId, ee.getMessage(), JOptionPane.ERROR_MESSAGE); + showMessageDialog("Error running reportNodeState for Node " + nNodeId, getSanitizedMessage(ee), JOptionPane.ERROR_MESSAGE); } } } @@ -574,6 +630,17 @@ public String getMenuItem() } } + /** + * Return a sanitized message to make common errors more meaningful. + * @param e {@link Exception} to get message from + * @return final message + */ + private String getSanitizedMessage(Exception e) + { + String sError = e.getMessage(); + return sError.contains("name cannot be null") ? "Node no longer available." : sError; + } + // ----- constants ------------------------------------------------------ private static final long serialVersionUID = -7612569043492412546L; diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherencePersistencePanel.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherencePersistencePanel.java index 7b99ef2..ac3278f 100644 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherencePersistencePanel.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherencePersistencePanel.java @@ -83,6 +83,7 @@ import javax.swing.JTextField; import javax.swing.ListSelectionModel; +import javax.swing.SwingConstants; import org.graalvm.visualvm.charts.SimpleXYChartSupport; @@ -200,7 +201,9 @@ public CoherencePersistencePanel(VisualVMModel model) new RenderHelper.DecimalRenderer(RenderHelper.MILLIS_FORMAT)); RenderHelper.setColumnRenderer(f_table, PersistenceData.TOTAL_ACTIVE_SPACE_USED_MB, new RenderHelper.IntegerRenderer()); - RenderHelper.setHeaderAlignment(f_table, JLabel.CENTER); + RenderHelper.setColumnRenderer(f_table, PersistenceData.TOTAL_BACKUP_SPACE_USED_MB, + new RenderHelper.IntegerRenderer()); + RenderHelper.setHeaderAlignment(f_table, SwingConstants.CENTER); // Add some space f_table.setIntercellSpacing(new Dimension(6, 3)); @@ -234,7 +237,7 @@ public CoherencePersistencePanel(VisualVMModel model) new RenderHelper.ToolTipRenderer()); RenderHelper.setColumnRenderer(f_tableNotifications, PersistenceNotificationsData.DURATION, new RenderHelper.IntegerRenderer()); - RenderHelper.setHeaderAlignment(f_tableNotifications, JLabel.CENTER); + RenderHelper.setHeaderAlignment(f_tableNotifications, SwingConstants.CENTER); // Add some space f_tableNotifications.setIntercellSpacing(new Dimension(6, 3)); @@ -272,17 +275,18 @@ public void updateGUI() final String MEM_FORMAT = "%,10.2f"; Object[] persistenceData = getPersistenceData(m_persistenceData); - long cTotalMemory = (Long) persistenceData[0]; - long cLatencyMax = (Long) persistenceData[1]; - float cLatencyTotal = (Float) persistenceData[2]; - int count = (Integer) persistenceData[3]; + long cTotalActive = (Long) persistenceData[0]; + long cTotalBackup = (Long) persistenceData[1]; + long cLatencyMax = (Long) persistenceData[2]; + float cLatencyTotal = (Float) persistenceData[3]; + int count = (Integer) persistenceData[4]; float cLatencyAverage = 0.0f; if (m_persistenceData != null) { m_cMaxMaxLatency = cLatencyMax; - f_txtTotalActiveSpaceUsed.setText(String.format(MEM_FORMAT, (cTotalMemory * 1.0f) / GraphHelper.MB)); + f_txtTotalActiveSpaceUsed.setText(String.format(MEM_FORMAT, (cTotalActive * 1.0f) / GraphHelper.MB)); cLatencyAverage = cLatencyTotal / count; if (cLatencyMax > m_cMaxMaxLatency) { @@ -294,7 +298,7 @@ public void updateGUI() f_txtTotalActiveSpaceUsed.setText(String.format(MEM_FORMAT, 0)); } - GraphHelper.addValuesToPersistenceActiveTotalGraph(f_persistenceTotalSpaceGraph, cTotalMemory); + GraphHelper.addValuesToPersistenceActiveTotalGraph(f_persistenceTotalSpaceGraph, cTotalActive, cTotalBackup); GraphHelper.addValuesToPersistenceLatencyGraph(f_persistenceLatencyGraph, cLatencyAverage * 1000.0f); f_txtMaxLatency.setText(Long.toString(m_cMaxMaxLatency)); @@ -900,12 +904,12 @@ else if (sType.indexOf(END) > 0) /** * The graph of persistence latency averages. */ - private final SimpleXYChartSupport f_persistenceLatencyGraph; + private final transient SimpleXYChartSupport f_persistenceLatencyGraph; /** * The graph of persistence latency averages. */ - private final SimpleXYChartSupport f_persistenceTotalSpaceGraph; + private final transient SimpleXYChartSupport f_persistenceTotalSpaceGraph; /** * the {@link ExportableJTable} to use to display data. diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceProxyPanel.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceProxyPanel.java index 98d9812..55f39f2 100755 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceProxyPanel.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceProxyPanel.java @@ -43,12 +43,12 @@ import java.util.Map.Entry; import javax.swing.JCheckBox; -import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTextField; +import javax.swing.SwingConstants; import org.graalvm.visualvm.charts.SimpleXYChartSupport; /** @@ -121,7 +121,7 @@ public CoherenceProxyPanel(VisualVMModel model) RenderHelper.setColumnRenderer(f_table, ProxyData.TOTAL_BYTES_SENT, new RenderHelper.IntegerRenderer()); RenderHelper.setColumnRenderer(f_table, ProxyData.TOTAL_MSG_RECEIVED, new RenderHelper.IntegerRenderer()); RenderHelper.setColumnRenderer(f_table, ProxyData.TOTAL_MSG_SENT, new RenderHelper.IntegerRenderer()); - RenderHelper.setHeaderAlignment(f_table, JLabel.CENTER); + RenderHelper.setHeaderAlignment(f_table, SwingConstants.CENTER); // Add some space f_table.setIntercellSpacing(new Dimension(6, 3)); @@ -247,12 +247,12 @@ public void updateData() /** * The graph of proxy server connections. */ - private final SimpleXYChartSupport f_proxyGraph; + private final transient SimpleXYChartSupport f_proxyGraph; /** * The graph of proxy server stats. */ - private final SimpleXYChartSupport f_proxyStatsGraph; + private final transient SimpleXYChartSupport f_proxyStatsGraph; /** * The proxy statistics data retrieved from the {@link VisualVMModel}. diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceServicePanel.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceServicePanel.java index 7b9ee40..748407b 100755 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceServicePanel.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceServicePanel.java @@ -49,7 +49,6 @@ import java.util.Set; import java.util.logging.Logger; -import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JOptionPane; import javax.swing.JScrollPane; @@ -57,6 +56,7 @@ import javax.swing.JTabbedPane; import javax.swing.JTextField; import javax.swing.ListSelectionModel; +import javax.swing.SwingConstants; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; @@ -119,8 +119,8 @@ else if (model.getClusterVersionAsInt() >= 121200) RenderHelper.setColumnRenderer(f_tableDetail, ServiceMemberData.TASK_AVERAGE_DURATION, new RenderHelper.DecimalRenderer()); - RenderHelper.setHeaderAlignment(table, JLabel.CENTER); - RenderHelper.setHeaderAlignment(f_tableDetail, JLabel.CENTER); + RenderHelper.setHeaderAlignment(table, SwingConstants.CENTER); + RenderHelper.setHeaderAlignment(f_tableDetail, SwingConstants.CENTER); table.setPreferredScrollableViewportSize(new Dimension(500, table.getRowHeight() * 5)); f_tableDetail.setPreferredScrollableViewportSize(new Dimension(700, 125)); @@ -437,7 +437,6 @@ public String getMenuItem() public void actionPerformed(ActionEvent e) { int nRow = getSelectedRow(); - int nCol = getSelectedColumn(); String sService = null; String sRawService = null; @@ -496,17 +495,28 @@ else if (f_nOption == SHOW_PARTITION_STATS) throw new RuntimeException("Invalid option " + f_nOption); } - showMessageDialog(Localization.getLocalText("LBL_details_service", new String[] { sRawService}), + showMessageDialog(Localization.getLocalText("LBL_details_service", sRawService), sResult, JOptionPane.INFORMATION_MESSAGE); } catch (Exception ee) { - showMessageDialog(Localization.getLocalText("ERR_cannot_run", new String[] { sRawService }), - ee.getMessage(), JOptionPane.ERROR_MESSAGE); + showMessageDialog(Localization.getLocalText("ERR_cannot_run", sRawService), + getSanitizedMessage(ee), JOptionPane.ERROR_MESSAGE); } } } + /** + * Return a sanitized message to make common errors more meaningful. + * @param e {@link Exception} to get message from + * @return final message + */ + private String getSanitizedMessage(Exception e) + { + String sError = e.getMessage(); + return sError.contains("name cannot be null") ? "Node no longer available or operation not valid for service type." : sError; + } + /** * Format a long value * @@ -676,27 +686,27 @@ public void updateRowSelection() /** * The graph of thread utilization percent. */ - private SimpleXYChartSupport m_threadUtilGraph = null; + private transient SimpleXYChartSupport m_threadUtilGraph = null; /** * The graph of task average duration. */ - private SimpleXYChartSupport m_taskAverageGraph = null; + private transient SimpleXYChartSupport m_taskAverageGraph = null; /** * The graph of task backlog. */ - private SimpleXYChartSupport m_taskBacklogGraph = null; + private transient SimpleXYChartSupport m_taskBacklogGraph = null; /** * The graph of request average. */ - private SimpleXYChartSupport m_requestAverageGraph = null; + private transient SimpleXYChartSupport m_requestAverageGraph = null; /** * The graph of service partitions. */ - private SimpleXYChartSupport m_servicePartitionsGraph = null; + private transient SimpleXYChartSupport m_servicePartitionsGraph = null; /** * The row selection listener. diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceTopicPanel.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceTopicPanel.java index 50a116d..e1ae668 100755 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceTopicPanel.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/panel/CoherenceTopicPanel.java @@ -40,12 +40,12 @@ import com.oracle.coherence.plugin.visualvm.tablemodel.model.Data; import com.oracle.coherence.plugin.visualvm.tablemodel.model.TopicData; -import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTextField; +import javax.swing.SwingConstants; import org.graalvm.visualvm.charts.SimpleXYChartSupport; /** @@ -104,7 +104,7 @@ public CoherenceTopicPanel(VisualVMModel model) RenderHelper.setColumnRenderer(f_table, TopicData.MEMORY_USAGE_BYTES, new RenderHelper.IntegerRenderer()); RenderHelper.setColumnRenderer(f_table, TopicData.PUBLISHER_SENDS, new RenderHelper.IntegerRenderer()); RenderHelper.setColumnRenderer(f_table, TopicData.SUBSCRIBER_RECEIVES, new RenderHelper.IntegerRenderer()); - RenderHelper.setHeaderAlignment(f_table, JLabel.CENTER); + RenderHelper.setHeaderAlignment(f_table, SwingConstants.CENTER); f_table.setIntercellSpacing(new Dimension(6, 3)); f_table.setRowHeight(f_table.getRowHeight() + 4); @@ -222,12 +222,12 @@ public void updateGUI() /** * The graph of unconsumed messages. */ - private final SimpleXYChartSupport f_unconsumedGraph; + private final transient SimpleXYChartSupport f_unconsumedGraph; /** * The graph of topics rates. */ - private final SimpleXYChartSupport f_topicsRatesGraph; + private final transient SimpleXYChartSupport f_topicsRatesGraph; /** * the {@link ExportableJTable} to use to display data. diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/HealthSummaryTableModel.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/HealthSummaryTableModel.java new file mode 100755 index 0000000..518e3e8 --- /dev/null +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/HealthSummaryTableModel.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.coherence.plugin.visualvm.tablemodel; + +import com.oracle.coherence.plugin.visualvm.tablemodel.model.Data; + +/** + * A model for holding cache Health data. + * + * @author tam 2022.06.22 + * @since 1.4.0 + */ +public class HealthSummaryTableModel + extends AbstractCoherenceTableModel + { + // ----- constructors --------------------------------------------------- + + /** + * Creates a table model with the given columns. + * + * @param asColumns the columns for this table model + */ + public HealthSummaryTableModel(String[] asColumns) + { + super(asColumns); + } + + // ----- constants ------------------------------------------------------ + + private static final long serialVersionUID = 8892857232931509048L; + } diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/AbstractData.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/AbstractData.java index cc0d0f1..66c69d0 100755 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/AbstractData.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/AbstractData.java @@ -320,10 +320,10 @@ public static String[] getDomainAndService(String sRawServiceName) */ protected String getFirstMemberOfArray(JsonNode nodeJson, String sAttributeName) { - JsonNode partitionsVulnerableNode = nodeJson.get(sAttributeName); - return partitionsVulnerableNode == null && partitionsVulnerableNode.isArray() - ? 0 + "" - : partitionsVulnerableNode.get(0).asText(); + JsonNode jsonNode = nodeJson.get(sAttributeName); + return jsonNode == null || !jsonNode.isArray() + ? (0 + "") + : jsonNode.get(0).asText(); } /** diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/CacheData.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/CacheData.java index 251c0a6..d0ee290 100755 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/CacheData.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/CacheData.java @@ -399,8 +399,9 @@ private Data getData(VisualVMModel model, String sServiceName, JsonNode cacheDet : nCacheSize / nMembers); data.setColumn(UNIT_CALCULATOR, sUnitCalculator); + JsonNode units = cacheDetails.get("units"); long cMemoryUsageBytes = Long.parseLong(getFirstMemberOfArray(cacheDetails, "unitFactor")) - * cacheDetails.get("units").asLong(); + * (units == null ? 0 : units.asLong()); data.setColumn(MEMORY_USAGE_BYTES, cMemoryUsageBytes); data.setColumn(MEMORY_USAGE_MB, (int) (cMemoryUsageBytes / 1024 / 1024)); diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/HealthData.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/HealthData.java new file mode 100644 index 0000000..22ccb6b --- /dev/null +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/HealthData.java @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.coherence.plugin.visualvm.tablemodel.model; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.SortedMap; +import java.util.TreeMap; + +import java.util.logging.Logger; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.oracle.coherence.plugin.visualvm.VisualVMModel; +import com.oracle.coherence.plugin.visualvm.helper.HttpRequestSender; +import com.oracle.coherence.plugin.visualvm.helper.RequestSender; + +/** + * A class to hold health data. + * + * @author tam 2022.06.22 + * @since 1.4.0 + */ +public class HealthData + extends AbstractData + { + // ----- constructors --------------------------------------------------- + + /** + * Create PersistenceData passing in the number of columns. + */ + public HealthData() + { + super(CLASS_NAME + 1); + } + + // ----- DataRetriever methods ------------------------------------------ + + @Override + public List> getJMXData(RequestSender requestSender, VisualVMModel model) + { + return null; + } + + @Override + public String getReporterReport() + { + return REPORT_HEALTH; // see comment below + } + + @Override + public Data processReporterData(Object[] aoColumns, VisualVMModel model) + { + Data data = new HealthData(); + + HealthKey key = new HealthKey((String) aoColumns[3], (String) aoColumns[4], Integer.parseInt(getNumberValue(aoColumns[2].toString()))); + + data.setColumn(HealthData.HEALTH_NAME, key); + data.setColumn(HealthData.NODE_ID, Integer.valueOf(getNumberValue(aoColumns[2].toString()))); + data.setColumn(HealthData.SUB_TYPE, aoColumns[4]); + data.setColumn(HealthData.STARTED, Boolean.valueOf(aoColumns[5].toString())); + data.setColumn(HealthData.LIVE, Boolean.valueOf(aoColumns[6].toString())); + data.setColumn(HealthData.READY, Boolean.valueOf(aoColumns[7].toString())); + data.setColumn(HealthData.SAFE, Boolean.valueOf(aoColumns[8].toString())); + data.setColumn(HealthData.CLASS_NAME, aoColumns[9].toString()); + + return data; + } + + @Override + public SortedMap getAggregatedDataFromHttpQuerying(VisualVMModel model, HttpRequestSender requestSender) + throws Exception + { + SortedMap mapData = new TreeMap<>(); + JsonNode allStorageMembers = requestSender.getAllHealthMembers(); + JsonNode healthItemsNode = allStorageMembers.get("items"); + + Data data; + + if (healthItemsNode != null && healthItemsNode.isArray()) + { + for (int i = 0; i < ((ArrayNode) healthItemsNode).size(); i++) + { + JsonNode details = healthItemsNode.get(i); + + data = new HealthData(); + String sName = details.get("name").asText(); + String sSubType = details.get("subType").asText(); + int nNodeId = details.get("nodeId").asInt(); + + HealthKey key = new HealthKey(sName, sSubType, nNodeId); + + data.setColumn(HealthData.HEALTH_NAME, key); + data.setColumn(HealthData.NODE_ID, nNodeId); + data.setColumn(HealthData.SUB_TYPE, sSubType); + data.setColumn(HealthData.STARTED, details.get("started").asBoolean()); + data.setColumn(HealthData.LIVE, details.get("live").asBoolean()); + data.setColumn(HealthData.READY, details.get("ready").asBoolean()); + data.setColumn(HealthData.SAFE, details.get("safe").asBoolean()); + data.setColumn(HealthData.CLASS_NAME, details.get("className").asText()); + + mapData.put(key, data); + } + } + return mapData; + } + + /** + * Key to be used for the Health Data. + */ + public static class HealthKey implements Comparable + { + + public HealthKey(String sName, String sSubType, int nNodeId) + { + f_sName = sName; + f_sSubType = sSubType; + f_nNodeId = nNodeId; + } + + public int getNodeId() { + return f_nNodeId; + } + + public String getName() { + return f_sName; + } + + public String getSubType() { + return f_sSubType; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + HealthKey healthKey = (HealthKey) o; + + if (f_nNodeId != healthKey.f_nNodeId) return false; + if (!Objects.equals(f_sName, healthKey.f_sName)) return false; + return Objects.equals(f_sSubType, healthKey.f_sSubType); + } + + @Override + public int hashCode() { + int result = f_sName != null ? f_sName.hashCode() : 0; + result = 31 * result + (f_sSubType != null ? f_sSubType.hashCode() : 0); + result = 31 * result + f_nNodeId; + return result; + } + + @Override + public String toString() + { + return f_sName + "/" + f_sSubType + "/" + f_nNodeId; + } + + @Override + public int compareTo(HealthKey o) { + int i = Integer.compare(o.f_nNodeId, this.f_nNodeId); + if (i != 0 ) + { + return i; + } + i = o.f_sName.compareTo(this.f_sName); + + if (i != 0 ) + { + return i; + } + + return o.f_sSubType.compareTo(this.f_sSubType); + } + + private final String f_sName; + private final String f_sSubType; + private final int f_nNodeId; + } + + // ----- constants ------------------------------------------------------ + + private static final long serialVersionUID = 7769559573242105947L; + + /** + * Array index for health name. + */ + public static final int HEALTH_NAME = 0; + + /** + * Array index for node id. + */ + public static final int NODE_ID = 1; + + /** + * Array index for sub-type. + */ + public static final int SUB_TYPE = 2; + + /** + * Array index for started. + */ + public static final int STARTED = 3; + + /** + * Array index for live. + */ + public static final int LIVE = 4; + + /** + * Array index for ready. + */ + public static final int READY = 5; + + /** + * Array index for safe + */ + public static final int SAFE = 6; + + /** + * Array index for description. + */ + public static final int CLASS_NAME = 7; + + /** + * The logger object to use. + */ + private static final Logger LOGGER = Logger.getLogger(HealthData.class.getName()); + + /** + * Report for cluster data. + */ + public static final String REPORT_HEALTH = "reports/visualvm/health-stats.xml"; + } diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/HealthSummaryData.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/HealthSummaryData.java new file mode 100644 index 0000000..4820862 --- /dev/null +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/HealthSummaryData.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.coherence.plugin.visualvm.tablemodel.model; + +import java.util.List; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +import com.oracle.coherence.plugin.visualvm.VisualVMModel; +import com.oracle.coherence.plugin.visualvm.helper.HttpRequestSender; +import com.oracle.coherence.plugin.visualvm.helper.RequestSender; + +/** + * A class to hold summary health data. + * + * @author tam 2022.06.22 + * @since 1.4.0 + */ +public class HealthSummaryData + extends AbstractData + { + // ----- constructors --------------------------------------------------- + + /** + * Create PersistenceData passing in the number of columns. + */ + public HealthSummaryData() + { + super(SAFE + 1); + } + + // ----- DataRetriever methods ------------------------------------------ + + @Override + public List> getJMXData(RequestSender requestSender, VisualVMModel model) + { + return null; + } + + @Override + public String getReporterReport() + { + return REPORT_HEALTH; // see comment below + } + + @Override + public Data processReporterData(Object[] aoColumns, VisualVMModel model) + { + return null; + } + + @Override + public SortedMap getAggregatedDataFromHttpQuerying(VisualVMModel model, HttpRequestSender requestSender) + throws Exception + { + return new TreeMap<>(); + } + + private static final long serialVersionUID = 7769559573242105947L; + + /** + * Array index for health name. + */ + public static final int HEALTH_NAME = 0; + + /** + * Array index for members. + */ + public static final int MEMBERS = 1; + + /** + * Array index for started. + */ + public static final int STARTED = 2; + + /** + * Array index for live. + */ + public static final int LIVE = 3; + + /** + * Array index for ready. + */ + public static final int READY = 4; + + /** + * Array index for safe + */ + public static final int SAFE = 5; + + /** + * Report for cluster data. + */ + public static final String REPORT_HEALTH = "reports/visualvm/health-stats.xml"; + } diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/MachineData.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/MachineData.java index 608c69a..6ef3476 100755 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/MachineData.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/MachineData.java @@ -105,7 +105,7 @@ public List> getJMXData(RequestSender requestSender, Vis new String[] { "Name", ATTR_FREE_MEM, ATTR_LOAD_AVG, ATTR_AVAIL_PROC, ATTR_TOTAL_MEM_AIX, ATTR_TOTAL_MEM }); String sOSType = getAttributeValueAsString(listAttr, "Name"); - String sMemoryAttr = sOSType.toLowerCase().contains("aix") ? ATTR_TOTAL_MEM_AIX : ATTR_TOTAL_MEM; + String sMemoryAttr = sOSType != null && sOSType.toLowerCase().contains("aix") ? ATTR_TOTAL_MEM_AIX : ATTR_TOTAL_MEM; data.setColumn(MACHINE_NAME, machineName); data.setColumn(FREE_PHYSICAL_MEMORY, Long.parseLong(getAttributeValueAsString(listAttr, ATTR_FREE_MEM))); @@ -130,7 +130,6 @@ public List> getJMXData(RequestSender requestSender, Vis // put it into the mapData with just a machine as the key mapData.put(machineName, data); - } } diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/PersistenceData.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/PersistenceData.java index ac6bfdb..dce4bb8 100644 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/PersistenceData.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/PersistenceData.java @@ -145,7 +145,7 @@ public List> getJMXData(RequestSender requestSender, Vis String sDomainPartition = asParts.length == 2 ? asParts[0] : null; sServiceName = sDomainPartition == null ? sServiceNameKey : asParts[1]; - // select only the current service so we can determine the number of storage-enabled + // select only the current service, so we can determine the number of storage-enabled // members. Set resultSet = requestSender.getMembersOfService(sServiceName, sDomainPartition); @@ -156,18 +156,26 @@ public List> getJMXData(RequestSender requestSender, Vis // only include storage-enabled members AttributeList listAttr = requestSender.getAttributes(objectName, - new String[] { "StorageEnabled", "PersistenceActiveSpaceUsed", "PersistenceLatencyMax", "PersistenceLatencyAverage" }); + new String[] { "StorageEnabled", MBEAN_ACTIVE_SPACE, MBEAN_BACKUP_SPACE, "PersistenceLatencyMax", "PersistenceLatencyAverage" }); if (Boolean.parseBoolean(getAttributeValueAsString(listAttr, "StorageEnabled"))) { data = (PersistenceData) mapData.get(sServiceNameKey); - // PersistenceActiveSpaceUsed is only valid for active persistence mode - if ("active".equals(data.getColumn(PERSISTENCE_MODE))) + // PersistenceActiveSpaceUsed is only valid for active or active-backup persistence mode + if (isActivePersistence((String) data.getColumn(PERSISTENCE_MODE))) { data.setColumn(TOTAL_ACTIVE_SPACE_USED, - (Long) data.getColumn(TOTAL_ACTIVE_SPACE_USED) - + Long.parseLong(getAttributeValueAsString(listAttr, "PersistenceActiveSpaceUsed"))); + ((Long) data.getColumn(TOTAL_ACTIVE_SPACE_USED)) + + + Long.parseLong(getAttributeValueAsString(listAttr, MBEAN_ACTIVE_SPACE))); + + String sData = getAttributeValueAsString(listAttr, MBEAN_BACKUP_SPACE); + + long nBackupSpaceUsed = sData == null ? 0L : Long.parseLong(sData); + + data.setColumn(TOTAL_BACKUP_SPACE_USED_MB, + (Long) data.getColumn(TOTAL_BACKUP_SPACE_USED_MB) + + Math.max(nBackupSpaceUsed, 0)); } // update the max (of the max latencies) @@ -199,6 +207,7 @@ public List> getJMXData(RequestSender requestSender, Vis } data.setColumn(TOTAL_ACTIVE_SPACE_USED_MB, (Long) data.getColumn(TOTAL_ACTIVE_SPACE_USED) / GraphHelper.MB); + data.setColumn(TOTAL_BACKUP_SPACE_USED_MB, (Long) data.getColumn(TOTAL_BACKUP_SPACE_USED_MB) / GraphHelper.MB); mapData.put(sServiceNameKey, data); } @@ -275,12 +284,18 @@ public SortedMap getAggregatedDataFromHttpQuerying(VisualVMModel m } // update the details for each node - // PersistenceActiveSpaceUsed is only valid for active persistence mode - if ("active".equals(sPersistenceMode)) + // PersistenceActiveSpaceUsed is only valid for active or active-backup persistence mode + if (isActivePersistence(sPersistenceMode)) { long nPersistenceActiveSpaceUsed = details.get("persistenceActiveSpaceUsed").asLong(); + JsonNode jsonBackup = details.get("persistenceBackupSpaceUsed"); + long nPersistenceBackupSpaceUsed = jsonBackup == null ? 0L : jsonBackup.asLong(); + data.setColumn(TOTAL_ACTIVE_SPACE_USED, (Long) data.getColumn(TOTAL_ACTIVE_SPACE_USED) + nPersistenceActiveSpaceUsed); + + data.setColumn(TOTAL_BACKUP_SPACE_USED_MB, + (Long) data.getColumn(TOTAL_BACKUP_SPACE_USED_MB) + nPersistenceBackupSpaceUsed); } // update the max (of the max latencies) @@ -312,6 +327,8 @@ public SortedMap getAggregatedDataFromHttpQuerying(VisualVMModel m v.setColumn(TOTAL_ACTIVE_SPACE_USED_MB, (Long) v.getColumn(TOTAL_ACTIVE_SPACE_USED) / GraphHelper.MB); + v.setColumn(TOTAL_BACKUP_SPACE_USED_MB, + (Long) v.getColumn(TOTAL_BACKUP_SPACE_USED_MB) / GraphHelper.MB); int cNodes = mapNodeCount.get(k); // update the average of the averages only if > 1 service node @@ -342,6 +359,7 @@ private Data createData(String sServiceName, String sPersistenceMode, String sDo data.setColumn(SERVICE_NAME, sServiceName); data.setColumn(PERSISTENCE_MODE, sPersistenceMode); data.setColumn(TOTAL_ACTIVE_SPACE_USED, 0L); + data.setColumn(TOTAL_BACKUP_SPACE_USED_MB, 0L); data.setColumn(MAX_LATENCY, 0L); data.setColumn(AVERAGE_LATENCY, 0.0f); @@ -409,6 +427,17 @@ public static String getMBeanName(String sServiceName) + "," + PERSISTENCE_COORDINATOR +",*"; } + /** + * Returns true if we are using active persistence mode. + * + * @param sPersistenceMode the persistence mode + * @return true if we are using active persistence mode. + */ + public static boolean isActivePersistence(String sPersistenceMode) + { + return sPersistenceMode != null && sPersistenceMode.startsWith("active"); + } + // ----- constants ------------------------------------------------------ private static final long serialVersionUID = 7769559573242105947L; @@ -443,28 +472,43 @@ public static String getMBeanName(String sServiceName) */ public static final int TOTAL_ACTIVE_SPACE_USED_MB = 3; + /** + * Array index for total backup space used MB. + */ + public static final int TOTAL_BACKUP_SPACE_USED_MB = 4; + /** * Array index for average latency */ - public static final int AVERAGE_LATENCY = 4; + public static final int AVERAGE_LATENCY = 5; /** * Array index for max latency. */ - public static final int MAX_LATENCY = 5; + public static final int MAX_LATENCY = 6; /** * Array index for number of snapshots. */ - public static final int SNAPSHOT_COUNT = 6; + public static final int SNAPSHOT_COUNT = 7; /** * Array index for status. */ - public static final int STATUS = 7; + public static final int STATUS = 8; /** * The logger object to use. */ private static final Logger LOGGER = Logger.getLogger(PersistenceData.class.getName()); + + /** + * Attribute for active space. + */ + private static final String MBEAN_ACTIVE_SPACE = "PersistenceActiveSpaceUsed"; + + /** + * Attribute for backup space. + */ + private static final String MBEAN_BACKUP_SPACE = "PersistenceBackupSpaceUsed"; } diff --git a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/ServiceData.java b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/ServiceData.java index d1e88dd..57ec084 100755 --- a/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/ServiceData.java +++ b/coherence-visualvm-plugin/src/main/java/com/oracle/coherence/plugin/visualvm/tablemodel/model/ServiceData.java @@ -103,8 +103,8 @@ public List> getJMXData(RequestSender sender, VisualVMMo // if its dist cache or federated then save so we don't, double count size for repl // caches - String sCacheType = (String) sender.getAttribute(cacheNameObjName, "Type"); - if (DISTRIBUTED_CACHE_TYPE.equals(sCacheType) || FEDERATED_CACHE_TYPE.equals(sCacheType) ) + String sServiceType = (String) sender.getAttribute(cacheNameObjName, "Type"); + if (isDistributed(sServiceType)) { setDistributedCaches.add(sServiceName); } @@ -205,7 +205,7 @@ public Data processReporterData(Object[] aoColumns, VisualVMModel model) data.setColumn(ServiceData.PARTITIONS_PENDING, Integer.valueOf(getNumberValue(aoColumns[nStart++].toString()))); // record the list of distributed & federated caches - if (DISTRIBUTED_CACHE_TYPE.equals(aoColumns[nStart]) || FEDERATED_CACHE_TYPE.equals(aoColumns[nStart])) + if (isDistributed((String) aoColumns[nStart])) { setDistributedCaches.add(data.getColumn(ServiceData.SERVICE_NAME).toString()); } @@ -269,8 +269,7 @@ public SortedMap getAggregatedDataFromHttpQuerying(VisualVMModel data.setColumn(ServiceData.MEMBERS, nTotalMemberCount); // record the list of distributed, federated or replicated caches - if (DISTRIBUTED_CACHE_TYPE.equals(sServiceType) || FEDERATED_CACHE_TYPE.equals(sServiceType) || - REPLICATED_CACHE_TYPE.equals(sServiceType)) + if (isDistributed(sServiceType) || REPLICATED_CACHE_TYPE.equals(sServiceType)) { data.setColumn(ServiceData.PARTITION_COUNT, serviceDetails.get("partitionsAll").asInt()); @@ -311,6 +310,18 @@ public SortedMap getAggregatedDataFromHttpQuerying(VisualVMModel return mapData; } + /** + * Returns true if the server type is a distributed cache. + * @param sServiceType cache type + * + * @return true if the cache type is a distributed cache + */ + public static boolean isDistributed(String sServiceType) + { + return DISTRIBUTED_CACHE_TYPE.equals(sServiceType) || FEDERATED_CACHE_TYPE.equals(sServiceType) || + PAGED_TOPIC_TYPE.equals(sServiceType); + } + // ----- constants ------------------------------------------------------ private static final long serialVersionUID = -9192162461585760564L; @@ -376,6 +387,11 @@ public SortedMap getAggregatedDataFromHttpQuerying(VisualVMModel */ private static final String DISTRIBUTED_CACHE_TYPE = "DistributedCache"; + /** + * Service of type PagedTopic. + */ + private static final String PAGED_TOPIC_TYPE = "PagedTopic"; + /** * Service of type FederatedCache. */ diff --git a/coherence-visualvm-plugin/src/main/resources/com/oracle/coherence/plugin/visualvm/Bundle.properties b/coherence-visualvm-plugin/src/main/resources/com/oracle/coherence/plugin/visualvm/Bundle.properties index 390bce3..d7df400 100644 --- a/coherence-visualvm-plugin/src/main/resources/com/oracle/coherence/plugin/visualvm/Bundle.properties +++ b/coherence-visualvm-plugin/src/main/resources/com/oracle/coherence/plugin/visualvm/Bundle.properties @@ -42,6 +42,7 @@ OpenIDE-Module-Long-Description=\
  • HTTP Servers - If your cluster is running proxy servers with HTTP acceptors, this tab displays information about the HTTP servers, the number of connections across each server, total connections and graphs of response codes, errors and requests over time for a selected service.
  • \
  • Executors - If your cluster is configured to run the Executor Service, this tab displays information about the number of tasks completed, in-progress and rejected.
  • \
  • gRPC Proxies - If your cluster is configured to run gRPC Proxies, this tab displays information regarding the gRPC requests and responses. Note: This currently only works when connected via JMX.
  • \ +
  • Health - If your cluster supports the Health Check API, this tab displays information regarding the status of all health endpoints.
  • \
  • Coherence*Web - If your cluster is configured for Coherence*Web, this tab displays information about the number applications deployed, the number of HTTP sessions being stored as well as other information regarding session reaping. (**)
  • \
  • Federation - If your cluster is configured with Federated Caching, this tab displays information about each federated service. If you select a service, on the next data refresh you will see detailed outbound/inbound federation traffic information for each node of the service as well as graphs of that information. (**)
  • \
  • Persistence - If your cluster is configured with Persistence, this tab displays information about each service configured with Persistence. Graphs showing active space used and any additional latencies incurred are also showed.
  • \ @@ -49,11 +50,11 @@ OpenIDE-Module-Long-Description=\
  • JCache - If your cluster is being used to store JCache caches, this tab displays JCache "Management" and "Statistics" MBean information regarding the configured caches.
  • \
  • HotCache - If your cluster contains HotCache node(s), then this tab lists the running HotCache instances. If you select an instance, on the next data refresh the console will display statistics and graphs for the operations performed. You may click on tabs and cache-ops to see further fine-grained information. (**)
  • \
    \ - Please see https://docs.oracle.com/en/middleware/standalone/coherence/14.1.1.0/manage/using-jmx-manage-oracle-coherence.html for more information on enabling JMX on your \ + Please see https://docs.oracle.com/en/middleware/standalone/coherence/14.1.1.2206/manage/using-jmx-manage-oracle-coherence.html for more information on enabling JMX on your \ Coherence cluster. \

    Note: This is a developer tool for viewing information about a single cluster at a time. For more time based enterprise monitoring you can enable Coherence metrics and use Grafana Dashboards or use a tool such as Oracle's Enterprise Manager \ for enterprise level monitoring, management and alerting. \ -

    Note: Items marked with ** will only show when connected to a commercial edition of Coherence. +

    Note: Items marked with ** will only show when connected to a commercial edition of Coherence where the feature is utilized. OpenIDE-Module-Short-Description=A Developer plug-in for providing high level information and statistics about a running Coherence Cluster. # Messages and labels that need to be internationalized @@ -112,8 +113,10 @@ LBL_member_departure_count=Member Departure Count LBL_total_cluster_memory_avail=Total Storage Heap Avail (MB) LBL_overview=Overview LBL_report_node_state=Generate Thread Dump +LBL_report_node_environment=Report Environment LBL_report_node_state_multi=Generate Multiple Thread Dumps LBL_state_for_node=Thread Dump(s) for Node +LBL_environment_for_node=Environment for Node LBL_number_thread_dumps=Thread Dumps LBL_time_between=Time Between Each (seconds) LBL_multi=Please enter the number of thread dumps and seconds between each @@ -127,6 +130,7 @@ LBL_data_saved=Thread Dump has been saved to {0}. # CoherencePersistencePanel LBL_total_active_space=Total Active Persistence Space Used (MB) +LBL_total_backup_space=Total Backyup Persistence Space Used (MB) LBL_max_latency_across_services=Max Latency Across Services (ms) LBL_must_select_row=You must select a row LBL_result=Result @@ -284,6 +288,16 @@ LBL_messages_received=Messages Received LBL_request_duration_mean=Mean Req Duration (ms) LBL_message_duration_mean=Mean Msg Duration (ms) +# Health +LBL_health_name=Name +LBL_health_subtype=Sub-Type +LBL_started=Started +LBL_live=Live +LBL_ready=Ready +LBL_safe=Safe +LBL_health_class=Class Name +LBL_total_health_checks=Total Health Checks - All Members + # ExportableJTable LBL_save_data_as=Save data as... LBL_unable_to_save=Unable to save data to file {0}. Error: {1} @@ -309,6 +323,7 @@ LBL_JCache=JCache LBL_executors=Executors LBL_http_proxy_servers=HTTP Servers LBL_grpc=gRPC Proxies +LBL_health=Health LBL_mt_warning=You have connected to a multi-tenant environment as a WebLogic Administrator.\n\ As a result you can see all Domain Partitions. When carrying out any operations, please\n\ ensure that you choose the correct partition for your operation. @@ -388,6 +403,7 @@ LBL_active_space_bytes=Active Space Used on disk (bytes) LBL_avge_persistence=Average Additional Latency (ms) LBL_max_persistence=Maximum Additional Latency (ms) LBL_active_space_mb=Active Space Used on disk (MB) +LBL_backup_space_mb=Backup Space Used on disk (MB) LBL_snapshot_count=Snapshot Count LBL_application_id=Application Id LBL_platform=Platform @@ -494,8 +510,9 @@ GRPH_task_backlog=Task Backlog for {0} GRPH_request_average=Request Average Duration for {0} (ms) GRPH_persistence_latency=Latency Average Across all 'active' Services (\u00b5s) GRPH_current_average_persistence=Current Average (\u00b5s) -GRPH_total_active_space=Total Active Space Used -GRPH_total_space=Total Space +GRPH_total_active_space=Total Active/Backup Space Used +GRPH_total_space=Total Active Space +GRPH_backup_space=Total Backup Space GRPH_session_sizes=HTTP Session Cache Count GRPH_total_session_count=Total Session Count GRPH_total_overflow_count=Total Overflow Count diff --git a/coherence-visualvm-plugin/src/main/resources/reports/visualvm/health-stats.xml b/coherence-visualvm-plugin/src/main/resources/reports/visualvm/health-stats.xml new file mode 100644 index 0000000..ce34d76 --- /dev/null +++ b/coherence-visualvm-plugin/src/main/resources/reports/visualvm/health-stats.xml @@ -0,0 +1,91 @@ + + + + + + + + {date}-health-stats.txt + {tab} + + + Coherence:type=Health,* + equals + + + + + global + {batch-counter} +
    Batch Counter
    +
    + + + key + nodeId +
    NodeId
    +
    + + + key + name +
    Service Name
    +
    + + + key + subType +
    Sub Type
    +
    + + + Started + + + + Live + + + + Ready + + + + Safe + + + + ClassName + +
    +
    +
    \ No newline at end of file diff --git a/coherence-visualvm-tests/coherence-visualvm-tests-ce/pom.xml b/coherence-visualvm-tests/coherence-visualvm-tests-ce/pom.xml index b23e537..700ae07 100644 --- a/coherence-visualvm-tests/coherence-visualvm-tests-ce/pom.xml +++ b/coherence-visualvm-tests/coherence-visualvm-tests-ce/pom.xml @@ -1,7 +1,7 @@ - 21.12.3 - 14.1.2-0-0-SNAPSHOT - + 21.12.4 + 14.1.2-0-0-SNAPSHOT -Xmx1g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${project.build.directory} -XX:+ExitOnOutOfMemoryError -Dfile.encoding=UTF-8 --illegal-access=permit - 2.11.3 + 2.13.3 ${jackson.version} 1.8 1.8 8 1.2.0 4.13.1 - RELEASE204 + 2.1 + RELEASE124 2.2 3.6.0 - 5.0.20 + 6.0.0 3.8.0 4.2.1 @@ -97,67 +97,67 @@ org.graalvm.visualvm.modules org-graalvm-visualvm-uisupport - ${jvisualvm.version} + ${visualvm.version} org.graalvm.visualvm.api org-graalvm-visualvm-application - ${jvisualvm.version} + ${visualvm.version} org.graalvm.visualvm.api org-graalvm-visualvm-application-views - ${jvisualvm.version} + ${visualvm.version} org.graalvm.visualvm.api org-graalvm-visualvm-charts - ${jvisualvm.version} + ${visualvm.version} org.graalvm.visualvm.api org-graalvm-visualvm-core - ${jvisualvm.version} + ${visualvm.version} org.graalvm.visualvm.api org-graalvm-visualvm-tools - ${jvisualvm.version} + ${visualvm.version} - org.graalvm.visualvm.api + org.netbeans.api org-openide-modules - ${jvisualvm.version} + ${netbeans.version} - org.graalvm.visualvm.api + org.netbeans.api org-openide-awt - ${jvisualvm.version} + ${netbeans.version} - org.graalvm.visualvm.api + org.netbeans.api org-openide-util - ${jvisualvm.version} + ${netbeans.version} - org.graalvm.visualvm.api + org.netbeans.api org-openide-dialogs - ${jvisualvm.version} + ${netbeans.version} - org.graalvm.visualvm.api + org.netbeans.api org-openide-windows - ${jvisualvm.version} + ${netbeans.version} - org.graalvm.visualvm.api + org.netbeans.api org-netbeans-modules-options-api - ${jvisualvm.version} + ${netbeans.version} org.graalvm.visualvm.modules org-graalvm-visualvm-lib-ui - ${jvisualvm.version} + ${visualvm.version} @@ -205,7 +205,6 @@ - org.apache.maven.plugins @@ -264,7 +263,6 @@ ${maven.nbm.plugin.version} - org.apache.maven.plugins @@ -282,5 +280,4 @@ -