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
def collect_db_pool_metrics do
# Get pool configuration
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
nil ->
# Repo not started, report zeros
: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
nil -> report_pool_metrics_unavailable(pool_size)
repo_pid when is_pid(repo_pid) -> collect_from_repo(repo_pid, pool_size)
end
rescue
e ->
Logger.debug("Error collecting pool metrics: #{inspect(e)}")
# Emit zero metrics on error
:telemetry.execute(
[:aprsme, :repo, :pool],
%{
size: 0,
idle: 0,
busy: 0,
available: 0,
queue_length: 0,
total: 0
},
%{}
)
report_pool_metrics_error()
end
defp collect_from_repo(repo_pid, pool_size) do
case Supervisor.which_children(repo_pid) do
children when is_list(children) ->
pool_info = find_pool_child(children)
collect_from_pool(pool_info, pool_size)
_ ->
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
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).
"""
@spec get_overlay_base_table_id(String.t()) :: String.t()
def get_overlay_base_table_id(base_symbol_code) do
# Map symbols to the correct sprite table based on APRS specification
# Most overlay symbols are in the alternate table (1)
case base_symbol_code do
# 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
def get_overlay_base_table_id(_base_symbol_code) do
# All overlay symbols are in the alternate table (1) per APRS specification
# This includes digipeaters, diamonds, squares, arrows, etc.
"1"
end
@doc """