122 lines
2.9 KiB
Elixir
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
|