Skip to main content

Overview

The Avg function retrieves the system load averages for the past 1, 5, and 15 minutes. Load average is a critical metric for understanding system utilization and performance.

Functions

func Avg() (*AvgStat, error)
func AvgWithContext(ctx context.Context) (*AvgStat, error)

Parameters

ctx
context.Context
Context for cancellation and timeout control

Returns

Returns a pointer to AvgStat containing the load averages, or an error if the operation fails.

AvgStat Structure

The AvgStat struct contains the system load averages over three time periods.
type AvgStat struct {
    Load1  float64 `json:"load1"`  // 1-minute load average
    Load5  float64 `json:"load5"`  // 5-minute load average
    Load15 float64 `json:"load15"` // 15-minute load average
}

Fields

Load1
float64
The load average over the last 1 minute. Represents recent system load.
Load5
float64
The load average over the last 5 minutes. Represents short-term trends.
Load15
float64
The load average over the last 15 minutes. Represents long-term trends.

Understanding Load Average

Load average represents the average number of processes that are:
  • Currently running on the CPU, or
  • Waiting to run (in the run queue)

Interpreting Load Values

Underutilized

Load < CPU coresSystem has spare capacity

Fully Utilized

Load ≈ CPU coresSystem is working efficiently

Overloaded

Load > CPU coresProcesses waiting for CPU time

Example Interpretations

On a 4-core system:
  • Load of 2.0 = 50% utilization (2/4 cores busy)
  • Load of 4.0 = 100% utilization (all cores busy)
  • Load of 8.0 = 200% utilization (processes waiting)

Load Patterns

  • Rising load (Load1 > Load5 > Load15): System getting busier
  • Falling load (Load1 < Load5 < Load15): System load decreasing
  • Stable load (Load1 ≈ Load5 ≈ Load15): Consistent workload

Usage Examples

Basic Usage

package main

import (
    "fmt"
    "github.com/shirou/gopsutil/v4/load"
)

func main() {
    loadAvg, err := load.Avg()
    if err != nil {
        panic(err)
    }
    
    fmt.Printf("Load Average:\n")
    fmt.Printf("  1 min:  %.2f\n", loadAvg.Load1)
    fmt.Printf("  5 min:  %.2f\n", loadAvg.Load5)
    fmt.Printf("  15 min: %.2f\n", loadAvg.Load15)
}

Calculate System Utilization

package main

import (
    "fmt"
    "github.com/shirou/gopsutil/v4/cpu"
    "github.com/shirou/gopsutil/v4/load"
)

func main() {
    // Get number of CPU cores
    cpuCount, err := cpu.Counts(true)
    if err != nil {
        panic(err)
    }
    
    loadAvg, err := load.Avg()
    if err != nil {
        panic(err)
    }
    
    // Calculate utilization percentage
    util1 := (loadAvg.Load1 / float64(cpuCount)) * 100
    util5 := (loadAvg.Load5 / float64(cpuCount)) * 100
    util15 := (loadAvg.Load15 / float64(cpuCount)) * 100
    
    fmt.Printf("System: %d CPU cores\n\n", cpuCount)
    fmt.Printf("Load Average | Utilization\n")
    fmt.Printf("------------------------\n")
    fmt.Printf("  1 min:  %.2f | %.1f%%\n", loadAvg.Load1, util1)
    fmt.Printf("  5 min:  %.2f | %.1f%%\n", loadAvg.Load5, util5)
    fmt.Printf("  15 min: %.2f | %.1f%%\n", loadAvg.Load15, util15)
}

Load Trend Analysis

package main

import (
    "fmt"
    "github.com/shirou/gopsutil/v4/load"
)

func main() {
    loadAvg, err := load.Avg()
    if err != nil {
        panic(err)
    }
    
    fmt.Printf("Load: %.2f, %.2f, %.2f\n", 
        loadAvg.Load1, loadAvg.Load5, loadAvg.Load15)
    
    // Analyze trend
    if loadAvg.Load1 > loadAvg.Load5 && loadAvg.Load5 > loadAvg.Load15 {
        fmt.Println("📈 Trend: Load is increasing")
    } else if loadAvg.Load1 < loadAvg.Load5 && loadAvg.Load5 < loadAvg.Load15 {
        fmt.Println("📉 Trend: Load is decreasing")
    } else {
        fmt.Println("📊 Trend: Load is stable")
    }
}

Alert on High Load

package main

import (
    "fmt"
    "github.com/shirou/gopsutil/v4/cpu"
    "github.com/shirou/gopsutil/v4/load"
)

func checkLoad() {
    cpuCount, _ := cpu.Counts(true)
    loadAvg, err := load.Avg()
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    threshold := float64(cpuCount) * 0.8 // 80% of CPU capacity
    
    if loadAvg.Load1 > threshold {
        utilization := (loadAvg.Load1 / float64(cpuCount)) * 100
        fmt.Printf("⚠️  HIGH LOAD ALERT!\n")
        fmt.Printf("   Load: %.2f (%.1f%% of %d cores)\n", 
            loadAvg.Load1, utilization, cpuCount)
    } else {
        fmt.Printf("✓ Load normal: %.2f\n", loadAvg.Load1)
    }
}

