mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
metrics/prometheus: minor cleanups
This commit is contained in:
parent
ae5c0fc0e4
commit
8e8d55ed8e
2 changed files with 35 additions and 31 deletions
|
|
@ -13,6 +13,7 @@
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package prometheus
|
package prometheus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -43,21 +44,26 @@ var (
|
||||||
nameQuantileTagTemplate = "{name=\"%s\",quantile=\"%s\"} %v\n"
|
nameQuantileTagTemplate = "{name=\"%s\",quantile=\"%s\"} %v\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// bufPool is a global pool of byte buffers to avoid constant reallocations.
|
||||||
var bufPool sync.Pool
|
var bufPool sync.Pool
|
||||||
|
|
||||||
|
// getBuf retrieves a new empty (but possibly non-0 capacity) buffer.
|
||||||
func getBuf() *bytes.Buffer {
|
func getBuf() *bytes.Buffer {
|
||||||
buf := bufPool.Get()
|
if item := bufPool.Get(); item != nil {
|
||||||
if buf == nil {
|
buf := item.(*bytes.Buffer)
|
||||||
return &bytes.Buffer{}
|
buf.Reset()
|
||||||
|
return buf
|
||||||
}
|
}
|
||||||
return buf.(*bytes.Buffer)
|
return &bytes.Buffer{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// giveBuf returns a used byte buffer to the pool.
|
||||||
func giveBuf(buf *bytes.Buffer) {
|
func giveBuf(buf *bytes.Buffer) {
|
||||||
buf.Reset()
|
|
||||||
bufPool.Put(buf)
|
bufPool.Put(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// collector is a collection of byte buffers that aggregate Prometheus reports
|
||||||
|
// for different metric types.
|
||||||
type collector struct {
|
type collector struct {
|
||||||
counters *bytes.Buffer
|
counters *bytes.Buffer
|
||||||
gauges *bytes.Buffer
|
gauges *bytes.Buffer
|
||||||
|
|
@ -67,6 +73,7 @@ type collector struct {
|
||||||
resettingTimers *bytes.Buffer
|
resettingTimers *bytes.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newCollector createa a new Prometheus metric aggregator.
|
||||||
func newCollector() *collector {
|
func newCollector() *collector {
|
||||||
return &collector{
|
return &collector{
|
||||||
counters: getBuf(),
|
counters: getBuf(),
|
||||||
|
|
@ -78,7 +85,9 @@ func newCollector() *collector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *collector) reset() {
|
// close releases all internally held byte buffers to be reused by subsequent
|
||||||
|
// metrics collection runs.
|
||||||
|
func (c *collector) close() {
|
||||||
giveBuf(c.counters)
|
giveBuf(c.counters)
|
||||||
giveBuf(c.gauges)
|
giveBuf(c.gauges)
|
||||||
giveBuf(c.histograms)
|
giveBuf(c.histograms)
|
||||||
|
|
@ -87,38 +96,34 @@ func (c *collector) reset() {
|
||||||
giveBuf(c.resettingTimers)
|
giveBuf(c.resettingTimers)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *collector) result() *bytes.Buffer {
|
// aggregate iterates over the different metric types and aggregates them into
|
||||||
|
// a single byte buffer.
|
||||||
|
func (c *collector) aggregate() *bytes.Buffer {
|
||||||
buf := getBuf()
|
buf := getBuf()
|
||||||
if c.counters.Len() > 0 {
|
if c.counters.Len() > 0 {
|
||||||
buf.Write(countersHeader)
|
buf.Write(countersHeader)
|
||||||
buf.Write(c.counters.Bytes())
|
buf.Write(c.counters.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.gauges.Len() > 0 {
|
if c.gauges.Len() > 0 {
|
||||||
buf.Write(gaugesHeader)
|
buf.Write(gaugesHeader)
|
||||||
buf.Write(c.gauges.Bytes())
|
buf.Write(c.gauges.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.meters.Len() > 0 {
|
if c.meters.Len() > 0 {
|
||||||
buf.Write(meterHeader)
|
buf.Write(meterHeader)
|
||||||
buf.Write(c.meters.Bytes())
|
buf.Write(c.meters.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.histograms.Len() > 0 {
|
if c.histograms.Len() > 0 {
|
||||||
buf.Write(histogramHeader)
|
buf.Write(histogramHeader)
|
||||||
buf.Write(c.histograms.Bytes())
|
buf.Write(c.histograms.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.timers.Len() > 0 {
|
if c.timers.Len() > 0 {
|
||||||
buf.Write(timerHeader)
|
buf.Write(timerHeader)
|
||||||
buf.Write(c.timers.Bytes())
|
buf.Write(c.timers.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.resettingTimers.Len() > 0 {
|
if c.resettingTimers.Len() > 0 {
|
||||||
buf.Write(resettingTimerHeader)
|
buf.Write(resettingTimerHeader)
|
||||||
buf.Write(c.resettingTimers.Bytes())
|
buf.Write(c.resettingTimers.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,48 +13,47 @@
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// Package prometheus exposes go-metrics into a Prometheus format.
|
||||||
package prometheus
|
package prometheus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler returns http handler which dump metrics in prometheus format
|
// Handler returns an HTTP handler which dump metrics in Prometheus format.
|
||||||
func Handler(reg metrics.Registry) http.Handler {
|
func Handler(reg metrics.Registry) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// Aggregate all the metris into a Prometheus collector
|
||||||
c := newCollector()
|
c := newCollector()
|
||||||
defer c.reset()
|
defer c.close()
|
||||||
|
|
||||||
reg.Each(func(name string, i interface{}) {
|
reg.Each(func(name string, i interface{}) {
|
||||||
switch m := i.(type) {
|
switch m := i.(type) {
|
||||||
case metrics.Counter:
|
case metrics.Counter:
|
||||||
ms := m.Snapshot()
|
c.addCounter(name, m.Snapshot())
|
||||||
c.addCounter(name, ms)
|
|
||||||
case metrics.Gauge:
|
case metrics.Gauge:
|
||||||
ms := m.Snapshot()
|
c.addGuage(name, m.Snapshot())
|
||||||
c.addGuage(name, ms)
|
|
||||||
case metrics.GaugeFloat64:
|
case metrics.GaugeFloat64:
|
||||||
ms := m.Snapshot()
|
c.addGuageFloat64(name, m.Snapshot())
|
||||||
c.addGuageFloat64(name, ms)
|
|
||||||
case metrics.Histogram:
|
case metrics.Histogram:
|
||||||
ms := m.Snapshot()
|
c.addHistogram(name, m.Snapshot())
|
||||||
c.addHistogram(name, ms)
|
|
||||||
case metrics.Meter:
|
case metrics.Meter:
|
||||||
ms := m.Snapshot()
|
c.addMeter(name, m.Snapshot())
|
||||||
c.addMeter(name, ms)
|
|
||||||
case metrics.Timer:
|
case metrics.Timer:
|
||||||
ms := m.Snapshot()
|
c.addTimer(name, m.Snapshot())
|
||||||
c.addTimer(name, ms)
|
|
||||||
case metrics.ResettingTimer:
|
case metrics.ResettingTimer:
|
||||||
ms := m.Snapshot()
|
c.addResettingTimer(name, m.Snapshot())
|
||||||
c.addResettingTimer(name, ms)
|
default:
|
||||||
|
log.Warn("Unknown Prometheus metric type", "type", fmt.Sprintf("%T", i))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
// Aggregate the results into a single buffer and send to the user
|
||||||
res := c.result()
|
res := c.aggregate()
|
||||||
defer giveBuf(res)
|
defer giveBuf(res)
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "text/plain")
|
w.Header().Add("Content-Type", "text/plain")
|
||||||
Loading…
Reference in a new issue