store

package
v0.3.88 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package store implements the SQLite persistence layer for Klever Node Hub.

DEPENDENCY NOTE: This package uses modernc.org/sqlite as a pure-Go SQLite driver (no CGO required). This enables cross-compilation to all target platforms without a C compiler. Sensitive fields (certificates, keys) are encrypted at the application level using the crypto module's AES-256-GCM.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ExtractNumericMetrics

func ExtractNumericMetrics(raw map[string]any) map[string]float64

ExtractNumericMetrics extracts numeric values from a map[string]any, converting JSON number types to float64.

Types

type AggregatedPoint

type AggregatedPoint struct {
	AvgValue    float64 `json:"avg_value"`
	MinValue    float64 `json:"min_value"`
	MaxValue    float64 `json:"max_value"`
	SampleCount int     `json:"sample_count"`
	BucketStart int64   `json:"bucket_start"`
	BucketEnd   int64   `json:"bucket_end"`
}

AggregatedPoint is a decimated time-series data point with min/max/avg.

type AlertRecord

type AlertRecord struct {
	ID         string `json:"id"`
	RuleID     string `json:"rule_id"`
	RuleName   string `json:"rule_name"`
	NodeID     string `json:"node_id,omitempty"`
	ServerID   string `json:"server_id,omitempty"`
	Severity   string `json:"severity"`
	State      string `json:"state"` // pending, firing, resolved
	Message    string `json:"message"`
	FiredAt    int64  `json:"fired_at,omitempty"`
	ResolvedAt int64  `json:"resolved_at,omitempty"`
	NotifiedAt int64  `json:"notified_at,omitempty"`
	Acked      bool   `json:"acked"`
	CreatedAt  int64  `json:"created_at"`
}

AlertRecord represents a stored alert instance.

type AlertRule

type AlertRule struct {
	ID          string  `json:"id"`
	Name        string  `json:"name"`
	Enabled     bool    `json:"enabled"`
	MetricName  string  `json:"metric_name"`
	Condition   string  `json:"condition"` // gt, lt, eq, stall
	Threshold   float64 `json:"threshold"`
	DurationSec int     `json:"duration_sec"` // must breach for this many seconds
	Severity    string  `json:"severity"`     // critical, warning, info
	NodeFilter  string  `json:"node_filter"`  // "*" or specific node ID
	CooldownMin int     `json:"cooldown_min"` // minutes between re-alerts
	Builtin     bool    `json:"builtin"`      // true for default rules
	CreatedAt   int64   `json:"created_at"`
	UpdatedAt   int64   `json:"updated_at"`
}

AlertRule defines a threshold-based alert rule.

type AlertStore

type AlertStore struct {
	// contains filtered or unexported fields
}

AlertStore handles persistence for alert rules and alert history.

func NewAlertStore

func NewAlertStore(db *DB) *AlertStore

NewAlertStore creates a new alert store.

func (*AlertStore) AcknowledgeAlert

func (s *AlertStore) AcknowledgeAlert(id string) error

AcknowledgeAlert marks an alert as acknowledged.

func (*AlertStore) CreateAlert

func (s *AlertStore) CreateAlert(alert *AlertRecord) error

CreateAlert inserts a new alert record.

func (*AlertStore) CreateRule

func (s *AlertStore) CreateRule(rule *AlertRule) error

CreateRule inserts a new alert rule.

func (*AlertStore) DeleteRule

func (s *AlertStore) DeleteRule(id string) error

DeleteRule removes an alert rule by ID.

func (*AlertStore) GetActiveAlertByRuleAndNode

func (s *AlertStore) GetActiveAlertByRuleAndNode(ruleID, nodeID string) (*AlertRecord, error)

GetActiveAlertByRuleAndNode finds an active alert for a specific rule+node combo.

func (*AlertStore) GetActiveAlertByRuleAndServer

func (s *AlertStore) GetActiveAlertByRuleAndServer(ruleID, serverID string) (*AlertRecord, error)

GetActiveAlertByRuleAndServer finds an active alert for a specific rule+server combo.

func (*AlertStore) GetRule

func (s *AlertStore) GetRule(id string) (*AlertRule, error)

GetRule retrieves a single alert rule by ID.

func (*AlertStore) ListActiveAlerts

func (s *AlertStore) ListActiveAlerts() ([]AlertRecord, error)

ListActiveAlerts returns alerts in pending or firing state.

func (*AlertStore) ListAlertHistory

func (s *AlertStore) ListAlertHistory(limit int) ([]AlertRecord, error)

