diff --git a/cmd/main.go b/cmd/main.go new file mode 100644 index 0000000..d54f6d8 --- /dev/null +++ b/cmd/main.go @@ -0,0 +1,32 @@ +package cmd + +import ( + "github.com/urfave/cli/v2" + + "syscall" +) + +func Main(args []string) error { + + cli.VersionFlag = &cli.BoolFlag{ + Name: "version", Aliases: []string{"V"}, + Usage: "print version only", + } + app := &cli.App{ + Name: "goup", + Usage: "Resource monitoring go application", + Copyright: "Apache License 2.0", + HideHelpCommand: true, + EnableBashCompletion: true, + Commands: []*cli.Command{ + cmdMonitor(), + }, + } + + err := app.Run(args) + if errno, ok := err.(syscall.Errno); ok && errno == 0 { + err = nil + } + return err + +} diff --git a/cmd/monitor.go b/cmd/monitor.go new file mode 100644 index 0000000..13e8d2f --- /dev/null +++ b/cmd/monitor.go @@ -0,0 +1,80 @@ +package cmd + +import ( + "fmt" + "github.com/rivo/tview" + "github.com/shirou/gopsutil/v3/cpu" + "github.com/shirou/gopsutil/v3/mem" + "github.com/shirou/gopsutil/v3/process" + "github.com/urfave/cli/v2" + "sort" + "time" +) + +func cmdMonitor() *cli.Command { + return &cli.Command{ + Name: "profile", + Action: profile, + Usage: "Show reousrce usage of system", + Description: ` +Resource monitoring tools + +Examples: +# Monitor real time operations +$ goup profile + +`, + } +} +func profile(ctx *cli.Context) error { + + app := tview.NewApplication() + textView := tview.NewTextView().SetDynamicColors(true) + + go func() { + for { + // Fetch metrics + cpuPercent, _ := cpu.Percent(0, false) + memStats, _ := mem.VirtualMemory() + + // Fetch processes + procs, _ := process.Processes() + var procStats []string + for _, p := range procs { + name, _ := p.Name() + cpu, _ := p.CPUPercent() + procStats = append(procStats, fmt.Sprintf("%-20s %.2f%%", name, cpu)) + } + + // Sort processes by CPU usage + sort.Slice(procStats, func(i, j int) bool { + return procStats[i] > procStats[j] + }) + + // Display top 5 processes + topProcs := "" + for i := 0; i < 5 && i < len(procStats); i++ { + topProcs += procStats[i] + "\n" + } + + // Update display + stats := fmt.Sprintf( + "[yellow]CPU Usage:[white] %.2f%%\n[yellow]Memory Usage:[white] %.2f%% of %.2fGB\n\n[yellow]Top Processes:\n[white]%s", + cpuPercent[0], + memStats.UsedPercent, + float64(memStats.Total)/1e9, + topProcs, + ) + + app.QueueUpdateDraw(func() { + textView.SetText(stats) + }) + time.Sleep(1 * time.Second) + } + }() + + if err := app.SetRoot(textView, true).Run(); err != nil { + return err + } + return nil +} diff --git a/go.mod b/go.mod index 5238f85..55e289e 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,15 @@ -module github.com/JoshuaGabriel/mytop +module github.com/JoshuaGabriel/goup go 1.20 require ( github.com/rivo/tview v0.0.0-20241103174730-c76f7879f592 github.com/shirou/gopsutil/v3 v3.24.5 + github.com/urfave/cli/v2 v2.27.5 ) require ( + github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/gdamore/encoding v1.0.0 // indirect github.com/gdamore/tcell/v2 v2.7.1 // indirect github.com/go-ole/go-ole v1.2.6 // indirect @@ -16,9 +18,11 @@ require ( github.com/mattn/go-runewidth v0.0.15 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/rivo/uniseg v0.4.7 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/tklauser/go-sysconf v0.3.14 // indirect github.com/tklauser/numcpus v0.8.0 // indirect + github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect golang.org/x/sys v0.20.0 // indirect golang.org/x/term v0.17.0 // indirect diff --git a/go.sum b/go.sum index dcea3ca..68a934d 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= +github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= @@ -22,6 +24,8 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -32,6 +36,10 @@ github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZ github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY= github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY= github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE= +github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= +github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= diff --git a/main.go b/main.go index d9af4e6..13d89da 100644 --- a/main.go +++ b/main.go @@ -1,63 +1,12 @@ package main import ( - "fmt" - "sort" - "time" - - "github.com/rivo/tview" - "github.com/shirou/gopsutil/v3/cpu" - "github.com/shirou/gopsutil/v3/mem" - "github.com/shirou/gopsutil/v3/process" + "github.com/JoshuaGabriel/goup/cmd" + "os" ) func main() { - app := tview.NewApplication() - textView := tview.NewTextView().SetDynamicColors(true) - - go func() { - for { - // Fetch metrics - cpuPercent, _ := cpu.Percent(0, false) - memStats, _ := mem.VirtualMemory() - - // Fetch processes - procs, _ := process.Processes() - var procStats []string - for _, p := range procs { - name, _ := p.Name() - cpu, _ := p.CPUPercent() - procStats = append(procStats, fmt.Sprintf("%-20s %.2f%%", name, cpu)) - } - - // Sort processes by CPU usage - sort.Slice(procStats, func(i, j int) bool { - return procStats[i] > procStats[j] - }) - - // Display top 5 processes - topProcs := "" - for i := 0; i < 5 && i < len(procStats); i++ { - topProcs += procStats[i] + "\n" - } - - // Update display - stats := fmt.Sprintf( - "[yellow]CPU Usage:[white] %.2f%%\n[yellow]Memory Usage:[white] %.2f%% of %.2fGB\n\n[yellow]Top Processes:\n[white]%s", - cpuPercent[0], - memStats.UsedPercent, - float64(memStats.Total)/1e9, - topProcs, - ) - - app.QueueUpdateDraw(func() { - textView.SetText(stats) - }) - time.Sleep(1 * time.Second) - } - }() - - if err := app.SetRoot(textView, true).Run(); err != nil { - panic(err) + if err := cmd.Main(os.Args); err != nil { + os.Exit(1) } }