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. 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)
    }
}

Comments