Skip to content

Go Runtime Metrics and Go Version Mapping

This page helps you to quickly query when a metric of runtime/metrics was supported. For example, you can query the table to know metrics /gc/gogc:percent was added in go1.21.0

Runtime Metrics Table

Metric Name Initial Supported Go Version
/cgo/go-to-c-calls:calls go1.19
/cpu/classes/gc/mark/assist:cpu-seconds go1.20
/cpu/classes/gc/mark/dedicated:cpu-seconds go1.20
/cpu/classes/gc/mark/idle:cpu-seconds go1.20
/cpu/classes/gc/pause:cpu-seconds go1.20
/cpu/classes/gc/total:cpu-seconds go1.20
/cpu/classes/idle:cpu-seconds go1.20
/cpu/classes/scavenge/assist:cpu-seconds go1.20
/cpu/classes/scavenge/background:cpu-seconds go1.20
/cpu/classes/scavenge/total:cpu-seconds go1.20
/cpu/classes/total:cpu-seconds go1.20
/cpu/classes/user:cpu-seconds go1.20
/gc/cycles/automatic:gc-cycles go1.16
/gc/cycles/forced:gc-cycles go1.16
/gc/cycles/total:gc-cycles go1.16
/gc/gogc:percent go1.21.0
/gc/gomemlimit:bytes go1.21.0
/gc/heap/allocs-by-size:bytes go1.16
/gc/heap/allocs:bytes go1.17
/gc/heap/allocs:objects go1.17
/gc/heap/frees-by-size:bytes go1.16
/gc/heap/frees:bytes go1.17
/gc/heap/frees:objects go1.17
/gc/heap/goal:bytes go1.16
/gc/heap/live:bytes go1.21.0
/gc/heap/objects:objects go1.16
/gc/heap/tiny/allocs:objects go1.17
/gc/limiter/last-enabled:gc-cycle go1.19
/gc/pauses:seconds go1.16
/gc/scan/globals:bytes go1.21.0
/gc/scan/heap:bytes go1.21.0
/gc/scan/stack:bytes go1.21.0
/gc/scan/total:bytes go1.21.0
/gc/stack/starting-size:bytes go1.19
/godebug/non-default-behavior/allowmultiplevcs:events go1.25.0
/godebug/non-default-behavior/asynctimerchan:events go1.23.0
/godebug/non-default-behavior/containermaxprocs:events go1.25.0
/godebug/non-default-behavior/embedfollowsymlinks:events go1.25.0
/godebug/non-default-behavior/execerrdot:events go1.21.0
/godebug/non-default-behavior/gocachehash:events go1.21.0
/godebug/non-default-behavior/gocachetest:events go1.21.0
/godebug/non-default-behavior/gocacheverify:events go1.21.0
/godebug/non-default-behavior/gotestjsonbuildtext:events go1.24.0
/godebug/non-default-behavior/gotypesalias:events go1.22.0
/godebug/non-default-behavior/http2client:events go1.21.0
/godebug/non-default-behavior/http2server:events go1.21.0
/godebug/non-default-behavior/httplaxcontentlength:events go1.22.0
/godebug/non-default-behavior/httpmuxgo121:events go1.22.0
/godebug/non-default-behavior/httpservecontentkeepheaders:events go1.23.0
/godebug/non-default-behavior/installgoroot:events go1.21.0
/godebug/non-default-behavior/jstmpllitinterp:events go1.21.0
/godebug/non-default-behavior/multipartmaxheaders:events go1.21.0
/godebug/non-default-behavior/multipartmaxparts:events go1.21.0
/godebug/non-default-behavior/multipathtcp:events go1.21.0
/godebug/non-default-behavior/netedns0:events go1.23.0
/godebug/non-default-behavior/panicnil:events go1.21.0
/godebug/non-default-behavior/randautoseed:events go1.21.0
/godebug/non-default-behavior/randseednop:events go1.24.0
/godebug/non-default-behavior/rsa1024min:events go1.24.0
/godebug/non-default-behavior/tarinsecurepath:events go1.21.0
/godebug/non-default-behavior/tls10server:events go1.22.0
/godebug/non-default-behavior/tls3des:events go1.23.0
/godebug/non-default-behavior/tlsmaxrsasize:events go1.22.0
/godebug/non-default-behavior/tlsrsakex:events go1.22.0
/godebug/non-default-behavior/tlssha1:events go1.25.0
/godebug/non-default-behavior/tlsunsafeekm:events go1.22.0
/godebug/non-default-behavior/updatemaxprocs:events go1.25.0
/godebug/non-default-behavior/winreadlinkvolume:events go1.23.0
/godebug/non-default-behavior/winsymlink:events go1.23.0
/godebug/non-default-behavior/x509keypairleaf:events go1.23.0
/godebug/non-default-behavior/x509negativeserial:events go1.23.0
/godebug/non-default-behavior/x509rsacrt:events go1.24.0
/godebug/non-default-behavior/x509sha1:events go1.21.0
/godebug/non-default-behavior/x509sha256skid:events go1.25.0
/godebug/non-default-behavior/x509usefallbackroots:events go1.21.0
/godebug/non-default-behavior/x509usepolicies:events go1.22.0
/godebug/non-default-behavior/zipinsecurepath:events go1.21.0
/memory/classes/heap/free:bytes go1.16
/memory/classes/heap/objects:bytes go1.16
/memory/classes/heap/released:bytes go1.16
/memory/classes/heap/stacks:bytes go1.16
/memory/classes/heap/unused:bytes go1.16
/memory/classes/metadata/mcache/free:bytes go1.16
/memory/classes/metadata/mcache/inuse:bytes go1.16
/memory/classes/metadata/mspan/free:bytes go1.16
/memory/classes/metadata/mspan/inuse:bytes go1.16
/memory/classes/metadata/other:bytes go1.16
/memory/classes/os-stacks:bytes go1.16
/memory/classes/other:bytes go1.16
/memory/classes/profiling/buckets:bytes go1.16
/memory/classes/total:bytes go1.16
/sched/gomaxprocs:threads go1.19
/sched/goroutines:goroutines go1.16
/sched/latencies:seconds go1.17
/sched/pauses/stopping/gc:seconds go1.22.0
/sched/pauses/stopping/other:seconds go1.22.0
/sched/pauses/total/gc:seconds go1.22.0
/sched/pauses/total/other:seconds go1.22.0
/sync/mutex/wait/total:seconds go1.20

