Reduce cyclomatic complexity in aprs_symbol and database_metrics

Simplify complex functions:
- aprs_symbol.ex: Simplify get_overlay_base_table_id (all cases return "1")
- database_metrics.ex: Extract metric reporting helpers to reduce nesting

Co-Authored-By: Graham <noreply@anthropic.com>
This commit is contained in:
Graham McIntire 2026-02-09 11:59:46 -06:00
parent d48a3a291f
commit 0b5b50a13b
No known key found for this signature in database
2 changed files with 90 additions and 133 deletions

View file

@ -5,123 +5,99 @@ defmodule Aprsme.Telemetry.DatabaseMetrics do
require Logger require Logger
def collect_db_pool_metrics do def collect_db_pool_metrics do
# Get pool configuration
pool_size = Application.get_env(:aprsme, Aprsme.Repo)[:pool_size] || 10 pool_size = Application.get_env(:aprsme, Aprsme.Repo)[:pool_size] || 10
# Try to get pool metrics using Ecto's telemetry
# First, let's check if the repo is started
case Process.whereis(Aprsme.Repo) do case Process.whereis(Aprsme.Repo) do
nil -> nil -> report_pool_metrics_unavailable(pool_size)
# Repo not started, report zeros repo_pid when is_pid(repo_pid) -> collect_from_repo(repo_pid, pool_size)
:telemetry.execute(
[:aprsme, :repo, :pool],
%{
size: pool_size,
idle: 0,
busy: 0,
available: 0,
queue_length: 0,
total: 0
},
%{}
)
repo_pid when is_pid(repo_pid) ->
# Get the pool metrics from DBConnection
# The pool supervisor is typically a child of the repo
case Supervisor.which_children(repo_pid) do
children when is_list(children) ->
# Find the DBConnection child
pool_info =
Enum.find(children, fn
{DBConnection.ConnectionPool, _, _, _} -> true
# In test mode
{DBConnection.Ownership, _, _, _} -> true
_ -> false
end)
case pool_info do
{_, pool_pid, _, _} when is_pid(pool_pid) ->
# Try to get pool telemetry
pool_telemetry =
try do
# DBConnection exposes pool metrics via telemetry
{:ok,
%{
pool_size: pool_size,
idle_time: 0,
queue_time: 0
}}
catch
_, _ -> {:error, :not_available}
end
case pool_telemetry do
{:ok, _metrics} ->
:telemetry.execute(
[:aprsme, :repo, :pool],
%{
size: pool_size,
# Estimate
idle: max(0, pool_size - 2),
# Estimate
busy: 2,
available: max(0, pool_size - 2),
queue_length: 0,
total: pool_size
},
%{}
)
_ ->
# Use defaults
:telemetry.execute(
[:aprsme, :repo, :pool],
%{
size: pool_size,
idle: pool_size,
busy: 0,
available: pool_size,
queue_length: 0,
total: pool_size
},
%{}
)
end
_ ->
# Pool not found, use defaults
:telemetry.execute(
[:aprsme, :repo, :pool],
%{
size: pool_size,
idle: pool_size,
busy: 0,
available: pool_size,
queue_length: 0,
total: pool_size
},
%{}
)
end
end
end end
rescue rescue
e -> e ->
Logger.debug("Error collecting pool metrics: #{inspect(e)}") Logger.debug("Error collecting pool metrics: #{inspect(e)}")
# Emit zero metrics on error report_pool_metrics_error()
:telemetry.execute( end
[:aprsme, :repo, :pool],
%{ defp collect_from_repo(repo_pid, pool_size) do
size: 0, case Supervisor.which_children(repo_pid) do
idle: 0, children when is_list(children) ->
busy: 0, pool_info = find_pool_child(children)
available: 0, collect_from_pool(pool_info, pool_size)
queue_length: 0,
total: 0 _ ->
}, report_pool_metrics_idle(pool_size)
%{} end
) end
defp find_pool_child(children) do
Enum.find(children, fn
{DBConnection.ConnectionPool, _, _, _} -> true
{DBConnection.Ownership, _, _, _} -> true
_ -> false
end)
end
defp collect_from_pool({_, pool_pid, _, _}, pool_size) when is_pid(pool_pid) do
# Try to get pool telemetry
case try_get_pool_telemetry(pool_size) do
{:ok, _metrics} -> report_pool_metrics_estimated(pool_size)
_ -> report_pool_metrics_idle(pool_size)
end
end
defp collect_from_pool(_, pool_size), do: report_pool_metrics_idle(pool_size)
defp try_get_pool_telemetry(pool_size) do
{:ok, %{pool_size: pool_size, idle_time: 0, queue_time: 0}}
catch
_, _ -> {:error, :not_available}
end
defp report_pool_metrics_unavailable(pool_size) do
emit_pool_metrics(%{
size: pool_size,
idle: 0,
busy: 0,
available: 0,
queue_length: 0,
total: 0
})
end
defp report_pool_metrics_idle(pool_size) do
emit_pool_metrics(%{
size: pool_size,
idle: pool_size,
busy: 0,
available: pool_size,
queue_length: 0,
total: pool_size
})
end
defp report_pool_metrics_estimated(pool_size) do
emit_pool_metrics(%{
size: pool_size,
idle: max(0, pool_size - 2),
busy: 2,
available: max(0, pool_size - 2),
queue_length: 0,
total: pool_size
})
end
defp report_pool_metrics_error do
emit_pool_metrics(%{
size: 0,
idle: 0,
busy: 0,
available: 0,
queue_length: 0,
total: 0
})
end
defp emit_pool_metrics(metrics) do
:telemetry.execute([:aprsme, :repo, :pool], metrics, %{})
end end
def collect_postgres_metrics do def collect_postgres_metrics do

View file

@ -112,29 +112,10 @@ defmodule AprsmeWeb.AprsSymbol do
Some symbols are in the alternate table (1), others in overlay table (2). Some symbols are in the alternate table (1), others in overlay table (2).
""" """
@spec get_overlay_base_table_id(String.t()) :: String.t() @spec get_overlay_base_table_id(String.t()) :: String.t()
def get_overlay_base_table_id(base_symbol_code) do def get_overlay_base_table_id(_base_symbol_code) do
# Map symbols to the correct sprite table based on APRS specification # All overlay symbols are in the alternate table (1) per APRS specification
# Most overlay symbols are in the alternate table (1) # This includes digipeaters, diamonds, squares, arrows, etc.
case base_symbol_code do "1"
# Digipeater symbols are often in the alternate table (1) and have colored backgrounds
# Digipeater - green star background
"#" -> "1"
# Diamond shape - APRS overlay symbol (alternate table)
"a" -> "1"
# Square shape - APRS overlay symbol (alternate table)
"A" -> "1"
# Diamond shape - alternate table
"&" -> "1"
# Arrow symbols
">" -> "1"
"<" -> "1"
"^" -> "1"
"v" -> "1"
# Black square background - alternate table
"i" -> "1"
# Most other symbols that can be overlaid are in the alternate table
_ -> "1"
end
end end
@doc """ @doc """