Skip to content

Instantly share code, notes, and snippets.

@bruskiza
Created May 12, 2025 20:39
Show Gist options
  • Save bruskiza/c3f2455da933efe0d6f5e051f7e4a4a5 to your computer and use it in GitHub Desktop.
Save bruskiza/c3f2455da933efe0d6f5e051f7e4a4a5 to your computer and use it in GitHub Desktop.
Dstat in Golang
package main
import (
"fmt"
"log"
"time"
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/net"
)
func formatBytes(b uint64) string {
const unit = 1024
if b < unit {
return fmt.Sprintf("%d B", b)
}
div, exp := int64(unit), 0
for n := b / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%.1f %ciB", float64(b)/float64(div), "KMGTPE"[exp])
}
func main() {
fmt.Printf("--total-cpu-usage-- -dsk/total- -net/total- ---paging-- ---system--\n")
fmt.Printf("usr sys idl wai stl| read writ| recv send| in out | int csw \n")
prevDiskIO, err := disk.IOCounters("")
if err != nil {
log.Printf("Error getting initial disk IO counters: %v", err)
return
}
prevNetIO, err := net.IOCounters(false)
if err != nil {
log.Printf("Error getting initial network IO counters: %v", err)
return
}
var prevNetRecv uint64
var prevNetSent uint64
if len(prevNetIO) > 0 {
prevNetRecv = prevNetIO[0].BytesRecv
prevNetSent = prevNetIO[0].BytesSent
}
prevCPU, err := cpu.Times(false)
if err != nil {
log.Printf("Error getting initial CPU times: %v", err)
return
}
for i := 0; i < 7; i++ {
currentCPU, err := cpu.Times(false)
if err != nil {
log.Printf("Error getting CPU times: %v", err)
return
}
var usr, sys, idle, wait, steal float64
if len(currentCPU) > 0 && len(prevCPU) > 0 {
delta := currentCPU[0].Total() - prevCPU[0].Total()
if delta > 0 {
usr = (currentCPU[0].User - prevCPU[0].User) / delta * 100
sys = (currentCPU[0].System - prevCPU[0].System) / delta * 100
idle = (currentCPU[0].Idle - prevCPU[0].Idle) / delta * 100
wait = (currentCPU[0].Iowait - prevCPU[0].Iowait) / delta * 100
steal = (currentCPU[0].Steal - prevCPU[0].Steal) / delta * 100
}
}
prevCPU = currentCPU
currentDiskIO, err := disk.IOCounters("")
if err != nil {
log.Printf("Error getting disk IO counters: %v", err)
return
}
var readBytes uint64
var writeBytes uint64
if currentDiskIO != nil && prevDiskIO != nil {
for _, currentIO := range currentDiskIO {
for _, prevIO := range prevDiskIO {
if currentIO.SerialNumber == prevIO.SerialNumber {
readBytes += currentIO.ReadBytes - prevIO.ReadBytes
writeBytes += currentIO.WriteBytes - prevIO.WriteBytes
break
}
}
}
}
prevDiskIO = currentDiskIO
currentNetIO, err := net.IOCounters(false)
if err != nil {
log.Printf("Error getting network IO counters: %v", err)
return
}
var recvBytes uint64
var sentBytes uint64
if len(currentNetIO) > 0 {
recvBytes = currentNetIO[0].BytesRecv - prevNetRecv
sentBytes = currentNetIO[0].BytesSent - prevNetSent
prevNetRecv = currentNetIO[0].BytesRecv
prevNetSent = currentNetIO[0].BytesSent
}
// Paging and system stats are more complex and might require different psutil functions
// For simplicity, we'll output 0 for paging and placeholders for system stats
fmt.Printf("%3.0f %3.0f %3.0f %3.0f %3.0f|%5s %5s|%5s %5s|%4d %4d | %3d %4d \n",
usr, sys, idle, wait, steal,
formatBytes(readBytes), formatBytes(writeBytes),
formatBytes(recvBytes), formatBytes(sentBytes),
0, 0, // Paging in/out (requires more specific metrics)
0, 0, // Interrupts and context switches (requires more specific metrics)
)
time.Sleep(1 * time.Second)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment