This is an automated email from the ASF dual-hosted git repository. maciej pushed a commit to branch java-stats-update in repository https://gitbox.apache.org/repos/asf/iggy.git
commit b1d6d80e54343c3af92db14f964c3848d01d2091 Author: Maciej Modzelewski <[email protected]> AuthorDate: Wed Mar 18 13:17:34 2026 +0100 feat(java): add new stats fields to match server sysinfo updates The server recently added iggy_server_version, semver, cache_metrics, threads_count, and disk space fields to the sysinfo stats response. The Java SDK was missing support for these fields, causing deserialization to fail with the updated server. Add CacheMetrics record and extend Stats with the new fields. Update both binary and JSON deserialization paths with corresponding test coverage. --- .../blocking/http/CacheMetricsKeyMixin.java} | 42 +++----- .../client/blocking/http/ObjectMapperFactory.java | 2 + .../org/apache/iggy/serde/BytesDeserializer.java | 34 +++++- .../iggy/system/{Stats.java => CacheMetrics.java} | 24 +---- .../system/{Stats.java => CacheMetricsKey.java} | 38 +++---- .../main/java/org/apache/iggy/system/Stats.java | 10 +- .../iggy/client/blocking/SystemClientBaseTest.java | 5 + .../client/blocking/http/ObjectMapperTest.java | 119 +++++++++++++++++++++ .../apache/iggy/serde/BytesDeserializerTest.java | 116 +++++++++++++++++++- 9 files changed, 312 insertions(+), 78 deletions(-) diff --git a/foreign/java/java-sdk/src/main/java/org/apache/iggy/system/Stats.java b/foreign/java/java-sdk/src/main/java/org/apache/iggy/client/blocking/http/CacheMetricsKeyMixin.java similarity index 53% copy from foreign/java/java-sdk/src/main/java/org/apache/iggy/system/Stats.java copy to foreign/java/java-sdk/src/main/java/org/apache/iggy/client/blocking/http/CacheMetricsKeyMixin.java index 906e37c9d..35fd0fb70 100644 --- a/foreign/java/java-sdk/src/main/java/org/apache/iggy/system/Stats.java +++ b/foreign/java/java-sdk/src/main/java/org/apache/iggy/client/blocking/http/CacheMetricsKeyMixin.java @@ -17,30 +17,22 @@ * under the License. */ -package org.apache.iggy.system; +package org.apache.iggy.client.blocking.http; -import java.math.BigInteger; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import org.apache.iggy.system.CacheMetricsKey; -public record Stats( - Long processId, - Float cpuUsage, - Float totalCpuUsage, - String memoryUsage, - String totalMemory, - String availableMemory, - BigInteger runTime, - BigInteger startTime, - String readBytes, - String writtenBytes, - String messagesSizeBytes, - Long streamsCount, - Long topicsCount, - Long partitionsCount, - Long segmentsCount, - BigInteger messagesCount, - Long clientsCount, - Long consumerGroupsCount, - String hostname, - String osName, - String osVersion, - String kernelVersion) {} +/** + * Jackson mixin for {@link CacheMetricsKey} to keep the domain object free of serialization annotations. + */ +abstract class CacheMetricsKeyMixin { + + @JsonCreator + static CacheMetricsKey fromString(String key) { + throw new UnsupportedOperationException("Mixin method should not be called directly"); + } + + @JsonValue + public abstract String toString(); +} diff --git a/foreign/java/java-sdk/src/main/java/org/apache/iggy/client/blocking/http/ObjectMapperFactory.java b/foreign/java/java-sdk/src/main/java/org/apache/iggy/client/blocking/http/ObjectMapperFactory.java index 167db5d36..cdc2a7584 100644 --- a/foreign/java/java-sdk/src/main/java/org/apache/iggy/client/blocking/http/ObjectMapperFactory.java +++ b/foreign/java/java-sdk/src/main/java/org/apache/iggy/client/blocking/http/ObjectMapperFactory.java @@ -22,6 +22,7 @@ package org.apache.iggy.client.blocking.http; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; import org.apache.iggy.message.Message; +import org.apache.iggy.system.CacheMetricsKey; import tools.jackson.databind.DeserializationFeature; import tools.jackson.databind.EnumNamingStrategies; import tools.jackson.databind.MapperFeature; @@ -43,6 +44,7 @@ final class ObjectMapperFactory { .withConfigOverride( List.class, list -> list.setNullHandling(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY))) .addMixIn(Message.class, MessageMixin.class) + .addMixIn(CacheMetricsKey.class, CacheMetricsKeyMixin.class) .build(); private ObjectMapperFactory() {} diff --git a/foreign/java/java-sdk/src/main/java/org/apache/iggy/serde/BytesDeserializer.java b/foreign/java/java-sdk/src/main/java/org/apache/iggy/serde/BytesDeserializer.java index 3fb1c843f..7b4328b0c 100644 --- a/foreign/java/java-sdk/src/main/java/org/apache/iggy/serde/BytesDeserializer.java +++ b/foreign/java/java-sdk/src/main/java/org/apache/iggy/serde/BytesDeserializer.java @@ -37,6 +37,8 @@ import org.apache.iggy.personalaccesstoken.PersonalAccessTokenInfo; import org.apache.iggy.personalaccesstoken.RawPersonalAccessToken; import org.apache.iggy.stream.StreamBase; import org.apache.iggy.stream.StreamDetails; +import org.apache.iggy.system.CacheMetrics; +import org.apache.iggy.system.CacheMetricsKey; import org.apache.iggy.system.ClientInfo; import org.apache.iggy.system.ClientInfoDetails; import org.apache.iggy.system.ConsumerGroupInfo; @@ -255,6 +257,30 @@ public final class BytesDeserializer { var kernelVersion = response.readCharSequence(toInt(kernelVersionLength), StandardCharsets.UTF_8) .toString(); + var iggyServerVersionLength = response.readUnsignedIntLE(); + var iggyServerVersion = response.readCharSequence(toInt(iggyServerVersionLength), StandardCharsets.UTF_8) + .toString(); + + var semverValue = response.readUnsignedIntLE(); + var iggyServerSemver = semverValue != 0 ? Optional.of(semverValue) : Optional.<Long>empty(); + + var metricsCount = response.readUnsignedIntLE(); + Map<CacheMetricsKey, CacheMetrics> cacheMetrics = new HashMap<>(); + for (int i = 0; i < metricsCount; i++) { + var streamId = response.readUnsignedIntLE(); + var topicId = response.readUnsignedIntLE(); + var partitionId = response.readUnsignedIntLE(); + var hits = readU64AsBigInteger(response); + var misses = readU64AsBigInteger(response); + var hitRatio = response.readFloatLE(); + var key = new CacheMetricsKey(streamId, topicId, partitionId); + cacheMetrics.put(key, new CacheMetrics(hits, misses, hitRatio)); + } + + var threadsCount = response.readUnsignedIntLE(); + var freeDiskSpace = readU64AsBigInteger(response); + var totalDiskSpace = readU64AsBigInteger(response); + return new Stats( processId, cpuUsage, @@ -277,7 +303,13 @@ public final class BytesDeserializer { hostname, osName, osVersion, - kernelVersion); + kernelVersion, + iggyServerVersion, + iggyServerSemver, + cacheMetrics, + threadsCount, + freeDiskSpace.toString(), + totalDiskSpace.toString()); } public static ClientInfoDetails readClientInfoDetails(ByteBuf response) { diff --git a/foreign/java/java-sdk/src/main/java/org/apache/iggy/system/Stats.java b/foreign/java/java-sdk/src/main/java/org/apache/iggy/system/CacheMetrics.java similarity index 57% copy from foreign/java/java-sdk/src/main/java/org/apache/iggy/system/Stats.java copy to foreign/java/java-sdk/src/main/java/org/apache/iggy/system/CacheMetrics.java index 906e37c9d..f173d627a 100644 --- a/foreign/java/java-sdk/src/main/java/org/apache/iggy/system/Stats.java +++ b/foreign/java/java-sdk/src/main/java/org/apache/iggy/system/CacheMetrics.java @@ -21,26 +21,4 @@ package org.apache.iggy.system; import java.math.BigInteger; -public record Stats( - Long processId, - Float cpuUsage, - Float totalCpuUsage, - String memoryUsage, - String totalMemory, - String availableMemory, - BigInteger runTime, - BigInteger startTime, - String readBytes, - String writtenBytes, - String messagesSizeBytes, - Long streamsCount, - Long topicsCount, - Long partitionsCount, - Long segmentsCount, - BigInteger messagesCount, - Long clientsCount, - Long consumerGroupsCount, - String hostname, - String osName, - String osVersion, - String kernelVersion) {} +public record CacheMetrics(BigInteger hits, BigInteger misses, Float hitRatio) {} diff --git a/foreign/java/java-sdk/src/main/java/org/apache/iggy/system/Stats.java b/foreign/java/java-sdk/src/main/java/org/apache/iggy/system/CacheMetricsKey.java similarity index 55% copy from foreign/java/java-sdk/src/main/java/org/apache/iggy/system/Stats.java copy to foreign/java/java-sdk/src/main/java/org/apache/iggy/system/CacheMetricsKey.java index 906e37c9d..11be433d3 100644 --- a/foreign/java/java-sdk/src/main/java/org/apache/iggy/system/Stats.java +++ b/foreign/java/java-sdk/src/main/java/org/apache/iggy/system/CacheMetricsKey.java @@ -19,28 +19,18 @@ package org.apache.iggy.system; -import java.math.BigInteger; +public record CacheMetricsKey(Long streamId, Long topicId, Long partitionId) { -public record Stats( - Long processId, - Float cpuUsage, - Float totalCpuUsage, - String memoryUsage, - String totalMemory, - String availableMemory, - BigInteger runTime, - BigInteger startTime, - String readBytes, - String writtenBytes, - String messagesSizeBytes, - Long streamsCount, - Long topicsCount, - Long partitionsCount, - Long segmentsCount, - BigInteger messagesCount, - Long clientsCount, - Long consumerGroupsCount, - String hostname, - String osName, - String osVersion, - String kernelVersion) {} + public static CacheMetricsKey fromString(String key) { + String[] parts = key.split("-"); + if (parts.length != 3) { + throw new IllegalArgumentException("Invalid cache metrics key: " + key); + } + return new CacheMetricsKey(Long.parseLong(parts[0]), Long.parseLong(parts[1]), Long.parseLong(parts[2])); + } + + @Override + public String toString() { + return streamId + "-" + topicId + "-" + partitionId; + } +} diff --git a/foreign/java/java-sdk/src/main/java/org/apache/iggy/system/Stats.java b/foreign/java/java-sdk/src/main/java/org/apache/iggy/system/Stats.java index 906e37c9d..8a5f6b52b 100644 --- a/foreign/java/java-sdk/src/main/java/org/apache/iggy/system/Stats.java +++ b/foreign/java/java-sdk/src/main/java/org/apache/iggy/system/Stats.java @@ -20,6 +20,8 @@ package org.apache.iggy.system; import java.math.BigInteger; +import java.util.Map; +import java.util.Optional; public record Stats( Long processId, @@ -43,4 +45,10 @@ public record Stats( String hostname, String osName, String osVersion, - String kernelVersion) {} + String kernelVersion, + String iggyServerVersion, + Optional<Long> iggyServerSemver, + Map<CacheMetricsKey, CacheMetrics> cacheMetrics, + Long threadsCount, + String freeDiskSpace, + String totalDiskSpace) {} diff --git a/foreign/java/java-sdk/src/test/java/org/apache/iggy/client/blocking/SystemClientBaseTest.java b/foreign/java/java-sdk/src/test/java/org/apache/iggy/client/blocking/SystemClientBaseTest.java index 058c84e85..01d55315b 100644 --- a/foreign/java/java-sdk/src/test/java/org/apache/iggy/client/blocking/SystemClientBaseTest.java +++ b/foreign/java/java-sdk/src/test/java/org/apache/iggy/client/blocking/SystemClientBaseTest.java @@ -42,6 +42,11 @@ public abstract class SystemClientBaseTest extends IntegrationTest { // then assertThat(stats).isNotNull(); + assertThat(stats.processId()).isNotNull(); + assertThat(stats.hostname()).isNotEmpty(); + assertThat(stats.threadsCount()).isNotNull(); + assertThat(stats.freeDiskSpace()).isNotNull(); + assertThat(stats.totalDiskSpace()).isNotNull(); } @Test diff --git a/foreign/java/java-sdk/src/test/java/org/apache/iggy/client/blocking/http/ObjectMapperTest.java b/foreign/java/java-sdk/src/test/java/org/apache/iggy/client/blocking/http/ObjectMapperTest.java index 53c8f58bc..320221dab 100644 --- a/foreign/java/java-sdk/src/test/java/org/apache/iggy/client/blocking/http/ObjectMapperTest.java +++ b/foreign/java/java-sdk/src/test/java/org/apache/iggy/client/blocking/http/ObjectMapperTest.java @@ -21,11 +21,15 @@ package org.apache.iggy.client.blocking.http; import org.apache.iggy.message.Message; import org.apache.iggy.message.PolledMessages; +import org.apache.iggy.system.CacheMetricsKey; +import org.apache.iggy.system.Stats; +import org.assertj.core.data.Offset; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import tools.jackson.databind.ObjectMapper; +import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.util.Base64; @@ -38,6 +42,121 @@ class ObjectMapperTest { @Nested class Deserialization { + @Nested + @DisplayName("Stats") + class StatsDeserialization { + + @Test + void shouldDeserializeAllStatsFields() { + // given + String json = """ + { + "process_id": 1234, + "cpu_usage": 12.5, + "total_cpu_usage": 50.0, + "memory_usage": "1000000", + "total_memory": "8000000", + "available_memory": "7000000", + "run_time": 3600, + "start_time": 1000000, + "read_bytes": "500", + "written_bytes": "600", + "messages_size_bytes": "1000", + "streams_count": 5, + "topics_count": 10, + "partitions_count": 20, + "segments_count": 100, + "messages_count": 5000, + "clients_count": 3, + "consumer_groups_count": 2, + "hostname": "localhost", + "os_name": "Linux", + "os_version": "5.4.0", + "kernel_version": "5.4.0-1", + "iggy_server_version": "0.7.1", + "iggy_server_semver": 701000, + "cache_metrics": { + "1-1-1": {"hits": 100, "misses": 10, "hit_ratio": 0.91} + }, + "threads_count": 42, + "free_disk_space": "500000000000", + "total_disk_space": "1000000000000" + } + """; + + // when + var stats = objectMapper.readValue(json, Stats.class); + + // then + assertThat(stats.processId()).isEqualTo(1234L); + assertThat(stats.cpuUsage()).isEqualTo(12.5f); + assertThat(stats.totalCpuUsage()).isEqualTo(50.0f); + assertThat(stats.memoryUsage()).isEqualTo("1000000"); + assertThat(stats.streamsCount()).isEqualTo(5L); + assertThat(stats.hostname()).isEqualTo("localhost"); + assertThat(stats.osName()).isEqualTo("Linux"); + assertThat(stats.iggyServerVersion()).isEqualTo("0.7.1"); + assertThat(stats.iggyServerSemver()).isPresent().hasValue(701000L); + var key = new CacheMetricsKey(1L, 1L, 1L); + assertThat(stats.cacheMetrics()).hasSize(1); + assertThat(stats.cacheMetrics()).containsKey(key); + assertThat(stats.cacheMetrics().get(key).hits()).isEqualTo(BigInteger.valueOf(100)); + assertThat(stats.cacheMetrics().get(key).misses()).isEqualTo(BigInteger.valueOf(10)); + assertThat(stats.cacheMetrics().get(key).hitRatio()).isCloseTo(0.91f, Offset.offset(0.01f)); + assertThat(stats.threadsCount()).isEqualTo(42L); + assertThat(stats.freeDiskSpace()).isEqualTo("500000000000"); + assertThat(stats.totalDiskSpace()).isEqualTo("1000000000000"); + } + + @Test + void shouldDeserializeStatsWithNullSemverAndEmptyCacheMetrics() { + // given + String json = """ + { + "process_id": 1234, + "cpu_usage": 12.5, + "total_cpu_usage": 50.0, + "memory_usage": "1000000", + "total_memory": "8000000", + "available_memory": "7000000", + "run_time": 3600, + "start_time": 1000000, + "read_bytes": "500", + "written_bytes": "600", + "messages_size_bytes": "1000", + "streams_count": 5, + "topics_count": 10, + "partitions_count": 20, + "segments_count": 100, + "messages_count": 5000, + "clients_count": 3, + "consumer_groups_count": 2, + "hostname": "localhost", + "os_name": "Linux", + "os_version": "5.4.0", + "kernel_version": "5.4.0-1", + "iggy_server_version": "0.6.1", + "iggy_server_semver": null, + "cache_metrics": {}, + "threads_count": 8, + "free_disk_space": "250000000000", + "total_disk_space": "500000000000" + } + """; + + // when + var stats = objectMapper.readValue(json, Stats.class); + + // then + assertThat(stats.iggyServerVersion()).isEqualTo("0.6.1"); + assertThat(stats.iggyServerSemver()).isEmpty(); + assertThat(stats.cacheMetrics()).isEmpty(); + assertThat(stats.threadsCount()).isEqualTo(8L); + assertThat(stats.freeDiskSpace()).isEqualTo("250000000000"); + assertThat(stats.totalDiskSpace()).isEqualTo("500000000000"); + } + } + @Nested @DisplayName("PolledMessages") class PolledMessagesDeserialization { diff --git a/foreign/java/java-sdk/src/test/java/org/apache/iggy/serde/BytesDeserializerTest.java b/foreign/java/java-sdk/src/test/java/org/apache/iggy/serde/BytesDeserializerTest.java index 6d8dfa8c4..f592ce5a5 100644 --- a/foreign/java/java-sdk/src/test/java/org/apache/iggy/serde/BytesDeserializerTest.java +++ b/foreign/java/java-sdk/src/test/java/org/apache/iggy/serde/BytesDeserializerTest.java @@ -24,6 +24,7 @@ import io.netty.buffer.Unpooled; import org.apache.commons.lang3.ArrayUtils; import org.apache.iggy.message.HeaderKey; import org.apache.iggy.message.HeaderKind; +import org.apache.iggy.system.CacheMetricsKey; import org.apache.iggy.topic.CompressionAlgorithm; import org.apache.iggy.user.UserStatus; import org.junit.jupiter.api.Nested; @@ -421,10 +422,7 @@ class BytesDeserializerTest { @Nested class StatsDeserialization { - @Test - void shouldDeserializeStats() { - // given - ByteBuf buffer = Unpooled.buffer(); + private void writeBaseStatsFields(ByteBuf buffer) { buffer.writeIntLE(1234); // process ID buffer.writeFloatLE(12.5f); // CPU usage buffer.writeFloatLE(50.0f); // total CPU usage @@ -451,6 +449,24 @@ class BytesDeserializerTest { buffer.writeBytes("5.4.0".getBytes()); buffer.writeIntLE(7); // kernel version length buffer.writeBytes("5.4.0-1".getBytes()); + } + + private void writeServerVersionFields(ByteBuf buffer) { + buffer.writeIntLE(5); // iggy_server_version length + buffer.writeBytes("0.6.1".getBytes()); + buffer.writeIntLE(601000); // iggy_server_semver + } + + @Test + void shouldDeserializeStats() { + // given + ByteBuf buffer = Unpooled.buffer(); + writeBaseStatsFields(buffer); + writeServerVersionFields(buffer); + buffer.writeIntLE(0); // cache_metrics (empty) + buffer.writeIntLE(42); // threads count + writeU64(buffer, BigInteger.valueOf(500_000_000_000L)); // free disk space + writeU64(buffer, BigInteger.valueOf(1_000_000_000_000L)); // total disk space // when var stats = readStats(buffer); @@ -458,9 +474,101 @@ class BytesDeserializerTest { // then assertThat(stats.processId()).isEqualTo(1234L); assertThat(stats.cpuUsage()).isEqualTo(12.5f); + assertThat(stats.totalCpuUsage()).isEqualTo(50.0f); + assertThat(stats.memoryUsage()).isEqualTo("1000000"); + assertThat(stats.totalMemory()).isEqualTo("8000000"); + assertThat(stats.availableMemory()).isEqualTo("7000000"); + assertThat(stats.runTime()).isEqualTo(BigInteger.valueOf(3600)); + assertThat(stats.startTime()).isEqualTo(BigInteger.valueOf(1000000)); + assertThat(stats.readBytes()).isEqualTo("500"); + assertThat(stats.writtenBytes()).isEqualTo("600"); + assertThat(stats.messagesSizeBytes()).isEqualTo("1000"); assertThat(stats.streamsCount()).isEqualTo(5L); + assertThat(stats.topicsCount()).isEqualTo(10L); + assertThat(stats.partitionsCount()).isEqualTo(20L); + assertThat(stats.segmentsCount()).isEqualTo(100L); + assertThat(stats.messagesCount()).isEqualTo(BigInteger.valueOf(5000)); + assertThat(stats.clientsCount()).isEqualTo(3L); + assertThat(stats.consumerGroupsCount()).isEqualTo(2L); assertThat(stats.hostname()).isEqualTo("localhost"); assertThat(stats.osName()).isEqualTo("Linux"); + assertThat(stats.osVersion()).isEqualTo("5.4.0"); + assertThat(stats.kernelVersion()).isEqualTo("5.4.0-1"); + assertThat(stats.iggyServerVersion()).isEqualTo("0.6.1"); + assertThat(stats.iggyServerSemver()).isPresent().hasValue(601000L); + assertThat(stats.cacheMetrics()).isEmpty(); + assertThat(stats.threadsCount()).isEqualTo(42L); + assertThat(stats.freeDiskSpace()).isEqualTo("500000000000"); + assertThat(stats.totalDiskSpace()).isEqualTo("1000000000000"); + } + + @Test + void shouldDeserializeStatsWithNullSemver() { + // given + ByteBuf buffer = Unpooled.buffer(); + writeBaseStatsFields(buffer); + buffer.writeIntLE(5); // iggy_server_version length + buffer.writeBytes("0.6.1".getBytes()); + buffer.writeIntLE(0); // iggy_server_semver = 0 (None) + buffer.writeIntLE(0); // cache_metrics (empty) + buffer.writeIntLE(8); // threads count + writeU64(buffer, BigInteger.valueOf(100_000_000_000L)); // free disk space + writeU64(buffer, BigInteger.valueOf(200_000_000_000L)); // total disk space + + // when + var stats = readStats(buffer); + + // then + assertThat(stats.iggyServerVersion()).isEqualTo("0.6.1"); + assertThat(stats.iggyServerSemver()).isEmpty(); + assertThat(stats.threadsCount()).isEqualTo(8L); + } + + @Test + void shouldDeserializeStatsWithCacheMetrics() { + // given + ByteBuf buffer = Unpooled.buffer(); + writeBaseStatsFields(buffer); + writeServerVersionFields(buffer); + // cache_metrics (2 entries) + buffer.writeIntLE(2); // count + // entry 1: key "1-1-1" + buffer.writeIntLE(1); // stream_id + buffer.writeIntLE(1); // topic_id + buffer.writeIntLE(1); // partition_id + writeU64(buffer, BigInteger.valueOf(100)); // hits + writeU64(buffer, BigInteger.valueOf(10)); // misses + buffer.writeFloatLE(0.91f); // hit_ratio + // entry 2: key "1-2-1" + buffer.writeIntLE(1); // stream_id + buffer.writeIntLE(2); // topic_id + buffer.writeIntLE(1); // partition_id + writeU64(buffer, BigInteger.valueOf(200)); // hits + writeU64(buffer, BigInteger.valueOf(50)); // misses + buffer.writeFloatLE(0.80f); // hit_ratio + // new fields + buffer.writeIntLE(16); // threads count + writeU64(buffer, BigInteger.valueOf(250_000_000_000L)); // free disk space + writeU64(buffer, BigInteger.valueOf(500_000_000_000L)); // total disk space + + // when + var stats = readStats(buffer); + + // then + var key1 = new CacheMetricsKey(1L, 1L, 1L); + var key2 = new CacheMetricsKey(1L, 2L, 1L); + assertThat(stats.cacheMetrics()).hasSize(2); + assertThat(stats.cacheMetrics()).containsKey(key1); + assertThat(stats.cacheMetrics()).containsKey(key2); + assertThat(stats.cacheMetrics().get(key1).hits()).isEqualTo(BigInteger.valueOf(100)); + assertThat(stats.cacheMetrics().get(key1).misses()).isEqualTo(BigInteger.valueOf(10)); + assertThat(stats.cacheMetrics().get(key1).hitRatio()) + .isCloseTo(0.91f, org.assertj.core.data.Offset.offset(0.01f)); + assertThat(stats.cacheMetrics().get(key2).hits()).isEqualTo(BigInteger.valueOf(200)); + assertThat(stats.cacheMetrics().get(key2).misses()).isEqualTo(BigInteger.valueOf(50)); + assertThat(stats.threadsCount()).isEqualTo(16L); + assertThat(stats.freeDiskSpace()).isEqualTo("250000000000"); + assertThat(stats.totalDiskSpace()).isEqualTo("500000000000"); } }