Raw Json from go1.16 to go1.25.0

runtime/metrics was added in go1.16 so I start the go version here. Below is the json representation for the markdown table below for you to reference, you can also view the raw json data for each go version so you can customize based on your usage.

{
  "/cgo/go-to-c-calls:calls": "go1.19",
  "/cpu/classes/gc/mark/assist:cpu-seconds": "go1.20",
  "/cpu/classes/gc/mark/dedicated:cpu-seconds": "go1.20",
  "/cpu/classes/gc/mark/idle:cpu-seconds": "go1.20",
  "/cpu/classes/gc/pause:cpu-seconds": "go1.20",
  "/cpu/classes/gc/total:cpu-seconds": "go1.20",
  "/cpu/classes/idle:cpu-seconds": "go1.20",
  "/cpu/classes/scavenge/assist:cpu-seconds": "go1.20",
  "/cpu/classes/scavenge/background:cpu-seconds": "go1.20",
  "/cpu/classes/scavenge/total:cpu-seconds": "go1.20",
  "/cpu/classes/total:cpu-seconds": "go1.20",
  "/cpu/classes/user:cpu-seconds": "go1.20",
  "/gc/cycles/automatic:gc-cycles": "go1.16",
  "/gc/cycles/forced:gc-cycles": "go1.16",
  "/gc/cycles/total:gc-cycles": "go1.16",
  "/gc/gogc:percent": "go1.21.0",
  "/gc/gomemlimit:bytes": "go1.21.0",
  "/gc/heap/allocs-by-size:bytes": "go1.16",
  "/gc/heap/allocs:bytes": "go1.17",
  "/gc/heap/allocs:objects": "go1.17",
  "/gc/heap/frees-by-size:bytes": "go1.16",
  "/gc/heap/frees:bytes": "go1.17",
  "/gc/heap/frees:objects": "go1.17",
  "/gc/heap/goal:bytes": "go1.16",
  "/gc/heap/live:bytes": "go1.21.0",
  "/gc/heap/objects:objects": "go1.16",
  "/gc/heap/tiny/allocs:objects": "go1.17",
  "/gc/limiter/last-enabled:gc-cycle": "go1.19",
  "/gc/pauses:seconds": "go1.16",
  "/gc/scan/globals:bytes": "go1.21.0",
  "/gc/scan/heap:bytes": "go1.21.0",
  "/gc/scan/stack:bytes": "go1.21.0",
  "/gc/scan/total:bytes": "go1.21.0",
  "/gc/stack/starting-size:bytes": "go1.19",
  "/godebug/non-default-behavior/allowmultiplevcs:events": "go1.25.0",
  "/godebug/non-default-behavior/asynctimerchan:events": "go1.23.0",
  "/godebug/non-default-behavior/containermaxprocs:events": "go1.25.0",
  "/godebug/non-default-behavior/embedfollowsymlinks:events": "go1.25.0",
  "/godebug/non-default-behavior/execerrdot:events": "go1.21.0",
  "/godebug/non-default-behavior/gocachehash:events": "go1.21.0",
  "/godebug/non-default-behavior/gocachetest:events": "go1.21.0",
  "/godebug/non-default-behavior/gocacheverify:events": "go1.21.0",
  "/godebug/non-default-behavior/gotestjsonbuildtext:events": "go1.24.0",
  "/godebug/non-default-behavior/gotypesalias:events": "go1.22.0",
  "/godebug/non-default-behavior/http2client:events": "go1.21.0",
  "/godebug/non-default-behavior/http2server:events": "go1.21.0",
  "/godebug/non-default-behavior/httplaxcontentlength:events": "go1.22.0",
  "/godebug/non-default-behavior/httpmuxgo121:events": "go1.22.0",
  "/godebug/non-default-behavior/httpservecontentkeepheaders:events": "go1.23.0",
  "/godebug/non-default-behavior/installgoroot:events": "go1.21.0",
  "/godebug/non-default-behavior/jstmpllitinterp:events": "go1.21.0",
  "/godebug/non-default-behavior/multipartmaxheaders:events": "go1.21.0",
  "/godebug/non-default-behavior/multipartmaxparts:events": "go1.21.0",
  "/godebug/non-default-behavior/multipathtcp:events": "go1.21.0",
  "/godebug/non-default-behavior/netedns0:events": "go1.23.0",
  "/godebug/non-default-behavior/panicnil:events": "go1.21.0",
  "/godebug/non-default-behavior/randautoseed:events": "go1.21.0",
  "/godebug/non-default-behavior/randseednop:events": "go1.24.0",
  "/godebug/non-default-behavior/rsa1024min:events": "go1.24.0",
  "/godebug/non-default-behavior/tarinsecurepath:events": "go1.21.0",
  "/godebug/non-default-behavior/tls10server:events": "go1.22.0",
  "/godebug/non-default-behavior/tls3des:events": "go1.23.0",
  "/godebug/non-default-behavior/tlsmaxrsasize:events": "go1.22.0",
  "/godebug/non-default-behavior/tlsrsakex:events": "go1.22.0",
  "/godebug/non-default-behavior/tlssha1:events": "go1.25.0",
  "/godebug/non-default-behavior/tlsunsafeekm:events": "go1.22.0",
  "/godebug/non-default-behavior/updatemaxprocs:events": "go1.25.0",
  "/godebug/non-default-behavior/winreadlinkvolume:events": "go1.23.0",
  "/godebug/non-default-behavior/winsymlink:events": "go1.23.0",
  "/godebug/non-default-behavior/x509keypairleaf:events": "go1.23.0",
  "/godebug/non-default-behavior/x509negativeserial:events": "go1.23.0",
  "/godebug/non-default-behavior/x509rsacrt:events": "go1.24.0",
  "/godebug/non-default-behavior/x509sha1:events": "go1.21.0",
  "/godebug/non-default-behavior/x509sha256skid:events": "go1.25.0",
  "/godebug/non-default-behavior/x509usefallbackroots:events": "go1.21.0",
  "/godebug/non-default-behavior/x509usepolicies:events": "go1.22.0",
  "/godebug/non-default-behavior/zipinsecurepath:events": "go1.21.0",
  "/memory/classes/heap/free:bytes": "go1.16",
  "/memory/classes/heap/objects:bytes": "go1.16",
  "/memory/classes/heap/released:bytes": "go1.16",
  "/memory/classes/heap/stacks:bytes": "go1.16",
  "/memory/classes/heap/unused:bytes": "go1.16",
  "/memory/classes/metadata/mcache/free:bytes": "go1.16",
  "/memory/classes/metadata/mcache/inuse:bytes": "go1.16",
  "/memory/classes/metadata/mspan/free:bytes": "go1.16",
  "/memory/classes/metadata/mspan/inuse:bytes": "go1.16",
  "/memory/classes/metadata/other:bytes": "go1.16",
  "/memory/classes/os-stacks:bytes": "go1.16",
  "/memory/classes/other:bytes": "go1.16",
  "/memory/classes/profiling/buckets:bytes": "go1.16",
  "/memory/classes/total:bytes": "go1.16",
  "/sched/gomaxprocs:threads": "go1.19",
  "/sched/goroutines:goroutines": "go1.16",
  "/sched/latencies:seconds": "go1.17",
  "/sched/pauses/stopping/gc:seconds": "go1.22.0",
  "/sched/pauses/stopping/other:seconds": "go1.22.0",
  "/sched/pauses/total/gc:seconds": "go1.22.0",
  "/sched/pauses/total/other:seconds": "go1.22.0",
  "/sync/mutex/wait/total:seconds": "go1.20"
}

