167 lines
5.0 KiB
Go
167 lines
5.0 KiB
Go
package queries
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/Fimeg/RedFlag/aggregator-server/internal/models"
|
|
"github.com/google/uuid"
|
|
"github.com/lib/pq"
|
|
)
|
|
|
|
// StorageMetricsQueries handles storage metrics database operations
|
|
type StorageMetricsQueries struct {
|
|
db *sql.DB
|
|
}
|
|
|
|
// NewStorageMetricsQueries creates a new storage metrics queries instance
|
|
func NewStorageMetricsQueries(db *sql.DB) *StorageMetricsQueries {
|
|
return &StorageMetricsQueries{db: db}
|
|
}
|
|
|
|
// InsertStorageMetric inserts a new storage metric
|
|
func (q *StorageMetricsQueries) InsertStorageMetric(ctx context.Context, metric models.StorageMetric) error {
|
|
query := `
|
|
INSERT INTO storage_metrics (
|
|
id, agent_id, mountpoint, device, disk_type, filesystem,
|
|
total_bytes, used_bytes, available_bytes, used_percent,
|
|
severity, metadata, created_at
|
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
|
|
`
|
|
|
|
_, err := q.db.ExecContext(ctx, query,
|
|
metric.ID, metric.AgentID, metric.Mountpoint, metric.Device,
|
|
metric.DiskType, metric.Filesystem, metric.TotalBytes,
|
|
metric.UsedBytes, metric.AvailableBytes, metric.UsedPercent,
|
|
metric.Severity, pq.Array(metric.Metadata), metric.CreatedAt,
|
|
)
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed to insert storage metric: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetStorageMetricsByAgentID retrieves storage metrics for an agent
|
|
func (q *StorageMetricsQueries) GetStorageMetricsByAgentID(ctx context.Context, agentID uuid.UUID, limit, offset int) ([]models.StorageMetric, error) {
|
|
query := `
|
|
SELECT id, agent_id, mountpoint, device, disk_type, filesystem,
|
|
total_bytes, used_bytes, available_bytes, used_percent,
|
|
severity, metadata, created_at
|
|
FROM storage_metrics
|
|
WHERE agent_id = $1
|
|
ORDER BY created_at DESC
|
|
LIMIT $2 OFFSET $3
|
|
`
|
|
|
|
rows, err := q.db.QueryContext(ctx, query, agentID, limit, offset)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to query storage metrics: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
var metrics []models.StorageMetric
|
|
for rows.Next() {
|
|
var metric models.StorageMetric
|
|
var metadataMap map[string]interface{}
|
|
|
|
err := rows.Scan(
|
|
&metric.ID, &metric.AgentID, &metric.Mountpoint, &metric.Device,
|
|
&metric.DiskType, &metric.Filesystem, &metric.TotalBytes,
|
|
&metric.UsedBytes, &metric.AvailableBytes, &metric.UsedPercent,
|
|
&metric.Severity, &metadataMap, &metric.CreatedAt,
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to scan storage metric: %w", err)
|
|
}
|
|
|
|
metric.Metadata = metadataMap
|
|
metrics = append(metrics, metric)
|
|
}
|
|
|
|
if err := rows.Err(); err != nil {
|
|
return nil, fmt.Errorf("error iterating storage metrics: %w", err)
|
|
}
|
|
|
|
return metrics, nil
|
|
}
|
|
|
|
// GetLatestStorageMetrics retrieves the most recent storage metrics per mountpoint
|
|
func (q *StorageMetricsQueries) GetLatestStorageMetrics(ctx context.Context, agentID uuid.UUID) ([]models.StorageMetric, error) {
|
|
query := `
|
|
SELECT DISTINCT ON (mountpoint)
|
|
id, agent_id, mountpoint, device, disk_type, filesystem,
|
|
total_bytes, used_bytes, available_bytes, used_percent,
|
|
severity, metadata, created_at
|
|
FROM storage_metrics
|
|
WHERE agent_id = $1
|
|
ORDER BY mountpoint, created_at DESC
|
|
`
|
|
|
|
rows, err := q.db.QueryContext(ctx, query, agentID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to query latest storage metrics: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
var metrics []models.StorageMetric
|
|
for rows.Next() {
|
|
var metric models.StorageMetric
|
|
var metadataMap map[string]interface{}
|
|
|
|
err := rows.Scan(
|
|
&metric.ID, &metric.AgentID, &metric.Mountpoint, &metric.Device,
|
|
&metric.DiskType, &metric.Filesystem, &metric.TotalBytes,
|
|
&metric.UsedBytes, &metric.AvailableBytes, &metric.UsedPercent,
|
|
&metric.Severity, &metadataMap, &metric.CreatedAt,
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to scan storage metric: %w", err)
|
|
}
|
|
|
|
metric.Metadata = metadataMap
|
|
metrics = append(metrics, metric)
|
|
}
|
|
|
|
if err := rows.Err(); err != nil {
|
|
return nil, fmt.Errorf("error iterating latest storage metrics: %w", err)
|
|
}
|
|
|
|
return metrics, nil
|
|
}
|
|
|
|
// GetStorageMetricsSummary returns summary statistics for an agent
|
|
func (q *StorageMetricsQueries) GetStorageMetricsSummary(ctx context.Context, agentID uuid.UUID) (map[string]interface{}, error) {
|
|
query := `
|
|
SELECT
|
|
COUNT(*) as total_disks,
|
|
COUNT(CASE WHEN severity = 'critical' THEN 1 END) as critical_disks,
|
|
COUNT(CASE WHEN severity = 'important' THEN 1 END) as important_disks,
|
|
AVG(used_percent) as avg_used_percent,
|
|
MAX(used_percent) as max_used_percent,
|
|
MIN(created_at) as first_collected_at,
|
|
MAX(created_at) as last_collected_at
|
|
FROM storage_metrics
|
|
WHERE agent_id = $1
|
|
AND created_at >= NOW() - INTERVAL '24 hours'
|
|
`
|
|
|
|
var summary map[string]interface{}
|
|
err := q.db.QueryRowContext(ctx, query, agentID).Scan(
|
|
&summary["total_disks"],
|
|
&summary["critical_disks"],
|
|
&summary["important_disks"],
|
|
&summary["avg_used_percent"],
|
|
&summary["max_used_percent"],
|
|
&summary["first_collected_at"],
|
|
&summary["last_collected_at"],
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get storage metrics summary: %w", err)
|
|
}
|
|
|
|
return summary, nil
|
|
} |