mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
metrics/*,cmd/geth,core/blockchain: Implemented support for informational metrics
- Created GaugeInfo metrics type for registering informational metrics. - Updated all related metrics modules to support the new GaugeInfo type. - Registered chain/info GaugeInfo with the chain_id value. - Registered geth/info GaugeInfo with system and build parameters. Implements #21783
This commit is contained in:
parent
d4e345c7d4
commit
44a7ea23f5
16 changed files with 409 additions and 1 deletions
|
|
@ -22,6 +22,8 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"unicode"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
|
@ -35,6 +37,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/eth/catalyst"
|
||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||
"github.com/ethereum/go-ethereum/eth/protocols/eth"
|
||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||
"github.com/ethereum/go-ethereum/internal/flags"
|
||||
"github.com/ethereum/go-ethereum/internal/version"
|
||||
|
|
@ -161,6 +164,24 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
|
|||
}
|
||||
applyMetricConfig(ctx, &cfg)
|
||||
|
||||
// Create Info Gauge with geth system and build information
|
||||
gethInfoGauge := metrics.NewRegisteredGaugeInfo("geth/info", nil)
|
||||
protocolVersions := ""
|
||||
for idx, val := range eth.ProtocolVersions {
|
||||
protocolVersions += strconv.FormatUint(uint64(val), 10)
|
||||
if idx < len(eth.ProtocolVersions)-1 {
|
||||
protocolVersions += ","
|
||||
}
|
||||
}
|
||||
gethInfo := metrics.GaugeInfoValue{
|
||||
metrics.NewGaugeInfoEntry("version", params.VersionWithMeta),
|
||||
metrics.NewGaugeInfoEntry("arch", runtime.GOARCH),
|
||||
metrics.NewGaugeInfoEntry("os", runtime.GOOS),
|
||||
metrics.NewGaugeInfoEntry("commit", gitCommit),
|
||||
metrics.NewGaugeInfoEntry("protocol_versions", protocolVersions),
|
||||
}
|
||||
gethInfoGauge.Update(gethInfo)
|
||||
|
||||
return stack, cfg
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ var (
|
|||
headFinalizedBlockGauge = metrics.NewRegisteredGauge("chain/head/finalized", nil)
|
||||
headSafeBlockGauge = metrics.NewRegisteredGauge("chain/head/safe", nil)
|
||||
|
||||
chainInfoGauge = metrics.NewRegisteredGaugeInfo("chain/info", nil)
|
||||
|
||||
accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil)
|
||||
accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil)
|
||||
accountUpdateTimer = metrics.NewRegisteredTimer("chain/account/updates", nil)
|
||||
|
|
@ -322,6 +324,12 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
|||
bc.currentFinalBlock.Store(nil)
|
||||
bc.currentSafeBlock.Store(nil)
|
||||
|
||||
// Update chain info data metrics
|
||||
chainInfoGauge.Update(
|
||||
metrics.GaugeInfoValue{
|
||||
{Key: "chain_id", Val: bc.chainConfig.ChainID.String()},
|
||||
})
|
||||
|
||||
// If Geth is initialized with an external ancient store, re-initialize the
|
||||
// missing chain indexes and chain flags. This procedure can survive crash
|
||||
// and can be resumed in next restart since chain flags are updated in last step.
|
||||
|
|
|
|||
|
|
@ -95,6 +95,20 @@ func (exp *exp) getFloat(name string) *expvar.Float {
|
|||
return v
|
||||
}
|
||||
|
||||
func (exp *exp) getInfo(name string) *expvar.String {
|
||||
var v *expvar.String
|
||||
exp.expvarLock.Lock()
|
||||
p := expvar.Get(name)
|
||||
if p != nil {
|
||||
v = p.(*expvar.String)
|
||||
} else {
|
||||
v = new(expvar.String)
|
||||
expvar.Publish(name, v)
|
||||
}
|
||||
exp.expvarLock.Unlock()
|
||||
return v
|
||||
}
|
||||
|
||||
func (exp *exp) publishCounter(name string, metric metrics.Counter) {
|
||||
v := exp.getInt(name)
|
||||
v.Set(metric.Count())
|
||||
|
|
@ -113,6 +127,10 @@ func (exp *exp) publishGaugeFloat64(name string, metric metrics.GaugeFloat64) {
|
|||
exp.getFloat(name).Set(metric.Value())
|
||||
}
|
||||
|
||||
func (exp *exp) publishGaugeInfo(name string, metric metrics.GaugeInfo) {
|
||||
exp.getInfo(name).Set(fmt.Sprintf("%s", metric.Value()))
|
||||
}
|
||||
|
||||
func (exp *exp) publishHistogram(name string, metric metrics.Histogram) {
|
||||
h := metric.Snapshot()
|
||||
ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
|
||||
|
|
@ -178,6 +196,8 @@ func (exp *exp) syncToExpvar() {
|
|||
exp.publishGauge(name, i)
|
||||
case metrics.GaugeFloat64:
|
||||
exp.publishGaugeFloat64(name, i)
|
||||
case metrics.GaugeInfo:
|
||||
exp.publishGaugeInfo(name, i)
|
||||
case metrics.Histogram:
|
||||
exp.publishHistogram(name, i)
|
||||
case metrics.Meter:
|
||||
|
|
|
|||
175
metrics/gauge_info.go
Normal file
175
metrics/gauge_info.go
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
package metrics
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// GaugeInfos hold a GaugeInfoValue value that can be set arbitrarily.
|
||||
type GaugeInfo interface {
|
||||
Snapshot() GaugeInfo
|
||||
Update(GaugeInfoValue)
|
||||
Value() GaugeInfoValue
|
||||
ValueJsonString() string
|
||||
}
|
||||
|
||||
type GaugeInfoEntry struct {
|
||||
Key string
|
||||
Val string
|
||||
}
|
||||
|
||||
type GaugeInfoValue []GaugeInfoEntry
|
||||
|
||||
func NewGaugeInfoEntry(key string, val string) GaugeInfoEntry {
|
||||
return GaugeInfoEntry{key, val}
|
||||
}
|
||||
|
||||
// GetOrRegisterGaugeInfo returns an existing GaugeInfo or constructs and registers a
|
||||
// new StandardGaugeInfo.
|
||||
func GetOrRegisterGaugeInfo(name string, r Registry) GaugeInfo {
|
||||
if nil == r {
|
||||
r = DefaultRegistry
|
||||
}
|
||||
return r.GetOrRegister(name, NewGaugeInfo()).(GaugeInfo)
|
||||
}
|
||||
|
||||
// NewGaugeInfo constructs a new StandardGaugeInfo.
|
||||
func NewGaugeInfo() GaugeInfo {
|
||||
if !Enabled {
|
||||
return NilGaugeInfo{}
|
||||
}
|
||||
return &StandardGaugeInfo{
|
||||
value: GaugeInfoValue{},
|
||||
}
|
||||
}
|
||||
|
||||
// NewRegisteredGaugeInfo constructs and registers a new StandardGaugeInfo.
|
||||
func NewRegisteredGaugeInfo(name string, r Registry) GaugeInfo {
|
||||
c := NewGaugeInfo()
|
||||
if nil == r {
|
||||
r = DefaultRegistry
|
||||
}
|
||||
r.Register(name, c)
|
||||
return c
|
||||
}
|
||||
|
||||
// NewFunctionalGauge constructs a new FunctionalGauge.
|
||||
func NewFunctionalGaugeInfo(f func() GaugeInfoValue) GaugeInfo {
|
||||
if !Enabled {
|
||||
return NilGaugeInfo{}
|
||||
}
|
||||
return &FunctionalGaugeInfo{value: f}
|
||||
}
|
||||
|
||||
// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge.
|
||||
func NewRegisteredFunctionalGaugeInfo(name string, r Registry, f func() GaugeInfoValue) GaugeInfo {
|
||||
c := NewFunctionalGaugeInfo(f)
|
||||
if nil == r {
|
||||
r = DefaultRegistry
|
||||
}
|
||||
r.Register(name, c)
|
||||
return c
|
||||
}
|
||||
|
||||
// GaugeInfoSnapshot is a read-only copy of another GaugeInfo.
|
||||
type GaugeInfoSnapshot GaugeInfoValue
|
||||
|
||||
// Snapshot returns the snapshot.
|
||||
func (g GaugeInfoSnapshot) Snapshot() GaugeInfo { return g }
|
||||
|
||||
// Update panics.
|
||||
func (GaugeInfoSnapshot) Update(GaugeInfoValue) {
|
||||
panic("Update called on a GaugeInfoSnapshot")
|
||||
}
|
||||
|
||||
// Value returns the value at the time the snapshot was taken.
|
||||
func (g GaugeInfoSnapshot) Value() GaugeInfoValue { return GaugeInfoValue(g) }
|
||||
|
||||
// Value returns the value at the time the snapshot was taken in JSON string format.
|
||||
func (g GaugeInfoSnapshot) ValueJsonString() string {
|
||||
return gaugeInfoValueToJsonString(g.Value())
|
||||
}
|
||||
|
||||
// NilGauge is a no-op Gauge.
|
||||
type NilGaugeInfo struct{}
|
||||
|
||||
// Snapshot is a no-op.
|
||||
func (NilGaugeInfo) Snapshot() GaugeInfo { return NilGaugeInfo{} }
|
||||
|
||||
// Update is a no-op.
|
||||
func (NilGaugeInfo) Update(v GaugeInfoValue) {}
|
||||
|
||||
// Value is a no-op.
|
||||
func (NilGaugeInfo) Value() GaugeInfoValue { return GaugeInfoValue{} }
|
||||
|
||||
// Value is a no-op.
|
||||
func (NilGaugeInfo) ValueJsonString() string { return gaugeInfoValueToJsonString(GaugeInfoValue{}) }
|
||||
|
||||
// StandardGaugeInfo is the standard implementation of a GaugeInfo and uses
|
||||
// sync.Mutex to manage a single string value.
|
||||
type StandardGaugeInfo struct {
|
||||
mutex sync.Mutex
|
||||
value GaugeInfoValue
|
||||
}
|
||||
|
||||
// Snapshot returns a read-only copy of the gauge.
|
||||
func (g *StandardGaugeInfo) Snapshot() GaugeInfo {
|
||||
return GaugeInfoSnapshot(g.Value())
|
||||
}
|
||||
|
||||
// Update updates the gauge's value.
|
||||
func (g *StandardGaugeInfo) Update(v GaugeInfoValue) {
|
||||
g.mutex.Lock()
|
||||
defer g.mutex.Unlock()
|
||||
g.value = v
|
||||
}
|
||||
|
||||
// Value returns the gauge's current value.
|
||||
func (g *StandardGaugeInfo) Value() GaugeInfoValue {
|
||||
g.mutex.Lock()
|
||||
defer g.mutex.Unlock()
|
||||
return g.value
|
||||
}
|
||||
|
||||
// Value returns the gauge's current value in JSON string format.
|
||||
func (g *StandardGaugeInfo) ValueJsonString() string {
|
||||
g.mutex.Lock()
|
||||
defer g.mutex.Unlock()
|
||||
return gaugeInfoValueToJsonString(g.value)
|
||||
}
|
||||
|
||||
// FunctionalGaugeInfo returns value from given function
|
||||
type FunctionalGaugeInfo struct {
|
||||
value func() GaugeInfoValue
|
||||
}
|
||||
|
||||
// Value returns the gauge's current value.
|
||||
func (g FunctionalGaugeInfo) Value() GaugeInfoValue {
|
||||
return g.value()
|
||||
}
|
||||
|
||||
// Value returns the gauge's current value in JSON string format
|
||||
func (g FunctionalGaugeInfo) ValueJsonString() string {
|
||||
return gaugeInfoValueToJsonString(g.value())
|
||||
}
|
||||
|
||||
// Snapshot returns the snapshot.
|
||||
func (g FunctionalGaugeInfo) Snapshot() GaugeInfo { return GaugeInfoSnapshot(g.Value()) }
|
||||
|
||||
// Update panics.
|
||||
func (FunctionalGaugeInfo) Update(GaugeInfoValue) {
|
||||
panic("Update called on a FunctionalGaugeInfo")
|
||||
}
|
||||
|
||||
// Custom conversion to Json to avoid printing "Key" and "Val"
|
||||
func gaugeInfoValueToJsonString(g GaugeInfoValue) string {
|
||||
lastIdx := len(g) - 1
|
||||
v := "{"
|
||||
for idx, entry := range g {
|
||||
v += "\"" + entry.Key + "\":\"" + entry.Val + "\""
|
||||
if idx != lastIdx {
|
||||
v += ","
|
||||
}
|
||||
}
|
||||
v += "}"
|
||||
return v
|
||||
}
|
||||
129
metrics/gauge_info_test.go
Normal file
129
metrics/gauge_info_test.go
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
package metrics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkGuageInfo(b *testing.B) {
|
||||
g := NewGaugeInfo()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
g.Update(GaugeInfoValue{
|
||||
{"chain_id", string(rune(i))},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGaugeInfo(t *testing.T) {
|
||||
g := NewGaugeInfo()
|
||||
g.Update(GaugeInfoValue{
|
||||
{"chain_id", "5"},
|
||||
},
|
||||
)
|
||||
expected := GaugeInfoValue{
|
||||
{"chain_id", "5"},
|
||||
}
|
||||
for idx, v := range g.Value() {
|
||||
if v.Key != expected[idx].Key || v.Val != expected[idx].Val {
|
||||
t.Errorf("g.Value()[%v]: %v != %v\n", idx, v, expected[idx])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGaugeInfoSnapshot(t *testing.T) {
|
||||
g := NewGaugeInfo()
|
||||
g.Update(GaugeInfoValue{
|
||||
{"chain_id", "5"},
|
||||
})
|
||||
snapshot := g.Snapshot()
|
||||
g.Update(GaugeInfoValue{
|
||||
{"chain_id", "1"},
|
||||
})
|
||||
expected := GaugeInfoValue{
|
||||
{"chain_id", "5"},
|
||||
}
|
||||
for idx, v := range snapshot.Value() {
|
||||
if v.Key != expected[idx].Key || v.Val != expected[idx].Val {
|
||||
t.Errorf("g.Value()[%v]: %v != %v\n", idx, v, expected[idx])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrRegisterGaugeInfo(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
NewRegisteredGaugeInfo("foo", r).Update(GaugeInfoValue{
|
||||
{"chain_id", "5"},
|
||||
})
|
||||
expected := GaugeInfoValue{
|
||||
{"chain_id", "5"},
|
||||
}
|
||||
g := GetOrRegisterGaugeInfo("foo", r)
|
||||
for idx, v := range g.Value() {
|
||||
if v.Key != expected[idx].Key || v.Val != expected[idx].Val {
|
||||
t.Fatal(g)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFunctionalGaugeInfo(t *testing.T) {
|
||||
info := GaugeInfoValue{
|
||||
{"chain_id", "0"},
|
||||
}
|
||||
counter := 1
|
||||
fg := NewFunctionalGaugeInfo(func() GaugeInfoValue {
|
||||
info[0].Val = strconv.Itoa(counter)
|
||||
counter++
|
||||
return info
|
||||
})
|
||||
fg.Value()
|
||||
fg.Value()
|
||||
if info[0].Val != "2" {
|
||||
t.Error("info[0].Val != \"2\" -> ", info[0].Val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrRegisterFunctionalGaugeInfo(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
NewRegisteredFunctionalGaugeInfo("foo", r, func() GaugeInfoValue {
|
||||
return GaugeInfoValue{
|
||||
{"chain_id", "5"},
|
||||
}
|
||||
})
|
||||
expected := GaugeInfoValue{
|
||||
{"chain_id", "5"},
|
||||
}
|
||||
g := GetOrRegisterGaugeInfo("foo", r)
|
||||
for idx, v := range g.Value() {
|
||||
if v.Key != expected[idx].Key || v.Val != expected[idx].Val {
|
||||
t.Fatal(g)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGaugeInfoValueJsonString(t *testing.T) {
|
||||
g := NewGaugeInfo()
|
||||
g.Update(GaugeInfoValue{
|
||||
{"chain_id", "5"},
|
||||
{"anotherKey", "any_string_value"},
|
||||
{"third_key", "anything"},
|
||||
},
|
||||
)
|
||||
expected := `{"chain_id":"5","anotherKey":"any_string_value","third_key":"anything"}`
|
||||
got := g.ValueJsonString()
|
||||
if got != expected {
|
||||
t.Errorf("g.ValueToJsonString(): %s != %s\n", got, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleGetOrRegisterGaugeInfo() {
|
||||
m := "chain/info"
|
||||
g := GetOrRegisterGaugeInfo(m, nil)
|
||||
g.Update(GaugeInfoValue{
|
||||
{"chain_id", "5"},
|
||||
{"random_value", "10"},
|
||||
{"chain_data", "356"},
|
||||
})
|
||||
fmt.Println(g.Value()) // Output: [{chain_id 5} {random_value 10} {chain_data 356}]
|
||||
}
|
||||
|
|
@ -73,6 +73,8 @@ func graphite(c *GraphiteConfig) error {
|
|||
fmt.Fprintf(w, "%s.%s.value %d %d\n", c.Prefix, name, metric.Value(), now)
|
||||
case GaugeFloat64:
|
||||
fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Value(), now)
|
||||
case GaugeInfo:
|
||||
fmt.Fprintf(w, "%s.%s.value %s %d\n", c.Prefix, name, metric.ValueJsonString(), now)
|
||||
case Histogram:
|
||||
h := metric.Snapshot()
|
||||
ps := h.Percentiles(c.Percentiles)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,13 @@ func readMeter(namespace, name string, i interface{}) (string, map[string]interf
|
|||
"value": metric.Snapshot().Value(),
|
||||
}
|
||||
return measurement, fields
|
||||
case metrics.GaugeInfo:
|
||||
ms := metric.Snapshot()
|
||||
measurement := fmt.Sprintf("%s%s.gauge", namespace, name)
|
||||
fields := map[string]interface{}{
|
||||
"value": ms.ValueJsonString(),
|
||||
}
|
||||
return measurement, fields
|
||||
case metrics.Histogram:
|
||||
ms := metric.Snapshot()
|
||||
if ms.Count() <= 0 {
|
||||
|
|
|
|||
|
|
@ -126,6 +126,10 @@ func (rep *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot B
|
|||
measurement[Name] = name
|
||||
measurement[Value] = m.Value()
|
||||
snapshot.Gauges = append(snapshot.Gauges, measurement)
|
||||
case metrics.GaugeInfo:
|
||||
measurement[Name] = name
|
||||
measurement[Value] = m.Value()
|
||||
snapshot.Gauges = append(snapshot.Gauges, measurement)
|
||||
case metrics.Histogram:
|
||||
if m.Count() > 0 {
|
||||
gauges := make([]Measurement, histogramGaugeCount)
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@ func LogScaled(r Registry, freq time.Duration, scale time.Duration, l Logger) {
|
|||
case GaugeFloat64:
|
||||
l.Printf("gauge %s\n", name)
|
||||
l.Printf(" value: %f\n", metric.Value())
|
||||
case GaugeInfo:
|
||||
l.Printf("gauge %s\n", name)
|
||||
l.Printf(" value: %s\n", metric.Value())
|
||||
case Healthcheck:
|
||||
metric.Check()
|
||||
l.Printf("healthcheck %s\n", name)
|
||||
|
|
|
|||
|
|
@ -77,6 +77,8 @@ func openTSDB(c *OpenTSDBConfig) error {
|
|||
fmt.Fprintf(w, "put %s.%s.value %d %d host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname)
|
||||
case GaugeFloat64:
|
||||
fmt.Fprintf(w, "put %s.%s.value %d %f host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname)
|
||||
case GaugeInfo:
|
||||
fmt.Fprintf(w, "put %s.%s.value %d %s host=%s\n", c.Prefix, name, now, metric.ValueJsonString(), shortHostname)
|
||||
case Histogram:
|
||||
h := metric.Snapshot()
|
||||
ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
|
||||
|
|
|
|||
|
|
@ -62,6 +62,10 @@ func (c *collector) addGaugeFloat64(name string, m metrics.GaugeFloat64) {
|
|||
c.writeGaugeCounter(name, m.Value())
|
||||
}
|
||||
|
||||
func (c *collector) addGaugeInfo(name string, m metrics.GaugeInfo) {
|
||||
c.writeGaugeInfo(name, m.Value())
|
||||
}
|
||||
|
||||
func (c *collector) addHistogram(name string, m metrics.Histogram) {
|
||||
pv := []float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999}
|
||||
ps := m.Percentiles(pv)
|
||||
|
|
@ -102,6 +106,19 @@ func (c *collector) addResettingTimer(name string, m metrics.ResettingTimer) {
|
|||
c.buff.WriteRune('\n')
|
||||
}
|
||||
|
||||
func (c *collector) writeGaugeInfo(name string, value metrics.GaugeInfoValue) {
|
||||
name = mutateKey(name)
|
||||
c.buff.WriteString(fmt.Sprintf(typeGaugeTpl, name))
|
||||
c.buff.WriteString(fmt.Sprintf("%s {", name))
|
||||
for idx, entry := range value {
|
||||
c.buff.WriteString(fmt.Sprintf("%s=\"%s\"", entry.Key, entry.Val))
|
||||
if idx != len(value)-1 {
|
||||
c.buff.WriteString(", ")
|
||||
}
|
||||
}
|
||||
c.buff.WriteString("} 1 \n\n")
|
||||
}
|
||||
|
||||
func (c *collector) writeGaugeCounter(name string, value interface{}) {
|
||||
name = mutateKey(name)
|
||||
c.buff.WriteString(fmt.Sprintf(typeGaugeTpl, name))
|
||||
|
|
|
|||
|
|
@ -32,6 +32,16 @@ func TestCollector(t *testing.T) {
|
|||
gaugeFloat64.Update(34567.89)
|
||||
c.addGaugeFloat64("test/gauge_float64", gaugeFloat64)
|
||||
|
||||
gaugeInfo := metrics.NewGaugeInfo()
|
||||
gaugeInfo.Update(metrics.GaugeInfoValue{
|
||||
metrics.NewGaugeInfoEntry("version", "1.10.18-unstable"),
|
||||
metrics.NewGaugeInfoEntry("arch", "amd64"),
|
||||
metrics.NewGaugeInfoEntry("os", "linux"),
|
||||
metrics.NewGaugeInfoEntry("commit", "7caa2d8163ae3132c1c2d6978c76610caee2d949"),
|
||||
metrics.NewGaugeInfoEntry("protocol_versions", "64 65 66"),
|
||||
})
|
||||
c.addGaugeInfo("geth/info", gaugeInfo)
|
||||
|
||||
histogram := metrics.NewHistogram(&metrics.NilSample{})
|
||||
c.addHistogram("test/histogram", histogram)
|
||||
|
||||
|
|
@ -74,6 +84,9 @@ test_gauge 23456
|
|||
# TYPE test_gauge_float64 gauge
|
||||
test_gauge_float64 34567.89
|
||||
|
||||
# TYPE geth_info gauge
|
||||
geth_info {version="1.10.18-unstable", arch="amd64", os="linux", commit="7caa2d8163ae3132c1c2d6978c76610caee2d949", protocol_versions="64 65 66"} 1
|
||||
|
||||
# TYPE test_histogram_count counter
|
||||
test_histogram_count 0
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ func Handler(reg metrics.Registry) http.Handler {
|
|||
c.addGauge(name, m.Snapshot())
|
||||
case metrics.GaugeFloat64:
|
||||
c.addGaugeFloat64(name, m.Snapshot())
|
||||
case metrics.GaugeInfo:
|
||||
c.addGaugeInfo(name, m.Snapshot())
|
||||
case metrics.Histogram:
|
||||
c.addHistogram(name, m.Snapshot())
|
||||
case metrics.Meter:
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ func (r *StandardRegistry) Unregister(name string) {
|
|||
|
||||
func (r *StandardRegistry) loadOrRegister(name string, i interface{}) (interface{}, bool, bool) {
|
||||
switch i.(type) {
|
||||
case Counter, CounterFloat64, Gauge, GaugeFloat64, Healthcheck, Histogram, Meter, Timer, ResettingTimer:
|
||||
case Counter, CounterFloat64, Gauge, GaugeFloat64, GaugeInfo, Healthcheck, Histogram, Meter, Timer, ResettingTimer:
|
||||
default:
|
||||
return nil, false, false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ func Syslog(r Registry, d time.Duration, w *syslog.Writer) {
|
|||
w.Info(fmt.Sprintf("gauge %s: value: %d", name, metric.Value()))
|
||||
case GaugeFloat64:
|
||||
w.Info(fmt.Sprintf("gauge %s: value: %f", name, metric.Value()))
|
||||
case GaugeInfo:
|
||||
w.Info(fmt.Sprintf("gauge %s: value: %s", name, metric.Value()))
|
||||
case Healthcheck:
|
||||
metric.Check()
|
||||
w.Info(fmt.Sprintf("healthcheck %s: error: %v", name, metric.Error()))
|
||||
|
|
|
|||
|
|
@ -39,6 +39,9 @@ func WriteOnce(r Registry, w io.Writer) {
|
|||
case GaugeFloat64:
|
||||
fmt.Fprintf(w, "gauge %s\n", namedMetric.name)
|
||||
fmt.Fprintf(w, " value: %f\n", metric.Value())
|
||||
case GaugeInfo:
|
||||
fmt.Fprintf(w, "gauge %s\n", namedMetric.name)
|
||||
fmt.Fprintf(w, " value: %s\n", metric.ValueJsonString())
|
||||
case Healthcheck:
|
||||
metric.Check()
|
||||
fmt.Fprintf(w, "healthcheck %s\n", namedMetric.name)
|
||||
|
|
|
|||
Loading…
Reference in a new issue