func main() {
    checkLoad()
}

Continuous Monitoring

package main

import (
    "fmt"
    "time"
    "github.com/shirou/gopsutil/v4/load"
)

func main() {
    fmt.Println("Load Average Monitor (Ctrl+C to exit)")
    fmt.Println("Time     | 1min  | 5min  | 15min")
    fmt.Println("---------|-------|-------|-------")
    
    ticker := time.NewTicker(5 * time.Second)
    defer ticker.Stop()
    
    for range ticker.C {
        loadAvg, err := load.Avg()
        if err != nil {
            fmt.Println("Error:", err)
            continue
        }
        
        fmt.Printf("%s | %.2f  | %.2f  | %.2f\n",
            time.Now().Format("15:04:05"),
            loadAvg.Load1,
            loadAvg.Load5,
            loadAvg.Load15)
    }
}

Using Context

package main

import (
    "context"
    "fmt"
    "time"
    "github.com/shirou/gopsutil/v4/load"
)

func main() {
    // Create context with timeout
    ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
    defer cancel()
    
    loadAvg, err := load.AvgWithContext(ctx)
    if err != nil {
        if ctx.Err() == context.DeadlineExceeded {
            fmt.Println("Operation timed out")
        } else {
            fmt.Println("Error:", err)
        }
        return
    }
    
    fmt.Printf("Load: %.2f, %.2f, %.2f\n", 
        loadAvg.Load1, loadAvg.Load5, loadAvg.Load15)
}

JSON Output

package main

import (
    "encoding/json"
    "fmt"
    "github.com/shirou/gopsutil/v4/load"
)

func main() {
    loadAvg, err := load.Avg()
    if err != nil {
        panic(err)
    }
    
    // Convert to JSON
    jsonData, err := json.MarshalIndent(loadAvg, "", "  ")
    if err != nil {
        panic(err)
    }
    
    fmt.Println(string(jsonData))
}
Output:
{
  "load1": 2.45,
  "load5": 2.12,
  "load15": 1.89
}

Compare with Thresholds

package main

import (
    "fmt"
    "github.com/shirou/gopsutil/v4/cpu"
    "github.com/shirou/gopsutil/v4/load"
)

type LoadStatus int

const (
    LoadNormal LoadStatus = iota
    LoadWarning
    LoadCritical
)

func getLoadStatus(loadAvg *load.AvgStat, cpuCount int) LoadStatus {
    threshold := float64(cpuCount)
    
    if loadAvg.Load1 > threshold*1.5 {
        return LoadCritical
    } else if loadAvg.Load1 > threshold*0.8 {
        return LoadWarning
    }
    return LoadNormal
}

func main() {
    cpuCount, _ := cpu.Counts(true)
    loadAvg, err := load.Avg()
    if err != nil {
        panic(err)
    }
    
    status := getLoadStatus(loadAvg, cpuCount)
    
    fmt.Printf("CPU Cores: %d\n", cpuCount)
    fmt.Printf("Load: %.2f\n", loadAvg.Load1)
    
    switch status {
    case LoadNormal:
        fmt.Println("Status: ✓ Normal")
    case LoadWarning:
        fmt.Println("Status: ⚠ Warning - High load")
    case LoadCritical:
        fmt.Println("Status: ✗ Critical - System overloaded")
    }
}

Platform-Specific Implementation

Linux

On Linux, the function attempts two methods:
  1. File-based (/proc/loadavg): Reads load averages from the proc filesystem
  2. Syscall fallback (sysinfo()): Uses the system call if file reading fails
// Example /proc/loadavg content:
// 1.23 2.45 3.67 2/567 12345

Other Platforms

  • macOS/BSD: Uses sysinfo() or equivalent syscall
  • Windows: Limited support, may use alternative metrics
  • Solaris/AIX: Platform-specific implementations

Performance Notes

  • Reading load average is a very lightweight operation
  • Safe to call frequently (e.g., every few seconds)
  • No significant system overhead
  • Data is maintained by the kernel

Error Handling

Common errors:
  • Permission issues (rare, as load average is world-readable)
  • Missing /proc/loadavg file on non-standard systems
  • Syscall failures
loadAvg, err := load.Avg()
if err != nil {
    fmt.Printf("Failed to get load average: %v\n", err)
    // Handle error appropriately
    return
}

Common Use Cases

Track system load over time to identify performance trends and patterns.
Use load metrics to trigger automatic resource scaling in cloud environments.
Set up alerts when load exceeds predefined thresholds.
Analyze load patterns to plan hardware and resource requirements.
Make routing decisions based on current system load.
Identify performance issues by correlating load spikes with other metrics.

Best Practices

Always consider CPU count: Compare load average to the number of CPU cores for meaningful interpretation.
Load alone isn’t enough: Combine with CPU usage, I/O metrics, and memory stats for complete picture.
Watch all three values: Use Load1 for immediate issues, Load5 for short-term trends, and Load15 for long-term patterns.

See Also

Build docs developers (and LLMs) love