132 líneas
3.5 KiB
Go
132 líneas
3.5 KiB
Go
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")
|
|
}
|