towerops/lib/towerops/monitoring.ex
2025-12-21 17:17:35 -06:00

122 lines
2.9 KiB
Elixir

defmodule Towerops.Monitoring do
@moduledoc """
The Monitoring context.
"""
import Ecto.Query
alias Ecto.Adapters.SQL
alias Towerops.Monitoring.Check
alias Towerops.Repo
@doc """
Creates a monitoring check.
"""
def create_check(attrs) do
%Check{}
|> Check.changeset(attrs)
|> Repo.insert()
end
@doc """
Returns the list of checks for an equipment.
"""
def list_equipment_checks(equipment_id, limit \\ 100) do
Repo.all(from(c in Check, where: c.equipment_id == ^equipment_id, order_by: [desc: c.checked_at], limit: ^limit))
end
@doc """
Returns the latest check for an equipment.
"""
def get_latest_check(equipment_id) do
Repo.one(from(c in Check, where: c.equipment_id == ^equipment_id, order_by: [desc: c.checked_at], limit: 1))
end
@doc """
Deletes old monitoring checks older than the given date.
"""
def delete_old_checks(older_than_date) do
Repo.delete_all(from(c in Check, where: c.checked_at < ^older_than_date))
end
@doc """
Gets hourly statistics for equipment over a time range.
Uses TimescaleDB continuous aggregate for performance.
"""
def get_hourly_stats(equipment_id, start_time, end_time) do
query = """
SELECT
bucket,
total_checks,
successful_checks,
failed_checks,
avg_response_time_ms,
min_response_time_ms,
max_response_time_ms,
ROUND(100.0 * successful_checks / NULLIF(total_checks, 0), 2) as uptime_percentage
FROM monitoring_checks_hourly
WHERE equipment_id = $1
AND bucket >= $2
AND bucket <= $3
ORDER BY bucket ASC
"""
SQL.query!(
Repo,
query,
[equipment_id, start_time, end_time]
)
end
@doc """
Gets daily statistics for equipment over a time range.
Uses TimescaleDB continuous aggregate for performance.
"""
def get_daily_stats(equipment_id, start_time, end_time) do
query = """
SELECT
bucket,
total_checks,
successful_checks,
failed_checks,
avg_response_time_ms,
min_response_time_ms,
max_response_time_ms,
uptime_percentage
FROM monitoring_checks_daily
WHERE equipment_id = $1
AND bucket >= $2
AND bucket <= $3
ORDER BY bucket ASC
"""
SQL.query!(
Repo,
query,
[equipment_id, start_time, end_time]
)
end
@doc """
Gets uptime percentage for equipment over the last N days.
"""
def get_uptime_percentage(equipment_id, days_ago \\ 30) do
start_time = DateTime.add(DateTime.utc_now(), -days_ago * 24 * 60 * 60, :second)
query = """
SELECT
AVG(uptime_percentage) as avg_uptime
FROM monitoring_checks_daily
WHERE equipment_id = $1
AND bucket >= $2
"""
case SQL.query!(Repo, query, [equipment_id, start_time]) do
%{rows: [[uptime]]} when not is_nil(uptime) ->
Float.round(uptime, 2)
_ ->
nil
end
end
end