class

JaneHQ::Storage

Inherits Reference < Object

Persistence layer over SQLite. Holds latest-state per agent (history is a later phase). Safe for concurrent use from the ingest fiber and web fibers via crystal-db's connection pool + a short busy timeout.

Constants

AGENT_COLUMNS = "id, hostname, os, kernel, uptime, cpu_model, cpu_cores, cpu_usage, load_avg,\ntotal_memory, used_memory, free_memory, memory_usage, jane_version,\nunmonitored, alert_count, check_count, first_seen, last_seen"
ALERT_GROUP_COLUMNS = "id, name, enabled, services, statuses, events, alert_type, alert_target,\nalert_count, alert_frequency_minutes"
ALERT_GROUP_TARGETS_SQL = "SELECT t.kind, t.ref, COALESCE(g.name, t.ref)\nFROM alert_group_targets t\nLEFT JOIN host_groups g ON t.kind = ? AND g.id = CAST(t.ref AS INTEGER)\nWHERE t.alert_group_id = ?\nORDER BY t.kind, COALESCE(g.name, t.ref)"

The bound values are 'group' (the JOIN's kind test) then the rule id.

DEFAULT_GROUP_NAME = "All Hosts"

Seeded on first migration; shows every agent and is not editable.

GROUP_COLUMNS = "g.id, g.name, g.is_default,\n(SELECT COUNT(*) FROM host_group_members m WHERE m.group_id = g.id)"
INSERT_ALERT_GROUP_SQL = "INSERT INTO alert_groups\n (name, enabled, services, statuses, events, alert_type, alert_target,\n alert_count, alert_frequency_minutes, created_at)\nVALUES (?,?,?,?,?,?,?,?,?,?)"
INSERT_CHECK_SQL = "INSERT INTO checks\n (agent_id, name, status, current, threshold, message, tags, description)\nVALUES (?,?,?,?,?,?,?,?)"
UPDATE_ALERT_GROUP_SQL = "UPDATE alert_groups SET\n name = ?, enabled = ?, services = ?, statuses = ?, events = ?,\n alert_type = ?, alert_target = ?, alert_count = ?, alert_frequency_minutes = ?\nWHERE id = ?"
UPSERT_AGENT_SQL = "INSERT INTO agents (\n hostname, os, kernel, uptime, cpu_model, cpu_cores, cpu_usage,\n load_avg, total_memory, used_memory, free_memory, memory_usage,\n jane_version, unmonitored, alert_count, check_count, first_seen, last_seen\n) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)\nON CONFLICT(hostname) DO UPDATE SET\n os=excluded.os, kernel=excluded.kernel, uptime=excluded.uptime,\n cpu_model=excluded.cpu_model, cpu_cores=excluded.cpu_cores,\n cpu_usage=excluded.cpu_usage, load_avg=excluded.load_avg,\n total_memory=excluded.total_memory, used_memory=excluded.used_memory,\n free_memory=excluded.free_memory, memory_usage=excluded.memory_usage,\n jane_version=excluded.jane_version, unmonitored=excluded.unmonitored,\n alert_count=excluded.alert_count, check_count=excluded.check_count,\n last_seen=excluded.last_seen"

Constructors

new(db_path : String)
Source

Instance methods

agent_by_hostname(hostname : String) : AgentRecord | Nil
Source
agents_in_group(group : GroupRecord) : Array(AgentRecord)

Agents in one group, in the dashboard's severity order. The default group has no membership rows — it means "everything".

Source
alert_checks_for(agent_id : Int64) : Array(CheckRecord)

Only the alerting checks — what the dashboard's Glance popover shows.

Source
alert_group_by_id(id : Int64) : AlertGroupRecord | Nil
Source
alert_group_targets(alert_group_id : Int64) : Array(AlertTarget)

The hosts and host groups one rule watches, host groups first and each labelled with its current name.

Source
all_agents

All agents, most-alerting first, then most-recently-seen. This ordering is the dashboard's "organize by severity" requirement.

Source
all_alert_groups
Source
all_groups

Default group first, then alphabetical — the order of the dashboard's group picker.

Source
checks_for(agent_id : Int64) : Array(CheckRecord)
Source
close
Source
create_alert_group(name : String, targets : Array(AlertTarget), services : Array(String), statuses : Array(String), events : Array(String), alert_type : String, alert_target : String, alert_count : String = AlertRules::DEFAULT_ALERT_COUNT, alert_frequency_minutes : Int32 = AlertRules::DEFAULT_ALERT_FREQUENCY_MINUTES, enabled : Bool = true, now : Int64 = Time.utc.to_unix) : Int64

Raises SQLite3::Exception on a duplicate name (UNIQUE on alert_groups.name).

Source
create_group(name : String, hostnames : Array(String), now : Int64 = Time.utc.to_unix) : Int64

Raises SQLite3::Exception on a duplicate name (UNIQUE on host_groups.name).

Source
default_group
Source
delete_alert_group(id : Int64)
Source
delete_group(id : Int64)
Source
distinct_check_names

Every distinct check name any agent has reported — the "Service" choices on the alert group form.

Source
group_by_id(id : Int64) : GroupRecord | Nil
Source
group_hostnames(group_id : Int64) : Array(String)
Source
persist(payload : Payload, now : Int64 = Time.utc.to_unix)

Store one agent report: upsert the agent row (refreshing metrics and the denormalized alert_count) and replace its checks with this snapshot.

Source
set_alert_group_enabled(id : Int64, enabled : Bool)
Source
update_alert_group(id : Int64, name : String, targets : Array(AlertTarget), services : Array(String), statuses : Array(String), events : Array(String), alert_type : String, alert_target : String, enabled : Bool, alert_count : String = AlertRules::DEFAULT_ALERT_COUNT, alert_frequency_minutes : Int32 = AlertRules::DEFAULT_ALERT_FREQUENCY_MINUTES)
Source
update_group(id : Int64, name : String, hostnames : Array(String))
Source