131
internal/cmd/stats.go
Archivo normal
131
internal/cmd/stats.go
Archivo normal
@@ -0,0 +1,131 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/yourusername/buque/internal/models"
|
||||
"github.com/yourusername/buque/internal/stats"
|
||||
)
|
||||
|
||||
var statsCmd = &cobra.Command{
|
||||
Use: "stats [environment]",
|
||||
Short: "Show container statistics",
|
||||
Long: `Display resource usage statistics for containers. If an environment is specified, shows only containers from that environment.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
collector, err := stats.NewCollector()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer collector.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
continuous, _ := cmd.Flags().GetBool("continuous")
|
||||
interval, _ := cmd.Flags().GetInt("interval")
|
||||
sortBy, _ := cmd.Flags().GetString("sort")
|
||||
|
||||
if continuous {
|
||||
// Clear screen and show stats continuously
|
||||
fmt.Print("\033[2J") // Clear screen
|
||||
|
||||
ticker := time.NewTicker(time.Duration(interval) * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
case <-ticker.C:
|
||||
fmt.Print("\033[H") // Move cursor to home position
|
||||
|
||||
if err := displayStats(ctx, collector, args, sortBy); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("\nRefreshing every %d seconds... (Press Ctrl+C to exit)\n", interval)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return displayStats(ctx, collector, args, sortBy)
|
||||
},
|
||||
}
|
||||
|
||||
func displayStats(ctx context.Context, collector *stats.Collector, args []string, sortBy string) error {
|
||||
var containerStats []models.ContainerStats
|
||||
var err error
|
||||
|
||||
if len(args) > 0 {
|
||||
// Show stats for specific environment
|
||||
containerStats, err = collector.CollectForEnvironment(ctx, args[0])
|
||||
} else {
|
||||
// Show stats for all containers
|
||||
containerStats, err = collector.CollectAll(ctx)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(containerStats) == 0 {
|
||||
fmt.Println("No running containers found.")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sort stats
|
||||
containerStats = collector.SortStats(containerStats, sortBy, true)
|
||||
|
||||
// Display in table format
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
fmt.Fprintln(w, "CONTAINER\tENVIRONMENT\tCPU %\tMEMORY USAGE\tMEMORY %\tNET I/O\tBLOCK I/O")
|
||||
|
||||
for _, stat := range containerStats {
|
||||
netIO := fmt.Sprintf("%s / %s",
|
||||
stats.FormatBytes(stat.NetworkRx),
|
||||
stats.FormatBytes(stat.NetworkTx))
|
||||
blockIO := fmt.Sprintf("%s / %s",
|
||||
stats.FormatBytes(stat.BlockRead),
|
||||
stats.FormatBytes(stat.BlockWrite))
|
||||
memUsage := fmt.Sprintf("%s / %s",
|
||||
stats.FormatBytes(stat.MemoryUsage),
|
||||
stats.FormatBytes(stat.MemoryLimit))
|
||||
|
||||
fmt.Fprintf(w, "%s\t%s\t%.2f%%\t%s\t%.2f%%\t%s\t%s\n",
|
||||
stat.Name,
|
||||
stat.Environment,
|
||||
stat.CPUPercentage,
|
||||
memUsage,
|
||||
stat.MemoryPercent,
|
||||
netIO,
|
||||
blockIO,
|
||||
)
|
||||
}
|
||||
|
||||
w.Flush()
|
||||
|
||||
// Show aggregated stats
|
||||
aggStats, err := collector.GetAggregatedStats(ctx)
|
||||
if err == nil {
|
||||
fmt.Printf("\nTotal Containers: %d\n", aggStats.TotalContainers)
|
||||
fmt.Printf("Total CPU: %.2f%%\n", aggStats.TotalCPUPercent)
|
||||
fmt.Printf("Total Memory: %s / %s (%.2f%%)\n",
|
||||
stats.FormatBytes(aggStats.TotalMemoryUsage),
|
||||
stats.FormatBytes(aggStats.TotalMemoryLimit),
|
||||
aggStats.TotalMemoryPercent)
|
||||
fmt.Printf("Total Network: %s / %s\n",
|
||||
stats.FormatBytes(aggStats.TotalNetworkRx),
|
||||
stats.FormatBytes(aggStats.TotalNetworkTx))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
statsCmd.Flags().BoolP("continuous", "c", false, "Continuous monitoring mode")
|
||||
statsCmd.Flags().IntP("interval", "i", 2, "Refresh interval in seconds (for continuous mode)")
|
||||
statsCmd.Flags().StringP("sort", "s", "cpu", "Sort by: cpu, memory, network, name")
|
||||
}
|
||||
Referencia en una nueva incidencia
Block a user