From f320d28a6c6e75ea844f2880fcea76ccbe62541e Mon Sep 17 00:00:00 2001 From: "Matt T. Proud" Date: Wed, 3 Apr 2013 18:33:32 +0200 Subject: [PATCH 1/6] Rearrange file and package per convention. WIP - Please review but do not merge. --- .travis.yml | 6 +- LICENSE | 4 +- Makefile | 16 +- Makefile.TRAVIS | 28 +++ TODO | 3 - documentation.go | 11 -- documentation/documentation.go | 43 ++++- documentation/styleguide.go | 48 ----- examples/Makefile | 36 ++++ examples/delegator/.gitignore | 1 + examples/delegator/Makefile | 32 ++++ examples/delegator/main.go | 8 +- examples/documentation.go | 8 - examples/random/.gitignore | 1 + examples/random/Makefile | 32 ++++ examples/random/main.go | 22 +-- examples/simple/.gitignore | 1 + examples/simple/Makefile | 32 ++++ examples/simple/main.go | 6 +- maths/documentation.go | 22 --- maths/maths_test.go | 20 -- metrics/constants.go | 20 -- metrics/documentation.go | 48 ----- metrics/eviction_test.go | 179 ------------------ prometheus/.gitignore | 1 + prometheus/Makefile | 25 +++ .../accumulating_bucket.go | 11 +- .../accumulating_bucket_test.go | 14 +- {metrics => prometheus}/bucket.go | 6 +- constants.go => prometheus/constants.go | 17 +- {metrics => prometheus}/counter.go | 11 +- {metrics => prometheus}/counter_test.go | 7 +- {maths => prometheus}/distributions.go | 10 +- prometheus/documentation.go | 16 ++ {metrics => prometheus}/eviction.go | 12 +- prometheus/eviction_test.go | 177 +++++++++++++++++ {exp => prometheus/exp}/coarsemux.go | 25 ++- {exp => prometheus/exp}/documentation.go | 2 +- .../exp}/responsewriter_delegator.go | 2 +- {metrics => prometheus}/gauge.go | 7 +- {metrics => prometheus}/gauge_test.go | 7 +- {maths => prometheus}/helpers_for_testing.go | 4 +- {metrics => prometheus}/histogram.go | 10 +- {metrics => prometheus}/histogram_test.go | 4 +- {utility/test => prometheus}/interface.go | 6 +- {metrics => prometheus}/metric.go | 4 +- {utility => prometheus}/priority_queue.go | 20 +- .../priority_queue_test.go | 18 +- .../prometheus_test.go | 6 +- registry.go => prometheus/registry.go | 20 +- .../registry_test.go | 24 ++- {utility => prometheus}/signature.go | 6 +- {utility => prometheus}/signature_test.go | 9 +- {maths => prometheus}/statistics.go | 52 +++-- {maths => prometheus}/statistics_test.go | 52 ++--- {metrics => prometheus}/tallying_bucket.go | 74 ++++---- .../tallying_bucket_test.go | 31 ++- telemetry.go => prometheus/telemetry.go | 22 +-- {utility => prometheus}/test_helper.go | 6 +- {metrics => prometheus}/timer.go | 4 +- {metrics => prometheus}/timer_test.go | 4 +- utility/documentation.go | 20 -- utility/utility_test.go | 20 -- 63 files changed, 716 insertions(+), 677 deletions(-) create mode 100644 Makefile.TRAVIS delete mode 100644 documentation.go delete mode 100644 documentation/styleguide.go create mode 100644 examples/Makefile create mode 100644 examples/delegator/.gitignore create mode 100644 examples/delegator/Makefile delete mode 100644 examples/documentation.go create mode 100644 examples/random/.gitignore create mode 100644 examples/random/Makefile create mode 100644 examples/simple/.gitignore create mode 100644 examples/simple/Makefile delete mode 100644 maths/documentation.go delete mode 100644 maths/maths_test.go delete mode 100644 metrics/constants.go delete mode 100644 metrics/documentation.go delete mode 100644 metrics/eviction_test.go create mode 100644 prometheus/.gitignore create mode 100644 prometheus/Makefile rename {metrics => prometheus}/accumulating_bucket.go (91%) rename {metrics => prometheus}/accumulating_bucket_test.go (93%) rename {metrics => prometheus}/bucket.go (88%) rename constants.go => prometheus/constants.go (78%) rename {metrics => prometheus}/counter.go (92%) rename {metrics => prometheus}/counter_test.go (96%) rename {maths => prometheus}/distributions.go (74%) create mode 100644 prometheus/documentation.go rename {metrics => prometheus}/eviction.go (76%) create mode 100644 prometheus/eviction_test.go rename {exp => prometheus/exp}/coarsemux.go (67%) rename {exp => prometheus/exp}/documentation.go (91%) rename {exp => prometheus/exp}/responsewriter_delegator.go (98%) rename {metrics => prometheus}/gauge.go (93%) rename {metrics => prometheus}/gauge_test.go (94%) rename {maths => prometheus}/helpers_for_testing.go (93%) rename {metrics => prometheus}/histogram.go (97%) rename {metrics => prometheus}/histogram_test.go (75%) rename {utility/test => prometheus}/interface.go (77%) rename {metrics => prometheus}/metric.go (89%) rename {utility => prometheus}/priority_queue.go (61%) rename {utility => prometheus}/priority_queue_test.go (58%) rename metrics/metrics_test.go => prometheus/prometheus_test.go (72%) rename registry.go => prometheus/registry.go (94%) rename registry_test.go => prometheus/registry_test.go (92%) rename {utility => prometheus}/signature.go (87%) rename {utility => prometheus}/signature_test.go (75%) rename {maths => prometheus}/statistics.go (63%) rename {maths => prometheus}/statistics_test.go (56%) rename {metrics => prometheus}/tallying_bucket.go (68%) rename {metrics => prometheus}/tallying_bucket_test.go (62%) rename telemetry.go => prometheus/telemetry.go (64%) rename {utility => prometheus}/test_helper.go (84%) rename {metrics => prometheus}/timer.go (96%) rename {metrics => prometheus}/timer_test.go (95%) delete mode 100644 utility/documentation.go delete mode 100644 utility/utility_test.go diff --git a/.travis.yml b/.travis.yml index c28cb48..60e95ad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,4 @@ language: go -before_script: - - go get -v github.com/prometheus/client_golang - script: - - go build -a -v github.com/prometheus/client_golang/... - - go test -v github.com/prometheus/client_golang/... + - make -f Makefile.TRAVIS diff --git a/LICENSE b/LICENSE index 22a717f..fe2fbf5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2012, Matt T. Proud +Copyright (c) 2013, Prometheus Team All rights reserved. Redistribution and use in source and binary forms, with or without @@ -19,4 +19,4 @@ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile b/Makefile index 5527b63..c43f4c3 100644 --- a/Makefile +++ b/Makefile @@ -16,17 +16,20 @@ MAKE_ARTIFACTS = search_index all: test build: - go build ./... + $(MAKE) -C prometheus build + $(MAKE) -C examples build test: build - go test ./... $(GO_TEST_FLAGS) + $(MAKE) -C prometheus test + $(MAKE) -C examples test + +advice: test + $(MAKE) -C prometheus advice + $(MAKE) -C examples advice format: find . -iname '*.go' -exec gofmt -w -s=true '{}' ';' -advice: - go tool vet . - search_index: godoc -index -write_index -index_files='search_index' @@ -34,6 +37,9 @@ documentation: search_index godoc -http=:6060 -index -index_files='search_index' clean: + $(MAKE) -C examples clean rm -f $(MAKE_ARTIFACTS) + find . -iname '*~' -exec rm -f '{}' ';' + find . -iname '*#' -exec rm -f '{}' ';' .PHONY: advice build clean documentation format test diff --git a/Makefile.TRAVIS b/Makefile.TRAVIS new file mode 100644 index 0000000..78a3a68 --- /dev/null +++ b/Makefile.TRAVIS @@ -0,0 +1,28 @@ +# 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 github.com/matttproud/gocheck + +test: dependencies preparation + $(MAKE) test + +.PHONY: dependencies preparation test diff --git a/TODO b/TODO index faa56e9..34f3b6d 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,2 @@ - Validate repository for Go code fluency and idiomatic adherence. -- Decouple HTTP report handler from our project and incorporate into this - repository. -- Implement labeled metric support. - Evaluate using atomic types versus locks. diff --git a/documentation.go b/documentation.go deleted file mode 100644 index 87f3504..0000000 --- a/documentation.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2012, Matt T. Proud -// All rights reserved. -// -// Use of this source code is governed by a BSD-style license that can be found -// in the LICENSE file. - -// registry.go provides a container for centralized exposition of metrics to -// their prospective consumers. -// -// registry.Register("human_readable_metric_name", "metric docstring", map[string]string{"baseLabel": "baseLabelValue"}, metric) -package registry diff --git a/documentation/documentation.go b/documentation/documentation.go index 32265ae..9e556ab 100644 --- a/documentation/documentation.go +++ b/documentation/documentation.go @@ -1,8 +1,49 @@ -// Copyright (c) 2013, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style license that can be found // in the LICENSE file. // A repository of various Prometheus client documentation and advice. +// +// Please try to observe the following rules when naming metrics: +// +// - Use underbars "_" to separate words. +// +// - Have the metric name start from generality and work toward specificity +// toward the end. For example, when working with multiple caching subsystems, +// consider using the following structure "cache" + "user_credentials" → +// "cache_user_credentials" and "cache" + "value_transformations" → +// "cache_value_transformations". +// +// - Have whatever is being measured follow the system and subsystem names cited +// supra. For instance, with "insertions", "deletions", "evictions", +// "replacements" of the above cache, they should be named as +// "cache_user_credentials_insertions" and "cache_user_credentials_deletions" +// and "cache_user_credentials_deletions" and +// "cache_user_credentials_evictions". +// +// - If what is being measured has a standardized unit around it, consider +// providing a unit for it. +// +// - Consider adding an additional suffix that designates what the value +// represents such as a "total" or "size"---e.g., +// "cache_user_credentials_size_kb" or +// "cache_user_credentials_insertions_total". +// +// - Give heed to how future-proof the names are. Things may depend on these +// names; and as your service evolves, the calculated values may take on +// different meanings, which can be difficult to reflect if deployed code +// depends on antique names. +// +// Further considerations: +// +// - The Registry's exposition mechanism is not backed by authorization and +// authentication. This is something that will need to be addressed for +// production services that are directly exposed to the outside world. +// +// - Engage in as little in-process processing of values as possible. The job +// of processing and aggregation of these values belongs in a separate +// post-processing job. The same goes for archiving. I will need to evaluate +// hooks into something like OpenTSBD. package documentation diff --git a/documentation/styleguide.go b/documentation/styleguide.go deleted file mode 100644 index dfed6b0..0000000 --- a/documentation/styleguide.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2013, Matt T. Proud -// All rights reserved. -// -// Use of this source code is governed by a BSD-style license that can be found -// in the LICENSE file. - -// Please try to observe the following rules when naming metrics: -// -// - Use underbars "_" to separate words. -// -// - Have the metric name start from generality and work toward specificity -// toward the end. For example, when working with multiple caching subsystems, -// consider using the following structure "cache" + "user_credentials" → -// "cache_user_credentials" and "cache" + "value_transformations" → -// "cache_value_transformations". -// -// - Have whatever is being measured follow the system and subsystem names cited -// supra. For instance, with "insertions", "deletions", "evictions", -// "replacements" of the above cache, they should be named as -// "cache_user_credentials_insertions" and "cache_user_credentials_deletions" -// and "cache_user_credentials_deletions" and -// "cache_user_credentials_evictions". -// -// - If what is being measured has a standardized unit around it, consider -// providing a unit for it. -// -// - Consider adding an additional suffix that designates what the value -// represents such as a "total" or "size"---e.g., -// "cache_user_credentials_size_kb" or -// "cache_user_credentials_insertions_total". -// -// - Give heed to how future-proof the names are. Things may depend on these -// names; and as your service evolves, the calculated values may take on -// different meanings, which can be difficult to reflect if deployed code -// depends on antique names. -// -// Further considerations: -// -// - The Registry's exposition mechanism is not backed by authorization and -// authentication. This is something that will need to be addressed for -// production services that are directly exposed to the outside world. -// -// - Engage in as little in-process processing of values as possible. The job -// of processing and aggregation of these values belongs in a separate -// post-processing job. The same goes for archiving. I will need to evaluate -// hooks into something like OpenTSBD. - -package documentation diff --git a/examples/Makefile b/examples/Makefile new file mode 100644 index 0000000..2493ff3 --- /dev/null +++ b/examples/Makefile @@ -0,0 +1,36 @@ +# 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. + +all: test + +build: + $(MAKE) -C delegator build + $(MAKE) -C random build + $(MAKE) -C simple build + +test: build + $(MAKE) -C delegator test + $(MAKE) -C random test + $(MAKE) -C simple test + +advice: test + $(MAKE) -C delegator advice + $(MAKE) -C random advice + $(MAKE) -C simple advice + +clean: + $(MAKE) -C delegator clean + $(MAKE) -C random clean + $(MAKE) -C simple clean + +.PHONY: advice build clean test diff --git a/examples/delegator/.gitignore b/examples/delegator/.gitignore new file mode 100644 index 0000000..8d83f4b --- /dev/null +++ b/examples/delegator/.gitignore @@ -0,0 +1 @@ +delegator \ No newline at end of file diff --git a/examples/delegator/Makefile b/examples/delegator/Makefile new file mode 100644 index 0000000..c60b94c --- /dev/null +++ b/examples/delegator/Makefile @@ -0,0 +1,32 @@ +# 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. + +MAKE_ARTIFACTS = delegator + +all: test + +build: delegator + +delegator: + go build . + +test: build + go test . $(GO_TEST_FLAGS) + +advice: + go tool vet . + +clean: + rm -f $(MAKE_ARTIFACTS) + +.PHONY: advice build clean test diff --git a/examples/delegator/main.go b/examples/delegator/main.go index 87258b1..4ff59ed 100644 --- a/examples/delegator/main.go +++ b/examples/delegator/main.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style @@ -10,8 +10,8 @@ package main import ( "flag" - "github.com/prometheus/client_golang" - "github.com/prometheus/client_golang/exp" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/exp" "net/http" ) @@ -48,7 +48,7 @@ func main() { exp.HandleFunc("/hello", helloHandler) exp.HandleFunc("/goodbye", goodbyeHandler) exp.HandleFunc("/teapot", teapotHandler) - exp.Handle(registry.ExpositionResource, registry.DefaultHandler) + exp.Handle(prometheus.ExpositionResource, prometheus.DefaultHandler) http.ListenAndServe(*listeningAddress, exp.DefaultCoarseMux) } diff --git a/examples/documentation.go b/examples/documentation.go deleted file mode 100644 index e7586b9..0000000 --- a/examples/documentation.go +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2012, Matt T. Proud -// All rights reserved. -// -// Use of this source code is governed by a BSD-style license that can be found -// in the LICENSE file. - -// Various Prometheus client examples. -package examples diff --git a/examples/random/.gitignore b/examples/random/.gitignore new file mode 100644 index 0000000..19cec5d --- /dev/null +++ b/examples/random/.gitignore @@ -0,0 +1 @@ +random \ No newline at end of file diff --git a/examples/random/Makefile b/examples/random/Makefile new file mode 100644 index 0000000..c54b305 --- /dev/null +++ b/examples/random/Makefile @@ -0,0 +1,32 @@ +# 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. + +MAKE_ARTIFACTS = random + +all: test + +build: random + +random: + go build . + +test: build + go test . $(GO_TEST_FLAGS) + +advice: + go tool vet . + +clean: + rm -f $(MAKE_ARTIFACTS) + +.PHONY: advice clean build test diff --git a/examples/random/main.go b/examples/random/main.go index f3bc001..dd41e2e 100644 --- a/examples/random/main.go +++ b/examples/random/main.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style @@ -13,9 +13,7 @@ package main import ( "flag" - "github.com/prometheus/client_golang" - "github.com/prometheus/client_golang/maths" - "github.com/prometheus/client_golang/metrics" + "github.com/prometheus/client_golang/prometheus" "math/rand" "net/http" "time" @@ -28,27 +26,27 @@ var ( // Create a histogram to track fictitious interservice RPC latency for three // distinct services. - rpcLatency = metrics.NewHistogram(&metrics.HistogramSpecification{ + rpcLatency = prometheus.NewHistogram(&prometheus.HistogramSpecification{ // Four distinct histogram buckets for values: // - equally-sized, // - 0 to 50, 50 to 100, 100 to 150, and 150 to 200. - Starts: metrics.EquallySizedBucketsFor(0, 200, 4), + Starts: prometheus.EquallySizedBucketsFor(0, 200, 4), // Create histogram buckets using an accumulating bucket, a bucket that // holds sample values subject to an eviction policy: // - 50 elements are allowed per bucket. // - Once 50 have been reached, the bucket empties 10 elements, averages the // evicted elements, and re-appends that back to the bucket. - BucketBuilder: metrics.AccumulatingBucketBuilder(metrics.EvictAndReplaceWith(10, maths.Average), 50), + BucketBuilder: prometheus.AccumulatingBucketBuilder(prometheus.EvictAndReplaceWith(10, prometheus.AverageReducer), 50), // The histogram reports percentiles 1, 5, 50, 90, and 99. ReportablePercentiles: []float64{0.01, 0.05, 0.5, 0.90, 0.99}, }) - rpcCalls = metrics.NewCounter() + rpcCalls = prometheus.NewCounter() // If for whatever reason you are resistant to the idea of having a static // registry for metrics, which is a really bad idea when using Prometheus- // enabled library code, you can create your own. - customRegistry = registry.NewRegistry() + customRegistry = prometheus.NewRegistry() ) func main() { @@ -69,13 +67,13 @@ func main() { } }() - http.Handle(registry.ExpositionResource, customRegistry.Handler()) + http.Handle(prometheus.ExpositionResource, customRegistry.Handler()) http.ListenAndServe(*listeningAddress, nil) } func init() { - customRegistry.Register("rpc_latency_microseconds", "RPC latency.", registry.NilLabels, rpcLatency) - customRegistry.Register("rpc_calls_total", "RPC calls.", registry.NilLabels, rpcCalls) + customRegistry.Register("rpc_latency_microseconds", "RPC latency.", prometheus.NilLabels, rpcLatency) + customRegistry.Register("rpc_calls_total", "RPC calls.", prometheus.NilLabels, rpcCalls) } var ( diff --git a/examples/simple/.gitignore b/examples/simple/.gitignore new file mode 100644 index 0000000..8fd3246 --- /dev/null +++ b/examples/simple/.gitignore @@ -0,0 +1 @@ +simple \ No newline at end of file diff --git a/examples/simple/Makefile b/examples/simple/Makefile new file mode 100644 index 0000000..dba8a98 --- /dev/null +++ b/examples/simple/Makefile @@ -0,0 +1,32 @@ +# 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. + +MAKE_ARTIFACTS = simple + +all: test + +build: simple + +simple: + go build . + +test: build + go test . $(GO_TEST_FLAGS) + +advice: + go tool vet . + +clean: + rm -f $(MAKE_ARTIFACTS) + +.PHONY: advice build clean test diff --git a/examples/simple/main.go b/examples/simple/main.go index 0b4e9df..25d527d 100644 --- a/examples/simple/main.go +++ b/examples/simple/main.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style @@ -10,14 +10,14 @@ package main import ( "flag" - "github.com/prometheus/client_golang" + "github.com/prometheus/client_golang/prometheus" "net/http" ) func main() { flag.Parse() - http.Handle(registry.ExpositionResource, registry.DefaultHandler) + http.Handle(prometheus.ExpositionResource, prometheus.DefaultHandler) http.ListenAndServe(*listeningAddress, nil) } diff --git a/maths/documentation.go b/maths/documentation.go deleted file mode 100644 index af7fbed..0000000 --- a/maths/documentation.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2012, Matt T. Proud -// All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// The maths package provides a number of mathematical-related helpers: -// -// distributions.go provides basic distribution-generating functions that are -// used primarily in testing contexts. -// -// helpers_for_testing.go provides a testing assistents for this package and its -// dependents. -// -// maths_test.go provides a test suite for all tests in the maths package -// hierarchy. It employs the gocheck framework for test scaffolding. -// -// statistics.go provides basic summary statistics functions for the purpose of -// metrics aggregation. -// -// statistics_test.go provides a test complement for the statistics.go module. -package maths diff --git a/maths/maths_test.go b/maths/maths_test.go deleted file mode 100644 index 4e5ff10..0000000 --- a/maths/maths_test.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2012, Matt T. Proud -// All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package maths - -import ( - . "github.com/matttproud/gocheck" - "testing" -) - -type S struct{} - -var _ = Suite(&S{}) - -func TestMaths(t *testing.T) { - TestingT(t) -} diff --git a/metrics/constants.go b/metrics/constants.go deleted file mode 100644 index 11c9a9b..0000000 --- a/metrics/constants.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2012, Matt T. Proud -// All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// constants.go provides package-level constants for metrics. -package metrics - -const ( - counterTypeValue = "counter" - floatBitCount = 64 - floatFormat = 'f' - floatPrecision = 6 - gaugeTypeValue = "gauge" - histogramTypeValue = "histogram" - typeKey = "type" - valueKey = "value" - labelsKey = "labels" -) diff --git a/metrics/documentation.go b/metrics/documentation.go deleted file mode 100644 index 8e60d61..0000000 --- a/metrics/documentation.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2012, Matt T. Proud -// All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// The metrics package provides general descriptors for the concept of -// exportable metrics. - -// accumulating_bucket.go provides a histogram bucket type that accumulates -// elements until a given capacity and enacts a given eviction policy upon -// such a condition. - -// accumulating_bucket_test.go provides a test complement for the -// accumulating_bucket_go module. - -// eviction.go provides several histogram bucket eviction strategies. - -// eviction_test.go provides a test complement for the eviction.go module. - -// gauge.go provides a scalar metric that one can monitor. It is useful for -// certain cases, such as instantaneous temperature. - -// gauge_test.go provides a test complement for the gauge.go module. - -// histogram.go provides a basic histogram metric, which can accumulate scalar -// event values or samples. The underlying histogram implementation is designed -// to be performant in that it accepts tolerable inaccuracies. - -// histogram_test.go provides a test complement for the histogram.go module. - -// metric.go provides fundamental interface expectations for the various -// metrics. - -// metrics_test.go provides a test suite for all tests in the metrics package -// hierarchy. It employs the gocheck framework for test scaffolding. - -// tallying_bucket.go provides a histogram bucket type that aggregates tallies -// of events that fall into its ranges versus a summary of the values -// themselves. - -// tallying_bucket_test.go provides a test complement for the -// tallying_bucket.go module. - -// timer.go provides a scalar metric that times how long a given event takes. - -// timer_test.go provides a test complement for the timer.go module. -package metrics diff --git a/metrics/eviction_test.go b/metrics/eviction_test.go deleted file mode 100644 index efc3e73..0000000 --- a/metrics/eviction_test.go +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright (c) 2012, Matt T. Proud -// 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 ( - "container/heap" - . "github.com/matttproud/gocheck" - "github.com/prometheus/client_golang/maths" - "github.com/prometheus/client_golang/utility" -) - -func (s *S) TestEvictOldest(c *C) { - q := make(utility.PriorityQueue, 0, 10) - heap.Init(&q) - var e EvictionPolicy = EvictOldest(5) - - for i := 0; i < 10; i++ { - var item utility.Item = utility.Item{ - Priority: int64(i), - Value: float64(i), - } - - heap.Push(&q, &item) - } - - c.Check(q, HasLen, 10) - - e(&q) - - c.Check(q, HasLen, 5) - - c.Check(heap.Pop(&q), utility.ValueEquals, 4.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 3.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 2.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 1.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 0.0) -} - -func (s *S) TestEvictAndReplaceWithAverage(c *C) { - q := make(utility.PriorityQueue, 0, 10) - heap.Init(&q) - var e EvictionPolicy = EvictAndReplaceWith(5, maths.Average) - - for i := 0; i < 10; i++ { - var item utility.Item = utility.Item{ - Priority: int64(i), - Value: float64(i), - } - - heap.Push(&q, &item) - } - - c.Check(q, HasLen, 10) - - e(&q) - - c.Check(q, HasLen, 6) - - c.Check(heap.Pop(&q), utility.ValueEquals, 4.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 3.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 2.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 1.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 0.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 7.0) -} - -func (s *S) TestEvictAndReplaceWithMedian(c *C) { - q := make(utility.PriorityQueue, 0, 10) - heap.Init(&q) - var e EvictionPolicy = EvictAndReplaceWith(5, maths.Median) - - for i := 0; i < 10; i++ { - var item utility.Item = utility.Item{ - Priority: int64(i), - Value: float64(i), - } - - heap.Push(&q, &item) - } - - c.Check(q, HasLen, 10) - - e(&q) - - c.Check(q, HasLen, 6) - - c.Check(heap.Pop(&q), utility.ValueEquals, 4.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 3.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 2.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 1.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 0.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 7.0) -} - -func (s *S) TestEvictAndReplaceWithFirstMode(c *C) { - q := make(utility.PriorityQueue, 0, 10) - heap.Init(&q) - e := EvictAndReplaceWith(5, maths.FirstMode) - - for i := 0; i < 10; i++ { - heap.Push(&q, &utility.Item{ - Priority: int64(i), - Value: float64(i), - }) - } - - c.Check(q, HasLen, 10) - - e(&q) - - c.Check(q, HasLen, 6) - - c.Check(heap.Pop(&q), utility.ValueEquals, 4.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 3.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 2.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 1.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 0.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 9.0) -} - -func (s *S) TestEvictAndReplaceWithMinimum(c *C) { - q := make(utility.PriorityQueue, 0, 10) - heap.Init(&q) - var e EvictionPolicy = EvictAndReplaceWith(5, maths.Minimum) - - for i := 0; i < 10; i++ { - var item utility.Item = utility.Item{ - Priority: int64(i), - Value: float64(i), - } - - heap.Push(&q, &item) - } - - c.Check(q, HasLen, 10) - - e(&q) - - c.Check(q, HasLen, 6) - - c.Check(heap.Pop(&q), utility.ValueEquals, 4.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 3.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 2.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 1.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 0.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 5.0) -} - -func (s *S) TestEvictAndReplaceWithMaximum(c *C) { - q := make(utility.PriorityQueue, 0, 10) - heap.Init(&q) - var e EvictionPolicy = EvictAndReplaceWith(5, maths.Maximum) - - for i := 0; i < 10; i++ { - var item utility.Item = utility.Item{ - Priority: int64(i), - Value: float64(i), - } - - heap.Push(&q, &item) - } - - c.Check(q, HasLen, 10) - - e(&q) - - c.Check(q, HasLen, 6) - - c.Check(heap.Pop(&q), utility.ValueEquals, 4.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 3.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 2.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 1.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 0.0) - c.Check(heap.Pop(&q), utility.ValueEquals, 9.0) -} diff --git a/prometheus/.gitignore b/prometheus/.gitignore new file mode 100644 index 0000000..3460f03 --- /dev/null +++ b/prometheus/.gitignore @@ -0,0 +1 @@ +command-line-arguments.test diff --git a/prometheus/Makefile b/prometheus/Makefile new file mode 100644 index 0000000..85b7b46 --- /dev/null +++ b/prometheus/Makefile @@ -0,0 +1,25 @@ +# 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. + +all: test + +build: + go build ./... + +test: build + go test ./... $(GO_TEST_FLAGS) + +advice: + go tool vet . + +.PHONY: advice build test diff --git a/metrics/accumulating_bucket.go b/prometheus/accumulating_bucket.go similarity index 91% rename from metrics/accumulating_bucket.go rename to prometheus/accumulating_bucket.go index 7c219b7..73d8530 100644 --- a/metrics/accumulating_bucket.go +++ b/prometheus/accumulating_bucket.go @@ -1,16 +1,15 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // 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 +package prometheus import ( "bytes" "container/heap" "fmt" - "github.com/prometheus/client_golang/utility" "math" "sort" "sync" @@ -18,7 +17,7 @@ import ( ) type AccumulatingBucket struct { - elements utility.PriorityQueue + elements priorityQueue evictionPolicy EvictionPolicy maximumSize int mutex sync.RWMutex @@ -31,7 +30,7 @@ type AccumulatingBucket struct { func AccumulatingBucketBuilder(evictionPolicy EvictionPolicy, maximumSize int) BucketBuilder { return func() Bucket { return &AccumulatingBucket{ - elements: make(utility.PriorityQueue, 0, maximumSize), + elements: make(priorityQueue, 0, maximumSize), evictionPolicy: evictionPolicy, maximumSize: maximumSize, } @@ -47,7 +46,7 @@ func (b *AccumulatingBucket) Add(value float64) { b.observations++ size := len(b.elements) - v := utility.Item{ + v := item{ Priority: -1 * time.Now().UnixNano(), Value: value, } diff --git a/metrics/accumulating_bucket_test.go b/prometheus/accumulating_bucket_test.go similarity index 93% rename from metrics/accumulating_bucket_test.go rename to prometheus/accumulating_bucket_test.go index 789c682..b575ed3 100644 --- a/metrics/accumulating_bucket_test.go +++ b/prometheus/accumulating_bucket_test.go @@ -1,15 +1,13 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // 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 +package prometheus import ( . "github.com/matttproud/gocheck" - "github.com/prometheus/client_golang/maths" - "github.com/prometheus/client_golang/utility" "time" ) @@ -51,7 +49,7 @@ func (s *S) TestAccumulatingBucketBuilderWithEvictOldest(c *C) { } func (s *S) TestAccumulatingBucketBuilderWithEvictAndReplaceWithAverage(c *C) { - var evictAndReplaceWithAverage EvictionPolicy = EvictAndReplaceWith(3, maths.Average) + var evictAndReplaceWithAverage EvictionPolicy = EvictAndReplaceWith(3, AverageReducer) c.Assert(evictAndReplaceWithAverage, Not(IsNil)) @@ -86,7 +84,7 @@ func (s *S) TestAccumulatingBucketBuilderWithEvictAndReplaceWithAverage(c *C) { func (s *S) TestAccumulatingBucket(c *C) { var b AccumulatingBucket = AccumulatingBucket{ - elements: make(utility.PriorityQueue, 0, 10), + elements: make(priorityQueue, 0, 10), maximumSize: 5, } @@ -112,13 +110,13 @@ func (s *S) TestAccumulatingBucket(c *C) { func (s *S) TestAccumulatingBucketValueForIndex(c *C) { var b AccumulatingBucket = AccumulatingBucket{ - elements: make(utility.PriorityQueue, 0, 100), + elements: make(priorityQueue, 0, 100), maximumSize: 100, evictionPolicy: EvictOldest(50), } for i := 0; i <= 100; i++ { - c.Assert(b.ValueForIndex(i), maths.IsNaN) + c.Assert(b.ValueForIndex(i), IsNaN) } // The bucket has only observed one item and contains now one item. diff --git a/metrics/bucket.go b/prometheus/bucket.go similarity index 88% rename from metrics/bucket.go rename to prometheus/bucket.go index d4a8414..fe5f42c 100644 --- a/metrics/bucket.go +++ b/prometheus/bucket.go @@ -1,12 +1,10 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// bucket.go provides fundamental interface expectations for various bucket -// types. -package metrics +package prometheus // The Histogram class and associated types build buckets on their own. type BucketBuilder func() Bucket diff --git a/constants.go b/prometheus/constants.go similarity index 78% rename from constants.go rename to prometheus/constants.go index e992d5e..58dc855 100644 --- a/constants.go +++ b/prometheus/constants.go @@ -1,10 +1,10 @@ -// Copyright (c) 2013, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style license that can be found // in the LICENSE file. -package registry +package prometheus var ( // NilLabels is a nil set of labels merely for end-user convenience. @@ -14,8 +14,7 @@ var ( // interface. DefaultHandler = DefaultRegistry.Handler() - // This is the default registry with which Metric objects are associated. It - // is primarily a read-only object after server instantiation. + // This is the default registry with which Metric objects are associated. DefaultRegistry = NewRegistry() ) @@ -39,4 +38,14 @@ const ( docstringKey = "docstring" metricKey = "metric" nameLabel = "name" + + counterTypeValue = "counter" + floatBitCount = 64 + floatFormat = 'f' + floatPrecision = 6 + gaugeTypeValue = "gauge" + histogramTypeValue = "histogram" + typeKey = "type" + valueKey = "value" + labelsKey = "labels" ) diff --git a/metrics/counter.go b/prometheus/counter.go similarity index 92% rename from metrics/counter.go rename to prometheus/counter.go index 78bdce2..74b76dd 100644 --- a/metrics/counter.go +++ b/prometheus/counter.go @@ -1,14 +1,13 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // 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 +package prometheus import ( "fmt" - "github.com/prometheus/client_golang/utility" "sync" ) @@ -49,7 +48,7 @@ func (metric *counter) Set(labels map[string]string, value float64) float64 { labels = map[string]string{} } - signature := utility.LabelsToSignature(labels) + signature := labelsToSignature(labels) if original, ok := metric.values[signature]; ok { original.value = value } else { @@ -91,7 +90,7 @@ func (metric *counter) IncrementBy(labels map[string]string, value float64) floa labels = map[string]string{} } - signature := utility.LabelsToSignature(labels) + signature := labelsToSignature(labels) if original, ok := metric.values[signature]; ok { original.value += value } else { @@ -116,7 +115,7 @@ func (metric *counter) DecrementBy(labels map[string]string, value float64) floa labels = map[string]string{} } - signature := utility.LabelsToSignature(labels) + signature := labelsToSignature(labels) if original, ok := metric.values[signature]; ok { original.value -= value } else { diff --git a/metrics/counter_test.go b/prometheus/counter_test.go similarity index 96% rename from metrics/counter_test.go rename to prometheus/counter_test.go index aa489e5..b2023f0 100644 --- a/metrics/counter_test.go +++ b/prometheus/counter_test.go @@ -1,18 +1,17 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // 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 +package prometheus import ( "encoding/json" - "github.com/prometheus/client_golang/utility/test" "testing" ) -func testCounter(t test.Tester) { +func testCounter(t tester) { type input struct { steps []func(g Counter) } diff --git a/maths/distributions.go b/prometheus/distributions.go similarity index 74% rename from maths/distributions.go rename to prometheus/distributions.go index 50783c6..47874a1 100644 --- a/maths/distributions.go +++ b/prometheus/distributions.go @@ -1,17 +1,17 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package maths +package prometheus import ( "math" ) // Go's standard library does not offer a factorial function. -func Factorial(of int) int64 { +func factorial(of int) int64 { if of <= 0 { return 1 } @@ -28,8 +28,8 @@ func Factorial(of int) int64 { // Calculate the value of a probability density for a given binomial statistic, // where k is the target count of true cases, n is the number of subjects, and // p is the probability. -func BinomialPDF(k, n int, p float64) float64 { - binomialCoefficient := float64(Factorial(n)) / float64(Factorial(k)*Factorial(n-k)) +func binomialPDF(k, n int, p float64) float64 { + binomialCoefficient := float64(factorial(n)) / float64(factorial(k)*factorial(n-k)) intermediate := math.Pow(p, float64(k)) * math.Pow(1-p, float64(n-k)) return binomialCoefficient * intermediate diff --git a/prometheus/documentation.go b/prometheus/documentation.go new file mode 100644 index 0000000..6da5e45 --- /dev/null +++ b/prometheus/documentation.go @@ -0,0 +1,16 @@ +// Copyright (c) 2013, Prometheus Team +// All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found +// in the LICENSE file. + +// Prometheus' client side metric primitives and telemetry exposition framework. +// +// This package provides both metric primitives and tools for their exposition +// to the Prometheus time series collection and computation framework. +// +// prometheus.Register("human_readable_metric_name", "metric docstring", map[string]string{"baseLabel": "baseLabelValue"}, metric) +// +// The examples under github.com/prometheus/client_golang/examples should be +// consulted. +package prometheus diff --git a/metrics/eviction.go b/prometheus/eviction.go similarity index 76% rename from metrics/eviction.go rename to prometheus/eviction.go index 904d08b..425a4a1 100644 --- a/metrics/eviction.go +++ b/prometheus/eviction.go @@ -1,15 +1,13 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // 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 +package prometheus import ( "container/heap" - "github.com/prometheus/client_golang/maths" - "github.com/prometheus/client_golang/utility" "time" ) @@ -29,17 +27,17 @@ func EvictOldest(count int) EvictionPolicy { // This factory produces an EvictionPolicy that applies some standardized // reduction methodology on the to-be-terminated values. -func EvictAndReplaceWith(count int, reducer maths.ReductionMethod) EvictionPolicy { +func EvictAndReplaceWith(count int, reducer ReductionMethod) EvictionPolicy { return func(h heap.Interface) { oldValues := make([]float64, count) for i := 0; i < count; i++ { - oldValues[i] = heap.Pop(h).(*utility.Item).Value.(float64) + oldValues[i] = heap.Pop(h).(*item).Value.(float64) } reduced := reducer(oldValues) - heap.Push(h, &utility.Item{ + heap.Push(h, &item{ Value: reduced, // TODO(mtp): Parameterize the priority generation since these tools are // useful. diff --git a/prometheus/eviction_test.go b/prometheus/eviction_test.go new file mode 100644 index 0000000..b782a0e --- /dev/null +++ b/prometheus/eviction_test.go @@ -0,0 +1,177 @@ +// Copyright (c) 2013, Prometheus Team +// All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package prometheus + +import ( + "container/heap" + . "github.com/matttproud/gocheck" +) + +func (s *S) TestEvictOldest(c *C) { + q := make(priorityQueue, 0, 10) + heap.Init(&q) + var e EvictionPolicy = EvictOldest(5) + + for i := 0; i < 10; i++ { + var item item = item{ + Priority: int64(i), + Value: float64(i), + } + + heap.Push(&q, &item) + } + + c.Check(q, HasLen, 10) + + e(&q) + + c.Check(q, HasLen, 5) + + c.Check(heap.Pop(&q), ValueEquals, 4.0) + c.Check(heap.Pop(&q), ValueEquals, 3.0) + c.Check(heap.Pop(&q), ValueEquals, 2.0) + c.Check(heap.Pop(&q), ValueEquals, 1.0) + c.Check(heap.Pop(&q), ValueEquals, 0.0) +} + +func (s *S) TestEvictAndReplaceWithAverage(c *C) { + q := make(priorityQueue, 0, 10) + heap.Init(&q) + var e EvictionPolicy = EvictAndReplaceWith(5, AverageReducer) + + for i := 0; i < 10; i++ { + var item item = item{ + Priority: int64(i), + Value: float64(i), + } + + heap.Push(&q, &item) + } + + c.Check(q, HasLen, 10) + + e(&q) + + c.Check(q, HasLen, 6) + + c.Check(heap.Pop(&q), ValueEquals, 4.0) + c.Check(heap.Pop(&q), ValueEquals, 3.0) + c.Check(heap.Pop(&q), ValueEquals, 2.0) + c.Check(heap.Pop(&q), ValueEquals, 1.0) + c.Check(heap.Pop(&q), ValueEquals, 0.0) + c.Check(heap.Pop(&q), ValueEquals, 7.0) +} + +func (s *S) TestEvictAndReplaceWithMedian(c *C) { + q := make(priorityQueue, 0, 10) + heap.Init(&q) + var e EvictionPolicy = EvictAndReplaceWith(5, MedianReducer) + + for i := 0; i < 10; i++ { + var item item = item{ + Priority: int64(i), + Value: float64(i), + } + + heap.Push(&q, &item) + } + + c.Check(q, HasLen, 10) + + e(&q) + + c.Check(q, HasLen, 6) + + c.Check(heap.Pop(&q), ValueEquals, 4.0) + c.Check(heap.Pop(&q), ValueEquals, 3.0) + c.Check(heap.Pop(&q), ValueEquals, 2.0) + c.Check(heap.Pop(&q), ValueEquals, 1.0) + c.Check(heap.Pop(&q), ValueEquals, 0.0) + c.Check(heap.Pop(&q), ValueEquals, 7.0) +} + +func (s *S) TestEvictAndReplaceWithFirstMode(c *C) { + q := make(priorityQueue, 0, 10) + heap.Init(&q) + e := EvictAndReplaceWith(5, FirstModeReducer) + + for i := 0; i < 10; i++ { + heap.Push(&q, &item{ + Priority: int64(i), + Value: float64(i), + }) + } + + c.Check(q, HasLen, 10) + + e(&q) + + c.Check(q, HasLen, 6) + + c.Check(heap.Pop(&q), ValueEquals, 4.0) + c.Check(heap.Pop(&q), ValueEquals, 3.0) + c.Check(heap.Pop(&q), ValueEquals, 2.0) + c.Check(heap.Pop(&q), ValueEquals, 1.0) + c.Check(heap.Pop(&q), ValueEquals, 0.0) + c.Check(heap.Pop(&q), ValueEquals, 9.0) +} + +func (s *S) TestEvictAndReplaceWithMinimum(c *C) { + q := make(priorityQueue, 0, 10) + heap.Init(&q) + var e EvictionPolicy = EvictAndReplaceWith(5, MinimumReducer) + + for i := 0; i < 10; i++ { + var item item = item{ + Priority: int64(i), + Value: float64(i), + } + + heap.Push(&q, &item) + } + + c.Check(q, HasLen, 10) + + e(&q) + + c.Check(q, HasLen, 6) + + c.Check(heap.Pop(&q), ValueEquals, 4.0) + c.Check(heap.Pop(&q), ValueEquals, 3.0) + c.Check(heap.Pop(&q), ValueEquals, 2.0) + c.Check(heap.Pop(&q), ValueEquals, 1.0) + c.Check(heap.Pop(&q), ValueEquals, 0.0) + c.Check(heap.Pop(&q), ValueEquals, 5.0) +} + +func (s *S) TestEvictAndReplaceWithMaximum(c *C) { + q := make(priorityQueue, 0, 10) + heap.Init(&q) + var e EvictionPolicy = EvictAndReplaceWith(5, MaximumReducer) + + for i := 0; i < 10; i++ { + var item item = item{ + Priority: int64(i), + Value: float64(i), + } + + heap.Push(&q, &item) + } + + c.Check(q, HasLen, 10) + + e(&q) + + c.Check(q, HasLen, 6) + + c.Check(heap.Pop(&q), ValueEquals, 4.0) + c.Check(heap.Pop(&q), ValueEquals, 3.0) + c.Check(heap.Pop(&q), ValueEquals, 2.0) + c.Check(heap.Pop(&q), ValueEquals, 1.0) + c.Check(heap.Pop(&q), ValueEquals, 0.0) + c.Check(heap.Pop(&q), ValueEquals, 9.0) +} diff --git a/exp/coarsemux.go b/prometheus/exp/coarsemux.go similarity index 67% rename from exp/coarsemux.go rename to prometheus/exp/coarsemux.go index 74af6d7..6c523da 100644 --- a/exp/coarsemux.go +++ b/prometheus/exp/coarsemux.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style license that can be found in @@ -8,8 +8,7 @@ package exp import ( "fmt" - "github.com/prometheus/client_golang" - "github.com/prometheus/client_golang/metrics" + "github.com/prometheus/client_golang/prometheus" "net/http" "strings" "time" @@ -33,11 +32,11 @@ type ( ) var ( - requestCounts = metrics.NewCounter() - requestDuration = metrics.NewCounter() - requestDurations = metrics.NewDefaultHistogram() - requestBytes = metrics.NewCounter() - responseBytes = metrics.NewCounter() + requestCounts = prometheus.NewCounter() + requestDuration = prometheus.NewCounter() + requestDurations = prometheus.NewDefaultHistogram() + requestBytes = prometheus.NewCounter() + responseBytes = prometheus.NewCounter() // DefaultCoarseMux is a drop-in replacement for http.DefaultServeMux that // provides standardized telemetry for Go's standard HTTP handler registration @@ -103,9 +102,9 @@ func HandleFunc(pattern string, handler http.HandlerFunc) { } func init() { - registry.Register("http_requests_total", "A counter of the total number of HTTP requests made against the default multiplexor.", registry.NilLabels, requestCounts) - registry.Register("http_request_durations_total_microseconds", "The total amount of time the default multiplexor has spent answering HTTP requests (microseconds).", registry.NilLabels, requestDuration) - registry.Register("http_request_durations_microseconds", "The amounts of time the default multiplexor has spent answering HTTP requests (microseconds).", registry.NilLabels, requestDurations) - registry.Register("http_request_bytes_total", "The total volume of content body sizes received (bytes).", registry.NilLabels, requestBytes) - registry.Register("http_response_bytes_total", "The total volume of response payloads emitted (bytes).", registry.NilLabels, responseBytes) + prometheus.Register("http_requests_total", "A counter of the total number of HTTP requests made against the default multiplexor.", prometheus.NilLabels, requestCounts) + prometheus.Register("http_request_durations_total_microseconds", "The total amount of time the default multiplexor has spent answering HTTP requests (microseconds).", prometheus.NilLabels, requestDuration) + prometheus.Register("http_request_durations_microseconds", "The amounts of time the default multiplexor has spent answering HTTP requests (microseconds).", prometheus.NilLabels, requestDurations) + prometheus.Register("http_request_bytes_total", "The total volume of content body sizes received (bytes).", prometheus.NilLabels, requestBytes) + prometheus.Register("http_response_bytes_total", "The total volume of response payloads emitted (bytes).", prometheus.NilLabels, responseBytes) } diff --git a/exp/documentation.go b/prometheus/exp/documentation.go similarity index 91% rename from exp/documentation.go rename to prometheus/exp/documentation.go index 7d358ca..9268a78 100644 --- a/exp/documentation.go +++ b/prometheus/exp/documentation.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style license that can be found in diff --git a/exp/responsewriter_delegator.go b/prometheus/exp/responsewriter_delegator.go similarity index 98% rename from exp/responsewriter_delegator.go rename to prometheus/exp/responsewriter_delegator.go index c92ec46..3f0b694 100644 --- a/exp/responsewriter_delegator.go +++ b/prometheus/exp/responsewriter_delegator.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style license that can be found in diff --git a/metrics/gauge.go b/prometheus/gauge.go similarity index 93% rename from metrics/gauge.go rename to prometheus/gauge.go index 7ea05c2..e5f6553 100644 --- a/metrics/gauge.go +++ b/prometheus/gauge.go @@ -1,14 +1,13 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // 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 +package prometheus import ( "fmt" - "github.com/prometheus/client_golang/utility" "sync" ) @@ -56,7 +55,7 @@ func (metric *gauge) Set(labels map[string]string, value float64) float64 { labels = map[string]string{} } - signature := utility.LabelsToSignature(labels) + signature := labelsToSignature(labels) if original, ok := metric.values[signature]; ok { original.value = value diff --git a/metrics/gauge_test.go b/prometheus/gauge_test.go similarity index 94% rename from metrics/gauge_test.go rename to prometheus/gauge_test.go index 5bc6c8f..8e7e5f1 100644 --- a/metrics/gauge_test.go +++ b/prometheus/gauge_test.go @@ -1,18 +1,17 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // 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 +package prometheus import ( "encoding/json" - "github.com/prometheus/client_golang/utility/test" "testing" ) -func testGauge(t test.Tester) { +func testGauge(t tester) { type input struct { steps []func(g Gauge) } diff --git a/maths/helpers_for_testing.go b/prometheus/helpers_for_testing.go similarity index 93% rename from maths/helpers_for_testing.go rename to prometheus/helpers_for_testing.go index aac7951..76dd5df 100644 --- a/maths/helpers_for_testing.go +++ b/prometheus/helpers_for_testing.go @@ -1,10 +1,10 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package maths +package prometheus import ( . "github.com/matttproud/gocheck" diff --git a/metrics/histogram.go b/prometheus/histogram.go similarity index 97% rename from metrics/histogram.go rename to prometheus/histogram.go index 8420998..ca3ce93 100644 --- a/metrics/histogram.go +++ b/prometheus/histogram.go @@ -1,16 +1,14 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // 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 +package prometheus import ( "bytes" "fmt" - "github.com/prometheus/client_golang/maths" - "github.com/prometheus/client_golang/utility" "math" "strconv" "sync" @@ -96,7 +94,7 @@ func (h *histogram) Add(labels map[string]string, value float64) { labels = map[string]string{} } - signature := utility.LabelsToSignature(labels) + signature := labelsToSignature(labels) var histogram *histogramVector = nil if original, ok := h.values[signature]; ok { histogram = original @@ -298,7 +296,7 @@ func NewDefaultHistogram() Histogram { return NewHistogram( &HistogramSpecification{ Starts: LogarithmicSizedBucketsFor(0, 4096), - BucketBuilder: AccumulatingBucketBuilder(EvictAndReplaceWith(10, maths.Average), 50), + BucketBuilder: AccumulatingBucketBuilder(EvictAndReplaceWith(10, AverageReducer), 50), ReportablePercentiles: []float64{0.01, 0.05, 0.5, 0.90, 0.99}, }, ) diff --git a/metrics/histogram_test.go b/prometheus/histogram_test.go similarity index 75% rename from metrics/histogram_test.go rename to prometheus/histogram_test.go index 5171059..acb3be3 100644 --- a/metrics/histogram_test.go +++ b/prometheus/histogram_test.go @@ -1,9 +1,9 @@ -// Copyright (c) 2013, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // 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 +package prometheus // TODO(matt): Re-Add tests for this type. diff --git a/utility/test/interface.go b/prometheus/interface.go similarity index 77% rename from utility/test/interface.go rename to prometheus/interface.go index de30938..9b5de19 100644 --- a/utility/test/interface.go +++ b/prometheus/interface.go @@ -1,12 +1,12 @@ -// Copyright (c) 2013, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package test +package prometheus -type Tester interface { +type tester interface { Error(args ...interface{}) Errorf(format string, args ...interface{}) Fatal(args ...interface{}) diff --git a/metrics/metric.go b/prometheus/metric.go similarity index 89% rename from metrics/metric.go rename to prometheus/metric.go index 65a1b6f..9753130 100644 --- a/metrics/metric.go +++ b/prometheus/metric.go @@ -1,10 +1,10 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // 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 +package prometheus // A Metric is something that can be exposed via the registry framework. type Metric interface { diff --git a/utility/priority_queue.go b/prometheus/priority_queue.go similarity index 61% rename from utility/priority_queue.go rename to prometheus/priority_queue.go index 36ebd64..0f43b68 100644 --- a/utility/priority_queue.go +++ b/prometheus/priority_queue.go @@ -1,44 +1,44 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package utility +package prometheus -type Item struct { +type item struct { Priority int64 Value interface{} index int } -type PriorityQueue []*Item +type priorityQueue []*item -func (q PriorityQueue) Len() int { +func (q priorityQueue) Len() int { return len(q) } -func (q PriorityQueue) Less(i, j int) bool { +func (q priorityQueue) Less(i, j int) bool { return q[i].Priority > q[j].Priority } -func (q PriorityQueue) Swap(i, j int) { +func (q priorityQueue) Swap(i, j int) { q[i], q[j] = q[j], q[i] q[i].index = i q[j].index = j } -func (q *PriorityQueue) Push(x interface{}) { +func (q *priorityQueue) Push(x interface{}) { queue := *q size := len(queue) queue = queue[0 : size+1] - item := x.(*Item) + item := x.(*item) item.index = size queue[size] = item *q = queue } -func (q *PriorityQueue) Pop() interface{} { +func (q *priorityQueue) Pop() interface{} { queue := *q size := len(queue) item := queue[size-1] diff --git a/utility/priority_queue_test.go b/prometheus/priority_queue_test.go similarity index 58% rename from utility/priority_queue_test.go rename to prometheus/priority_queue_test.go index 0f66a1a..63b5288 100644 --- a/utility/priority_queue_test.go +++ b/prometheus/priority_queue_test.go @@ -1,10 +1,10 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package utility +package prometheus import ( "container/heap" @@ -12,16 +12,16 @@ import ( ) func (s *S) TestPriorityQueueSort(c *C) { - q := make(PriorityQueue, 0, 6) + q := make(priorityQueue, 0, 6) c.Check(len(q), Equals, 0) - heap.Push(&q, &Item{Value: "newest", Priority: -100}) - heap.Push(&q, &Item{Value: "older", Priority: 90}) - heap.Push(&q, &Item{Value: "oldest", Priority: 100}) - heap.Push(&q, &Item{Value: "newer", Priority: -90}) - heap.Push(&q, &Item{Value: "new", Priority: -80}) - heap.Push(&q, &Item{Value: "old", Priority: 80}) + heap.Push(&q, &item{Value: "newest", Priority: -100}) + heap.Push(&q, &item{Value: "older", Priority: 90}) + heap.Push(&q, &item{Value: "oldest", Priority: 100}) + heap.Push(&q, &item{Value: "newer", Priority: -90}) + heap.Push(&q, &item{Value: "new", Priority: -80}) + heap.Push(&q, &item{Value: "old", Priority: 80}) c.Check(len(q), Equals, 6) diff --git a/metrics/metrics_test.go b/prometheus/prometheus_test.go similarity index 72% rename from metrics/metrics_test.go rename to prometheus/prometheus_test.go index a2a81ae..a5de18a 100644 --- a/metrics/metrics_test.go +++ b/prometheus/prometheus_test.go @@ -1,10 +1,10 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // 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 +package prometheus import ( . "github.com/matttproud/gocheck" @@ -15,6 +15,6 @@ type S struct{} var _ = Suite(&S{}) -func TestMetrics(t *testing.T) { +func TestPrometheus(t *testing.T) { TestingT(t) } diff --git a/registry.go b/prometheus/registry.go similarity index 94% rename from registry.go rename to prometheus/registry.go index 8c77310..28ab774 100644 --- a/registry.go +++ b/prometheus/registry.go @@ -1,10 +1,10 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style license that can be found // in the LICENSE file. -package registry +package prometheus import ( "compress/gzip" @@ -12,8 +12,6 @@ import ( "encoding/json" "flag" "fmt" - "github.com/prometheus/client_golang/metrics" - "github.com/prometheus/client_golang/utility" "io" "log" "net/http" @@ -46,7 +44,7 @@ var ( type container struct { baseLabels map[string]string docstring string - metric metrics.Metric + metric Metric name string } @@ -61,7 +59,7 @@ type registry struct { // own. type Registry interface { // Register a metric with a given name. Name should be globally unique. - Register(name, docstring string, baseLabels map[string]string, metric metrics.Metric) error + Register(name, docstring string, baseLabels map[string]string, metric Metric) error // Create a http.HandlerFunc that is tied to a Registry such that requests // against it generate a representation of the housed metrics. Handler() http.HandlerFunc @@ -79,7 +77,7 @@ func NewRegistry() Registry { } // Associate a Metric with the DefaultRegistry. -func Register(name, docstring string, baseLabels map[string]string, metric metrics.Metric) error { +func Register(name, docstring string, baseLabels map[string]string, metric Metric) error { return DefaultRegistry.Register(name, docstring, baseLabels, metric) } @@ -110,7 +108,7 @@ func (r registry) isValidCandidate(name string, baseLabels map[string]string) (s } baseLabels[nameLabel] = name - signature = utility.LabelsToSignature(baseLabels) + signature = labelsToSignature(baseLabels) if _, contains := r.signatureContainers[signature]; contains { err = fmt.Errorf("metric named %s with baseLabels %s is already registered", name, baseLabels) @@ -141,7 +139,7 @@ func (r registry) isValidCandidate(name string, baseLabels map[string]string) (s return } -func (r registry) Register(name, docstring string, baseLabels map[string]string, metric metrics.Metric) (err error) { +func (r registry) Register(name, docstring string, baseLabels map[string]string, metric Metric) (err error) { r.mutex.Lock() defer r.mutex.Unlock() @@ -271,7 +269,7 @@ func (registry registry) YieldExporter() http.HandlerFunc { func (registry registry) Handler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - var instrumentable metrics.InstrumentableCall = func() { + var instrumentable InstrumentableCall = func() { requestCount.Increment(nil) url := r.URL @@ -293,7 +291,7 @@ func (registry registry) Handler() http.HandlerFunc { } } - metrics.InstrumentCall(instrumentable, requestLatencyAccumulator) + InstrumentCall(instrumentable, requestLatencyAccumulator) } } diff --git a/registry_test.go b/prometheus/registry_test.go similarity index 92% rename from registry_test.go rename to prometheus/registry_test.go index 175c3a0..df0f1c2 100644 --- a/registry_test.go +++ b/prometheus/registry_test.go @@ -1,22 +1,20 @@ -// Copyright (c) 2013, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style license that can be found // in the LICENSE file. -package registry +package prometheus import ( "bytes" "fmt" - "github.com/prometheus/client_golang/metrics" - "github.com/prometheus/client_golang/utility/test" "io" "net/http" "testing" ) -func testRegister(t test.Tester) { +func testRegister(t tester) { var oldState = struct { abortOnMisuse bool debugRegistration bool @@ -181,7 +179,7 @@ func (r *fakeResponseWriter) Write(d []byte) (l int, err error) { func (r *fakeResponseWriter) WriteHeader(c int) { } -func testDecorateWriter(t test.Tester) { +func testDecorateWriter(t tester) { type input struct { headers map[string]string body []byte @@ -266,9 +264,9 @@ func BenchmarkDecorateWriter(b *testing.B) { } } -func testDumpToWriter(t test.Tester) { +func testDumpToWriter(t tester) { type input struct { - metrics map[string]metrics.Metric + metrics map[string]Metric } var scenarios = []struct { @@ -280,17 +278,17 @@ func testDumpToWriter(t test.Tester) { }, { in: input{ - metrics: map[string]metrics.Metric{ - "foo": metrics.NewCounter(), + metrics: map[string]Metric{ + "foo": NewCounter(), }, }, out: []byte("[{\"baseLabels\":{\"label_foo\":\"foo\",\"name\":\"foo\"},\"docstring\":\"metric foo\",\"metric\":{\"type\":\"counter\",\"value\":[]}}]"), }, { in: input{ - metrics: map[string]metrics.Metric{ - "foo": metrics.NewCounter(), - "bar": metrics.NewCounter(), + metrics: map[string]Metric{ + "foo": NewCounter(), + "bar": NewCounter(), }, }, out: []byte("[{\"baseLabels\":{\"label_bar\":\"bar\",\"name\":\"bar\"},\"docstring\":\"metric bar\",\"metric\":{\"type\":\"counter\",\"value\":[]}},{\"baseLabels\":{\"label_foo\":\"foo\",\"name\":\"foo\"},\"docstring\":\"metric foo\",\"metric\":{\"type\":\"counter\",\"value\":[]}}]"), diff --git a/utility/signature.go b/prometheus/signature.go similarity index 87% rename from utility/signature.go rename to prometheus/signature.go index 610af73..237170d 100644 --- a/utility/signature.go +++ b/prometheus/signature.go @@ -1,10 +1,10 @@ -// Copyright (c) 2013, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package utility +package prometheus import ( "bytes" @@ -17,7 +17,7 @@ const ( // LabelsToSignature provides a way of building a unique signature // (i.e., fingerprint) for a given label set sequence. -func LabelsToSignature(labels map[string]string) string { +func labelsToSignature(labels map[string]string) string { // TODO(matt): This is a wart, and we'll want to validate that collisions // do not occur in less-than-diligent environments. cardinality := len(labels) diff --git a/utility/signature_test.go b/prometheus/signature_test.go similarity index 75% rename from utility/signature_test.go rename to prometheus/signature_test.go index 1f924fc..f544237 100644 --- a/utility/signature_test.go +++ b/prometheus/signature_test.go @@ -1,17 +1,16 @@ -// Copyright (c) 2013, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package utility +package prometheus import ( - "github.com/prometheus/client_golang/utility/test" "testing" ) -func testLabelsToSignature(t test.Tester) { +func testLabelsToSignature(t tester) { var scenarios = []struct { in map[string]string out string @@ -24,7 +23,7 @@ func testLabelsToSignature(t test.Tester) { } for i, scenario := range scenarios { - actual := LabelsToSignature(scenario.in) + actual := labelsToSignature(scenario.in) if actual != scenario.out { t.Errorf("%d. expected %s, got %s", i, scenario.out, actual) diff --git a/maths/statistics.go b/prometheus/statistics.go similarity index 63% rename from maths/statistics.go rename to prometheus/statistics.go index 6e190c0..a419224 100644 --- a/maths/statistics.go +++ b/prometheus/statistics.go @@ -1,10 +1,10 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package maths +package prometheus import ( "math" @@ -14,11 +14,32 @@ import ( // TODO(mtp): Split this out into a summary statistics file once moving/rolling // averages are calculated. -// ReductionMethod provides a method for reducing metrics into a given scalar -// value. +// ReductionMethod provides a method for reducing metrics into a scalar value. type ReductionMethod func([]float64) float64 -var Average ReductionMethod = func(input []float64) float64 { +var ( + medianReducer = NearestRankReducer(50) +) + +// These are the canned ReductionMethods. +var ( + // Reduce to the average of the set. + AverageReducer = averageReducer + + // Extract the first modal value. + FirstModeReducer = firstModeReducer + + // Reduce to the maximum of the set. + MaximumReducer = maximumReducer + + // Reduce to the median of the set. + MedianReducer = medianReducer + + // Reduce to the minimum of the set. + MinimumReducer = minimumReducer +) + +func averageReducer(input []float64) float64 { count := 0.0 sum := 0.0 @@ -34,11 +55,10 @@ var Average ReductionMethod = func(input []float64) float64 { return sum / count } -// Extract the first modal value. -var FirstMode ReductionMethod = func(input []float64) float64 { +func firstModeReducer(input []float64) float64 { valuesToFrequency := map[float64]int64{} - var largestTally int64 = math.MinInt64 - var largestTallyValue float64 = math.NaN() + largestTally := int64(math.MinInt64) + largestTallyValue := math.NaN() for _, v := range input { presentCount, _ := valuesToFrequency[v] @@ -56,7 +76,7 @@ var FirstMode ReductionMethod = func(input []float64) float64 { } // Calculate the percentile by choosing the nearest neighboring value. -func NearestRank(input []float64, percentile float64) float64 { +func nearestRank(input []float64, percentile float64) float64 { inputSize := len(input) if inputSize == 0 { @@ -81,14 +101,12 @@ func NearestRank(input []float64, percentile float64) float64 { // Generate a ReductionMethod based off of extracting a given percentile value. func NearestRankReducer(percentile float64) ReductionMethod { return func(input []float64) float64 { - return NearestRank(input, percentile) + return nearestRank(input, percentile) } } -var Median ReductionMethod = NearestRankReducer(50) - -var Minimum ReductionMethod = func(input []float64) float64 { - var minimum float64 = math.MaxFloat64 +func minimumReducer(input []float64) float64 { + minimum := math.MaxFloat64 for _, v := range input { minimum = math.Min(minimum, v) @@ -97,8 +115,8 @@ var Minimum ReductionMethod = func(input []float64) float64 { return minimum } -var Maximum ReductionMethod = func(input []float64) float64 { - var maximum float64 = math.SmallestNonzeroFloat64 +func maximumReducer(input []float64) float64 { + maximum := math.SmallestNonzeroFloat64 for _, v := range input { maximum = math.Max(maximum, v) diff --git a/maths/statistics_test.go b/prometheus/statistics_test.go similarity index 56% rename from maths/statistics_test.go rename to prometheus/statistics_test.go index b17e980..8b64ce0 100644 --- a/maths/statistics_test.go +++ b/prometheus/statistics_test.go @@ -1,10 +1,10 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package maths +package prometheus import ( . "github.com/matttproud/gocheck" @@ -12,42 +12,42 @@ import ( func (s *S) TestAverageOnEmpty(c *C) { empty := []float64{} - var v float64 = Average(empty) + var v float64 = AverageReducer(empty) c.Assert(v, IsNaN) } func (s *S) TestAverageForSingleton(c *C) { input := []float64{5} - var v float64 = Average(input) + var v float64 = AverageReducer(input) c.Check(v, Equals, 5.0) } func (s *S) TestAverage(c *C) { input := []float64{5, 15} - var v float64 = Average(input) + var v float64 = AverageReducer(input) c.Check(v, Equals, 10.0) } func (s *S) TestFirstModeOnEmpty(c *C) { input := []float64{} - var v float64 = FirstMode(input) + var v float64 = FirstModeReducer(input) c.Assert(v, IsNaN) } func (s *S) TestFirstModeForSingleton(c *C) { input := []float64{5} - var v float64 = FirstMode(input) + var v float64 = FirstModeReducer(input) c.Check(v, Equals, 5.0) } func (s *S) TestFirstModeForUnimodal(c *C) { input := []float64{1, 2, 3, 4, 3} - var v float64 = FirstMode(input) + var v float64 = FirstModeReducer(input) c.Check(v, Equals, 3.0) } @@ -55,25 +55,25 @@ func (s *S) TestFirstModeForUnimodal(c *C) { func (s *S) TestNearestRankForEmpty(c *C) { input := []float64{} - c.Assert(NearestRank(input, 0), IsNaN) - c.Assert(NearestRank(input, 50), IsNaN) - c.Assert(NearestRank(input, 100), IsNaN) + c.Assert(nearestRank(input, 0), IsNaN) + c.Assert(nearestRank(input, 50), IsNaN) + c.Assert(nearestRank(input, 100), IsNaN) } func (s *S) TestNearestRankForSingleton(c *C) { input := []float64{5} - c.Check(NearestRank(input, 0), Equals, 5.0) - c.Check(NearestRank(input, 50), Equals, 5.0) - c.Check(NearestRank(input, 100), Equals, 5.0) + c.Check(nearestRank(input, 0), Equals, 5.0) + c.Check(nearestRank(input, 50), Equals, 5.0) + c.Check(nearestRank(input, 100), Equals, 5.0) } func (s *S) TestNearestRankForDouble(c *C) { input := []float64{5, 5} - c.Check(NearestRank(input, 0), Equals, 5.0) - c.Check(NearestRank(input, 50), Equals, 5.0) - c.Check(NearestRank(input, 100), Equals, 5.0) + c.Check(nearestRank(input, 0), Equals, 5.0) + c.Check(nearestRank(input, 50), Equals, 5.0) + c.Check(nearestRank(input, 100), Equals, 5.0) } func (s *S) TestNearestRankFor100(c *C) { @@ -83,9 +83,9 @@ func (s *S) TestNearestRankFor100(c *C) { input[i] = float64(i + 1) } - c.Check(NearestRank(input, 0), Equals, 1.0) - c.Check(NearestRank(input, 50), Equals, 51.0) - c.Check(NearestRank(input, 100), Equals, 100.0) + c.Check(nearestRank(input, 0), Equals, 1.0) + c.Check(nearestRank(input, 50), Equals, 51.0) + c.Check(nearestRank(input, 100), Equals, 100.0) } func (s *S) TestNearestRankFor101(c *C) { @@ -95,25 +95,25 @@ func (s *S) TestNearestRankFor101(c *C) { input[i] = float64(i + 1) } - c.Check(NearestRank(input, 0), Equals, 1.0) - c.Check(NearestRank(input, 50), Equals, 51.0) - c.Check(NearestRank(input, 100), Equals, 101.0) + c.Check(nearestRank(input, 0), Equals, 1.0) + c.Check(nearestRank(input, 50), Equals, 51.0) + c.Check(nearestRank(input, 100), Equals, 101.0) } func (s *S) TestMedianReducer(c *C) { input := []float64{1, 2, 3} - c.Check(Median(input), Equals, 2.0) + c.Check(MedianReducer(input), Equals, 2.0) } func (s *S) TestMinimum(c *C) { input := []float64{5, 1, 10, 1.1, 4} - c.Check(Minimum(input), Equals, 1.0) + c.Check(MinimumReducer(input), Equals, 1.0) } func (s *S) TestMaximum(c *C) { input := []float64{5, 1, 10, 1.1, 4} - c.Check(Maximum(input), Equals, 10.0) + c.Check(MaximumReducer(input), Equals, 10.0) } diff --git a/metrics/tallying_bucket.go b/prometheus/tallying_bucket.go similarity index 68% rename from metrics/tallying_bucket.go rename to prometheus/tallying_bucket.go index bbc6d9d..7ef1137 100644 --- a/metrics/tallying_bucket.go +++ b/prometheus/tallying_bucket.go @@ -1,14 +1,13 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // 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 +package prometheus import ( "fmt" - "github.com/prometheus/client_golang/maths" "math" "sync" ) @@ -35,38 +34,49 @@ func emptyFilter(e TallyingIndexEstimator) TallyingIndexEstimator { } } -// Report the smallest observed value in the bucket. -var Minimum TallyingIndexEstimator = emptyFilter(func(minimum, maximum float64, _, observations int) float64 { - return minimum -}) - -// Report the largest observed value in the bucket. -var Maximum TallyingIndexEstimator = emptyFilter(func(minimum, maximum float64, _, observations int) float64 { - return maximum -}) - -// Report the average of the extrema. -var Average TallyingIndexEstimator = emptyFilter(func(minimum, maximum float64, _, observations int) float64 { - return maths.Average([]float64{minimum, maximum}) -}) - -// Report the minimum value of the index is in the lower-third of observations, -// the average if in the middle-third, and the maximum if in the largest third. -var Uniform TallyingIndexEstimator = emptyFilter(func(minimum, maximum float64, index, observations int) float64 { - if observations == 1 { +var ( + minimumEstimator = emptyFilter(func(minimum, maximum float64, _, observations int) float64 { return minimum - } + }) - location := float64(index) / float64(observations) - - if location > upperThird { + maximumEstimator = emptyFilter(func(minimum, maximum float64, _, observations int) float64 { return maximum - } else if location < lowerThird { - return minimum - } + }) - return maths.Average([]float64{minimum, maximum}) -}) + averageEstimator = emptyFilter(func(minimum, maximum float64, _, observations int) float64 { + return AverageReducer([]float64{minimum, maximum}) + }) + + uniformEstimator = emptyFilter(func(minimum, maximum float64, index, observations int) float64 { + if observations == 1 { + return minimum + } + + location := float64(index) / float64(observations) + + if location > upperThird { + return maximum + } else if location < lowerThird { + return minimum + } + + return AverageReducer([]float64{minimum, maximum}) + }) +) + +// These are the canned TallyingIndexEstimators. +var ( + // Report the smallest observed value in the bucket. + MinimumEstimator = minimumEstimator + // Report the largest observed value in the bucket. + MaximumEstimator = maximumEstimator + // Report the average of the extrema. + AverageEstimator = averageEstimator + // Report the minimum value of the index if it is in the lower-third of + // observations, the average if in the middle-third, and the maximum if in + // the largest third + UniformEstimator = uniformEstimator +) // A TallyingBucket is a Bucket that tallies when an object is added to it. // Upon insertion, an object is compared against collected extrema and noted @@ -127,7 +137,7 @@ func (b *TallyingBucket) Reset() { // Produce a TallyingBucket with sane defaults. func DefaultTallyingBucket() TallyingBucket { return TallyingBucket{ - estimator: Minimum, + estimator: MinimumEstimator, largestObserved: math.SmallestNonzeroFloat64, smallestObserved: math.MaxFloat64, } diff --git a/metrics/tallying_bucket_test.go b/prometheus/tallying_bucket_test.go similarity index 62% rename from metrics/tallying_bucket_test.go rename to prometheus/tallying_bucket_test.go index 6f1048d..f674d5f 100644 --- a/metrics/tallying_bucket_test.go +++ b/prometheus/tallying_bucket_test.go @@ -1,40 +1,39 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // 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 +package prometheus import ( . "github.com/matttproud/gocheck" - "github.com/prometheus/client_golang/maths" ) func (s *S) TestTallyingPercentileEstimatorMinimum(c *C) { - c.Assert(Minimum(-2, -1, 0, 0), maths.IsNaN) - c.Check(Minimum(-2, -1, 0, 1), Equals, -2.0) + c.Assert(MinimumEstimator(-2, -1, 0, 0), IsNaN) + c.Check(MinimumEstimator(-2, -1, 0, 1), Equals, -2.0) } func (s *S) TestTallyingPercentileEstimatorMaximum(c *C) { - c.Assert(Maximum(-2, -1, 0, 0), maths.IsNaN) - c.Check(Maximum(-2, -1, 0, 1), Equals, -1.0) + c.Assert(MaximumEstimator(-2, -1, 0, 0), IsNaN) + c.Check(MaximumEstimator(-2, -1, 0, 1), Equals, -1.0) } func (s *S) TestTallyingPercentilesEstimatorAverage(c *C) { - c.Assert(Average(-2, -1, 0, 0), maths.IsNaN) - c.Check(Average(-2, -2, 0, 1), Equals, -2.0) - c.Check(Average(-1, -1, 0, 1), Equals, -1.0) - c.Check(Average(1, 1, 0, 2), Equals, 1.0) - c.Check(Average(2, 1, 0, 2), Equals, 1.5) + c.Assert(AverageEstimator(-2, -1, 0, 0), IsNaN) + c.Check(AverageEstimator(-2, -2, 0, 1), Equals, -2.0) + c.Check(AverageEstimator(-1, -1, 0, 1), Equals, -1.0) + c.Check(AverageEstimator(1, 1, 0, 2), Equals, 1.0) + c.Check(AverageEstimator(2, 1, 0, 2), Equals, 1.5) } func (s *S) TestTallyingPercentilesEstimatorUniform(c *C) { - c.Assert(Uniform(-5, 5, 0, 0), maths.IsNaN) + c.Assert(UniformEstimator(-5, 5, 0, 0), IsNaN) - c.Check(Uniform(-5, 5, 0, 2), Equals, -5.0) - c.Check(Uniform(-5, 5, 1, 2), Equals, 0.0) - c.Check(Uniform(-5, 5, 2, 2), Equals, 5.0) + c.Check(UniformEstimator(-5, 5, 0, 2), Equals, -5.0) + c.Check(UniformEstimator(-5, 5, 1, 2), Equals, 0.0) + c.Check(UniformEstimator(-5, 5, 2, 2), Equals, 5.0) } func (s *S) TestTallyingBucketBuilder(c *C) { diff --git a/telemetry.go b/prometheus/telemetry.go similarity index 64% rename from telemetry.go rename to prometheus/telemetry.go index 8ce1a6f..3cfa3fb 100644 --- a/telemetry.go +++ b/prometheus/telemetry.go @@ -1,15 +1,13 @@ -// Copyright (c) 2013, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style license that can be found // in the LICENSE file. // -package registry +package prometheus import ( - "github.com/prometheus/client_golang/maths" - "github.com/prometheus/client_golang/metrics" "time" ) @@ -17,18 +15,18 @@ import ( // exposed if the DefaultRegistry's exporter is hooked into the HTTP request // handler. var ( - marshalErrorCount = metrics.NewCounter() - dumpErrorCount = metrics.NewCounter() + marshalErrorCount = NewCounter() + dumpErrorCount = NewCounter() - requestCount = metrics.NewCounter() - requestLatencyBuckets = metrics.LogarithmicSizedBucketsFor(0, 1000) - requestLatency = metrics.NewHistogram(&metrics.HistogramSpecification{ + requestCount = NewCounter() + requestLatencyBuckets = LogarithmicSizedBucketsFor(0, 1000) + requestLatency = NewHistogram(&HistogramSpecification{ Starts: requestLatencyBuckets, - BucketBuilder: metrics.AccumulatingBucketBuilder(metrics.EvictAndReplaceWith(50, maths.Average), 1000), + BucketBuilder: AccumulatingBucketBuilder(EvictAndReplaceWith(50, AverageReducer), 1000), ReportablePercentiles: []float64{0.01, 0.05, 0.5, 0.9, 0.99}, }) - startTime = metrics.NewGauge() + startTime = NewGauge() ) func init() { @@ -42,7 +40,7 @@ func init() { // This callback accumulates the microsecond duration of the reporting // framework's overhead such that it can be reported. -var requestLatencyAccumulator metrics.CompletionCallback = func(duration time.Duration) { +var requestLatencyAccumulator CompletionCallback = func(duration time.Duration) { microseconds := float64(duration / time.Microsecond) requestLatency.Add(nil, microseconds) diff --git a/utility/test_helper.go b/prometheus/test_helper.go similarity index 84% rename from utility/test_helper.go rename to prometheus/test_helper.go index b3d8f7d..b5bd488 100644 --- a/utility/test_helper.go +++ b/prometheus/test_helper.go @@ -1,10 +1,10 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package utility +package prometheus import ( . "github.com/matttproud/gocheck" @@ -19,7 +19,7 @@ var ValueEquals Checker = &valueEqualsChecker{ } func (checker *valueEqualsChecker) Check(params []interface{}, names []string) (result bool, error string) { - actual := params[0].(*Item).Value + actual := params[0].(*item).Value expected := params[1] return actual == expected, "" diff --git a/metrics/timer.go b/prometheus/timer.go similarity index 96% rename from metrics/timer.go rename to prometheus/timer.go index 491d132..aa1ff92 100644 --- a/metrics/timer.go +++ b/prometheus/timer.go @@ -1,10 +1,10 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // 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 +package prometheus import ( "time" diff --git a/metrics/timer_test.go b/prometheus/timer_test.go similarity index 95% rename from metrics/timer_test.go rename to prometheus/timer_test.go index d3b12e1..e9dab08 100644 --- a/metrics/timer_test.go +++ b/prometheus/timer_test.go @@ -1,10 +1,10 @@ -// Copyright (c) 2012, Matt T. Proud +// Copyright (c) 2013, Prometheus Team // 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 +package prometheus import ( . "github.com/matttproud/gocheck" diff --git a/utility/documentation.go b/utility/documentation.go deleted file mode 100644 index 7b9628f..0000000 --- a/utility/documentation.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2012, Matt T. Proud -// All rights reserved. - -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// -// The utility package provides general purpose helpers to assist with this -// library. -// -// priority_queue.go provides a simple priority queue. -// -// priority_queue_test.go provides a test complement for the priority_queue.go -// module. -// -// test_helper.go provides a testing assistents for this package and its -// dependents. -// -// utility_test.go provides a test suite for all tests in the utility package -// hierarchy. It employs the gocheck framework for test scaffolding. -package documentation diff --git a/utility/utility_test.go b/utility/utility_test.go deleted file mode 100644 index 17244b1..0000000 --- a/utility/utility_test.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2012, Matt T. Proud -// All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package utility - -import ( - . "github.com/matttproud/gocheck" - "testing" -) - -type S struct{} - -var _ = Suite(&S{}) - -func TestUtility(t *testing.T) { - TestingT(t) -} From 9fccb9698965f218e4c89633096bd5154fc1447e Mon Sep 17 00:00:00 2001 From: Bernerd Schaefer Date: Fri, 19 Apr 2013 14:44:15 +0200 Subject: [PATCH 2/6] Remove timer.go and timer_test.go --- prometheus/registry.go | 31 +++++++++--------- prometheus/telemetry.go | 4 +-- prometheus/timer.go | 62 ------------------------------------ prometheus/timer_test.go | 69 ---------------------------------------- 4 files changed, 17 insertions(+), 149 deletions(-) delete mode 100644 prometheus/timer.go delete mode 100644 prometheus/timer_test.go diff --git a/prometheus/registry.go b/prometheus/registry.go index 28ab774..d968d3f 100644 --- a/prometheus/registry.go +++ b/prometheus/registry.go @@ -18,6 +18,7 @@ import ( "sort" "strings" "sync" + "time" ) const ( @@ -269,29 +270,27 @@ func (registry registry) YieldExporter() http.HandlerFunc { func (registry registry) Handler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - var instrumentable InstrumentableCall = func() { - requestCount.Increment(nil) - url := r.URL + defer requestLatencyAccumulator(time.Now()) - if strings.HasSuffix(url.Path, jsonSuffix) { - header := w.Header() - header.Set(ProtocolVersionHeader, APIVersion) - header.Set(contentTypeHeader, jsonContentType) + requestCount.Increment(nil) + url := r.URL - writer := decorateWriter(r, w) + if strings.HasSuffix(url.Path, jsonSuffix) { + header := w.Header() + header.Set(ProtocolVersionHeader, APIVersion) + header.Set(contentTypeHeader, jsonContentType) - if closer, ok := writer.(io.Closer); ok { - defer closer.Close() - } + writer := decorateWriter(r, w) - registry.dumpToWriter(writer) - - } else { - w.WriteHeader(http.StatusNotFound) + if closer, ok := writer.(io.Closer); ok { + defer closer.Close() } + registry.dumpToWriter(writer) + + } else { + w.WriteHeader(http.StatusNotFound) } - InstrumentCall(instrumentable, requestLatencyAccumulator) } } diff --git a/prometheus/telemetry.go b/prometheus/telemetry.go index 3cfa3fb..dc048bd 100644 --- a/prometheus/telemetry.go +++ b/prometheus/telemetry.go @@ -40,8 +40,8 @@ func init() { // This callback accumulates the microsecond duration of the reporting // framework's overhead such that it can be reported. -var requestLatencyAccumulator CompletionCallback = func(duration time.Duration) { - microseconds := float64(duration / time.Microsecond) +var requestLatencyAccumulator = func(began time.Time) { + microseconds := float64(time.Since(began) / time.Microsecond) requestLatency.Add(nil, microseconds) } diff --git a/prometheus/timer.go b/prometheus/timer.go deleted file mode 100644 index aa1ff92..0000000 --- a/prometheus/timer.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2013, Prometheus Team -// All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package prometheus - -import ( - "time" -) - -// This callback is called upon the completion of the timer—i.e., when it stops. -type CompletionCallback func(duration time.Duration) - -// This is meant to capture a function that a StopWatch can call for purposes -// of instrumentation. -type InstrumentableCall func() - -// StopWatch is the structure that captures instrumentation for durations. - -// N.B.(mtp): A major limitation hereof is that the StopWatch protocol cannot -// retain instrumentation if a panic percolates within the context that is -// being measured. -type StopWatch interface { - Stop() time.Duration -} - -type stopWatch struct { - endTime time.Time - onCompletion CompletionCallback - startTime time.Time -} - -// Return a new StopWatch that is ready for instrumentation. -func Start(onCompletion CompletionCallback) StopWatch { - return &stopWatch{ - onCompletion: onCompletion, - startTime: time.Now(), - } -} - -// Stop the StopWatch returning the elapsed duration of its lifetime while -// firing an optional CompletionCallback in the background. -func (s *stopWatch) Stop() time.Duration { - s.endTime = time.Now() - duration := s.endTime.Sub(s.startTime) - - if s.onCompletion != nil { - go s.onCompletion(duration) - } - - return duration -} - -// Provide a quick way of instrumenting a InstrumentableCall and emitting its -// duration. -func InstrumentCall(instrumentable InstrumentableCall, onCompletion CompletionCallback) time.Duration { - s := Start(onCompletion) - instrumentable() - return s.Stop() -} diff --git a/prometheus/timer_test.go b/prometheus/timer_test.go deleted file mode 100644 index e9dab08..0000000 --- a/prometheus/timer_test.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2013, Prometheus Team -// All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package prometheus - -import ( - . "github.com/matttproud/gocheck" - "time" -) - -func (s *S) TestTimerStart(c *C) { - stopWatch, ok := Start(nil).(*stopWatch) - if !ok { - c.Check(ok, Equals, true) - } - - c.Assert(stopWatch, Not(IsNil)) - c.Assert(stopWatch.startTime, Not(IsNil)) -} - -func (s *S) TestTimerStop(c *C) { - done := make(chan bool) - - var callbackInvoked bool = false - var complete CompletionCallback = func(duration time.Duration) { - callbackInvoked = true - done <- true - } - - stopWatch := Start(complete) - - c.Check(callbackInvoked, Equals, false) - - d := stopWatch.Stop() - - <-done - - c.Assert(d, Not(IsNil)) - c.Check(callbackInvoked, Equals, true) -} - -func (s *S) TestInstrumentCall(c *C) { - var callbackInvoked bool = false - var instrumentableInvoked bool = false - done := make(chan bool, 2) - - var complete CompletionCallback = func(duration time.Duration) { - callbackInvoked = true - done <- true - } - - var instrumentable InstrumentableCall = func() { - instrumentableInvoked = true - done <- true - } - - d := InstrumentCall(instrumentable, complete) - - c.Assert(d, Not(IsNil)) - - <-done - <-done - - c.Check(instrumentableInvoked, Equals, true) - c.Check(callbackInvoked, Equals, true) -} From 0b30e065c87d82f746a3c1f899ce95a4524cf3db Mon Sep 17 00:00:00 2001 From: Bernerd Schaefer Date: Fri, 19 Apr 2013 13:22:59 +0200 Subject: [PATCH 3/6] Metrics explicitly implement Metric interface --- prometheus/counter.go | 5 ++--- prometheus/gauge.go | 4 +--- prometheus/histogram.go | 4 +--- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/prometheus/counter.go b/prometheus/counter.go index 74b76dd..ba4a776 100644 --- a/prometheus/counter.go +++ b/prometheus/counter.go @@ -14,14 +14,13 @@ import ( // TODO(matt): Refactor to de-duplicate behaviors. type Counter interface { - AsMarshallable() map[string]interface{} + Metric + Decrement(labels map[string]string) float64 DecrementBy(labels map[string]string, value float64) float64 Increment(labels map[string]string) float64 IncrementBy(labels map[string]string, value float64) float64 - ResetAll() Set(labels map[string]string, value float64) float64 - String() string } type counterVector struct { diff --git a/prometheus/gauge.go b/prometheus/gauge.go index e5f6553..2fa255d 100644 --- a/prometheus/gauge.go +++ b/prometheus/gauge.go @@ -16,10 +16,8 @@ import ( // temperature or the hitherto bandwidth used, this would be the metric for such // circumstances. type Gauge interface { - AsMarshallable() map[string]interface{} - ResetAll() + Metric Set(labels map[string]string, value float64) float64 - String() string } type gaugeVector struct { diff --git a/prometheus/histogram.go b/prometheus/histogram.go index ca3ce93..e696f4d 100644 --- a/prometheus/histogram.go +++ b/prometheus/histogram.go @@ -52,10 +52,8 @@ type HistogramSpecification struct { } type Histogram interface { + Metric Add(labels map[string]string, value float64) - AsMarshallable() map[string]interface{} - ResetAll() - String() string } // The histogram is an accumulator for samples. It merely routes into which From 3433b798b390273f731ac206835ddbe2ee3bb043 Mon Sep 17 00:00:00 2001 From: Bernerd Schaefer Date: Fri, 19 Apr 2013 13:29:24 +0200 Subject: [PATCH 4/6] Use raw string literals in tests --- prometheus/counter_test.go | 24 ++++++++++++------------ prometheus/gauge_test.go | 12 ++++++------ prometheus/registry_test.go | 4 ++-- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/prometheus/counter_test.go b/prometheus/counter_test.go index b2023f0..e11b97e 100644 --- a/prometheus/counter_test.go +++ b/prometheus/counter_test.go @@ -28,7 +28,7 @@ func testCounter(t tester) { steps: []func(g Counter){}, }, out: output{ - value: "{\"type\":\"counter\",\"value\":[]}", + value: `{"type":"counter","value":[]}`, }, }, { @@ -40,7 +40,7 @@ func testCounter(t tester) { }, }, out: output{ - value: "{\"type\":\"counter\",\"value\":[{\"labels\":{},\"value\":1}]}", + value: `{"type":"counter","value":[{"labels":{},"value":1}]}`, }, }, { @@ -52,7 +52,7 @@ func testCounter(t tester) { }, }, out: output{ - value: "{\"type\":\"counter\",\"value\":[{\"labels\":{},\"value\":2}]}", + value: `{"type":"counter","value":[{"labels":{},"value":2}]}`, }, }, { @@ -67,7 +67,7 @@ func testCounter(t tester) { }, }, out: output{ - value: "{\"type\":\"counter\",\"value\":[{\"labels\":{},\"value\":5}]}", + value: `{"type":"counter","value":[{"labels":{},"value":5}]}`, }, }, { @@ -85,7 +85,7 @@ func testCounter(t tester) { }, }, out: output{ - value: "{\"type\":\"counter\",\"value\":[]}", + value: `{"type":"counter","value":[]}`, }, }, { @@ -97,7 +97,7 @@ func testCounter(t tester) { }, }, out: output{ - value: "{\"type\":\"counter\",\"value\":[{\"labels\":{\"handler\":\"/foo\"},\"value\":19}]}", + value: `{"type":"counter","value":[{"labels":{"handler":"/foo"},"value":19}]}`, }, }, { @@ -112,7 +112,7 @@ func testCounter(t tester) { }, }, out: output{ - value: "{\"type\":\"counter\",\"value\":[{\"labels\":{\"handler\":\"/foo\"},\"value\":24}]}", + value: `{"type":"counter","value":[{"labels":{"handler":"/foo"},"value":24}]}`, }, }, { @@ -124,7 +124,7 @@ func testCounter(t tester) { }, }, out: output{ - value: "{\"type\":\"counter\",\"value\":[{\"labels\":{\"handler\":\"/foo\"},\"value\":1}]}", + value: `{"type":"counter","value":[{"labels":{"handler":"/foo"},"value":1}]}`, }, }, { @@ -136,7 +136,7 @@ func testCounter(t tester) { }, }, out: output{ - value: "{\"type\":\"counter\",\"value\":[{\"labels\":{\"handler\":\"/foo\"},\"value\":-1}]}", + value: `{"type":"counter","value":[{"labels":{"handler":"/foo"},"value":-1}]}`, }, }, { @@ -151,7 +151,7 @@ func testCounter(t tester) { }, }, out: output{ - value: "{\"type\":\"counter\",\"value\":[{\"labels\":{\"handler\":\"/foo\"},\"value\":28}]}", + value: `{"type":"counter","value":[{"labels":{"handler":"/foo"},"value":28}]}`, }, }, { @@ -166,7 +166,7 @@ func testCounter(t tester) { }, }, out: output{ - value: "{\"type\":\"counter\",\"value\":[{\"labels\":{\"handler\":\"/foo\"},\"value\":36}]}", + value: `{"type":"counter","value":[{"labels":{"handler":"/foo"},"value":36}]}`, }, }, { @@ -181,7 +181,7 @@ func testCounter(t tester) { }, }, out: output{ - value: "{\"type\":\"counter\",\"value\":[{\"labels\":{\"handler\":\"/foo\"},\"value\":27}]}", + value: `{"type":"counter","value":[{"labels":{"handler":"/foo"},"value":27}]}`, }, }, } diff --git a/prometheus/gauge_test.go b/prometheus/gauge_test.go index 8e7e5f1..ee3d425 100644 --- a/prometheus/gauge_test.go +++ b/prometheus/gauge_test.go @@ -28,7 +28,7 @@ func testGauge(t tester) { steps: []func(g Gauge){}, }, out: output{ - value: "{\"type\":\"gauge\",\"value\":[]}", + value: `{"type":"gauge","value":[]}`, }, }, { @@ -40,7 +40,7 @@ func testGauge(t tester) { }, }, out: output{ - value: "{\"type\":\"gauge\",\"value\":[{\"labels\":{},\"value\":1}]}", + value: `{"type":"gauge","value":[{"labels":{},"value":1}]}`, }, }, { @@ -52,7 +52,7 @@ func testGauge(t tester) { }, }, out: output{ - value: "{\"type\":\"gauge\",\"value\":[{\"labels\":{},\"value\":2}]}", + value: `{"type":"gauge","value":[{"labels":{},"value":2}]}`, }, }, { @@ -67,7 +67,7 @@ func testGauge(t tester) { }, }, out: output{ - value: "{\"type\":\"gauge\",\"value\":[{\"labels\":{},\"value\":5}]}", + value: `{"type":"gauge","value":[{"labels":{},"value":5}]}`, }, }, { @@ -85,7 +85,7 @@ func testGauge(t tester) { }, }, out: output{ - value: "{\"type\":\"gauge\",\"value\":[]}", + value: `{"type":"gauge","value":[]}`, }, }, { @@ -97,7 +97,7 @@ func testGauge(t tester) { }, }, out: output{ - value: "{\"type\":\"gauge\",\"value\":[{\"labels\":{\"handler\":\"/foo\"},\"value\":19}]}", + value: `{"type":"gauge","value":[{"labels":{"handler":"/foo"},"value":19}]}`, }, }, } diff --git a/prometheus/registry_test.go b/prometheus/registry_test.go index df0f1c2..b1d8379 100644 --- a/prometheus/registry_test.go +++ b/prometheus/registry_test.go @@ -282,7 +282,7 @@ func testDumpToWriter(t tester) { "foo": NewCounter(), }, }, - out: []byte("[{\"baseLabels\":{\"label_foo\":\"foo\",\"name\":\"foo\"},\"docstring\":\"metric foo\",\"metric\":{\"type\":\"counter\",\"value\":[]}}]"), + out: []byte(`[{"baseLabels":{"label_foo":"foo","name":"foo"},"docstring":"metric foo","metric":{"type":"counter","value":[]}}]`), }, { in: input{ @@ -291,7 +291,7 @@ func testDumpToWriter(t tester) { "bar": NewCounter(), }, }, - out: []byte("[{\"baseLabels\":{\"label_bar\":\"bar\",\"name\":\"bar\"},\"docstring\":\"metric bar\",\"metric\":{\"type\":\"counter\",\"value\":[]}},{\"baseLabels\":{\"label_foo\":\"foo\",\"name\":\"foo\"},\"docstring\":\"metric foo\",\"metric\":{\"type\":\"counter\",\"value\":[]}}]"), + out: []byte(`[{"baseLabels":{"label_bar":"bar","name":"bar"},"docstring":"metric bar","metric":{"type":"counter","value":[]}},{"baseLabels":{"label_foo":"foo","name":"foo"},"docstring":"metric foo","metric":{"type":"counter","value":[]}}]`), }, } From 71dd60e431178eca416f3aef508b52e70c6c55ba Mon Sep 17 00:00:00 2001 From: Bernerd Schaefer Date: Fri, 19 Apr 2013 14:11:01 +0200 Subject: [PATCH 5/6] Registry and Metrics implement json.Marshaler * Drop `AsMarshallable()` from the Metric interface. Use `json.Marshaler` and `MarshalJSON()`, and leverage JSON struct tags where possible. * Add `MarshalJSON()` to Registry and remove `dumpToWriter`, which makes the registry handler much simpler. In addition to simplifying some of the marshalling behavior, this also has the nice side effect of cutting down the number of `map[string]interface{}` instances. --- prometheus/counter.go | 41 +++++++++-------- prometheus/counter_test.go | 4 +- prometheus/gauge.go | 28 ++++++------ prometheus/gauge_test.go | 4 +- prometheus/histogram.go | 26 ++++++----- prometheus/metric.go | 6 ++- prometheus/registry.go | 90 +++++++++++-------------------------- prometheus/registry_test.go | 8 ++-- prometheus/telemetry.go | 3 -- 9 files changed, 83 insertions(+), 127 deletions(-) diff --git a/prometheus/counter.go b/prometheus/counter.go index ba4a776..40f0532 100644 --- a/prometheus/counter.go +++ b/prometheus/counter.go @@ -7,6 +7,7 @@ package prometheus import ( + "encoding/json" "fmt" "sync" ) @@ -24,8 +25,8 @@ type Counter interface { } type counterVector struct { - labels map[string]string - value float64 + Labels map[string]string `json:"labels"` + Value float64 `json:"value"` } func NewCounter() Counter { @@ -49,11 +50,11 @@ func (metric *counter) Set(labels map[string]string, value float64) float64 { signature := labelsToSignature(labels) if original, ok := metric.values[signature]; ok { - original.value = value + original.Value = value } else { metric.values[signature] = &counterVector{ - labels: labels, - value: value, + Labels: labels, + Value: value, } } @@ -65,8 +66,8 @@ func (metric *counter) ResetAll() { defer metric.mutex.Unlock() for key, value := range metric.values { - for label := range value.labels { - delete(value.labels, label) + for label := range value.Labels { + delete(value.Labels, label) } delete(metric.values, key) } @@ -91,11 +92,11 @@ func (metric *counter) IncrementBy(labels map[string]string, value float64) floa signature := labelsToSignature(labels) if original, ok := metric.values[signature]; ok { - original.value += value + original.Value += value } else { metric.values[signature] = &counterVector{ - labels: labels, - value: value, + Labels: labels, + Value: value, } } @@ -116,11 +117,11 @@ func (metric *counter) DecrementBy(labels map[string]string, value float64) floa signature := labelsToSignature(labels) if original, ok := metric.values[signature]; ok { - original.value -= value + original.Value -= value } else { metric.values[signature] = &counterVector{ - labels: labels, - value: -1 * value, + Labels: labels, + Value: -1 * value, } } @@ -131,20 +132,18 @@ func (metric *counter) Decrement(labels map[string]string) float64 { return metric.DecrementBy(labels, 1) } -func (metric counter) AsMarshallable() map[string]interface{} { +func (metric counter) MarshalJSON() ([]byte, error) { metric.mutex.RLock() defer metric.mutex.RUnlock() - values := make([]map[string]interface{}, 0, len(metric.values)) + values := make([]*counterVector, 0, len(metric.values)) + for _, value := range metric.values { - values = append(values, map[string]interface{}{ - labelsKey: value.labels, - valueKey: value.value, - }) + values = append(values, value) } - return map[string]interface{}{ + return json.Marshal(map[string]interface{}{ valueKey: values, typeKey: counterTypeValue, - } + }) } diff --git a/prometheus/counter_test.go b/prometheus/counter_test.go index e11b97e..e9db571 100644 --- a/prometheus/counter_test.go +++ b/prometheus/counter_test.go @@ -193,9 +193,7 @@ func testCounter(t tester) { step(counter) } - marshallable := counter.AsMarshallable() - - bytes, err := json.Marshal(marshallable) + bytes, err := json.Marshal(counter) if err != nil { t.Errorf("%d. could not marshal into JSON %s", i, err) continue diff --git a/prometheus/gauge.go b/prometheus/gauge.go index 2fa255d..dd99976 100644 --- a/prometheus/gauge.go +++ b/prometheus/gauge.go @@ -7,6 +7,7 @@ package prometheus import ( + "encoding/json" "fmt" "sync" ) @@ -21,8 +22,8 @@ type Gauge interface { } type gaugeVector struct { - labels map[string]string - value float64 + Labels map[string]string `json:"labels"` + Value float64 `json:"value"` } func NewGauge() Gauge { @@ -56,11 +57,11 @@ func (metric *gauge) Set(labels map[string]string, value float64) float64 { signature := labelsToSignature(labels) if original, ok := metric.values[signature]; ok { - original.value = value + original.Value = value } else { metric.values[signature] = &gaugeVector{ - labels: labels, - value: value, + Labels: labels, + Value: value, } } @@ -72,27 +73,24 @@ func (metric *gauge) ResetAll() { defer metric.mutex.Unlock() for key, value := range metric.values { - for label := range value.labels { - delete(value.labels, label) + for label := range value.Labels { + delete(value.Labels, label) } delete(metric.values, key) } } -func (metric gauge) AsMarshallable() map[string]interface{} { +func (metric gauge) MarshalJSON() ([]byte, error) { metric.mutex.RLock() defer metric.mutex.RUnlock() - values := make([]map[string]interface{}, 0, len(metric.values)) + values := make([]*gaugeVector, 0, len(metric.values)) for _, value := range metric.values { - values = append(values, map[string]interface{}{ - labelsKey: value.labels, - valueKey: value.value, - }) + values = append(values, value) } - return map[string]interface{}{ + return json.Marshal(map[string]interface{}{ typeKey: gaugeTypeValue, valueKey: values, - } + }) } diff --git a/prometheus/gauge_test.go b/prometheus/gauge_test.go index ee3d425..103bbc5 100644 --- a/prometheus/gauge_test.go +++ b/prometheus/gauge_test.go @@ -109,9 +109,7 @@ func testGauge(t tester) { step(gauge) } - marshallable := gauge.AsMarshallable() - - bytes, err := json.Marshal(marshallable) + bytes, err := json.Marshal(gauge) if err != nil { t.Errorf("%d. could not marshal into JSON %s", i, err) continue diff --git a/prometheus/histogram.go b/prometheus/histogram.go index e696f4d..9988ac2 100644 --- a/prometheus/histogram.go +++ b/prometheus/histogram.go @@ -8,6 +8,7 @@ package prometheus import ( "bytes" + "encoding/json" "fmt" "math" "strconv" @@ -238,29 +239,30 @@ func formatFloat(value float64) string { return strconv.FormatFloat(value, floatFormat, floatPrecision, floatBitCount) } -func (h histogram) AsMarshallable() map[string]interface{} { +func (h histogram) MarshalJSON() ([]byte, error) { h.mutex.RLock() defer h.mutex.RUnlock() - result := make(map[string]interface{}, 2) - result[typeKey] = histogramTypeValue values := make([]map[string]interface{}, 0, len(h.values)) for signature, value := range h.values { - metricContainer := map[string]interface{}{} - metricContainer[labelsKey] = value.labels - intermediate := map[string]interface{}{} + percentiles := make(map[string]float64, len(h.reportablePercentiles)) + for _, percentile := range h.reportablePercentiles { formatted := formatFloat(percentile) - intermediate[formatted] = h.percentile(signature, percentile) + percentiles[formatted] = h.percentile(signature, percentile) } - metricContainer[valueKey] = intermediate - values = append(values, metricContainer) + + values = append(values, map[string]interface{}{ + labelsKey: value.labels, + valueKey: percentiles, + }) } - result[valueKey] = values - - return result + return json.Marshal(map[string]interface{}{ + typeKey: histogramTypeValue, + valueKey: values, + }) } func (h *histogram) ResetAll() { diff --git a/prometheus/metric.go b/prometheus/metric.go index 9753130..8d4d5da 100644 --- a/prometheus/metric.go +++ b/prometheus/metric.go @@ -6,10 +6,12 @@ package prometheus +import "encoding/json" + // A Metric is something that can be exposed via the registry framework. type Metric interface { - // Produce a JSON-consumable representation of the metric. - AsMarshallable() map[string]interface{} + // Produce a JSON representation of the metric. + json.Marshaler // Reset the parent metrics and delete all child metrics. ResetAll() // Produce a human-consumable representation of the metric. diff --git a/prometheus/registry.go b/prometheus/registry.go index d968d3f..ebe9871 100644 --- a/prometheus/registry.go +++ b/prometheus/registry.go @@ -43,9 +43,9 @@ var ( // container represents a top-level registered metric that encompasses its // static metadata. type container struct { - baseLabels map[string]string - docstring string - metric Metric + BaseLabels map[string]string `json:"baseLabels"` + Docstring string `json:"docstring"` + Metric Metric `json:"metric"` name string } @@ -82,6 +82,24 @@ func Register(name, docstring string, baseLabels map[string]string, metric Metri return DefaultRegistry.Register(name, docstring, baseLabels, metric) } +// Implements json.Marshaler +func (r registry) MarshalJSON() (_ []byte, err error) { + metrics := make([]interface{}, 0, len(r.signatureContainers)) + + keys := make([]string, 0, len(metrics)) + for key := range r.signatureContainers { + keys = append(keys, key) + } + + sort.Strings(keys) + + for _, key := range keys { + metrics = append(metrics, r.signatureContainers[key]) + } + + return json.Marshal(metrics) +} + // isValidCandidate returns true if the candidate is acceptable for use. In the // event of any apparent incorrect use it will report the problem, invalidate // the candidate, or outright abort. @@ -125,7 +143,7 @@ func (r registry) isValidCandidate(name string, baseLabels map[string]string) (s if useAggressiveSanityChecks { for _, container := range r.signatureContainers { if container.name == name { - err = fmt.Errorf("metric named %s with baseLabels %s is already registered as %s and risks causing confusion", name, baseLabels, container.baseLabels) + err = fmt.Errorf("metric named %s with baseLabels %s is already registered as %s and risks causing confusion", name, baseLabels, container.BaseLabels) if abortOnMisuse { panic(err) } else if debugRegistration { @@ -154,9 +172,9 @@ func (r registry) Register(name, docstring string, baseLabels map[string]string, } r.signatureContainers[signature] = container{ - baseLabels: baseLabels, - docstring: docstring, - metric: metric, + BaseLabels: baseLabels, + Docstring: docstring, + Metric: metric, name: name, } @@ -194,61 +212,6 @@ func (register registry) YieldBasicAuthExporter(username, password string) http. }) } -func (registry registry) dumpToWriter(writer io.Writer) (err error) { - defer func() { - if err != nil { - dumpErrorCount.Increment(nil) - } - }() - - numberOfMetrics := len(registry.signatureContainers) - keys := make([]string, 0, numberOfMetrics) - for key := range registry.signatureContainers { - keys = append(keys, key) - } - - sort.Strings(keys) - - _, err = writer.Write([]byte("[")) - if err != nil { - return - } - - index := 0 - - for _, key := range keys { - container := registry.signatureContainers[key] - intermediate := map[string]interface{}{ - baseLabelsKey: container.baseLabels, - docstringKey: container.docstring, - metricKey: container.metric.AsMarshallable(), - } - marshaled, err := json.Marshal(intermediate) - if err != nil { - marshalErrorCount.Increment(nil) - index++ - continue - } - - if index > 0 && index < numberOfMetrics { - _, err = writer.Write([]byte(",")) - if err != nil { - return err - } - } - - _, err = writer.Write(marshaled) - if err != nil { - return err - } - index++ - } - - _, err = writer.Write([]byte("]")) - - return -} - // decorateWriter annotates the response writer to handle any other behaviors // that might be beneficial to the client---e.g., GZIP encoding. func decorateWriter(request *http.Request, writer http.ResponseWriter) io.Writer { @@ -286,8 +249,7 @@ func (registry registry) Handler() http.HandlerFunc { defer closer.Close() } - registry.dumpToWriter(writer) - + json.NewEncoder(writer).Encode(registry) } else { w.WriteHeader(http.StatusNotFound) } diff --git a/prometheus/registry_test.go b/prometheus/registry_test.go index b1d8379..f756b84 100644 --- a/prometheus/registry_test.go +++ b/prometheus/registry_test.go @@ -8,6 +8,7 @@ package prometheus import ( "bytes" + "encoding/json" "fmt" "io" "net/http" @@ -305,15 +306,14 @@ func testDumpToWriter(t tester) { } } - actual := &bytes.Buffer{} + actual, err := json.Marshal(registry) - err := registry.dumpToWriter(actual) if err != nil { t.Errorf("%d. encountered error while dumping %s", i, err) } - if !bytes.Equal(scenario.out, actual.Bytes()) { - t.Errorf("%d. expected %q for dumping, got %q", i, scenario.out, actual.Bytes()) + if !bytes.Equal(scenario.out, actual) { + t.Errorf("%d. expected %q for dumping, got %q", i, scenario.out, actual) } } } diff --git a/prometheus/telemetry.go b/prometheus/telemetry.go index dc048bd..011c483 100644 --- a/prometheus/telemetry.go +++ b/prometheus/telemetry.go @@ -15,9 +15,6 @@ import ( // exposed if the DefaultRegistry's exporter is hooked into the HTTP request // handler. var ( - marshalErrorCount = NewCounter() - dumpErrorCount = NewCounter() - requestCount = NewCounter() requestLatencyBuckets = LogarithmicSizedBucketsFor(0, 1000) requestLatency = NewHistogram(&HistogramSpecification{ From 960107461e32642f8616978a610aa436c5855b87 Mon Sep 17 00:00:00 2001 From: "Matt T. Proud" Date: Sun, 28 Apr 2013 19:20:47 +0200 Subject: [PATCH 6/6] Migrate documentation to markdown. --- documentation/advice.md | 40 +++++++++++++++++++++++++++ documentation/documentation.go | 49 ---------------------------------- 2 files changed, 40 insertions(+), 49 deletions(-) create mode 100644 documentation/advice.md delete mode 100644 documentation/documentation.go diff --git a/documentation/advice.md b/documentation/advice.md new file mode 100644 index 0000000..dd629dc --- /dev/null +++ b/documentation/advice.md @@ -0,0 +1,40 @@ +Please try to observe the following rules when naming metrics: + +- Use underbars "_" to separate words. + +- Have the metric name start from generality and work toward specificity +toward the end. For example, when working with multiple caching subsystems, +consider using the following structure "cache" + "user_credentials" → +"cache_user_credentials" and "cache" + "value_transformations" → +"cache_value_transformations". + +- Have whatever is being measured follow the system and subsystem names cited +supra. For instance, with "insertions", "deletions", "evictions", +"replacements" of the above cache, they should be named as +"cache_user_credentials_insertions" and "cache_user_credentials_deletions" +and "cache_user_credentials_deletions" and +"cache_user_credentials_evictions". + +- If what is being measured has a standardized unit around it, consider +providing a unit for it. + +- Consider adding an additional suffix that designates what the value +represents such as a "total" or "size"---e.g., +"cache_user_credentials_size_kb" or +"cache_user_credentials_insertions_total". + +- Give heed to how future-proof the names are. Things may depend on these +names; and as your service evolves, the calculated values may take on +different meanings, which can be difficult to reflect if deployed code +depends on antique names. + +Further considerations: + +- The Registry's exposition mechanism is not backed by authorization and +authentication. This is something that will need to be addressed for +production services that are directly exposed to the outside world. + +- Engage in as little in-process processing of values as possible. The job +of processing and aggregation of these values belongs in a separate +post-processing job. The same goes for archiving. I will need to evaluate +hooks into something like OpenTSBD. diff --git a/documentation/documentation.go b/documentation/documentation.go deleted file mode 100644 index 9e556ab..0000000 --- a/documentation/documentation.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2013, Prometheus Team -// All rights reserved. -// -// Use of this source code is governed by a BSD-style license that can be found -// in the LICENSE file. - -// A repository of various Prometheus client documentation and advice. -// -// Please try to observe the following rules when naming metrics: -// -// - Use underbars "_" to separate words. -// -// - Have the metric name start from generality and work toward specificity -// toward the end. For example, when working with multiple caching subsystems, -// consider using the following structure "cache" + "user_credentials" → -// "cache_user_credentials" and "cache" + "value_transformations" → -// "cache_value_transformations". -// -// - Have whatever is being measured follow the system and subsystem names cited -// supra. For instance, with "insertions", "deletions", "evictions", -// "replacements" of the above cache, they should be named as -// "cache_user_credentials_insertions" and "cache_user_credentials_deletions" -// and "cache_user_credentials_deletions" and -// "cache_user_credentials_evictions". -// -// - If what is being measured has a standardized unit around it, consider -// providing a unit for it. -// -// - Consider adding an additional suffix that designates what the value -// represents such as a "total" or "size"---e.g., -// "cache_user_credentials_size_kb" or -// "cache_user_credentials_insertions_total". -// -// - Give heed to how future-proof the names are. Things may depend on these -// names; and as your service evolves, the calculated values may take on -// different meanings, which can be difficult to reflect if deployed code -// depends on antique names. -// -// Further considerations: -// -// - The Registry's exposition mechanism is not backed by authorization and -// authentication. This is something that will need to be addressed for -// production services that are directly exposed to the outside world. -// -// - Engage in as little in-process processing of values as possible. The job -// of processing and aggregation of these values belongs in a separate -// post-processing job. The same goes for archiving. I will need to evaluate -// hooks into something like OpenTSBD. -package documentation