This is an automated email from the ASF dual-hosted git repository.

sk0x50 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new ae13d04e7e8 IGNITE-27500 improve log message (#7350)
ae13d04e7e8 is described below

commit ae13d04e7e8866c42dbc8cdc33146b007784101b
Author: Egor <[email protected]>
AuthorDate: Fri Jan 16 15:22:57 2026 +0400

    IGNITE-27500 improve log message (#7350)
    
    Co-authored-by: Egor Kuts <[email protected]>
---
 .../metrics/LocalTopologyMetricsSource.java        |  20 +-
 .../LogPushExporterConfigurationSchema.java        |  14 +-
 .../metrics/exporters/log/LogPushExporter.java     |  76 ++++---
 .../internal/metrics/sources/JvmMetricSource.java  |  41 ++++
 .../internal/metrics/sources/OsMetricSource.java   |   6 +
 .../metrics/exporters/log/LogPushExporterTest.java | 242 +++++++++++++++++++--
 .../metrics/sources/JvmMetricSourceTest.java       |   7 +
 .../metrics/sources/OsMetricSourceTest.java        |  12 +-
 8 files changed, 361 insertions(+), 57 deletions(-)

diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/metrics/LocalTopologyMetricsSource.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/metrics/LocalTopologyMetricsSource.java
index 766c51eccb8..7e064b79b3a 100644
--- 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/metrics/LocalTopologyMetricsSource.java
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/metrics/LocalTopologyMetricsSource.java
@@ -20,11 +20,13 @@ package 
org.apache.ignite.internal.cluster.management.metrics;
 import java.util.List;
 import java.util.UUID;
 import org.apache.ignite.internal.metrics.AbstractMetricSource;
+import org.apache.ignite.internal.metrics.IntGauge;
 import org.apache.ignite.internal.metrics.Metric;
 import org.apache.ignite.internal.metrics.StringGauge;
 import org.apache.ignite.internal.metrics.UuidGauge;
 import org.apache.ignite.internal.network.TopologyService;
 import org.apache.ignite.internal.properties.IgniteProductVersion;
+import org.apache.ignite.network.NetworkAddress;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -116,7 +118,23 @@ public class LocalTopologyMetricsSource extends 
AbstractMetricSource<LocalTopolo
                 "Unique name of the local node",
                 () -> physicalTopology.localMember().name());
 
-        private final List<Metric> metrics = List.of(localNodeName, 
localNodeId, localNodeVersion);
+        private final StringGauge networkAddress = new StringGauge(
+                "NetworkAddress",
+                "Network address of the local node",
+                () -> {
+                    NetworkAddress addr = 
physicalTopology.localMember().address();
+                    return addr != null ? addr.host() : "";
+                });
+
+        private final IntGauge networkPort = new IntGauge(
+                "NetworkPort",
+                "Network port of the local node",
+                () -> {
+                    NetworkAddress addr = 
physicalTopology.localMember().address();
+                    return addr != null ? addr.port() : 0;
+                });
+
+        private final List<Metric> metrics = List.of(localNodeName, 
localNodeId, localNodeVersion, networkAddress, networkPort);
 
         @Override
         public Iterable<Metric> metrics() {
diff --git 
a/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/exporters/configuration/LogPushExporterConfigurationSchema.java
 
b/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/exporters/configuration/LogPushExporterConfigurationSchema.java
index cc100d00ac1..9658de0be15 100644
--- 
a/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/exporters/configuration/LogPushExporterConfigurationSchema.java
+++ 
b/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/exporters/configuration/LogPushExporterConfigurationSchema.java
@@ -32,19 +32,25 @@ public class LogPushExporterConfigurationSchema extends 
ExporterConfigurationSch
     @PublicName(legacyNames = "period")
     public long periodMillis = 30_000;
 
-    /** Whether to print metrics of one metric source in single log line. */
+    /** Whether to print each metric source on a separate line. */
     @Value(hasDefault = true)
-    public boolean oneLinePerMetricSource = true;
+    public boolean oneLinePerMetricSource = false;
 
     /**
      * List of enabled metric sources. If not empty, metric sources that are 
not enumerated will not be printed.
      * Wildcard '*' can be used in the end of each item. Some metrics are 
logged by default. To disable it, specify the empty list here
-     * explicitly. To print all metrics, include single string '*'.
+     * explicitly. To print all metrics, include a single string '*'.
      */
     @Value(hasDefault = true)
     public String[] enabledMetrics = {
             "metastorage",
             "placement-driver",
-            "resource.vacuum"
+            "resource.vacuum",
+            "jvm",
+            "os",
+            "topology.local",
+            "topology.cluster",
+            "thread.pools.partitions-executor",
+            "thread.pools.sql-executor"
     };
 }
diff --git 
a/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/exporters/log/LogPushExporter.java
 
b/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/exporters/log/LogPushExporter.java
index 20cccd68589..acfbf6a4d81 100644
--- 
a/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/exporters/log/LogPushExporter.java
+++ 
b/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/exporters/log/LogPushExporter.java
@@ -20,7 +20,6 @@ package org.apache.ignite.internal.metrics.exporters.log;
 import static java.util.Comparator.comparing;
 import static java.util.stream.Collectors.toList;
 import static org.apache.ignite.internal.util.IgniteUtils.findAny;
-import static org.apache.ignite.internal.util.IgniteUtils.forEachIndexed;
 
 import com.google.auto.service.AutoService;
 import java.util.Arrays;
@@ -42,11 +41,10 @@ import org.apache.ignite.internal.util.CollectionUtils;
 public class LogPushExporter extends PushMetricExporter {
     public static final String EXPORTER_NAME = "logPush";
 
-    /** Padding for individual metric output. */
-    private static final String PADDING = "  ";
+    /** Padding for individual metric output in multiline mode. */
+    private static final String PADDING = "  ^-- ";
 
     private volatile boolean oneLinePerMetricSource;
-
     private volatile List<String> enabledMetrics;
 
     @Override
@@ -71,52 +69,58 @@ public class LogPushExporter extends PushMetricExporter {
             return;
         }
 
-        var report = new StringBuilder("Metric report:");
-
+        var report = new StringBuilder("Metrics for local node:");
+        if (!oneLinePerMetricSource) {
+            report.append(' ');
+        }
+        boolean needSeparator = oneLinePerMetricSource;
         for (MetricSet metricSet : metricSets) {
             boolean hasMetricsWhiteList = hasMetricsWhiteList(metricSet);
 
             if (hasMetricsWhiteList || metricEnabled(metricSet.name())) {
-                
report.append('\n').append(metricSet.name()).append(oneLinePerMetricSource ? ' 
' : ':');
-
-                appendMetrics(report, metricSet, hasMetricsWhiteList);
+                needSeparator = appendMetricsOneLine(report, metricSet, 
hasMetricsWhiteList, needSeparator);
             }
         }
-
         log.info(report.toString());
     }
 
-    private void appendMetrics(StringBuilder sb, MetricSet metricSet, boolean 
hasMetricsWhiteList) {
+    private void addSeparatorIfNeeded(StringBuilder report, boolean 
needSeparator) {
+        if (needSeparator) {
+            if (oneLinePerMetricSource) {
+                report.append(System.lineSeparator()).append(PADDING);
+            } else {
+                report.append(", ");
+            }
+        }
+    }
+
+    /**
+     * Appends metrics in one-line format.
+     *
+     * @param sb String builder.
+     * @param metricSet Metric set.
+     * @param hasMetricsWhiteList Whether metrics whitelist is present.
+     * @return True if separator is needed for next item.
+     */
+    private boolean appendMetricsOneLine(StringBuilder sb, MetricSet 
metricSet, boolean hasMetricsWhiteList, boolean needSeparator) {
         List<Metric> metrics = StreamSupport.stream(metricSet.spliterator(), 
false)
                 .sorted(comparing(Metric::name))
                 .filter(m -> !hasMetricsWhiteList || 
metricEnabled(fqn(metricSet, m)))
                 .collect(toList());
-
-        sb.append(metricSetPrefix());
-
-        forEachIndexed(metrics, (m, i) -> 
appendMetricWithValue(oneLinePerMetricSource, sb, m, i));
-
-        sb.append(metricSetPostfix());
-    }
-
-    private static String commaInEnum(int i) {
-        return i == 0 ? "" : ", ";
-    }
-
-    private String metricSetPrefix() {
-        return oneLinePerMetricSource ? "[" : "";
-    }
-
-    private String metricSetPostfix() {
-        return oneLinePerMetricSource ? "]" : "";
-    }
-
-    private static void appendMetricWithValue(boolean oneLinePerMetricSource, 
StringBuilder sb, Metric m, int index) {
-        if (oneLinePerMetricSource) {
-            
sb.append(commaInEnum(index)).append(m.name()).append('=').append(m.getValueAsString());
-        } else {
-            sb.append('\n').append(PADDING).append(m.name()).append(": 
").append(m.getValueAsString());
+        if (metrics.isEmpty()) {
+            return needSeparator;
+        }
+        addSeparatorIfNeeded(sb, needSeparator);
+        sb.append(metricSet.name()).append(' ').append('[');
+        for (int i = 0; i < metrics.size(); i++) {
+            if (i > 0) {
+                sb.append(", ");
+            }
+            Metric m = metrics.get(i);
+            sb.append(m.name()).append('=').append(m.getValueAsString());
         }
+        sb.append(']');
+        return true;
     }
 
     private boolean metricEnabled(String name) {
diff --git 
a/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/sources/JvmMetricSource.java
 
b/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/sources/JvmMetricSource.java
index 9b13deba47f..36f0e081c71 100644
--- 
a/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/sources/JvmMetricSource.java
+++ 
b/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/sources/JvmMetricSource.java
@@ -102,6 +102,10 @@ public class JvmMetricSource implements MetricSource {
                 "memory.heap.Max",
                 "Maximum amount of heap memory",
                 () -> heapMemoryUsage.get().getMax());
+        metricSetBuilder.doubleGauge(
+                "memory.heap.FreePercent",
+                "Percentage of free heap memory",
+                () -> calculateHeapFreePercent(heapMemoryUsage.get()));
 
         CachedMemoryUsage nonHeapMemoryUsage = new 
CachedMemoryUsage(memoryMxBean::getNonHeapMemoryUsage, 
MEMORY_USAGE_CACHE_TIMEOUT);
         metricSetBuilder.longGauge(
@@ -126,6 +130,11 @@ public class JvmMetricSource implements MetricSource {
                 "Approximate total time spent on garbage collection in 
milliseconds, summed across all collectors.",
                 this::totalCollectionTime);
 
+        metricSetBuilder.doubleGauge(
+                "gc.CollectionTimePercent",
+                "Percentage of time spent on garbage collection relative to 
JVM uptime.",
+                this::gcTimePercent);
+
         metricSetBuilder.longGauge(
                 "UpTime",
                 "The uptime of the Java virtual machine in milliseconds.",
@@ -150,6 +159,38 @@ public class JvmMetricSource implements MetricSource {
         return total;
     }
 
+    private double gcTimePercent() {
+        long totalGcTime = totalCollectionTime();
+        long uptime = runtimeBean.getUptime();
+
+        if (uptime > 0) {
+            return (totalGcTime * 100.0) / uptime;
+        }
+
+        return 0.0;
+    }
+
+    /**
+     * Calculates the free heap memory percentage.
+     *
+     * @param heapUsage Current heap memory usage.
+     * @return Free heap memory percentage.
+     */
+    private double calculateHeapFreePercent(MemoryUsage heapUsage) {
+        long used = heapUsage.getUsed();
+        long max = heapUsage.getMax();
+        long committed = heapUsage.getCommitted();
+
+        // Calculate free percentage based on max if available, otherwise 
committed.
+        if (max > 0) {
+            return (Math.max(max - used, 0) * 100.0) / max;
+        } else if (committed > 0) {
+            return (Math.max(committed - used, 0) * 100.0) / committed;
+        }
+
+        return 0.0;
+    }
+
     @Override
     public synchronized void disable() {
         enabled = false;
diff --git 
a/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/sources/OsMetricSource.java
 
b/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/sources/OsMetricSource.java
index 6353605278f..82ffca9804c 100644
--- 
a/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/sources/OsMetricSource.java
+++ 
b/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/sources/OsMetricSource.java
@@ -87,6 +87,12 @@ public class OsMetricSource implements MetricSource {
                 cpuLoadSupplier()
         );
 
+        metricSetBuilder.intGauge(
+                "AvailableProcessors",
+                "Number of processors available to the Java virtual machine.",
+                operatingSystemMxBean::getAvailableProcessors
+        );
+
         enabled = true;
 
         return metricSetBuilder.build();
diff --git 
a/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/exporters/log/LogPushExporterTest.java
 
b/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/exporters/log/LogPushExporterTest.java
index 136b72fd546..2f91f3be3e6 100644
--- 
a/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/exporters/log/LogPushExporterTest.java
+++ 
b/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/exporters/log/LogPushExporterTest.java
@@ -20,7 +20,6 @@ package org.apache.ignite.internal.metrics.exporters.log;
 import static 
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.equalTo;
-import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
@@ -48,11 +47,15 @@ import org.apache.ignite.internal.metrics.LongGauge;
 import org.apache.ignite.internal.metrics.MetricManager;
 import org.apache.ignite.internal.metrics.MetricManagerImpl;
 import org.apache.ignite.internal.metrics.MetricSet;
+import org.apache.ignite.internal.metrics.StringGauge;
+import org.apache.ignite.internal.metrics.UuidGauge;
 import org.apache.ignite.internal.metrics.configuration.MetricChange;
 import org.apache.ignite.internal.metrics.configuration.MetricConfiguration;
 import org.apache.ignite.internal.metrics.exporters.PushMetricExporter;
 import 
org.apache.ignite.internal.metrics.exporters.configuration.LogPushExporterChange;
 import org.apache.ignite.internal.metrics.exporters.jmx.JmxExporter;
+import org.apache.ignite.internal.metrics.sources.JvmMetricSource;
+import org.apache.ignite.internal.metrics.sources.OsMetricSource;
 import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
 import org.apache.ignite.internal.testframework.IgniteTestUtils;
 import org.apache.ignite.internal.testframework.log4j2.LogInspector;
@@ -171,6 +174,12 @@ public class LogPushExporterTest extends 
BaseIgniteAbstractTest {
         metricManager = new MetricManagerImpl();
         metricManager.configure(metricConfiguration, () -> CLUSTER_ID, 
"nodeName");
 
+        // Register JVM and OS metric sources for system metrics (heap, CPU).
+        metricManager.registerSource(new JvmMetricSource());
+        metricManager.registerSource(new OsMetricSource());
+        metricManager.enable("jvm");
+        metricManager.enable("os");
+
         metricManager.registerSource(new TestMetricSource(metricSet));
         metricManager.registerSource(new 
TestMetricSource(fullyIncludedMetricSet));
         metricManager.registerSource(new 
TestMetricSource(partiallyIncludedMetricSet));
@@ -198,7 +207,108 @@ public class LogPushExporterTest extends 
BaseIgniteAbstractTest {
     @Test
     void testStart() {
         withLogInspector(
-                evt -> evt.getMessage().getFormattedMessage().contains("Metric 
report"),
+                evt -> 
evt.getMessage().getFormattedMessage().contains("Metrics for local node"),
+                logInspector -> {
+                    metricManager.start(Map.of("logPush", exporter));
+
+                    Awaitility.await()
+                            .atMost(Duration.ofMillis(500L))
+                            .until(logInspector::isMatched);
+                }
+        );
+    }
+
+    @Test
+    void testNewPrefixFormat() {
+        withLogInspector(
+                evt -> 
evt.getMessage().getFormattedMessage().contains("Metrics for local node:"),
+                logInspector -> {
+                    metricManager.start(Map.of("logPush", exporter));
+
+                    Awaitility.await()
+                            .atMost(Duration.ofMillis(500L))
+                            .until(logInspector::isMatched);
+                }
+        );
+    }
+
+    @Test
+    void testTopologyNodeCountIncluded() {
+        var topologyClusterMetricSet = new MetricSet("topology.cluster", 
Map.of(
+                "TotalNodes", new IntGauge("TotalNodes", "", () -> 3),
+                "ClusterId", new UuidGauge("ClusterId", "", () -> CLUSTER_ID)
+        ));
+
+        metricManager.registerSource(new 
TestMetricSource(topologyClusterMetricSet));
+        metricManager.enable(topologyClusterMetricSet.name());
+
+        mutateConfiguration(metricConfiguration, change ->
+                change.changeExporters().update("log", exporterChange ->
+                        exporterChange.convert(LogPushExporterChange.class)
+                                .changeEnabledMetrics("testSource", 
"topology.cluster")
+                )
+        );
+    }
+
+    @Test
+    void testThreadPoolMetricsIncluded() {
+        var threadPoolMetricSet = new 
MetricSet("thread.pools.partitions-executor", Map.of(
+                "Active", new IntGauge("Active", "", () -> 5),
+                "QueueSize", new IntGauge("QueueSize", "", () -> 10),
+                "Completed", new LongGauge("Completed", "", () -> 100L)
+        ));
+
+        metricManager.registerSource(new 
TestMetricSource(threadPoolMetricSet));
+        metricManager.enable(threadPoolMetricSet.name());
+
+        mutateConfiguration(metricConfiguration, change ->
+                change.changeExporters().update("log", exporterChange ->
+                        exporterChange.convert(LogPushExporterChange.class)
+                                .changeOneLinePerMetricSource(false)
+                                .changeEnabledMetrics("testSource", 
"thread.pools.*")
+                )
+        );
+
+        withLogInspector(
+                evt -> 
evt.getMessage().getFormattedMessage().contains("thread.pools.partitions-executor
 ["),
+                logInspector -> {
+                    metricManager.start(Map.of("logPush", exporter));
+
+                    Awaitility.await()
+                            .atMost(Duration.ofMillis(500L))
+                            .until(logInspector::isMatched);
+                }
+        );
+    }
+
+    @Test
+    void testThreadPoolMetricsWithMultiplePools() {
+        var pool1MetricSet = new MetricSet("thread.pools.partitions-executor", 
Map.of(
+                "Active", new IntGauge("Active", "", () -> 5)
+        ));
+        var pool2MetricSet = new MetricSet("thread.pools.rebalance-scheduler", 
Map.of(
+                "Active", new IntGauge("Active", "", () -> 2)
+        ));
+
+        metricManager.registerSource(new TestMetricSource(pool1MetricSet));
+        metricManager.registerSource(new TestMetricSource(pool2MetricSet));
+        metricManager.enable(pool1MetricSet.name());
+        metricManager.enable(pool2MetricSet.name());
+
+        mutateConfiguration(metricConfiguration, change ->
+                change.changeExporters().update("log", exporterChange ->
+                        exporterChange.convert(LogPushExporterChange.class)
+                                .changeOneLinePerMetricSource(false)
+                                .changeEnabledMetrics("testSource", 
"thread.pools.*")
+                )
+        );
+
+        withLogInspector(
+                evt -> {
+                    String msg = evt.getMessage().getFormattedMessage();
+                    return msg.contains("thread.pools.partitions-executor [")
+                            && msg.contains("thread.pools.rebalance-scheduler 
[");
+                },
                 logInspector -> {
                     metricManager.start(Map.of("logPush", exporter));
 
@@ -209,6 +319,99 @@ public class LogPushExporterTest extends 
BaseIgniteAbstractTest {
         );
     }
 
+    @Test
+    void testSingleLineOutput() {
+        mutateConfiguration(metricConfiguration, change ->
+                change.changeExporters().update("log", exporterChange ->
+                        exporterChange.convert(LogPushExporterChange.class)
+                                .changeOneLinePerMetricSource(false)
+                )
+        );
+
+        withLogInspector(
+                evt -> {
+                    String msg = evt.getMessage().getFormattedMessage();
+                    return msg.contains("Metrics for local node") && 
!msg.contains(System.lineSeparator());
+                },
+                logInspector -> {
+                    metricManager.start(Map.of("logPush", exporter));
+
+                    Awaitility.await()
+                            .atMost(Duration.ofMillis(500L))
+                            .until(logInspector::isMatched);
+                }
+        );
+    }
+
+    @Test
+    void testMultilineOutput() {
+        mutateConfiguration(metricConfiguration, change ->
+                change.changeExporters().update("log", exporterChange ->
+                        exporterChange.convert(LogPushExporterChange.class)
+                                .changeOneLinePerMetricSource(true)
+                )
+        );
+
+        withLogInspector(
+                evt -> {
+                    String msg = evt.getMessage().getFormattedMessage();
+                    // Check that metrics are formatted with newlines and 
padding
+                    return msg.contains("Metrics for local node")
+                            && msg.contains(System.lineSeparator() + "  ^-- " 
+ SRC_NAME + " ")
+                            && msg.contains(System.lineSeparator() + "  ^-- ");
+                },
+                logInspector -> {
+                    metricManager.start(Map.of("logPush", exporter));
+
+                    Awaitility.await()
+                            .atMost(Duration.ofMillis(500L))
+                            .until(logInspector::isMatched);
+                }
+        );
+    }
+
+    @Test
+    void testAllSystemMetricsInOneLog() {
+        var metastorageMetricSet = new MetricSet("metastorage", Map.of(
+                "TestMetric", new IntGauge("TestMetric", "", () -> 1)
+        ));
+        var placementDriverMetricSet = new MetricSet("placement-driver", 
Map.of(
+                "TestMetric", new IntGauge("TestMetric", "", () -> 1)
+        ));
+
+        metricManager.registerSource(new 
TestMetricSource(metastorageMetricSet));
+        metricManager.registerSource(new 
TestMetricSource(placementDriverMetricSet));
+        metricManager.enable(metastorageMetricSet.name());
+        metricManager.enable(placementDriverMetricSet.name());
+
+        mutateConfiguration(metricConfiguration, change ->
+                change.changeExporters().update("log", exporterChange ->
+                        exporterChange.convert(LogPushExporterChange.class)
+                                .changeEnabledMetrics("testSource", 
"metastorage", "placement-driver")
+                )
+        );
+    }
+
+    @Test
+    void testNetworkInfoFromTopologyLocal() {
+        var topologyLocalMetricSet = new MetricSet("topology.local", Map.of(
+                "NodeId", new UuidGauge("NodeId", "", () -> UUID.randomUUID()),
+                "NodeName", new StringGauge("NodeName", "", () -> "nodeName"),
+                "NetworkAddress", new StringGauge("NetworkAddress", "", () -> 
"10.2.51.131"),
+                "NetworkPort", new IntGauge("NetworkPort", "", () -> 3344)
+        ));
+
+        metricManager.registerSource(new 
TestMetricSource(topologyLocalMetricSet));
+        metricManager.enable(topologyLocalMetricSet.name());
+
+        mutateConfiguration(metricConfiguration, change ->
+                change.changeExporters().update("log", exporterChange ->
+                        exporterChange.convert(LogPushExporterChange.class)
+                                .changeEnabledMetrics("testSource", 
"topology.local")
+                )
+        );
+    }
+
     @Test
     void testMetricUpdate() {
         var intMetric = new AtomicIntMetric(MTRC_NAME, "");
@@ -222,7 +425,7 @@ public class LogPushExporterTest extends 
BaseIgniteAbstractTest {
         metricManager.start(Map.of("logPush", exporter));
 
         withLogInspector(
-                evt -> 
evt.getMessage().getFormattedMessage().contains(MTRC_NAME + ": 1"),
+                evt -> 
evt.getMessage().getFormattedMessage().contains(MTRC_NAME + "=1"),
                 logInspector -> {
                     intMetric.add(1);
 
@@ -236,7 +439,7 @@ public class LogPushExporterTest extends 
BaseIgniteAbstractTest {
     @Test
     void testConfigurationUpdate() {
         withLogInspector(
-                evt -> evt.getMessage().getFormattedMessage().contains("Metric 
report"),
+                evt -> 
evt.getMessage().getFormattedMessage().contains("Metrics for local node"),
                 logInspector -> {
                     metricManager.start(Map.of("logPush", exporter));
 
@@ -260,7 +463,7 @@ public class LogPushExporterTest extends 
BaseIgniteAbstractTest {
                 .until(fut::isCancelled);
 
         withLogInspector(
-                evt -> evt.getMessage().getFormattedMessage().contains("Metric 
report"),
+                evt -> 
evt.getMessage().getFormattedMessage().contains("Metrics for local node"),
                 logInspector -> {
                     Awaitility.await()
                             .between(Duration.ofMillis(800L), 
Duration.ofMillis(1200L))
@@ -272,7 +475,7 @@ public class LogPushExporterTest extends 
BaseIgniteAbstractTest {
     @Test
     void testSkipReconfigureScheduledTask() {
         withLogInspector(
-                evt -> evt.getMessage().getFormattedMessage().contains("Metric 
report"),
+                evt -> 
evt.getMessage().getFormattedMessage().contains("Metrics for local node"),
                 logInspector -> {
                     metricManager.start(Map.of("logPush", exporter));
 
@@ -324,7 +527,7 @@ public class LogPushExporterTest extends 
BaseIgniteAbstractTest {
         var fullMetricLongOneString = new AtomicBoolean();
 
         withLogInspector(
-                evt -> evt.getMessage().getFormattedMessage().contains("Metric 
report"),
+                evt -> 
evt.getMessage().getFormattedMessage().contains("Metrics for local node"),
                 logInspector -> {
                     logInspector.addHandler(evt -> evtMatches(evt, 
"FullMetricInt"), () -> fullMetricInt.set(true));
                     logInspector.addHandler(evt -> evtMatches(evt, 
"FullMetricLong"), () -> fullMetricLong.set(true));
@@ -338,11 +541,18 @@ public class LogPushExporterTest extends 
BaseIgniteAbstractTest {
                     logInspector.addHandler(evt -> evtMatches(evt, 
"IgnoredMetric"), () -> ignoredMetric.set(true));
 
                     logInspector.addHandler(
-                            evt -> evtMatches(evt, "full [FullMetricInt=42, 
FullMetricLong=42]"),
+                            evt -> evtMatches(evt, ": full [FullMetricInt=42, 
FullMetricLong=42]"),
                             () -> fullMetricSingleString.set(true)
                     );
-                    logInspector.addHandler(evt -> evtMatches(evt, "  
FullMetricInt: 42"), () -> fullMetricIntOneString.set(true));
-                    logInspector.addHandler(evt -> evtMatches(evt, "  
FullMetricLong: 42"), () -> fullMetricLongOneString.set(true));
+
+                    logInspector.addHandler(
+                            evt -> evtMatches(evt, "  ^-- full 
[FullMetricInt=42, FullMetricLong=42]"),
+                            () -> fullMetricIntOneString.set(true)
+                    );
+                    logInspector.addHandler(
+                            evt -> evtMatches(evt, "  ^-- full 
[FullMetricInt=42, FullMetricLong=42]"),
+                            () -> fullMetricLongOneString.set(true)
+                    );
 
                     Awaitility.await()
                             .atMost(Duration.ofMillis(2000L))
@@ -359,9 +569,15 @@ public class LogPushExporterTest extends 
BaseIgniteAbstractTest {
                     assertTrue(similarSetTwoMetricTwo.get());
                     assertFalse(ignoredMetric.get());
 
-                    assertEquals(oneLinePerMetricSource, 
fullMetricSingleString.get());
-                    assertEquals(!oneLinePerMetricSource, 
fullMetricIntOneString.get());
-                    assertEquals(!oneLinePerMetricSource, 
fullMetricLongOneString.get());
+                    if (oneLinePerMetricSource) {
+                        assertFalse(fullMetricSingleString.get());
+                        assertTrue(fullMetricIntOneString.get());
+                        assertTrue(fullMetricLongOneString.get());
+                    } else {
+                        assertTrue(fullMetricSingleString.get());
+                        assertFalse(fullMetricIntOneString.get());
+                        assertFalse(fullMetricLongOneString.get());
+                    }
                 }
         );
     }
diff --git 
a/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/sources/JvmMetricSourceTest.java
 
b/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/sources/JvmMetricSourceTest.java
index 5ea70ba6346..112feafaea6 100644
--- 
a/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/sources/JvmMetricSourceTest.java
+++ 
b/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/sources/JvmMetricSourceTest.java
@@ -28,6 +28,7 @@ import java.lang.management.RuntimeMXBean;
 import java.util.List;
 import java.util.Map;
 import javax.management.ObjectName;
+import org.apache.ignite.internal.metrics.DoubleMetric;
 import org.apache.ignite.internal.metrics.LongMetric;
 import org.junit.jupiter.api.Test;
 
@@ -47,6 +48,8 @@ public class JvmMetricSourceTest {
         assertEquals(memoryBean.heapUsed, 
metricSet.<LongMetric>get("memory.heap.Used").value());
         assertEquals(memoryBean.heapCommitted, 
metricSet.<LongMetric>get("memory.heap.Committed").value());
         assertEquals(memoryBean.heapMax, 
metricSet.<LongMetric>get("memory.heap.Max").value());
+        // Expected free percent: (90 - 15) / 90 * 100 = 83.33%
+        assertEquals(83.33, 
metricSet.<DoubleMetric>get("memory.heap.FreePercent").value(), 0.01);
 
         assertEquals(memoryBean.nonHeapInit, 
metricSet.<LongMetric>get("memory.non-heap.Init").value());
         assertEquals(memoryBean.nonHeapUsed, 
metricSet.<LongMetric>get("memory.non-heap.Used").value());
@@ -71,6 +74,8 @@ public class JvmMetricSourceTest {
         assertEquals(memoryBean.heapUsed, 
metricSet.<LongMetric>get("memory.heap.Used").value());
         assertEquals(memoryBean.heapCommitted, 
metricSet.<LongMetric>get("memory.heap.Committed").value());
         assertEquals(memoryBean.heapMax, 
metricSet.<LongMetric>get("memory.heap.Max").value());
+        // Expected free percent after update: (90 - 16) / 90 * 100 = 82.22%.
+        assertEquals(82.22, 
metricSet.<DoubleMetric>get("memory.heap.FreePercent").value(), 0.01);
 
         assertEquals(memoryBean.nonHeapInit, 
metricSet.<LongMetric>get("memory.non-heap.Init").value());
         assertEquals(memoryBean.nonHeapUsed, 
metricSet.<LongMetric>get("memory.non-heap.Used").value());
@@ -90,11 +95,13 @@ public class JvmMetricSourceTest {
         var metricSet = metricSource.enable();
 
         assertEquals(300, 
metricSet.<LongMetric>get("gc.CollectionTime").value());
+        assertEquals(30.0, 
metricSet.<DoubleMetric>get("gc.CollectionTimePercent").value(), 0.01);
 
         gcBean1.changeCollectionMetrics(1, 10);
         gcBean2.changeCollectionMetrics(1, 15);
 
         assertEquals(325, 
metricSet.<LongMetric>get("gc.CollectionTime").value());
+        assertEquals(32.5, 
metricSet.<DoubleMetric>get("gc.CollectionTimePercent").value(), 0.01);
     }
 
     @Test
diff --git 
a/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/sources/OsMetricSourceTest.java
 
b/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/sources/OsMetricSourceTest.java
index 167812d1ffa..0f6423a61f8 100644
--- 
a/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/sources/OsMetricSourceTest.java
+++ 
b/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/sources/OsMetricSourceTest.java
@@ -22,28 +22,34 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import java.lang.management.OperatingSystemMXBean;
 import javax.management.ObjectName;
 import org.apache.ignite.internal.metrics.DoubleMetric;
+import org.apache.ignite.internal.metrics.IntMetric;
 import org.junit.jupiter.api.Test;
 
 class OsMetricSourceTest {
     @Test
     void testOsMetrics() {
-        var osBean = new OperatingSystemBean(1.23);
+        var osBean = new OperatingSystemBean(1.23, 8);
         var metricSource = new OsMetricSource(osBean);
 
         var metricSet = metricSource.enable();
 
         assertEquals(1.23, metricSet.<DoubleMetric>get("LoadAverage").value());
+        assertEquals(8, 
metricSet.<IntMetric>get("AvailableProcessors").value());
 
         osBean.loadAverage = 2.34;
+        osBean.availableProcessors = 16;
 
         assertEquals(2.34, metricSet.<DoubleMetric>get("LoadAverage").value());
+        assertEquals(16, 
metricSet.<IntMetric>get("AvailableProcessors").value());
     }
 
     private static class OperatingSystemBean implements OperatingSystemMXBean {
         private double loadAverage;
+        private int availableProcessors;
 
-        private OperatingSystemBean(double loadAverage) {
+        private OperatingSystemBean(double loadAverage, int 
availableProcessors) {
             this.loadAverage = loadAverage;
+            this.availableProcessors = availableProcessors;
         }
 
         @Override
@@ -63,7 +69,7 @@ class OsMetricSourceTest {
 
         @Override
         public int getAvailableProcessors() {
-            throw new UnsupportedOperationException();
+            return availableProcessors;
         }
 
         @Override


Reply via email to