ListAlertHistory returns recent alerts (all states) with a limit.

func (*AlertStore) ListEnabledRules

func (s *AlertStore) ListEnabledRules() ([]AlertRule, error)

ListEnabledRules returns only enabled rules.

func (*AlertStore) ListRules

func (s *AlertStore) ListRules() ([]AlertRule, error)

ListRules retrieves all alert rules.

func (*AlertStore) PurgeOldAlerts

func (s *AlertStore) PurgeOldAlerts(olderThan time.Duration) (int64, error)

PurgeOldAlerts removes resolved alerts older than the given duration.

func (*AlertStore) ResolveAllFiring

func (s *AlertStore) ResolveAllFiring() (int64, error)

ResolveAllFiring marks all pending/firing alerts as resolved (e.g. on dashboard restart).

func (*AlertStore) RuleCount

func (s *AlertStore) RuleCount() (int, error)

RuleCount returns the total number of alert rules.

func (*AlertStore) UpdateAlert

func (s *AlertStore) UpdateAlert(alert *AlertRecord) error

UpdateAlert updates an alert's state and timestamps.

func (*AlertStore) UpdateRule

func (s *AlertStore) UpdateRule(rule *AlertRule) error

UpdateRule updates an existing alert rule.

type DB

type DB struct {
	// contains filtered or unexported fields
}

DB wraps the SQLite database connection with encryption support.

func Open

func Open(dbPath string) (*DB, error)

Open opens or creates a SQLite database at the given path. Enables WAL mode and foreign keys.

func (*DB) Close

func (d *DB) Close() error

Close closes the database connection.

func (*DB) SQL

func (d *DB) SQL() *sql.DB

SQL returns the underlying *sql.DB for advanced queries.

type DataPoint

type DataPoint struct {
	Value       float64 `json:"value"`
	CollectedAt int64   `json:"collected_at"`
}

DataPoint is a single time-series data point.

type MetricsStore

type MetricsStore struct {
	// contains filtered or unexported fields
}

MetricsStore handles persistence for node and system metrics.

func NewMetricsStore

func NewMetricsStore(db *DB) *MetricsStore

NewMetricsStore creates a new metrics store.

func (*MetricsStore) Decimate

func (s *MetricsStore) Decimate(olderThan time.Duration, bucketSize time.Duration) (int64, error)

Decimate aggregates raw metrics older than the cutoff into time buckets in metrics_archive, then deletes the aggregated raw rows. Returns the number of raw rows decimated.

The work is done in small, bucket-aligned time slices, each in its own short transaction, releasing the store lock between slices. A single big aggregate+delete transaction would hold the lock (shared with every agent heartbeat/metric write) for as long as the scan takes; during the hourly run that stalled heartbeat persistence enough to make the dashboard miss WebSocket pongs and drop every agent at once. Slicing bounds each lock hold to a few buckets' worth of rows.

func (*MetricsStore) InsertNodeMetrics

func (s *MetricsStore) InsertNodeMetrics(nodeID, serverID string, metrics map[string]float64, ts int64) error

InsertNodeMetrics inserts raw node metrics into metrics_recent. Only numeric values are stored; string metrics are skipped.

func (*MetricsStore) InsertSystemMetrics

func (s *MetricsStore) InsertSystemMetrics(serverID string, m *SystemMetricsRow) error

InsertSystemMetrics inserts a system metrics snapshot.

func (*MetricsStore) LatestNodeMetrics

func (s *MetricsStore) LatestNodeMetrics(nodeID string, metricNames []string) (map[string]float64, error)

LatestNodeMetrics returns the most recent value for each of the given metric names for a node.

func (*MetricsStore) Purge

func (s *MetricsStore) Purge(olderThan time.Duration) (int64, error)

Purge deletes archived metrics older than the given duration. Returns the number of rows deleted.

func (*MetricsStore) PurgeSystemMetrics

func (s *MetricsStore) PurgeSystemMetrics(olderThan time.Duration) (int64, error)

PurgeSystemMetrics deletes system metrics older than the given duration.

func (*MetricsStore) QueryArchive

func (s *MetricsStore) QueryArchive(nodeID, metricName string, from, to int64) ([]AggregatedPoint, error)

QueryArchive returns aggregated data points from metrics_archive.

func (*MetricsStore) QueryAutoResolution

func (s *MetricsStore) QueryAutoResolution(nodeID, metricName string, from, to int64, hotWindow time.Duration) (any, error)

