From 33fa8744e116273a2ddc3e6b20c4b332af9b1ac2 Mon Sep 17 00:00:00 2001 From: Meghdad Date: Mon, 11 May 2026 18:43:29 +0330 Subject: [PATCH] update calculating disk status. --- .../data/MonitorJsonParser.kt | 47 ++++++++++++++++++- .../data/DiskUsageCalculationTest.kt | 30 ++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 app/src/test/java/net/rodakot/ngxhttpmonitoringclient/data/DiskUsageCalculationTest.kt diff --git a/app/src/main/java/net/rodakot/ngxhttpmonitoringclient/data/MonitorJsonParser.kt b/app/src/main/java/net/rodakot/ngxhttpmonitoringclient/data/MonitorJsonParser.kt index 6b98645..fb8d07c 100644 --- a/app/src/main/java/net/rodakot/ngxhttpmonitoringclient/data/MonitorJsonParser.kt +++ b/app/src/main/java/net/rodakot/ngxhttpmonitoringclient/data/MonitorJsonParser.kt @@ -51,16 +51,45 @@ object MonitorJsonParser { if (disk == null) return null disk.number("used_pct")?.let { return it } disk.number("used_percent")?.let { return it } + + disk.obj("filesystem")?.let { filesystem -> + filesystem.obj("/")?.diskUsagePercent()?.let { return it } + var max: Double? = null + val names = filesystem.keys() + while (names.hasNext()) { + val item = filesystem.optJSONObject(names.next()) ?: continue + val usage = item.diskUsagePercent() + if (usage != null && (max == null || usage > max!!)) max = usage + } + if (max != null) return max + } + val filesystems = disk.array("filesystems") ?: disk.array("mounts") ?: return null var max: Double? = null for (index in 0 until filesystems.length()) { val item = filesystems.optJSONObject(index) ?: continue - val usage = item.number("used_pct") ?: item.number("used_percent") ?: item.number("usage") + val usage = item.diskUsagePercent() + if (usage != null && item.mountPath() == "/") return usage if (usage != null && (max == null || usage > max!!)) max = usage } return max } + private fun JSONObject.diskUsagePercent(): Double? { + number("used_pct")?.let { return it } + number("used_percent")?.let { return it } + number("usage")?.let { return it } + number("usage_pct")?.let { return it } + val used = firstNumber("used", "used_size", "used_bytes", "used_kb") + val total = firstNumber("total", "total_size", "total_bytes", "size", "size_bytes", "total_kb") + return usedPercentFromSizes(used, total) + } + + internal fun usedPercentFromSizes(used: Double?, total: Double?): Double? { + if (used == null || total == null || total <= 0.0) return null + return used / total * 100.0 + } + private fun normalizePercent(value: Double?): Double? { if (value == null) return null return if (value in 0.0..1.0) value * 100.0 else value @@ -69,16 +98,30 @@ object MonitorJsonParser { private fun JSONObject.obj(name: String): JSONObject? = optJSONObject(name) private fun JSONObject.array(name: String): JSONArray? = optJSONArray(name) + private fun JSONObject.firstNumber(vararg names: String): Double? { + for (name in names) number(name)?.let { return it } + return null + } + + private fun JSONObject.mountPath(): String? { + return string("path") ?: string("mount") ?: string("mount_point") ?: string("mounted_on") + } + private fun JSONObject.number(name: String): Double? { if (!has(name) || isNull(name)) return null val value = opt(name) return when (value) { is Number -> value.toDouble() - is String -> value.toDoubleOrNull() + is String -> value.trim().removeSuffix("%").replace(",", "").toDoubleOrNull() else -> null } } + private fun JSONObject.string(name: String): String? { + if (!has(name) || isNull(name)) return null + return optString(name).takeIf { it.isNotBlank() } + } + private fun JSONObject.int(name: String): Int? { if (!has(name) || isNull(name)) return null val value = opt(name) diff --git a/app/src/test/java/net/rodakot/ngxhttpmonitoringclient/data/DiskUsageCalculationTest.kt b/app/src/test/java/net/rodakot/ngxhttpmonitoringclient/data/DiskUsageCalculationTest.kt new file mode 100644 index 0000000..5510885 --- /dev/null +++ b/app/src/test/java/net/rodakot/ngxhttpmonitoringclient/data/DiskUsageCalculationTest.kt @@ -0,0 +1,30 @@ +package net.rodakot.ngxhttpmonitoringclient.data + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Test + +class DiskUsageCalculationTest { + @Test + fun usedPercentFromSizes_calculatesStoragePercent() { + assertEquals(25.0, MonitorJsonParser.usedPercentFromSizes(500.0, 2000.0) ?: -1.0, 0.001) + } + + @Test + fun usedPercentFromSizes_matchesMonitorApiRootFilesystemSample() { + assertEquals( + 20.307, + MonitorJsonParser.usedPercentFromSizes( + used = 100_424_171_520.0, + total = 494_532_001_792.0, + ) ?: -1.0, + 0.001, + ) + } + + @Test + fun usedPercentFromSizes_ignoresInvalidTotals() { + assertNull(MonitorJsonParser.usedPercentFromSizes(500.0, 0.0)) + assertNull(MonitorJsonParser.usedPercentFromSizes(500.0, null)) + } +}