mirror of
https://github.com/golang/go
synced 2024-11-23 11:30:06 -07:00
runtime/metrics: add package interface
This change creates the runtime/metrics package and adds the initial interface as laid out in the design document. For #37112. Change-Id: I202dcee08ab008dd63bf96f7a4162f5b5f813637 Reviewed-on: https://go-review.googlesource.com/c/go/+/247040 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Michael Knyszek <mknyszek@google.com> Reviewed-by: Michael Pratt <mpratt@google.com>
This commit is contained in:
parent
c02134abb0
commit
2159c26ceb
@ -138,6 +138,9 @@ var depsRules = `
|
||||
MATH
|
||||
< math/rand;
|
||||
|
||||
MATH
|
||||
< runtime/metrics;
|
||||
|
||||
MATH, unicode/utf8
|
||||
< strconv;
|
||||
|
||||
|
52
src/runtime/metrics/description.go
Normal file
52
src/runtime/metrics/description.go
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package metrics
|
||||
|
||||
// Description describes a runtime metric.
|
||||
type Description struct {
|
||||
// Name is the full name of the metric which includes the unit.
|
||||
//
|
||||
// The format of the metric may be described by the following regular expression.
|
||||
//
|
||||
// ^(?P<name>/[^:]+):(?P<unit>[^:*\/]+(?:[*\/][^:*\/]+)*)$
|
||||
//
|
||||
// The format splits the name into two components, separated by a colon: a path which always
|
||||
// starts with a /, and a machine-parseable unit. The name may contain any valid Unicode
|
||||
// codepoint in between / characters, but by convention will try to stick to lowercase
|
||||
// characters and hyphens. An example of such a path might be "/memory/heap/free".
|
||||
//
|
||||
// The unit is by convention a series of lowercase English unit names (singular or plural)
|
||||
// without prefixes delimited by '*' or '/'. The unit names may contain any valid Unicode
|
||||
// codepoint that is not a delimiter.
|
||||
// Examples of units might be "seconds", "bytes", "bytes/second", "cpu-seconds",
|
||||
// "byte*cpu-seconds", and "bytes/second/second".
|
||||
//
|
||||
// A complete name might look like "/memory/heap/free:bytes".
|
||||
Name string
|
||||
|
||||
// Kind is the kind of value for this metric.
|
||||
//
|
||||
// The purpose of this field is to allow users to filter out metrics whose values are
|
||||
// types which their application may not understand.
|
||||
Kind ValueKind
|
||||
|
||||
// Cumulative is whether or not the metric is cumulative. If a cumulative metric is just
|
||||
// a single number, then it increases monotonically. If the metric is a distribution,
|
||||
// then each bucket count increases monotonically.
|
||||
//
|
||||
// This flag thus indicates whether or not it's useful to compute a rate from this value.
|
||||
Cumulative bool
|
||||
|
||||
// StopTheWorld is whether or not the metric requires a stop-the-world
|
||||
// event in order to collect it.
|
||||
StopTheWorld bool
|
||||
}
|
||||
|
||||
var allDesc = []Description{}
|
||||
|
||||
// All returns a slice of containing metric descriptions for all supported metrics.
|
||||
func All() []Description {
|
||||
return allDesc
|
||||
}
|
49
src/runtime/metrics/doc.go
Normal file
49
src/runtime/metrics/doc.go
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package metrics provides a stable interface to access implementation-defined
|
||||
metrics exported by the Go runtime. This package is similar to existing functions
|
||||
like runtime.ReadMemStats and debug.ReadGCStats, but significantly more general.
|
||||
|
||||
The set of metrics defined by this package may evolve as the runtime itself
|
||||
evolves, and also enables variation across Go implementations, whose relevant
|
||||
metric sets may not intersect.
|
||||
|
||||
Interface
|
||||
|
||||
Metrics are designated by a string key, rather than, for example, a field name in
|
||||
a struct. The full list of supported metrics is always available in the slice of
|
||||
Descriptions returned by All. Each Description also includes useful information
|
||||
about the metric, such as how to display it (e.g. gauge vs. counter) and how difficult
|
||||
or disruptive it is to obtain it (e.g. do you need to stop the world?).
|
||||
|
||||
Thus, users of this API are encouraged to sample supported metrics defined by the
|
||||
slice returned by All to remain compatible across Go versions. Of course, situations
|
||||
arise where reading specific metrics is critical. For these cases, users are
|
||||
encouranged to use build tags, and although metrics may be deprecated and removed,
|
||||
users should consider this to be an exceptional and rare event, coinciding with a
|
||||
very large change in a particular Go implementation.
|
||||
|
||||
Each metric key also has a "kind" that describes the format of the metric's value.
|
||||
In the interest of not breaking users of this package, the "kind" for a given metric
|
||||
is guaranteed not to change. If it must change, then a new metric will be introduced
|
||||
with a new key and a new "kind."
|
||||
|
||||
Metric key format
|
||||
|
||||
As mentioned earlier, metric keys are strings. Their format is simple and well-defined,
|
||||
designed to be both human and machine readable. It is split into two components,
|
||||
separated by a colon: a rooted path and a unit. The choice to include the unit in
|
||||
the key is motivated by compatibility: if a metric's unit changes, its semantics likely
|
||||
did also, and a new key should be introduced.
|
||||
|
||||
For more details on the precise definition of the metric key's path and unit formats, see
|
||||
the documentation of the Name field of the Description struct.
|
||||
|
||||
Supported metrics
|
||||
|
||||
TODO(mknyszek): List them here as they're added.
|
||||
*/
|
||||
package metrics
|
30
src/runtime/metrics/histogram.go
Normal file
30
src/runtime/metrics/histogram.go
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package metrics
|
||||
|
||||
// Float64Histogram represents a distribution of float64 values.
|
||||
type Float64Histogram struct {
|
||||
// Counts contains the weights for each histogram bucket. The length of
|
||||
// Counts is equal to the length of Buckets (in the metric description)
|
||||
// plus one to account for the implicit minimum bucket.
|
||||
//
|
||||
// Given N buckets, the following is the mathematical relationship between
|
||||
// Counts and Buckets.
|
||||
// count[0] is the weight of the range (-inf, bucket[0])
|
||||
// count[n] is the weight of the range [bucket[n], bucket[n+1]), for 0 < n < N-1
|
||||
// count[N-1] is the weight of the range [bucket[N-1], inf)
|
||||
Counts []uint64
|
||||
|
||||
// Buckets contains the boundaries between histogram buckets, in increasing order.
|
||||
//
|
||||
// Because this slice contains boundaries, there are len(Buckets)+1 counts:
|
||||
// a count for all values less than the first boundary, a count covering each
|
||||
// [slice[i], slice[i+1]) interval, and a count for all values greater than or
|
||||
// equal to the last boundary.
|
||||
//
|
||||
// For a given metric name, the value of Buckets is guaranteed not to change
|
||||
// between calls until program exit.
|
||||
Buckets []float64
|
||||
}
|
29
src/runtime/metrics/sample.go
Normal file
29
src/runtime/metrics/sample.go
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package metrics
|
||||
|
||||
// Sample captures a single metric sample.
|
||||
type Sample struct {
|
||||
// Name is the name of the metric sampled.
|
||||
//
|
||||
// It must correspond to a name in one of the metric descriptions
|
||||
// returned by Descriptions.
|
||||
Name string
|
||||
|
||||
// Value is the value of the metric sample.
|
||||
Value Value
|
||||
}
|
||||
|
||||
// Read populates each Value field in the given slice of metric samples.
|
||||
//
|
||||
// Desired metrics should be present in the slice with the appropriate name.
|
||||
// The user of this API is encouraged to re-use the same slice between calls.
|
||||
//
|
||||
// Metric values with names not appearing in the value returned by Descriptions
|
||||
// will have the value populated as KindBad to indicate that the name is
|
||||
// unknown.
|
||||
func Read(m []Sample) {
|
||||
panic("unimplemented")
|
||||
}
|
69
src/runtime/metrics/value.go
Normal file
69
src/runtime/metrics/value.go
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"math"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// ValueKind is a tag for a metric Value which indicates its type.
|
||||
type ValueKind int
|
||||
|
||||
const (
|
||||
// KindBad indicates that the Value has no type and should not be used.
|
||||
KindBad ValueKind = iota
|
||||
|
||||
// KindUint64 indicates that the type of the Value is a uint64.
|
||||
KindUint64
|
||||
|
||||
// KindFloat64 indicates that the type of the Value is a float64.
|
||||
KindFloat64
|
||||
|
||||
// KindFloat64Histogram indicates that the type of the Value is a *Float64Histogram.
|
||||
KindFloat64Histogram
|
||||
)
|
||||
|
||||
// Value represents a metric value returned by the runtime.
|
||||
type Value struct {
|
||||
kind ValueKind
|
||||
scalar uint64 // contains scalar values for scalar Kinds.
|
||||
pointer unsafe.Pointer // contains non-scalar values.
|
||||
}
|
||||
|
||||
// Kind returns the a tag representing the kind of value this is.
|
||||
func (v Value) Kind() ValueKind {
|
||||
return v.kind
|
||||
}
|
||||
|
||||
// Uint64 returns the internal uint64 value for the metric.
|
||||
//
|
||||
// If v.Kind() != KindUint64, this method panics.
|
||||
func (v Value) Uint64() uint64 {
|
||||
if v.kind != KindUint64 {
|
||||
panic("called Uint64 on non-uint64 metric value")
|
||||
}
|
||||
return v.scalar
|
||||
}
|
||||
|
||||
// Float64 returns the internal float64 value for the metric.
|
||||
//
|
||||
// If v.Kind() != KindFloat64, this method panics.
|
||||
func (v Value) Float64() float64 {
|
||||
if v.kind != KindFloat64 {
|
||||
panic("called Float64 on non-float64 metric value")
|
||||
}
|
||||
return math.Float64frombits(v.scalar)
|
||||
}
|
||||
|
||||
// Float64Histogram returns the internal *Float64Histogram value for the metric.
|
||||
//
|
||||
// If v.Kind() != KindFloat64Histogram, this method panics.
|
||||
func (v Value) Float64Histogram() *Float64Histogram {
|
||||
if v.kind != KindFloat64Histogram {
|
||||
panic("called Float64 on non-float64 metric value")
|
||||
}
|
||||
return (*Float64Histogram)(v.pointer)
|
||||
}
|
Loading…
Reference in New Issue
Block a user