fix: display count sensor values as integers instead of floats

Connection counts (IPv4/IPv6, DHCP leases) were showing as floats
(e.g. 1270.0) in executor output, change detection messages, and
chart tooltips/axes. Now displayed as integers everywhere.
This commit is contained in:
Graham McIntire 2026-03-06 15:03:30 -06:00
parent 17bf1f83e8
commit 882a5d7eab
No known key found for this signature in database
5 changed files with 82 additions and 0 deletions

View file

@ -203,6 +203,9 @@ const SensorChart: SensorChartHook = {
if (unit === 'bps') {
return formatBps(value)
}
if (unit === '') {
return Math.round(value)
}
return value + unit
}
},
@ -233,6 +236,9 @@ const SensorChart: SensorChartHook = {
if (unit === 'bps') {
return formatBps(value)
}
if (unit === '') {
return Math.round(value)
}
return value + unit
}
},
@ -337,6 +343,9 @@ const SensorChart: SensorChartHook = {
if (unit === 'bps') {
return context.dataset.label + ': ' + formatBps(context.parsed.y)
}
if (unit === '') {
return context.dataset.label + ': ' + Math.round(context.parsed.y)
}
return context.dataset.label + ': ' + context.parsed.y.toFixed(1) + unit
}
}

View file

@ -159,6 +159,10 @@ defmodule Towerops.Monitoring.Executors.SnmpSensorExecutor do
"#{round(value)}#{unit || " RPM"}"
end
defp format_value(value, "count", _unit) do
"#{trunc(value)}"
end
defp format_value(value, sensor_type, unit) do
{precision, default_unit} = Map.get(@sensor_formats, sensor_type, {2, ""})
"#{Float.round(value, precision)}#{unit || default_unit}"

View file

@ -283,6 +283,10 @@ defmodule Towerops.Snmp.SensorChangeDetector do
end
end
defp format_sensor_value(value, "") when is_number(value) do
"#{trunc(value)}"
end
defp format_sensor_value(value, unit) when is_number(value) do
"#{Float.round(value / 1.0, 1)}#{unit}"
end

View file

@ -212,6 +212,45 @@ defmodule Towerops.Monitoring.Executors.SnmpSensorExecutorTest do
assert error_msg =~ "Sensor not found"
end
test "formats count sensor output as integer", %{device: device, snmp_device: snmp_device} do
sensor =
%Sensor{}
|> Sensor.changeset(%{
snmp_device_id: snmp_device.id,
sensor_descr: "Total number of ipv4 connections",
sensor_type: "count",
sensor_index: "mtxrCtIP4Entries.0",
sensor_oid: ".1.3.6.1.4.1.14988.1.1.22.1.2.0",
sensor_unit: "",
sensor_divisor: 1
})
|> Repo.insert!()
{:ok, check} =
Monitoring.create_check(%{
organization_id: device.organization_id,
device_id: device.id,
name: "IPv4 Connections",
check_type: "snmp_sensor",
source_type: "auto_discovery",
source_id: sensor.id,
config: %{
"sensor_type" => "count",
"sensor_oid" => ".1.3.6.1.4.1.14988.1.1.22.1.2.0",
"sensor_unit" => ""
}
})
expect(SnmpMock, :get, fn _ip, _oid, _opts ->
{:ok, {:integer, 1270}}
end)
assert {:ok, response} = SnmpSensorExecutor.execute(check)
assert response.value == 1270.0
assert response.output =~ "1270"
refute response.output =~ "1270.0"
end
test "returns error when SNMP fails", %{device: device, snmp_device: snmp_device} do
sensor =
%Sensor{}

View file

@ -276,6 +276,32 @@ defmodule Towerops.Snmp.SensorChangeDetectorTest do
assert "sensor_value_changed" in event_types
end
test "formats count sensor values as integers in event messages", %{
device: device,
snmp_device: snmp_device
} do
sensor =
create_sensor(snmp_device, %{
sensor_type: "count",
sensor_descr: "IPv4 Connections",
sensor_unit: "",
last_value: 1000.0
})
timestamp = DateTime.utc_now()
Phoenix.PubSub.subscribe(Towerops.PubSub, "device:#{device.id}")
SensorChangeDetector.detect_and_broadcast(sensor, 1270.0, timestamp)
assert_receive {:device_event, event}
assert event.event_type == "sensor_value_changed"
assert event.message =~ "1000"
refute event.message =~ "1000.0"
assert event.message =~ "1270"
refute event.message =~ "1270.0"
end
test "broadcasts to both device and global event topics", %{
device: device,
snmp_device: snmp_device