Skip to content

Commit

Permalink
Add types for Go runtime metrics (#322)
Browse files Browse the repository at this point in the history
* Adds realtime metrics type
* Adds profile type
* Make correct maps when merging
  • Loading branch information
klauspost authored Dec 18, 2024
1 parent 84f940d commit 79a85c8
Show file tree
Hide file tree
Showing 6 changed files with 1,263 additions and 121 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
go-version: [1.22.x]
go-version: [1.23.x]
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/vulncheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
go-version: [ 1.22.7 ]
go-version: [ 1.23.x ]
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v4
Expand Down
70 changes: 69 additions & 1 deletion metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"io"
"net/http"
"net/url"
"runtime/metrics"
"sort"
"strconv"
"strings"
Expand All @@ -39,7 +40,7 @@ import (

//msgp:clearomitted
//msgp:tag json
//go:generate msgp
//go:generate msgp -unexported

// MetricType is a bitfield representation of different metric types.
type MetricType uint32
Expand All @@ -57,6 +58,7 @@ const (
MetricsMem
MetricsCPU
MetricsRPC
MetricsRuntime

// MetricsAll must be last.
// Enables all metrics.
Expand Down Expand Up @@ -162,6 +164,7 @@ type Metrics struct {
Mem *MemMetrics `json:"mem,omitempty"`
CPU *CPUMetrics `json:"cpu,omitempty"`
RPC *RPCMetrics `json:"rpc,omitempty"`
Go *RuntimeMetrics `json:"go,omitempty"`
}

// Merge other into r.
Expand Down Expand Up @@ -201,6 +204,10 @@ func (r *Metrics) Merge(other *Metrics) {
r.RPC = &RPCMetrics{}
}
r.RPC.Merge(other.RPC)
if r.Go == nil && other.Go != nil {
r.Go = &RuntimeMetrics{}
}
r.Go.Merge(other.Go)
}

// Merge will merge other into r.
Expand Down Expand Up @@ -756,3 +763,64 @@ func (m *RPCMetrics) Merge(other *RPCMetrics) {
m.ByCaller[k] = existing
}
}

//msgp:replace metrics.Float64Histogram with:localF64H

// local copy of localF64H, can be casted to/from metrics.Float64Histogram
type localF64H struct {
Counts []uint64 `json:"counts,omitempty"`
Buckets []float64 `json:"buckets,omitempty"`
}

// RuntimeMetrics contains metrics for the go runtime.
// See more at https://pkg.go.dev/runtime/metrics
type RuntimeMetrics struct {
// UintMetrics contains KindUint64 values
UintMetrics map[string]uint64 `json:"uintMetrics,omitempty"`

// FloatMetrics contains KindFloat64 values
FloatMetrics map[string]float64 `json:"floatMetrics,omitempty"`

// HistMetrics contains KindFloat64Histogram values
HistMetrics map[string]metrics.Float64Histogram `json:"histMetrics,omitempty"`

// N tracks the number of merged entries.
N int `json:"n"`
}

// Merge other into 'm'.
func (m *RuntimeMetrics) Merge(other *RuntimeMetrics) {
if m == nil || other == nil {
return
}
if m.UintMetrics == nil {
m.UintMetrics = make(map[string]uint64, len(other.UintMetrics))
}
if m.FloatMetrics == nil {
m.FloatMetrics = make(map[string]float64, len(other.FloatMetrics))
}
if m.HistMetrics == nil {
m.HistMetrics = make(map[string]metrics.Float64Histogram, len(other.HistMetrics))
}
for k, v := range other.UintMetrics {
m.UintMetrics[k] += v
}
for k, v := range other.FloatMetrics {
m.FloatMetrics[k] += v
}
for k, v := range other.HistMetrics {
existing := m.HistMetrics[k]
if len(existing.Buckets) == 0 {
m.HistMetrics[k] = v
continue
}
// TODO: Technically, I guess we may have differing buckets,
// but they should be the same for the runtime.
if len(existing.Buckets) == len(v.Buckets) {
for i, count := range v.Counts {
existing.Counts[i] += count
}
}
}
m.N += other.N
}
Loading

0 comments on commit 79a85c8

Please sign in to comment.