Method

This table is generated, and you can refer to the code here. It requires you to run the code multiple times with different go versions as runtime/metrics resides inside golang source code bundled with go command. Here is the go version lists and the shell to trigger all go versions.

values=(
    "go1.25.0" 
    "go1.24.0"
    "go1.23.0"
    "go1.22.0"
    "go1.21.0"
    "go1.20"
    "go1.19"
    "go1.18"
    "go1.17"
    "go1.16"
)

for value in "${values[@]}"; do
  echo "Processing: $value"
  # find a go version managed tool to do so.
  xxx go run main.go --go="$value"
  # Optional: handle errors or output
  if [ $? -eq 0 ]; then
    echo "Command succeeded for $value"
  else
    echo "Command failed for $value"
  fi
done
Go Source Code to Retrieve Runtime Metrics
package main

import (
    "encoding/json"
    "io"
    "os"
    "runtime"
    "runtime/metrics"
)

func main() {
    getAllMetrics()
}

func getAllMetrics() {
    descriptions := metrics.All()
    gover := runtime.Version()
    metrics := make(map[string]metrics.Description)
    for _, desc := range descriptions {
        metrics[desc.Name] = desc
    }

    file, err := os.OpenFile("all.json", os.O_RDWR|os.O_CREATE, 0644)
    if err != nil {
        panic(err)
    }
    defer file.Close()
    data, err := io.ReadAll(file)
    if err != nil {
        panic(err)
    }
    if len(data) == 0 {
        data = []byte("{}")
    }
    var result map[string]interface{}
    err = json.Unmarshal(data, &result)
    if err != nil {
        panic(err)
    }
    result[gover] = metrics

    data, err = json.Marshal(result)
    if err != nil {
        panic(err)
    }
    err = os.WriteFile("all.json", data, 0644)
    if err != nil {
        panic(err)
    }
}
Parse Result of All Go Runtime Metrics
func format() {
    var m map[string]map[string]metrics.Description
    data, err := os.ReadFile("all.json")
    if err != nil {
        panic(err)
    }
    err = json.Unmarshal(data, &m)
    if err != nil {
        panic(err)
    }

    metricsVersionMap := make(map[string]string)
    for gover, metrics := range m {
        for name := range metrics {
            oldVer, exists := metricsVersionMap[name]
            if !exists {
                metricsVersionMap[name] = gover
                continue
            }
            // fill the earlier version
            if version.Compare(gover, oldVer) < 0 {
                metricsVersionMap[name] = gover
            }
        }
    }

    output, err := json.Marshal(metricsVersionMap)
    if err != nil {
        panic(err)
    }
    err = os.WriteFile("metrics_version.json", output, 0644)
    if err != nil {
        panic(err)
    }

    type tuple struct {
        Name    string `json:"name"`
        Version string `json:"version"`
    }
    var metricsArray []tuple
    for name, ver := range metricsVersionMap {
        metricsArray = append(metricsArray, tuple{
            Name:    name,
            Version: ver,
        })
    }

    sort.Slice(metricsArray, func(i, j int) bool {
        return metricsArray[i].Name < metricsArray[j].Name
    })

    var buf bytes.Buffer
    buf.WriteString("| Metric Name      | Initial Supported Go Version|\n|:-----------------|:----------------|\n")
    for _, t := range metricsArray {
        buf.WriteString("| " + t.Name + " | " + t.Version + " |\n")
    }
    err = os.WriteFile("METRICS_VERSION.md", buf.Bytes(), 0644)
    if err != nil {
        panic(err)
    }
}