feat: Factory integration complete with UI updates
- Command factory with CreateWithIdempotency support - SubsystemHandler uses factory for all scan commands - Idempotency prevents duplicate commands from rapid clicks - UI updates for AgentStorage and heartbeat - Includes previous factory, queries, and main.go changes Now all command creation goes through factory for consistent validation and UUID generation.
This commit is contained in:
@@ -72,21 +72,81 @@ func (h *StorageMetricsHandler) ReportStorageMetrics(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// StorageMetricResponse represents the response format for storage metrics
|
||||
type StorageMetricResponse struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
AgentID uuid.UUID `json:"agent_id"`
|
||||
Mountpoint string `json:"mountpoint"`
|
||||
Device string `json:"device"`
|
||||
DiskType string `json:"disk_type"`
|
||||
Filesystem string `json:"filesystem"`
|
||||
Total int64 `json:"total"` // Changed from total_bytes
|
||||
Used int64 `json:"used"` // Changed from used_bytes
|
||||
Available int64 `json:"available"` // Changed from available_bytes
|
||||
UsedPercent float64 `json:"used_percent"`
|
||||
Severity string `json:"severity"`
|
||||
IsRoot bool `json:"is_root"`
|
||||
IsLargest bool `json:"is_largest"`
|
||||
Metadata map[string]interface{} `json:"metadata,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// GetStorageMetrics handles GET /api/v1/agents/:id/storage-metrics
|
||||
func (h *StorageMetricsHandler) GetStorageMetrics(c *gin.Context) {
|
||||
// Get agent ID from context (set by middleware)
|
||||
agentID := c.MustGet("agent_id").(uuid.UUID)
|
||||
|
||||
// Get storage metrics
|
||||
metrics, err := h.queries.GetStorageMetricsByAgentID(c.Request.Context(), agentID, 100, 0)
|
||||
// Get the latest storage metrics (one per mountpoint)
|
||||
latestMetrics, err := h.queries.GetLatestStorageMetrics(c.Request.Context(), agentID)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Failed to retrieve storage metrics for agent %s: %v\n", agentID, err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve storage metrics"})
|
||||
return
|
||||
}
|
||||
|
||||
// Transform to response format
|
||||
var responseMetrics []StorageMetricResponse
|
||||
for _, metric := range latestMetrics {
|
||||
// Check if this is the root mountpoint
|
||||
isRoot := metric.Mountpoint == "/"
|
||||
|
||||
// Create response with fields matching frontend expectations
|
||||
responseMetric := StorageMetricResponse{
|
||||
ID: metric.ID,
|
||||
AgentID: metric.AgentID,
|
||||
Mountpoint: metric.Mountpoint,
|
||||
Device: metric.Device,
|
||||
DiskType: metric.DiskType,
|
||||
Filesystem: metric.Filesystem,
|
||||
Total: metric.TotalBytes, // Map total_bytes -> total
|
||||
Used: metric.UsedBytes, // Map used_bytes -> used
|
||||
Available: metric.AvailableBytes, // Map available_bytes -> available
|
||||
UsedPercent: metric.UsedPercent,
|
||||
Severity: metric.Severity,
|
||||
IsRoot: isRoot,
|
||||
IsLargest: false, // Will be determined below
|
||||
Metadata: metric.Metadata,
|
||||
CreatedAt: metric.CreatedAt,
|
||||
}
|
||||
responseMetrics = append(responseMetrics, responseMetric)
|
||||
}
|
||||
|
||||
// Determine which disk is the largest
|
||||
if len(responseMetrics) > 0 {
|
||||
var maxSize int64
|
||||
var maxIndex int
|
||||
for i, metric := range responseMetrics {
|
||||
if metric.Total > maxSize {
|
||||
maxSize = metric.Total
|
||||
maxIndex = i
|
||||
}
|
||||
}
|
||||
// Mark the largest disk
|
||||
responseMetrics[maxIndex].IsLargest = true
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"metrics": metrics,
|
||||
"total": len(metrics),
|
||||
"metrics": responseMetrics,
|
||||
"total": len(responseMetrics),
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user