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