defmodule Localiser.MQTT.Telemetry do @moduledoc """ GenServer responsible for tracking telemetry data related to MQTT messages. """ use GenServer require Logger def start_link(opts) do GenServer.start_link(__MODULE__, opts, name: __MODULE__) end def count_reading() do GenServer.cast(__MODULE__, :count_reading) end def count_error() do GenServer.cast(__MODULE__, :count_error) end @log_interval 60_000 # GenServer Callbacks @impl true def init(_opts) do schedule_log() {:ok, %{total_readings: 0, total_errors: 0}} end @impl true def handle_cast(:count_reading, state) do new_count = state.total_readings + 1 {:noreply, %{state | total_readings: new_count}} end @impl true def handle_cast(:count_error, state) do new_count = state.total_errors + 1 {:noreply, %{state | total_errors: new_count}} end @impl true def handle_info(:log_stats, state) do rate = if state.total_readings > 0 do Float.round(state.total_errors / state.total_readings * 100, 2) else 0.0 end Logger.info("[MQTT.Telemetry] #{state.total_readings} readings, #{state.total_errors} errors (#{rate} err rate) in last #{@log_interval / 1000}s.") schedule_log() {:noreply, state} end # Private helper functions defp schedule_log() do Process.send_after(self(), :log_stats, @log_interval) end end