forked from mirror/client_golang
Merge pull request #23 from prometheus/feature/summary/subtleties
Refresh of Histogram/Summary Behavior to Reflect Modern Expectations
This commit is contained in:
commit
98fc5b23c1
|
@ -23,3 +23,4 @@ _testmain.go
|
||||||
|
|
||||||
*~
|
*~
|
||||||
*#
|
*#
|
||||||
|
.build
|
||||||
|
|
|
@ -4,4 +4,4 @@ go:
|
||||||
- 1.1
|
- 1.1
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- make -f Makefile.TRAVIS
|
- make -f Makefile
|
||||||
|
|
55
Makefile
55
Makefile
|
@ -11,14 +11,53 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
MAKE_ARTIFACTS = search_index
|
OS = $(shell uname)
|
||||||
|
ARCH = $(shell uname -m)
|
||||||
|
|
||||||
|
BUILD_PATH = $(PWD)/.build
|
||||||
|
|
||||||
|
export GO_VERSION = 1.1
|
||||||
|
export GOOS = $(subst Darwin,darwin,$(subst Linux,linux,$(OS)))
|
||||||
|
export GOARCH = $(subst x86_64,amd64,$(ARCH))
|
||||||
|
export GOPKG = go$(GO_VERSION).$(GOOS)-$(GOARCH).tar.gz
|
||||||
|
export GOROOT = $(BUILD_PATH)/root/go
|
||||||
|
export GOPATH = $(BUILD_PATH)/root/gopath
|
||||||
|
export GOCC = $(GOROOT)/bin/go
|
||||||
|
export TMPDIR = /tmp
|
||||||
|
export GOENV = TMPDIR=$(TMPDIR) GOROOT=$(GOROOT) GOPATH=$(GOPATH)
|
||||||
|
export GO = $(GOENV) $(GOCC)
|
||||||
|
export GOFMT = $(GOROOT)/bin/gofmt
|
||||||
|
|
||||||
|
FULL_GOPATH = $(GOPATH)/src/github.com/prometheus/client_golang
|
||||||
|
FULL_GOPATH_BASE = $(GOPATH)/src/github.com/prometheus
|
||||||
|
|
||||||
|
MAKE_ARTIFACTS = search_index $(BUILD_PATH)
|
||||||
|
|
||||||
all: test
|
all: test
|
||||||
|
|
||||||
build:
|
$(BUILD_PATH):
|
||||||
|
mkdir -vp $(BUILD_PATH)
|
||||||
|
|
||||||
|
$(BUILD_PATH)/cache: $(BUILD_PATH)
|
||||||
|
mkdir -vp $(BUILD_PATH)/cache
|
||||||
|
|
||||||
|
$(BUILD_PATH)/root: $(BUILD_PATH)
|
||||||
|
mkdir -vp $(BUILD_PATH)/root
|
||||||
|
|
||||||
|
$(BUILD_PATH)/cache/$(GOPKG): $(BUILD_PATH)/cache
|
||||||
|
curl -o $@ http://go.googlecode.com/files/$(GOPKG)
|
||||||
|
|
||||||
|
$(GOCC): $(BUILD_PATH)/root $(BUILD_PATH)/cache/$(GOPKG)
|
||||||
|
tar -C $(BUILD_PATH)/root -xzf $(BUILD_PATH)/cache/$(GOPKG)
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
build: source_path dependencies
|
||||||
$(MAKE) -C prometheus build
|
$(MAKE) -C prometheus build
|
||||||
$(MAKE) -C examples build
|
$(MAKE) -C examples build
|
||||||
|
|
||||||
|
dependencies: source_path $(GOCC)
|
||||||
|
$(GO) get github.com/matttproud/gocheck
|
||||||
|
|
||||||
test: build
|
test: build
|
||||||
$(MAKE) -C prometheus test
|
$(MAKE) -C prometheus test
|
||||||
$(MAKE) -C examples test
|
$(MAKE) -C examples test
|
||||||
|
@ -28,18 +67,24 @@ advice: test
|
||||||
$(MAKE) -C examples advice
|
$(MAKE) -C examples advice
|
||||||
|
|
||||||
format:
|
format:
|
||||||
find . -iname '*.go' -exec gofmt -w -s=true '{}' ';'
|
find . -iname '*.go' | grep -v './.build/' | xargs -n1 -P1 $(GOFMT) -w -s=true
|
||||||
|
|
||||||
search_index:
|
search_index:
|
||||||
godoc -index -write_index -index_files='search_index'
|
godoc -index -write_index -index_files='search_index'
|
||||||
|
|
||||||
|
# source_path is responsible for ensuring that the builder has not done anything
|
||||||
|
# stupid like working on Prometheus outside of ${GOPATH}.
|
||||||
|
source_path:
|
||||||
|
-[ -d "$(FULL_GOPATH)" ] || { mkdir -vp $(FULL_GOPATH_BASE) ; ln -s "$(PWD)" "$(FULL_GOPATH)" ; }
|
||||||
|
[ -d "$(FULL_GOPATH)" ]
|
||||||
|
|
||||||
documentation: search_index
|
documentation: search_index
|
||||||
godoc -http=:6060 -index -index_files='search_index'
|
godoc -http=:6060 -index -index_files='search_index'
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(MAKE) -C examples clean
|
$(MAKE) -C examples clean
|
||||||
rm -f $(MAKE_ARTIFACTS)
|
rm -rf $(MAKE_ARTIFACTS)
|
||||||
find . -iname '*~' -exec rm -f '{}' ';'
|
find . -iname '*~' -exec rm -f '{}' ';'
|
||||||
find . -iname '*#' -exec rm -f '{}' ';'
|
find . -iname '*#' -exec rm -f '{}' ';'
|
||||||
|
|
||||||
.PHONY: advice build clean documentation format test
|
.PHONY: advice build clean documentation format source_path test
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
# Copyright 2013 Prometheus Team
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
PROMETHEUS_TARGET := "${GOPATH}/src/github.com/prometheus"
|
|
||||||
|
|
||||||
all: test
|
|
||||||
|
|
||||||
preparation:
|
|
||||||
mkdir -vp $(PROMETHEUS_TARGET)
|
|
||||||
ln -sf "$(PWD)" $(PROMETHEUS_TARGET)
|
|
||||||
|
|
||||||
dependencies:
|
|
||||||
go get code.google.com/p/goprotobuf/proto
|
|
||||||
go get github.com/matttproud/gocheck
|
|
||||||
go get github.com/matttproud/golang_protobuf_extensions/ext
|
|
||||||
go get github.com/prometheus/client_model/go
|
|
||||||
|
|
||||||
test: dependencies preparation
|
|
||||||
$(MAKE) test
|
|
||||||
|
|
||||||
.PHONY: dependencies preparation test
|
|
|
@ -18,13 +18,13 @@ all: test
|
||||||
build: delegator
|
build: delegator
|
||||||
|
|
||||||
delegator:
|
delegator:
|
||||||
go build .
|
$(GO) build .
|
||||||
|
|
||||||
test: build
|
test: build
|
||||||
go test . $(GO_TEST_FLAGS)
|
$(GO) test . $(GO_TEST_FLAGS)
|
||||||
|
|
||||||
advice:
|
advice:
|
||||||
go tool vet .
|
$(GO) tool vet .
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(MAKE_ARTIFACTS)
|
rm -f $(MAKE_ARTIFACTS)
|
||||||
|
|
|
@ -18,13 +18,13 @@ all: test
|
||||||
build: random
|
build: random
|
||||||
|
|
||||||
random:
|
random:
|
||||||
go build .
|
$(GO) build .
|
||||||
|
|
||||||
test: build
|
test: build
|
||||||
go test . $(GO_TEST_FLAGS)
|
$(GO) test . $(GO_TEST_FLAGS)
|
||||||
|
|
||||||
advice:
|
advice:
|
||||||
go tool vet .
|
$(GO) tool vet .
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(MAKE_ARTIFACTS)
|
rm -f $(MAKE_ARTIFACTS)
|
||||||
|
|
|
@ -18,13 +18,13 @@ all: test
|
||||||
build: simple
|
build: simple
|
||||||
|
|
||||||
simple:
|
simple:
|
||||||
go build .
|
$(GO) build .
|
||||||
|
|
||||||
test: build
|
test: build
|
||||||
go test . $(GO_TEST_FLAGS)
|
$(GO) test . $(GO_TEST_FLAGS)
|
||||||
|
|
||||||
advice:
|
advice:
|
||||||
go tool vet .
|
$(GO) tool vet .
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(MAKE_ARTIFACTS)
|
rm -f $(MAKE_ARTIFACTS)
|
||||||
|
|
|
@ -13,13 +13,16 @@
|
||||||
|
|
||||||
all: test
|
all: test
|
||||||
|
|
||||||
build:
|
build: dependencies
|
||||||
go build ./...
|
$(GO) build ./...
|
||||||
|
|
||||||
|
dependencies: $(GOCC)
|
||||||
|
$(GO) get -d
|
||||||
|
|
||||||
test: build
|
test: build
|
||||||
go test ./... $(GO_TEST_FLAGS)
|
$(GO) test ./... $(GO_TEST_FLAGS)
|
||||||
|
|
||||||
advice:
|
advice:
|
||||||
go tool vet .
|
$(GO) tool vet .
|
||||||
|
|
||||||
.PHONY: advice build test
|
.PHONY: advice build dependencies test
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
|
||||||
|
@ -54,6 +55,7 @@ type HistogramSpecification struct {
|
||||||
BucketBuilder BucketBuilder
|
BucketBuilder BucketBuilder
|
||||||
ReportablePercentiles []float64
|
ReportablePercentiles []float64
|
||||||
Starts []float64
|
Starts []float64
|
||||||
|
PurgeInterval time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
type Histogram interface {
|
type Histogram interface {
|
||||||
|
@ -82,11 +84,16 @@ type histogram struct {
|
||||||
values map[uint64]*histogramVector
|
values map[uint64]*histogramVector
|
||||||
// These are the percentile values that will be reported on marshalling.
|
// These are the percentile values that will be reported on marshalling.
|
||||||
reportablePercentiles []float64
|
reportablePercentiles []float64
|
||||||
|
|
||||||
|
purgeInterval time.Duration
|
||||||
|
lastPurge time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
type histogramVector struct {
|
type histogramVector struct {
|
||||||
buckets []Bucket
|
buckets []Bucket
|
||||||
labels map[string]string
|
labels map[string]string
|
||||||
|
sum float64
|
||||||
|
count uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *histogram) Add(labels map[string]string, value float64) {
|
func (h *histogram) Add(labels map[string]string, value float64) {
|
||||||
|
@ -124,6 +131,9 @@ func (h *histogram) Add(labels map[string]string, value float64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
histogram.buckets[lastIndex].Add(value)
|
histogram.buckets[lastIndex].Add(value)
|
||||||
|
|
||||||
|
histogram.sum += value
|
||||||
|
histogram.count++
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *histogram) String() string {
|
func (h *histogram) String() string {
|
||||||
|
@ -244,6 +254,8 @@ func formatFloat(value float64) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *histogram) MarshalJSON() ([]byte, error) {
|
func (h *histogram) MarshalJSON() ([]byte, error) {
|
||||||
|
h.Purge()
|
||||||
|
|
||||||
h.mutex.RLock()
|
h.mutex.RLock()
|
||||||
defer h.mutex.RUnlock()
|
defer h.mutex.RUnlock()
|
||||||
|
|
||||||
|
@ -269,10 +281,29 @@ func (h *histogram) MarshalJSON() ([]byte, error) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *histogram) Purge() {
|
||||||
|
if h.purgeInterval == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
h.mutex.Lock()
|
||||||
|
defer h.mutex.Unlock()
|
||||||
|
if time.Since(h.lastPurge) < h.purgeInterval {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
h.resetAll()
|
||||||
|
h.lastPurge = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
func (h *histogram) ResetAll() {
|
func (h *histogram) ResetAll() {
|
||||||
h.mutex.Lock()
|
h.mutex.Lock()
|
||||||
defer h.mutex.Unlock()
|
defer h.mutex.Unlock()
|
||||||
|
|
||||||
|
h.resetAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *histogram) resetAll() {
|
||||||
for signature, value := range h.values {
|
for signature, value := range h.values {
|
||||||
for _, bucket := range value.buckets {
|
for _, bucket := range value.buckets {
|
||||||
bucket.Reset()
|
bucket.Reset()
|
||||||
|
@ -289,6 +320,8 @@ func NewHistogram(specification *HistogramSpecification) Histogram {
|
||||||
bucketStarts: specification.Starts,
|
bucketStarts: specification.Starts,
|
||||||
reportablePercentiles: specification.ReportablePercentiles,
|
reportablePercentiles: specification.ReportablePercentiles,
|
||||||
values: map[uint64]*histogramVector{},
|
values: map[uint64]*histogramVector{},
|
||||||
|
lastPurge: time.Now(),
|
||||||
|
purgeInterval: specification.PurgeInterval,
|
||||||
}
|
}
|
||||||
|
|
||||||
return metric
|
return metric
|
||||||
|
@ -302,18 +335,24 @@ func NewDefaultHistogram() Histogram {
|
||||||
Starts: LogarithmicSizedBucketsFor(0, 4096),
|
Starts: LogarithmicSizedBucketsFor(0, 4096),
|
||||||
BucketBuilder: AccumulatingBucketBuilder(EvictAndReplaceWith(10, AverageReducer), 50),
|
BucketBuilder: AccumulatingBucketBuilder(EvictAndReplaceWith(10, AverageReducer), 50),
|
||||||
ReportablePercentiles: []float64{0.01, 0.05, 0.5, 0.90, 0.99},
|
ReportablePercentiles: []float64{0.01, 0.05, 0.5, 0.90, 0.99},
|
||||||
|
PurgeInterval: 15 * time.Minute,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (metric *histogram) dumpChildren(f *dto.MetricFamily) {
|
func (metric *histogram) dumpChildren(f *dto.MetricFamily) {
|
||||||
|
metric.Purge()
|
||||||
|
|
||||||
metric.mutex.RLock()
|
metric.mutex.RLock()
|
||||||
defer metric.mutex.RUnlock()
|
defer metric.mutex.RUnlock()
|
||||||
|
|
||||||
f.Type = dto.MetricType_SUMMARY.Enum()
|
f.Type = dto.MetricType_SUMMARY.Enum()
|
||||||
|
|
||||||
for signature, child := range metric.values {
|
for signature, child := range metric.values {
|
||||||
c := &dto.Summary{}
|
c := &dto.Summary{
|
||||||
|
SampleSum: proto.Float64(child.sum),
|
||||||
|
SampleCount: proto.Uint64(child.count),
|
||||||
|
}
|
||||||
|
|
||||||
m := &dto.Metric{
|
m := &dto.Metric{
|
||||||
Summary: c,
|
Summary: c,
|
||||||
|
|
Loading…
Reference in New Issue