towerops/lib/towerops/snmp/state_sensor.ex

79 lines
2.2 KiB
Elixir

defmodule Towerops.Snmp.StateSensor do
@moduledoc """
SNMP state sensor schema for monitoring device health status.
Unlike numeric sensors that track values like temperature or voltage,
state sensors track discrete states like power supply status, fan status,
and module operational status.
State values are mapped to generic status categories:
- ok: Normal operation
- warning: Degraded but functional
- critical: Failed or about to fail
- unknown: State not determined
"""
use Ecto.Schema
import Ecto.Changeset
alias Ecto.Association.NotLoaded
alias Towerops.Snmp.Device
@valid_statuses ~w(ok warning critical unknown)
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "snmp_state_sensors" do
field :sensor_index, :string
field :sensor_oid, :string
field :sensor_descr, :string
field :entity_type, :string
field :state_value, :integer
field :state_descr, :string
field :status, :string, default: "unknown"
field :last_checked_at, :utc_datetime
field :metadata, :map, default: %{}
belongs_to :snmp_device, Device
timestamps(type: :utc_datetime)
end
@type t :: %__MODULE__{
id: Ecto.UUID.t(),
sensor_index: String.t(),
sensor_oid: String.t(),
sensor_descr: String.t() | nil,
entity_type: String.t() | nil,
state_value: integer() | nil,
state_descr: String.t() | nil,
status: String.t(),
last_checked_at: DateTime.t() | nil,
metadata: map(),
snmp_device_id: Ecto.UUID.t(),
snmp_device: NotLoaded.t() | Device.t(),
inserted_at: DateTime.t(),
updated_at: DateTime.t()
}
@doc false
def changeset(state_sensor, attrs) do
state_sensor
|> cast(attrs, [
:snmp_device_id,
:sensor_index,
:sensor_oid,
:sensor_descr,
:entity_type,
:state_value,
:state_descr,
:status,
:last_checked_at,
:metadata
])
|> validate_required([:snmp_device_id, :sensor_index, :sensor_oid])
|> validate_inclusion(:status, @valid_statuses)
|> unique_constraint([:snmp_device_id, :sensor_index])
|> foreign_key_constraint(:snmp_device_id)
end
end