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