QueryAutoResolution automatically selects metrics_recent or metrics_archive based on the requested time range. If the range starts within the hot window (7 days), it uses recent data; otherwise archive data.

func (*MetricsStore) QueryRecent

func (s *MetricsStore) QueryRecent(nodeID, metricName string, from, to int64) ([]DataPoint, error)

QueryRecent returns raw data points from metrics_recent for a specific metric.

func (*MetricsStore) QuerySystemMetrics

func (s *MetricsStore) QuerySystemMetrics(serverID string, from, to int64) ([]SystemMetricsRow, error)

QuerySystemMetrics returns system metrics for a server within a time range.

type NodeStore

type NodeStore struct {
	// contains filtered or unexported fields
}

NodeStore handles node persistence.

func NewNodeStore

func NewNodeStore(db *DB) *NodeStore

NewNodeStore creates a new NodeStore.

func (*NodeStore) Create

func (s *NodeStore) Create(node *models.Node) error

Create inserts a new node.

func (*NodeStore) Delete

func (s *NodeStore) Delete(id string) error

Delete removes a node by ID.

func (*NodeStore) GetByContainerAndServer added in v0.3.36

func (s *NodeStore) GetByContainerAndServer(containerName, serverID string) (*models.Node, error)

GetByContainerAndServer retrieves a node by container name scoped to a specific server.

func (*NodeStore) GetByContainerID

func (s *NodeStore) GetByContainerID(containerID string) (*models.Node, error)

GetByContainerID retrieves a node by its Docker container name. Deprecated: Use GetByContainerAndServer for unambiguous lookups.

func (*NodeStore) GetByID

func (s *NodeStore) GetByID(id string) (*models.Node, error)

GetByID retrieves a node by ID.

func (*NodeStore) ListAll

func (s *NodeStore) ListAll(statusFilter string) ([]models.Node, error)

ListAll retrieves all nodes, optionally filtered by status.

func (*NodeStore) ListByServer

func (s *NodeStore) ListByServer(serverID string) ([]models.Node, error)

ListByServer retrieves all nodes for a server.

func (*NodeStore) SetMaintenance added in v0.3.78

func (s *NodeStore) SetMaintenance(id string, maintenance bool) error

SetMaintenance marks a node as intentionally stopped (true) or clears that mark (false) by toggling a "maintenance" key in its metadata. While set, the alert evaluator suppresses node-offline alerts for the node — so deliberately stopping nodes from the dashboard doesn't spam alerts.

func (*NodeStore) Update

func (s *NodeStore) Update(node *models.Node) error

Update updates a node's fields.

func (*NodeStore) UpdateStatus

func (s *NodeStore) UpdateStatus(id, status string) error

UpdateStatus updates only the node's status.

func (*NodeStore) UpdateStatusByServer

func (s *NodeStore) UpdateStatusByServer(serverID, status string) error

UpdateStatusByServer sets the status of all nodes belonging to a server.

type ServerStore

type ServerStore struct {
	// contains filtered or unexported fields
}

ServerStore handles server persistence.

func NewServerStore

func NewServerStore(db *DB) *ServerStore

NewServerStore creates a new ServerStore.

func (*ServerStore) Create

func (s *ServerStore) Create(server *models.Server) error

Create inserts a new server.

func (*ServerStore) Delete

func (s *ServerStore) Delete(id string) error

Delete removes a server by ID.

func (*ServerStore) GetByID

func (s *ServerStore) GetByID(id string) (*models.Server, error)

GetByID retrieves a server by ID.

func (*ServerStore) List

func (s *ServerStore) List() ([]models.Server, error)

List retrieves all servers.

func (*ServerStore) ResetAllStatus

func (s *ServerStore) ResetAllStatus(status string) error

ResetAllStatus sets all servers to the given status (e.g. on dashboard startup).

func (*ServerStore) Update

func (s *ServerStore) Update(server *models.Server) error

Update updates a server's fields.

func (*ServerStore) UpdateHeartbeat

func (s *ServerStore) UpdateHeartbeat(id string, timestamp int64) error

UpdateHeartbeat updates only the heartbeat timestamp and sets status to online.

func (*ServerStore) UpdatePublicIP

func (s *ServerStore) UpdatePublicIP(id, publicIP, region string) error

UpdatePublicIP updates the server's public IP and region.

func (*ServerStore) UpdateStatus

func (s *ServerStore) UpdateStatus(id, status string) error

UpdateStatus sets the server status (e.g. "online", "offline").

type SettingsStore

type SettingsStore struct {
	// contains filtered or unexported fields
}

SettingsStore handles key-value settings persistence.

func NewSettingsStore

func NewSettingsStore(db *DB) *SettingsStore

NewSettingsStore creates a new SettingsStore.

func (*SettingsStore) Delete

func (s *SettingsStore) Delete(key string) error

Delete removes a setting by key.

func (*SettingsStore) Get

func (s *SettingsStore) Get(key string) (string, error)

Get retrieves a setting value by key. Returns empty string if not found.

func (*SettingsStore) GetAll

func (s *SettingsStore) GetAll() (map[string]string, error)

GetAll retrieves all settings as a map.

func (*SettingsStore) HeartbeatTimeout added in v0.3.66

func (s *SettingsStore) HeartbeatTimeout() time.Duration

HeartbeatTimeout reads the agent heartbeat timeout from settings. It is the single source of truth for "how long without a heartbeat before an agent counts as offline" — used by both the hub health check and the Agent Offline alert rule. Falls back to the default when missing or unparseable, and clamps to [30s, 600s] to match the Settings UI bounds.

func (*SettingsStore) Set

func (s *SettingsStore) Set(key, value string) error

Set stores a setting value. Creates or updates.

type SystemMetricsRow

type SystemMetricsRow struct {
	ServerID    string  `json:"server_id"`
	CPUPercent  float64 `json:"cpu_percent"`
	MemPercent  float64 `json:"mem_percent"`
	MemTotal    uint64  `json:"mem_total"`
	MemUsed     uint64  `json:"mem_used"`
	DiskPercent float64 `json:"disk_percent"`
	DiskTotal   uint64  `json:"disk_total"`
	DiskUsed    uint64  `json:"disk_used"`
	LoadAvg1    float64 `json:"load_avg_1"`
	CollectedAt int64   `json:"collected_at"`
}

SystemMetricsRow represents a row from the system_metrics table.

type VersionChange added in v0.3.66

type VersionChange struct {
	ID         int64  `json:"id"`
	NodeID     string `json:"node_id"`
	ServerID   string `json:"server_id"`
	Version    string `json:"version"`
	DetectedAt int64  `json:"detected_at"`
	Evaluated  bool   `json:"evaluated"`
}

VersionChange represents one observed version change for a node.

type VersionHistoryStore added in v0.3.66

type VersionHistoryStore struct {
	// contains filtered or unexported fields
}

VersionHistoryStore persists node version changes for regression detection.

func NewVersionHistoryStore added in v0.3.66

func NewVersionHistoryStore(db *DB) *VersionHistoryStore

NewVersionHistoryStore creates a new VersionHistoryStore.

func (*VersionHistoryStore) LastChange added in v0.3.66

func (s *VersionHistoryStore) LastChange(nodeID string) (*VersionChange, error)

LastChange returns the most recent version change for a node (evaluated or not), or nil if the node has no history. Used by the passive performance report on the node detail page.

func (*VersionHistoryStore) LatestVersion added in v0.3.66

func (s *VersionHistoryStore) LatestVersion(nodeID string) (string, error)

LatestVersion returns the most recently recorded version for a node, or "" if the node has no history yet.

func (*VersionHistoryStore) MarkEvaluated added in v0.3.66

func (s *VersionHistoryStore) MarkEvaluated(id int64) error

MarkEvaluated flags a version change as evaluated so the regression detector never alerts on it twice.

func (*VersionHistoryStore) PendingEvaluations added in v0.3.66

func (s *VersionHistoryStore) PendingEvaluations(now, minAgeSec, maxAgeSec int64) ([]VersionChange, error)

PendingEvaluations returns version changes that are not yet evaluated and whose detection time is between minAge and maxAge seconds ago. The lower bound gives the new version time to settle (so initial sync noise is past); the upper bound stops us from evaluating ancient changes after a restart.

func (*VersionHistoryStore) PreviousChange added in v0.3.66

func (s *VersionHistoryStore) PreviousChange(change VersionChange) (*VersionChange, error)

PreviousChange returns the version-change row immediately before the given change for the same node (used to know what the node upgraded *from* and when). Returns nil if this is the node's first recorded version.

func (*VersionHistoryStore) RecordVersion added in v0.3.66

func (s *VersionHistoryStore) RecordVersion(nodeID, serverID, version string, detectedAt int64) (bool, error)

RecordVersion records a version for a node, but only if it differs from the most recently recorded version. Returns true if a new change row was inserted (i.e. the version actually changed), false if unchanged.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL