Browse Source

Merge pull request #3681 from yichengq/godep-update

Godeps: update prometheus dependency
Yicheng Qin 10 years ago
parent
commit
f78ccbbd3f
100 changed files with 4241 additions and 1070 deletions
  1. 11 13
      Godeps/Godeps.json
  2. 0 55
      Godeps/_workspace/src/github.com/prometheus/client_golang/model/labelname_test.go
  3. 0 64
      Godeps/_workspace/src/github.com/prometheus/client_golang/model/labelset.go
  4. 0 192
      Godeps/_workspace/src/github.com/prometheus/client_golang/model/metric.go
  5. 0 79
      Godeps/_workspace/src/github.com/prometheus/client_golang/model/sample.go
  6. 0 114
      Godeps/_workspace/src/github.com/prometheus/client_golang/model/sample_test.go
  7. 0 37
      Godeps/_workspace/src/github.com/prometheus/client_golang/model/samplevalue.go
  8. 0 116
      Godeps/_workspace/src/github.com/prometheus/client_golang/model/timestamp.go
  9. 10 9
      Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/desc.go
  10. 6 5
      Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/doc.go
  11. 1 3
      Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/example_selfcollector_test.go
  12. 24 3
      Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/examples_test.go
  13. 1 2
      Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/expvar_test.go
  14. 215 2
      Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/go_collector.go
  15. 4 0
      Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/go_collector_test.go
  16. 7 5
      Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/histogram.go
  17. 8 0
      Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/histogram_test.go
  18. 42 3
      Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/http.go
  19. 2 0
      Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/metric.go
  20. 43 64
      Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/registry.go
  21. 10 10
      Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/registry_test.go
  22. 10 7
      Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/summary.go
  23. 1 1
      Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/untyped.go
  24. 1 2
      Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/value.go
  25. 8 2
      Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/vec.go
  26. 0 43
      Godeps/_workspace/src/github.com/prometheus/client_golang/text/proto.go
  27. BIN
      Godeps/_workspace/src/github.com/prometheus/client_golang/text/testdata/protobuf
  28. BIN
      Godeps/_workspace/src/github.com/prometheus/client_golang/text/testdata/protobuf.gz
  29. BIN
      Godeps/_workspace/src/github.com/prometheus/client_golang/text/testdata/text.gz
  30. 4 2
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/bench_test.go
  31. 410 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/decode.go
  32. 356 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/decode_test.go
  33. 87 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/encode.go
  34. 40 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/expfmt.go
  35. 18 18
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz.go
  36. 2 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_0
  37. 6 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_1
  38. 12 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_2
  39. 22 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_3
  40. 10 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_4
  41. 1 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_0
  42. 1 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_1
  43. 1 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_10
  44. 1 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_11
  45. 3 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_12
  46. 3 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_13
  47. 3 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_14
  48. 2 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_15
  49. 2 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_16
  50. 1 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_17
  51. 1 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_18
  52. 3 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_19
  53. 3 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_2
  54. 1 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_3
  55. 1 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_4
  56. 1 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_5
  57. 1 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_6
  58. 3 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_7
  59. 1 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_8
  60. 1 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_9
  61. 1 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/minimal
  62. 161 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/json_decode.go
  63. 124 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/json_decode_test.go
  64. 46 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/json2
  65. 516 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/protobuf
  66. 129 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/protobuf.gz
  67. 163 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/test.gz
  68. 0 0
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/text
  69. 8 18
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/text_create.go
  70. 20 17
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/text_create_test.go
  71. 36 30
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/text_parse.go
  72. 10 12
      Godeps/_workspace/src/github.com/prometheus/common/expfmt/text_parse_test.go
  73. 109 0
      Godeps/_workspace/src/github.com/prometheus/common/model/alert.go
  74. 12 17
      Godeps/_workspace/src/github.com/prometheus/common/model/fingerprinting.go
  75. 94 10
      Godeps/_workspace/src/github.com/prometheus/common/model/labels.go
  76. 36 0
      Godeps/_workspace/src/github.com/prometheus/common/model/labels_test.go
  77. 153 0
      Godeps/_workspace/src/github.com/prometheus/common/model/labelset.go
  78. 81 0
      Godeps/_workspace/src/github.com/prometheus/common/model/metric.go
  79. 12 59
      Godeps/_workspace/src/github.com/prometheus/common/model/metric_test.go
  80. 2 1
      Godeps/_workspace/src/github.com/prometheus/common/model/model.go
  81. 12 12
      Godeps/_workspace/src/github.com/prometheus/common/model/signature.go
  82. 30 30
      Godeps/_workspace/src/github.com/prometheus/common/model/signature_test.go
  83. 60 0
      Godeps/_workspace/src/github.com/prometheus/common/model/silence.go
  84. 230 0
      Godeps/_workspace/src/github.com/prometheus/common/model/time.go
  85. 13 13
      Godeps/_workspace/src/github.com/prometheus/common/model/time_test.go
  86. 395 0
      Godeps/_workspace/src/github.com/prometheus/common/model/value.go
  87. 362 0
      Godeps/_workspace/src/github.com/prometheus/common/model/value_test.go
  88. 2 0
      Godeps/_workspace/src/github.com/prometheus/procfs/.travis.yml
  89. 8 0
      Godeps/_workspace/src/github.com/prometheus/procfs/AUTHORS.md
  90. 6 0
      Godeps/_workspace/src/github.com/prometheus/procfs/Makefile
  91. 0 0
      Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/0
  92. 1 0
      Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/0
  93. 0 0
      Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/1
  94. 1 0
      Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/1
  95. 1 0
      Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/10
  96. 0 0
      Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/2
  97. 1 0
      Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/2
  98. 0 0
      Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/3
  99. 1 0
      Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/3
  100. 0 0
      Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26232/fd/0

+ 11 - 13
Godeps/Godeps.json

@@ -83,29 +83,27 @@
 			"ImportPath": "github.com/matttproud/golang_protobuf_extensions/pbutil",
 			"Rev": "fc2b8d3a73c4867e51861bbdd5ae3c1f0869dd6a"
 		},
-		{
-			"ImportPath": "github.com/prometheus/client_golang/model",
-			"Comment": "0.5.0-10-ga842dc1",
-			"Rev": "a842dc11e0621c34a71cab634d1d0190a59802a8"
-		},
 		{
 			"ImportPath": "github.com/prometheus/client_golang/prometheus",
-			"Comment": "0.5.0-10-ga842dc1",
-			"Rev": "a842dc11e0621c34a71cab634d1d0190a59802a8"
-		},
-		{
-			"ImportPath": "github.com/prometheus/client_golang/text",
-			"Comment": "0.5.0-10-ga842dc1",
-			"Rev": "a842dc11e0621c34a71cab634d1d0190a59802a8"
+			"Comment": "0.7.0-52-ge51041b",
+			"Rev": "e51041b3fa41cece0dca035740ba6411905be473"
 		},
 		{
 			"ImportPath": "github.com/prometheus/client_model/go",
 			"Comment": "model-0.0.2-12-gfa8ad6f",
 			"Rev": "fa8ad6fec33561be4280a8f0514318c79d7f6cb6"
 		},
+		{
+			"ImportPath": "github.com/prometheus/common/expfmt",
+			"Rev": "ffe929a3f4c4faeaa10f2b9535c2b1be3ad15650"
+		},
+		{
+			"ImportPath": "github.com/prometheus/common/model",
+			"Rev": "ffe929a3f4c4faeaa10f2b9535c2b1be3ad15650"
+		},
 		{
 			"ImportPath": "github.com/prometheus/procfs",
-			"Rev": "ee2372b58cee877abe07cde670d04d3b3bac5ee6"
+			"Rev": "454a56f35412459b5e684fd5ec0f9211b94f002a"
 		},
 		{
 			"ImportPath": "github.com/stretchr/testify/assert",

+ 0 - 55
Godeps/_workspace/src/github.com/prometheus/client_golang/model/labelname_test.go

@@ -1,55 +0,0 @@
-// Copyright 2013 The Prometheus Authors
-// 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.
-
-package model
-
-import (
-	"sort"
-	"testing"
-)
-
-func testLabelNames(t testing.TB) {
-	var scenarios = []struct {
-		in  LabelNames
-		out LabelNames
-	}{
-		{
-			in:  LabelNames{"ZZZ", "zzz"},
-			out: LabelNames{"ZZZ", "zzz"},
-		},
-		{
-			in:  LabelNames{"aaa", "AAA"},
-			out: LabelNames{"AAA", "aaa"},
-		},
-	}
-
-	for i, scenario := range scenarios {
-		sort.Sort(scenario.in)
-
-		for j, expected := range scenario.out {
-			if expected != scenario.in[j] {
-				t.Errorf("%d.%d expected %s, got %s", i, j, expected, scenario.in[j])
-			}
-		}
-	}
-}
-
-func TestLabelNames(t *testing.T) {
-	testLabelNames(t)
-}
-
-func BenchmarkLabelNames(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		testLabelNames(b)
-	}
-}

+ 0 - 64
Godeps/_workspace/src/github.com/prometheus/client_golang/model/labelset.go

@@ -1,64 +0,0 @@
-// Copyright 2013 The Prometheus Authors
-// 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.
-
-package model
-
-import (
-	"fmt"
-	"sort"
-	"strings"
-)
-
-// A LabelSet is a collection of LabelName and LabelValue pairs.  The LabelSet
-// may be fully-qualified down to the point where it may resolve to a single
-// Metric in the data store or not.  All operations that occur within the realm
-// of a LabelSet can emit a vector of Metric entities to which the LabelSet may
-// match.
-type LabelSet map[LabelName]LabelValue
-
-// Merge is a helper function to non-destructively merge two label sets.
-func (l LabelSet) Merge(other LabelSet) LabelSet {
-	result := make(LabelSet, len(l))
-
-	for k, v := range l {
-		result[k] = v
-	}
-
-	for k, v := range other {
-		result[k] = v
-	}
-
-	return result
-}
-
-func (l LabelSet) String() string {
-	labelStrings := make([]string, 0, len(l))
-	for label, value := range l {
-		labelStrings = append(labelStrings, fmt.Sprintf("%s=%q", label, value))
-	}
-
-	switch len(labelStrings) {
-	case 0:
-		return ""
-	default:
-		sort.Strings(labelStrings)
-		return fmt.Sprintf("{%s}", strings.Join(labelStrings, ", "))
-	}
-}
-
-// MergeFromMetric merges Metric into this LabelSet.
-func (l LabelSet) MergeFromMetric(m Metric) {
-	for k, v := range m {
-		l[k] = v
-	}
-}

+ 0 - 192
Godeps/_workspace/src/github.com/prometheus/client_golang/model/metric.go

@@ -1,192 +0,0 @@
-// Copyright 2013 The Prometheus Authors
-// 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.
-
-package model
-
-import (
-	"encoding/json"
-	"fmt"
-	"sort"
-	"strings"
-)
-
-var separator = []byte{0}
-
-// A Metric is similar to a LabelSet, but the key difference is that a Metric is
-// a singleton and refers to one and only one stream of samples.
-type Metric map[LabelName]LabelValue
-
-// Equal compares the metrics.
-func (m Metric) Equal(o Metric) bool {
-	if len(m) != len(o) {
-		return false
-	}
-	for ln, lv := range m {
-		olv, ok := o[ln]
-		if !ok {
-			return false
-		}
-		if olv != lv {
-			return false
-		}
-	}
-	return true
-}
-
-// Before compares the metrics, using the following criteria:
-//
-// If m has fewer labels than o, it is before o. If it has more, it is not.
-//
-// If the number of labels is the same, the superset of all label names is
-// sorted alphanumerically. The first differing label pair found in that order
-// determines the outcome: If the label does not exist at all in m, then m is
-// before o, and vice versa. Otherwise the label value is compared
-// alphanumerically.
-//
-// If m and o are equal, the method returns false.
-func (m Metric) Before(o Metric) bool {
-	if len(m) < len(o) {
-		return true
-	}
-	if len(m) > len(o) {
-		return false
-	}
-
-	lns := make(LabelNames, 0, len(m)+len(o))
-	for ln := range m {
-		lns = append(lns, ln)
-	}
-	for ln := range o {
-		lns = append(lns, ln)
-	}
-	// It's probably not worth it to de-dup lns.
-	sort.Sort(lns)
-	for _, ln := range lns {
-		mlv, ok := m[ln]
-		if !ok {
-			return true
-		}
-		olv, ok := o[ln]
-		if !ok {
-			return false
-		}
-		if mlv < olv {
-			return true
-		}
-		if mlv > olv {
-			return false
-		}
-	}
-	return false
-}
-
-// String implements Stringer.
-func (m Metric) String() string {
-	metricName, hasName := m[MetricNameLabel]
-	numLabels := len(m) - 1
-	if !hasName {
-		numLabels = len(m)
-	}
-	labelStrings := make([]string, 0, numLabels)
-	for label, value := range m {
-		if label != MetricNameLabel {
-			labelStrings = append(labelStrings, fmt.Sprintf("%s=%q", label, value))
-		}
-	}
-
-	switch numLabels {
-	case 0:
-		if hasName {
-			return string(metricName)
-		}
-		return "{}"
-	default:
-		sort.Strings(labelStrings)
-		return fmt.Sprintf("%s{%s}", metricName, strings.Join(labelStrings, ", "))
-	}
-}
-
-// Fingerprint returns a Metric's Fingerprint.
-func (m Metric) Fingerprint() Fingerprint {
-	return metricToFingerprint(m)
-}
-
-// Fingerprint returns a Metric's Fingerprint calculated by a faster hashing
-// algorithm, which is, however, more susceptible to hash collisions.
-func (m Metric) FastFingerprint() Fingerprint {
-	return metricToFastFingerprint(m)
-}
-
-// Clone returns a copy of the Metric.
-func (m Metric) Clone() Metric {
-	clone := Metric{}
-	for k, v := range m {
-		clone[k] = v
-	}
-	return clone
-}
-
-// MergeFromLabelSet merges a label set into this Metric, prefixing a collision
-// prefix to the label names merged from the label set where required.
-func (m Metric) MergeFromLabelSet(labels LabelSet, collisionPrefix LabelName) {
-	for k, v := range labels {
-		if collisionPrefix != "" {
-			for {
-				if _, exists := m[k]; !exists {
-					break
-				}
-				k = collisionPrefix + k
-			}
-		}
-
-		m[k] = v
-	}
-}
-
-// COWMetric wraps a Metric to enable copy-on-write access patterns.
-type COWMetric struct {
-	Copied bool
-	Metric Metric
-}
-
-// Set sets a label name in the wrapped Metric to a given value and copies the
-// Metric initially, if it is not already a copy.
-func (m *COWMetric) Set(ln LabelName, lv LabelValue) {
-	m.doCOW()
-	m.Metric[ln] = lv
-}
-
-// Delete deletes a given label name from the wrapped Metric and copies the
-// Metric initially, if it is not already a copy.
-func (m *COWMetric) Delete(ln LabelName) {
-	m.doCOW()
-	delete(m.Metric, ln)
-}
-
-// doCOW copies the underlying Metric if it is not already a copy.
-func (m *COWMetric) doCOW() {
-	if !m.Copied {
-		m.Metric = m.Metric.Clone()
-		m.Copied = true
-	}
-}
-
-// String implements fmt.Stringer.
-func (m COWMetric) String() string {
-	return m.Metric.String()
-}
-
-// MarshalJSON implements json.Marshaler.
-func (m COWMetric) MarshalJSON() ([]byte, error) {
-	return json.Marshal(m.Metric)
-}

+ 0 - 79
Godeps/_workspace/src/github.com/prometheus/client_golang/model/sample.go

@@ -1,79 +0,0 @@
-// Copyright 2013 The Prometheus Authors
-// 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.
-
-package model
-
-// Sample is a sample value with a timestamp and a metric.
-type Sample struct {
-	Metric    Metric
-	Value     SampleValue
-	Timestamp Timestamp
-}
-
-// Equal compares first the metrics, then the timestamp, then the value.
-func (s *Sample) Equal(o *Sample) bool {
-	if s == o {
-		return true
-	}
-
-	if !s.Metric.Equal(o.Metric) {
-		return false
-	}
-	if !s.Timestamp.Equal(o.Timestamp) {
-		return false
-	}
-	if !s.Value.Equal(o.Value) {
-		return false
-	}
-
-	return true
-}
-
-// Samples is a sortable Sample slice. It implements sort.Interface.
-type Samples []*Sample
-
-func (s Samples) Len() int {
-	return len(s)
-}
-
-// Less compares first the metrics, then the timestamp.
-func (s Samples) Less(i, j int) bool {
-	switch {
-	case s[i].Metric.Before(s[j].Metric):
-		return true
-	case s[j].Metric.Before(s[i].Metric):
-		return false
-	case s[i].Timestamp.Before(s[j].Timestamp):
-		return true
-	default:
-		return false
-	}
-}
-
-func (s Samples) Swap(i, j int) {
-	s[i], s[j] = s[j], s[i]
-}
-
-// Equal compares two sets of samples and returns true if they are equal.
-func (s Samples) Equal(o Samples) bool {
-	if len(s) != len(o) {
-		return false
-	}
-
-	for i, sample := range s {
-		if !sample.Equal(o[i]) {
-			return false
-		}
-	}
-	return true
-}

+ 0 - 114
Godeps/_workspace/src/github.com/prometheus/client_golang/model/sample_test.go

@@ -1,114 +0,0 @@
-// Copyright 2013 The Prometheus Authors
-// 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.
-
-package model
-
-import (
-	"sort"
-	"testing"
-)
-
-func TestSamplesSort(t *testing.T) {
-	input := Samples{
-		&Sample{
-			Metric: Metric{
-				MetricNameLabel: "A",
-			},
-			Timestamp: 1,
-		},
-		&Sample{
-			Metric: Metric{
-				MetricNameLabel: "A",
-			},
-			Timestamp: 2,
-		},
-		&Sample{
-			Metric: Metric{
-				MetricNameLabel: "C",
-			},
-			Timestamp: 1,
-		},
-		&Sample{
-			Metric: Metric{
-				MetricNameLabel: "C",
-			},
-			Timestamp: 2,
-		},
-		&Sample{
-			Metric: Metric{
-				MetricNameLabel: "B",
-			},
-			Timestamp: 1,
-		},
-		&Sample{
-			Metric: Metric{
-				MetricNameLabel: "B",
-			},
-			Timestamp: 2,
-		},
-	}
-
-	expected := Samples{
-		&Sample{
-			Metric: Metric{
-				MetricNameLabel: "A",
-			},
-			Timestamp: 1,
-		},
-		&Sample{
-			Metric: Metric{
-				MetricNameLabel: "A",
-			},
-			Timestamp: 2,
-		},
-		&Sample{
-			Metric: Metric{
-				MetricNameLabel: "B",
-			},
-			Timestamp: 1,
-		},
-		&Sample{
-			Metric: Metric{
-				MetricNameLabel: "B",
-			},
-			Timestamp: 2,
-		},
-		&Sample{
-			Metric: Metric{
-				MetricNameLabel: "C",
-			},
-			Timestamp: 1,
-		},
-		&Sample{
-			Metric: Metric{
-				MetricNameLabel: "C",
-			},
-			Timestamp: 2,
-		},
-	}
-
-	sort.Sort(input)
-
-	for i, actual := range input {
-		actualFp := actual.Metric.Fingerprint()
-		expectedFp := expected[i].Metric.Fingerprint()
-
-		if !actualFp.Equal(expectedFp) {
-			t.Fatalf("%d. Incorrect fingerprint. Got %s; want %s", i, actualFp.String(), expectedFp.String())
-		}
-
-		if actual.Timestamp != expected[i].Timestamp {
-			t.Fatalf("%d. Incorrect timestamp. Got %s; want %s", i, actual.Timestamp, expected[i].Timestamp)
-		}
-	}
-}

+ 0 - 37
Godeps/_workspace/src/github.com/prometheus/client_golang/model/samplevalue.go

@@ -1,37 +0,0 @@
-// Copyright 2013 The Prometheus Authors
-// 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.
-
-package model
-
-import (
-	"fmt"
-	"strconv"
-)
-
-// A SampleValue is a representation of a value for a given sample at a given
-// time.
-type SampleValue float64
-
-// Equal does a straight v==o.
-func (v SampleValue) Equal(o SampleValue) bool {
-	return v == o
-}
-
-// MarshalJSON implements json.Marshaler.
-func (v SampleValue) MarshalJSON() ([]byte, error) {
-	return []byte(fmt.Sprintf(`"%s"`, v)), nil
-}
-
-func (v SampleValue) String() string {
-	return strconv.FormatFloat(float64(v), 'f', -1, 64)
-}

+ 0 - 116
Godeps/_workspace/src/github.com/prometheus/client_golang/model/timestamp.go

@@ -1,116 +0,0 @@
-// Copyright 2013 The Prometheus Authors
-// 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.
-
-package model
-
-import (
-	"math"
-	"strconv"
-
-	native_time "time"
-)
-
-// Timestamp is the number of milliseconds since the epoch
-// (1970-01-01 00:00 UTC) excluding leap seconds.
-type Timestamp int64
-
-const (
-	// MinimumTick is the minimum supported time resolution. This has to be
-	// at least native_time.Second in order for the code below to work.
-	MinimumTick = native_time.Millisecond
-	// second is the timestamp duration equivalent to one second.
-	second = int64(native_time.Second / MinimumTick)
-	// The number of nanoseconds per minimum tick.
-	nanosPerTick = int64(MinimumTick / native_time.Nanosecond)
-
-	// Earliest is the earliest timestamp representable. Handy for
-	// initializing a high watermark.
-	Earliest = Timestamp(math.MinInt64)
-	// Latest is the latest timestamp representable. Handy for initializing
-	// a low watermark.
-	Latest = Timestamp(math.MaxInt64)
-)
-
-// Equal reports whether two timestamps represent the same instant.
-func (t Timestamp) Equal(o Timestamp) bool {
-	return t == o
-}
-
-// Before reports whether the timestamp t is before o.
-func (t Timestamp) Before(o Timestamp) bool {
-	return t < o
-}
-
-// After reports whether the timestamp t is after o.
-func (t Timestamp) After(o Timestamp) bool {
-	return t > o
-}
-
-// Add returns the Timestamp t + d.
-func (t Timestamp) Add(d native_time.Duration) Timestamp {
-	return t + Timestamp(d/MinimumTick)
-}
-
-// Sub returns the Duration t - o.
-func (t Timestamp) Sub(o Timestamp) native_time.Duration {
-	return native_time.Duration(t-o) * MinimumTick
-}
-
-// Time returns the time.Time representation of t.
-func (t Timestamp) Time() native_time.Time {
-	return native_time.Unix(int64(t)/second, (int64(t)%second)*nanosPerTick)
-}
-
-// Unix returns t as a Unix time, the number of seconds elapsed
-// since January 1, 1970 UTC.
-func (t Timestamp) Unix() int64 {
-	return int64(t) / second
-}
-
-// UnixNano returns t as a Unix time, the number of nanoseconds elapsed
-// since January 1, 1970 UTC.
-func (t Timestamp) UnixNano() int64 {
-	return int64(t) * nanosPerTick
-}
-
-// String returns a string representation of the timestamp.
-func (t Timestamp) String() string {
-	return strconv.FormatFloat(float64(t)/float64(second), 'f', -1, 64)
-}
-
-// MarshalJSON implements the json.Marshaler interface.
-func (t Timestamp) MarshalJSON() ([]byte, error) {
-	return []byte(t.String()), nil
-}
-
-// Now returns the current time as a Timestamp.
-func Now() Timestamp {
-	return TimestampFromTime(native_time.Now())
-}
-
-// TimestampFromTime returns the Timestamp equivalent to the time.Time t.
-func TimestampFromTime(t native_time.Time) Timestamp {
-	return TimestampFromUnixNano(t.UnixNano())
-}
-
-// TimestampFromUnix returns the Timestamp equivalent to the Unix timestamp t
-// provided in seconds.
-func TimestampFromUnix(t int64) Timestamp {
-	return Timestamp(t * second)
-}
-
-// TimestampFromUnixNano returns the Timestamp equivalent to the Unix timestamp
-// t provided in nanoseconds.
-func TimestampFromUnixNano(t int64) Timestamp {
-	return Timestamp(t / nanosPerTick)
-}

+ 10 - 9
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/desc.go

@@ -9,18 +9,19 @@ import (
 	"sort"
 	"strings"
 
-	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_golang/model"
-
-	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
-
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
+	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
 )
 
 var (
 	metricNameRE = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_:]*$`)
-	labelNameRE  = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`)
+	labelNameRE  = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$")
 )
 
+// reservedLabelPrefix is a prefix which is not legal in user-supplied
+// label names.
+const reservedLabelPrefix = "__"
+
 // Labels represents a collection of label name -> value mappings. This type is
 // commonly used with the With(Labels) and GetMetricWith(Labels) methods of
 // metric vector Collectors, e.g.:
@@ -134,7 +135,7 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *
 	for _, val := range labelValues {
 		b.Reset()
 		b.WriteString(val)
-		b.WriteByte(model.SeparatorByte)
+		b.WriteByte(separatorByte)
 		h.Write(b.Bytes())
 	}
 	d.id = h.Sum64()
@@ -145,12 +146,12 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *
 	h.Reset()
 	b.Reset()
 	b.WriteString(help)
-	b.WriteByte(model.SeparatorByte)
+	b.WriteByte(separatorByte)
 	h.Write(b.Bytes())
 	for _, labelName := range labelNames {
 		b.Reset()
 		b.WriteString(labelName)
-		b.WriteByte(model.SeparatorByte)
+		b.WriteByte(separatorByte)
 		h.Write(b.Bytes())
 	}
 	d.dimHash = h.Sum64()
@@ -195,5 +196,5 @@ func (d *Desc) String() string {
 
 func checkLabelName(l string) bool {
 	return labelNameRE.MatchString(l) &&
-		!strings.HasPrefix(l, model.ReservedLabelPrefix)
+		!strings.HasPrefix(l, reservedLabelPrefix)
 }

+ 6 - 5
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/doc.go

@@ -61,12 +61,13 @@
 // It also exports some stats about the HTTP usage of the /metrics
 // endpoint. (See the Handler function for more detail.)
 //
-// A more advanced metric type is the Summary.
+// Two more advanced metric types are the Summary and Histogram.
 //
-// In addition to the fundamental metric types Gauge, Counter, and Summary, a
-// very important part of the Prometheus data model is the partitioning of
-// samples along dimensions called labels, which results in metric vectors. The
-// fundamental types are GaugeVec, CounterVec, and SummaryVec.
+// In addition to the fundamental metric types Gauge, Counter, Summary, and
+// Histogram, a very important part of the Prometheus data model is the
+// partitioning of samples along dimensions called labels, which results in
+// metric vectors. The fundamental types are GaugeVec, CounterVec, SummaryVec,
+// and HistogramVec.
 //
 // Those are all the parts needed for basic usage. Detailed documentation and
 // examples are provided below.

+ 1 - 3
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/example_selfcollector_test.go

@@ -17,10 +17,8 @@ import (
 	"runtime"
 
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
-
-	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
-
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus"
+	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
 )
 
 func NewCallbackMetric(desc *prometheus.Desc, callback func() float64) *CallbackMetric {

+ 24 - 3
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/examples_test.go

@@ -23,11 +23,9 @@ import (
 	"sort"
 	"time"
 
-	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
-
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
-
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus"
+	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
 )
 
 func ExampleGauge() {
@@ -392,6 +390,9 @@ func ExampleSummaryVec() {
 		temps.WithLabelValues("lithobates-catesbeianus").Observe(32 + math.Floor(100*math.Cos(float64(i)*0.11))/10)
 	}
 
+	// Create a Summary without any observations.
+	temps.WithLabelValues("leiopelma-hochstetteri")
+
 	// Just for demonstration, let's check the state of the summary vector
 	// by (ab)using its Collect method and the Write method of its elements
 	// (which is usually only used by Prometheus internally - code like the
@@ -414,6 +415,26 @@ func ExampleSummaryVec() {
 	// Output:
 	// [label: <
 	//   name: "species"
+	//   value: "leiopelma-hochstetteri"
+	// >
+	// summary: <
+	//   sample_count: 0
+	//   sample_sum: 0
+	//   quantile: <
+	//     quantile: 0.5
+	//     value: nan
+	//   >
+	//   quantile: <
+	//     quantile: 0.9
+	//     value: nan
+	//   >
+	//   quantile: <
+	//     quantile: 0.99
+	//     value: nan
+	//   >
+	// >
+	//  label: <
+	//   name: "species"
 	//   value: "lithobates-catesbeianus"
 	// >
 	// summary: <

+ 1 - 2
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/expvar_test.go

@@ -19,9 +19,8 @@ import (
 	"sort"
 	"strings"
 
-	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
-
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus"
+	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
 )
 
 func ExampleExpvarCollector() {

+ 215 - 2
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/go_collector.go

@@ -1,6 +1,7 @@
 package prometheus
 
 import (
+	"fmt"
 	"runtime"
 	"runtime/debug"
 	"time"
@@ -9,6 +10,9 @@ import (
 type goCollector struct {
 	goroutines Gauge
 	gcDesc     *Desc
+
+	// metrics to describe and collect
+	metrics memStatsMetrics
 }
 
 // NewGoCollector returns a collector which exports metrics about the current
@@ -16,20 +20,216 @@ type goCollector struct {
 func NewGoCollector() *goCollector {
 	return &goCollector{
 		goroutines: NewGauge(GaugeOpts{
-			Name: "go_goroutines",
-			Help: "Number of goroutines that currently exist.",
+			Namespace: "go",
+			Name:      "goroutines",
+			Help:      "Number of goroutines that currently exist.",
 		}),
 		gcDesc: NewDesc(
 			"go_gc_duration_seconds",
 			"A summary of the GC invocation durations.",
 			nil, nil),
+		metrics: memStatsMetrics{
+			{
+				desc: NewDesc(
+					memstatNamespace("alloc_bytes"),
+					"Number of bytes allocated and still in use.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.Alloc) },
+				valType: GaugeValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("alloc_bytes_total"),
+					"Total number of bytes allocated, even if freed.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.TotalAlloc) },
+				valType: CounterValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("sys_bytes"),
+					"Number of bytes obtained by system. Sum of all system allocations.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.Sys) },
+				valType: GaugeValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("lookups_total"),
+					"Total number of pointer lookups.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.Lookups) },
+				valType: CounterValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("mallocs_total"),
+					"Total number of mallocs.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.Mallocs) },
+				valType: CounterValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("frees_total"),
+					"Total number of frees.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.Frees) },
+				valType: CounterValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("heap_alloc_bytes"),
+					"Number of heap bytes allocated and still in use.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.HeapAlloc) },
+				valType: GaugeValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("heap_sys_bytes"),
+					"Number of heap bytes obtained from system.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.HeapSys) },
+				valType: GaugeValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("heap_idle_bytes"),
+					"Number of heap bytes waiting to be used.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.HeapIdle) },
+				valType: GaugeValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("heap_inuse_bytes"),
+					"Number of heap bytes that are in use.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.HeapInuse) },
+				valType: GaugeValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("heap_released_bytes_total"),
+					"Total number of heap bytes released to OS.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.HeapReleased) },
+				valType: CounterValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("heap_objects"),
+					"Number of allocated objects.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.HeapObjects) },
+				valType: GaugeValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("stack_inuse_bytes"),
+					"Number of bytes in use by the stack allocator.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.StackInuse) },
+				valType: GaugeValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("stack_sys_bytes"),
+					"Number of bytes obtained from system for stack allocator.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.StackSys) },
+				valType: GaugeValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("mspan_inuse_bytes"),
+					"Number of bytes in use by mspan structures.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.MSpanInuse) },
+				valType: GaugeValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("mspan_sys_bytes"),
+					"Number of bytes used for mspan structures obtained from system.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.MSpanSys) },
+				valType: GaugeValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("mcache_inuse_bytes"),
+					"Number of bytes in use by mcache structures.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.MCacheInuse) },
+				valType: GaugeValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("mcache_sys_bytes"),
+					"Number of bytes used for mcache structures obtained from system.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.MCacheSys) },
+				valType: GaugeValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("buck_hash_sys_bytes"),
+					"Number of bytes used by the profiling bucket hash table.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.BuckHashSys) },
+				valType: GaugeValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("gc_sys_bytes"),
+					"Number of bytes used for garbage collection system metadata.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.GCSys) },
+				valType: GaugeValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("other_sys_bytes"),
+					"Number of bytes used for other system allocations.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.OtherSys) },
+				valType: GaugeValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("next_gc_bytes"),
+					"Number of heap bytes when next garbage collection will take place.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.NextGC) },
+				valType: GaugeValue,
+			}, {
+				desc: NewDesc(
+					memstatNamespace("last_gc_time_seconds"),
+					"Number of seconds since 1970 of last garbage collection.",
+					nil, nil,
+				),
+				eval:    func(ms *runtime.MemStats) float64 { return float64(ms.LastGC*10 ^ 9) },
+				valType: GaugeValue,
+			},
+		},
 	}
 }
 
+func memstatNamespace(s string) string {
+	return fmt.Sprintf("go_memstats_%s", s)
+}
+
 // Describe returns all descriptions of the collector.
 func (c *goCollector) Describe(ch chan<- *Desc) {
 	ch <- c.goroutines.Desc()
 	ch <- c.gcDesc
+
+	for _, i := range c.metrics {
+		ch <- i.desc
+	}
 }
 
 // Collect returns the current state of all metrics of the collector.
@@ -47,4 +247,17 @@ func (c *goCollector) Collect(ch chan<- Metric) {
 	}
 	quantiles[0.0] = stats.PauseQuantiles[0].Seconds()
 	ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), float64(stats.PauseTotal.Seconds()), quantiles)
+
+	ms := &runtime.MemStats{}
+	runtime.ReadMemStats(ms)
+	for _, i := range c.metrics {
+		ch <- MustNewConstMetric(i.desc, i.valType, i.eval(ms))
+	}
+}
+
+// memStatsMetrics provide description, value, and value type for memstat metrics.
+type memStatsMetrics []struct {
+	desc    *Desc
+	eval    func(*runtime.MemStats) float64
+	valType ValueType
 }

+ 4 - 0
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/go_collector_test.go

@@ -50,6 +50,10 @@ func TestGoCollector(t *testing.T) {
 					t.Errorf("want 1 new goroutine, got %d", diff)
 				}
 
+				// GoCollector performs two sends per call.
+				// On line 27 we need to receive the second send
+				// to shut down cleanly.
+				<-ch
 				return
 			}
 		case <-time.After(1 * time.Second):

+ 7 - 5
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/histogram.go

@@ -21,8 +21,6 @@ import (
 	"sync/atomic"
 
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
-
-	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_golang/model"
 	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
 )
 
@@ -49,6 +47,10 @@ type Histogram interface {
 	Observe(float64)
 }
 
+// bucketLabel is used for the label that defines the upper bound of a
+// bucket of a histogram ("le" -> "less or equal").
+const bucketLabel = "le"
+
 var (
 	// DefBuckets are the default Histogram buckets. The default buckets are
 	// tailored to broadly measure the response time (in seconds) of a
@@ -57,7 +59,7 @@ var (
 	DefBuckets = []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10}
 
 	errBucketLabelNotAllowed = fmt.Errorf(
-		"%q is not allowed as label name in histograms", model.BucketLabel,
+		"%q is not allowed as label name in histograms", bucketLabel,
 	)
 )
 
@@ -171,12 +173,12 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr
 	}
 
 	for _, n := range desc.variableLabels {
-		if n == model.BucketLabel {
+		if n == bucketLabel {
 			panic(errBucketLabelNotAllowed)
 		}
 	}
 	for _, lp := range desc.constLabelPairs {
-		if lp.GetName() == model.BucketLabel {
+		if lp.GetName() == bucketLabel {
 			panic(errBucketLabelNotAllowed)
 		}
 	}

+ 8 - 0
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/histogram_test.go

@@ -124,6 +124,10 @@ func BenchmarkHistogramWrite8(b *testing.B) {
 var testBuckets = []float64{-2, -1, -0.5, 0, 0.5, 1, 2, math.Inf(+1)}
 
 func TestHistogramConcurrency(t *testing.T) {
+	if testing.Short() {
+		t.Skip("Skipping test in short mode.")
+	}
+
 	rand.Seed(42)
 
 	it := func(n uint32) bool {
@@ -198,6 +202,10 @@ func TestHistogramConcurrency(t *testing.T) {
 }
 
 func TestHistogramVecConcurrency(t *testing.T) {
+	if testing.Short() {
+		t.Skip("Skipping test in short mode.")
+	}
+
 	rand.Seed(42)
 
 	objectives := make([]float64, 0, len(DefObjectives))

+ 42 - 3
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/http.go

@@ -14,6 +14,9 @@
 package prometheus
 
 import (
+	"bufio"
+	"io"
+	"net"
 	"net/http"
 	"strconv"
 	"strings"
@@ -141,7 +144,18 @@ func InstrumentHandlerFuncWithOpts(opts SummaryOpts, handlerFunc func(http.Respo
 			urlLen = len(r.URL.String())
 		}
 		go computeApproximateRequestSize(r, out, urlLen)
-		handlerFunc(delegate, r)
+
+		_, cn := w.(http.CloseNotifier)
+		_, fl := w.(http.Flusher)
+		_, hj := w.(http.Hijacker)
+		_, rf := w.(io.ReaderFrom)
+		var rw http.ResponseWriter
+		if cn && fl && hj && rf {
+			rw = &fancyResponseWriterDelegator{delegate}
+		} else {
+			rw = delegate
+		}
+		handlerFunc(rw, r)
 
 		elapsed := float64(time.Since(now)) / float64(time.Microsecond)
 
@@ -178,7 +192,7 @@ type responseWriterDelegator struct {
 
 	handler, method string
 	status          int
-	written         int
+	written         int64
 	wroteHeader     bool
 }
 
@@ -193,7 +207,32 @@ func (r *responseWriterDelegator) Write(b []byte) (int, error) {
 		r.WriteHeader(http.StatusOK)
 	}
 	n, err := r.ResponseWriter.Write(b)
-	r.written += n
+	r.written += int64(n)
+	return n, err
+}
+
+type fancyResponseWriterDelegator struct {
+	*responseWriterDelegator
+}
+
+func (f *fancyResponseWriterDelegator) CloseNotify() <-chan bool {
+	return f.ResponseWriter.(http.CloseNotifier).CloseNotify()
+}
+
+func (f *fancyResponseWriterDelegator) Flush() {
+	f.ResponseWriter.(http.Flusher).Flush()
+}
+
+func (f *fancyResponseWriterDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+	return f.ResponseWriter.(http.Hijacker).Hijack()
+}
+
+func (f *fancyResponseWriterDelegator) ReadFrom(r io.Reader) (int64, error) {
+	if !f.wroteHeader {
+		f.WriteHeader(http.StatusOK)
+	}
+	n, err := f.ResponseWriter.(io.ReaderFrom).ReadFrom(r)
+	f.written += n
 	return n, err
 }
 

+ 2 - 0
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/metric.go

@@ -19,6 +19,8 @@ import (
 	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
 )
 
+const separatorByte byte = 255
+
 // A Metric models a single sample value with its meta data being exported to
 // Prometheus. Implementers of Metric in this package inclued Gauge, Counter,
 // Untyped, and Summary. Users can implement their own Metric types, but that

+ 43 - 64
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/registry.go

@@ -33,13 +33,9 @@ import (
 	"strings"
 	"sync"
 
-	"github.com/coreos/etcd/Godeps/_workspace/src/bitbucket.org/ww/goautoneg"
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
-
 	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
-
-	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_golang/model"
-	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_golang/text"
+	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/common/expfmt"
 )
 
 var (
@@ -170,6 +166,11 @@ func Unregister(c Collector) bool {
 // checks are performed, but no further consistency checks (which would require
 // knowledge of a metric descriptor).
 //
+// Sorting concerns: The caller is responsible for sorting the label pairs in
+// each metric. However, the order of metrics will be sorted by the registry as
+// it is required anyway after merging with the metric families collected
+// conventionally.
+//
 // The function must be callable at any time and concurrently.
 func SetMetricFamilyInjectionHook(hook func() []*dto.MetricFamily) {
 	defRegistry.metricFamilyInjectionHook = hook
@@ -341,7 +342,7 @@ func (r *registry) Push(job, instance, pushURL, method string) error {
 	}
 	buf := r.getBuf()
 	defer r.giveBuf(buf)
-	if _, err := r.writePB(buf, text.WriteProtoDelimited); err != nil {
+	if err := r.writePB(expfmt.NewEncoder(buf, expfmt.FmtProtoDelim)); err != nil {
 		if r.panicOnCollectError {
 			panic(err)
 		}
@@ -364,11 +365,11 @@ func (r *registry) Push(job, instance, pushURL, method string) error {
 }
 
 func (r *registry) ServeHTTP(w http.ResponseWriter, req *http.Request) {
-	enc, contentType := chooseEncoder(req)
+	contentType := expfmt.Negotiate(req.Header)
 	buf := r.getBuf()
 	defer r.giveBuf(buf)
 	writer, encoding := decorateWriter(req, buf)
-	if _, err := r.writePB(writer, enc); err != nil {
+	if err := r.writePB(expfmt.NewEncoder(writer, contentType)); err != nil {
 		if r.panicOnCollectError {
 			panic(err)
 		}
@@ -379,7 +380,7 @@ func (r *registry) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 		closer.Close()
 	}
 	header := w.Header()
-	header.Set(contentTypeHeader, contentType)
+	header.Set(contentTypeHeader, string(contentType))
 	header.Set(contentLengthHeader, fmt.Sprint(buf.Len()))
 	if encoding != "" {
 		header.Set(contentEncodingHeader, encoding)
@@ -387,7 +388,7 @@ func (r *registry) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 	w.Write(buf.Bytes())
 }
 
-func (r *registry) writePB(w io.Writer, writeEncoded encoder) (int, error) {
+func (r *registry) writePB(encoder expfmt.Encoder) error {
 	var metricHashes map[uint64]struct{}
 	if r.collectChecksEnabled {
 		metricHashes = make(map[uint64]struct{})
@@ -439,7 +440,7 @@ func (r *registry) writePB(w io.Writer, writeEncoded encoder) (int, error) {
 			// TODO: Consider different means of error reporting so
 			// that a single erroneous metric could be skipped
 			// instead of blowing up the whole collection.
-			return 0, fmt.Errorf("error collecting metric %v: %s", desc, err)
+			return fmt.Errorf("error collecting metric %v: %s", desc, err)
 		}
 		switch {
 		case metricFamily.Type != nil:
@@ -455,11 +456,11 @@ func (r *registry) writePB(w io.Writer, writeEncoded encoder) (int, error) {
 		case dtoMetric.Histogram != nil:
 			metricFamily.Type = dto.MetricType_HISTOGRAM.Enum()
 		default:
-			return 0, fmt.Errorf("empty metric collected: %s", dtoMetric)
+			return fmt.Errorf("empty metric collected: %s", dtoMetric)
 		}
 		if r.collectChecksEnabled {
 			if err := r.checkConsistency(metricFamily, dtoMetric, desc, metricHashes); err != nil {
-				return 0, err
+				return err
 			}
 		}
 		metricFamily.Metric = append(metricFamily.Metric, dtoMetric)
@@ -473,7 +474,7 @@ func (r *registry) writePB(w io.Writer, writeEncoded encoder) (int, error) {
 				if r.collectChecksEnabled {
 					for _, m := range mf.Metric {
 						if err := r.checkConsistency(mf, m, nil, metricHashes); err != nil {
-							return 0, err
+							return err
 						}
 					}
 				}
@@ -482,7 +483,7 @@ func (r *registry) writePB(w io.Writer, writeEncoded encoder) (int, error) {
 			for _, m := range mf.Metric {
 				if r.collectChecksEnabled {
 					if err := r.checkConsistency(existingMF, m, nil, metricHashes); err != nil {
-						return 0, err
+						return err
 					}
 				}
 				existingMF.Metric = append(existingMF.Metric, m)
@@ -503,15 +504,12 @@ func (r *registry) writePB(w io.Writer, writeEncoded encoder) (int, error) {
 	}
 	sort.Strings(names)
 
-	var written int
 	for _, name := range names {
-		w, err := writeEncoded(w, metricFamiliesByName[name])
-		written += w
-		if err != nil {
-			return written, err
+		if err := encoder.Encode(metricFamiliesByName[name]); err != nil {
+			return err
 		}
 	}
-	return written, nil
+	return nil
 }
 
 func (r *registry) checkConsistency(metricFamily *dto.MetricFamily, dtoMetric *dto.Metric, desc *Desc, metricHashes map[uint64]struct{}) error {
@@ -520,10 +518,11 @@ func (r *registry) checkConsistency(metricFamily *dto.MetricFamily, dtoMetric *d
 	if metricFamily.GetType() == dto.MetricType_GAUGE && dtoMetric.Gauge == nil ||
 		metricFamily.GetType() == dto.MetricType_COUNTER && dtoMetric.Counter == nil ||
 		metricFamily.GetType() == dto.MetricType_SUMMARY && dtoMetric.Summary == nil ||
+		metricFamily.GetType() == dto.MetricType_HISTOGRAM && dtoMetric.Histogram == nil ||
 		metricFamily.GetType() == dto.MetricType_UNTYPED && dtoMetric.Untyped == nil {
 		return fmt.Errorf(
-			"collected metric %q is not a %s",
-			dtoMetric, metricFamily.Type,
+			"collected metric %s %s is not a %s",
+			metricFamily.GetName(), dtoMetric, metricFamily.GetType(),
 		)
 	}
 
@@ -531,19 +530,24 @@ func (r *registry) checkConsistency(metricFamily *dto.MetricFamily, dtoMetric *d
 	h := fnv.New64a()
 	var buf bytes.Buffer
 	buf.WriteString(metricFamily.GetName())
-	buf.WriteByte(model.SeparatorByte)
+	buf.WriteByte(separatorByte)
 	h.Write(buf.Bytes())
+	// Make sure label pairs are sorted. We depend on it for the consistency
+	// check. Label pairs must be sorted by contract. But the point of this
+	// method is to check for contract violations. So we better do the sort
+	// now.
+	sort.Sort(LabelPairSorter(dtoMetric.Label))
 	for _, lp := range dtoMetric.Label {
 		buf.Reset()
 		buf.WriteString(lp.GetValue())
-		buf.WriteByte(model.SeparatorByte)
+		buf.WriteByte(separatorByte)
 		h.Write(buf.Bytes())
 	}
 	metricHash := h.Sum64()
 	if _, exists := metricHashes[metricHash]; exists {
 		return fmt.Errorf(
-			"collected metric %q was collected before with the same name and label values",
-			dtoMetric,
+			"collected metric %s %s was collected before with the same name and label values",
+			metricFamily.GetName(), dtoMetric,
 		)
 	}
 	metricHashes[metricHash] = struct{}{}
@@ -555,14 +559,14 @@ func (r *registry) checkConsistency(metricFamily *dto.MetricFamily, dtoMetric *d
 	// Desc consistency with metric family.
 	if metricFamily.GetName() != desc.fqName {
 		return fmt.Errorf(
-			"collected metric %q has name %q but should have %q",
-			dtoMetric, metricFamily.GetName(), desc.fqName,
+			"collected metric %s %s has name %q but should have %q",
+			metricFamily.GetName(), dtoMetric, metricFamily.GetName(), desc.fqName,
 		)
 	}
 	if metricFamily.GetHelp() != desc.help {
 		return fmt.Errorf(
-			"collected metric %q has help %q but should have %q",
-			dtoMetric, metricFamily.GetHelp(), desc.help,
+			"collected metric %s %s has help %q but should have %q",
+			metricFamily.GetName(), dtoMetric, metricFamily.GetHelp(), desc.help,
 		)
 	}
 
@@ -576,8 +580,8 @@ func (r *registry) checkConsistency(metricFamily *dto.MetricFamily, dtoMetric *d
 	}
 	if len(lpsFromDesc) != len(dtoMetric.Label) {
 		return fmt.Errorf(
-			"labels in collected metric %q are inconsistent with descriptor %s",
-			dtoMetric, desc,
+			"labels in collected metric %s %s are inconsistent with descriptor %s",
+			metricFamily.GetName(), dtoMetric, desc,
 		)
 	}
 	sort.Sort(LabelPairSorter(lpsFromDesc))
@@ -586,8 +590,8 @@ func (r *registry) checkConsistency(metricFamily *dto.MetricFamily, dtoMetric *d
 		if lpFromDesc.GetName() != lpFromMetric.GetName() ||
 			lpFromDesc.Value != nil && lpFromDesc.GetValue() != lpFromMetric.GetValue() {
 			return fmt.Errorf(
-				"labels in collected metric %q are inconsistent with descriptor %s",
-				dtoMetric, desc,
+				"labels in collected metric %s %s are inconsistent with descriptor %s",
+				metricFamily.GetName(), dtoMetric, desc,
 			)
 		}
 	}
@@ -597,7 +601,10 @@ func (r *registry) checkConsistency(metricFamily *dto.MetricFamily, dtoMetric *d
 
 	// Is the desc registered?
 	if _, exist := r.descIDs[desc.id]; !exist {
-		return fmt.Errorf("collected metric %q with unregistered descriptor %s", dtoMetric, desc)
+		return fmt.Errorf(
+			"collected metric %s %s with unregistered descriptor %s",
+			metricFamily.GetName(), dtoMetric, desc,
+		)
 	}
 
 	return nil
@@ -672,34 +679,6 @@ func newDefaultRegistry() *registry {
 	return r
 }
 
-func chooseEncoder(req *http.Request) (encoder, string) {
-	accepts := goautoneg.ParseAccept(req.Header.Get(acceptHeader))
-	for _, accept := range accepts {
-		switch {
-		case accept.Type == "application" &&
-			accept.SubType == "vnd.google.protobuf" &&
-			accept.Params["proto"] == "io.prometheus.client.MetricFamily":
-			switch accept.Params["encoding"] {
-			case "delimited":
-				return text.WriteProtoDelimited, DelimitedTelemetryContentType
-			case "text":
-				return text.WriteProtoText, ProtoTextTelemetryContentType
-			case "compact-text":
-				return text.WriteProtoCompactText, ProtoCompactTextTelemetryContentType
-			default:
-				continue
-			}
-		case accept.Type == "text" &&
-			accept.SubType == "plain" &&
-			(accept.Params["version"] == "0.0.4" || accept.Params["version"] == ""):
-			return text.MetricFamilyToText, TextTelemetryContentType
-		default:
-			continue
-		}
-	}
-	return text.MetricFamilyToText, TextTelemetryContentType
-}
-
 // decorateWriter wraps a writer to handle gzip compression if requested.  It
 // returns the decorated writer and the appropriate "Content-Encoding" header
 // (which is empty if no compression is enabled).

+ 10 - 10
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/registry_test.go

@@ -68,14 +68,14 @@ func testHandler(t testing.TB) {
 		Metric: []*dto.Metric{
 			{
 				Label: []*dto.LabelPair{
-					{
-						Name:  proto.String("externallabelname"),
-						Value: proto.String("externalval1"),
-					},
 					{
 						Name:  proto.String("externalconstname"),
 						Value: proto.String("externalconstvalue"),
 					},
+					{
+						Name:  proto.String("externallabelname"),
+						Value: proto.String("externalval1"),
+					},
 				},
 				Counter: &dto.Counter{
 					Value: proto.Float64(1),
@@ -100,27 +100,27 @@ func testHandler(t testing.TB) {
 	externalMetricFamilyAsBytes := externalBuf.Bytes()
 	externalMetricFamilyAsText := []byte(`# HELP externalname externaldocstring
 # TYPE externalname counter
-externalname{externallabelname="externalval1",externalconstname="externalconstvalue"} 1
+externalname{externalconstname="externalconstvalue",externallabelname="externalval1"} 1
 `)
 	externalMetricFamilyAsProtoText := []byte(`name: "externalname"
 help: "externaldocstring"
 type: COUNTER
 metric: <
-  label: <
-    name: "externallabelname"
-    value: "externalval1"
-  >
   label: <
     name: "externalconstname"
     value: "externalconstvalue"
   >
+  label: <
+    name: "externallabelname"
+    value: "externalval1"
+  >
   counter: <
     value: 1
   >
 >
 
 `)
-	externalMetricFamilyAsProtoCompactText := []byte(`name:"externalname" help:"externaldocstring" type:COUNTER metric:<label:<name:"externallabelname" value:"externalval1" > label:<name:"externalconstname" value:"externalconstvalue" > counter:<value:1 > > 
+	externalMetricFamilyAsProtoCompactText := []byte(`name:"externalname" help:"externaldocstring" type:COUNTER metric:<label:<name:"externalconstname" value:"externalconstvalue" > label:<name:"externallabelname" value:"externalval1" > counter:<value:1 > > 
 `)
 
 	expectedMetricFamily := &dto.MetricFamily{

+ 10 - 7
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/summary.go

@@ -23,12 +23,13 @@ import (
 
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/beorn7/perks/quantile"
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
-
 	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
-
-	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_golang/model"
 )
 
+// quantileLabel is used for the label that defines the quantile in a
+// summary.
+const quantileLabel = "quantile"
+
 // A Summary captures individual observations from an event or sample stream and
 // summarizes them in a manner similar to traditional summary statistics: 1. sum
 // of observations, 2. observation count, 3. rank estimations.
@@ -57,7 +58,7 @@ var (
 	DefObjectives = map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}
 
 	errQuantileLabelNotAllowed = fmt.Errorf(
-		"%q is not allowed as label name in summaries", model.QuantileLabel,
+		"%q is not allowed as label name in summaries", quantileLabel,
 	)
 )
 
@@ -112,7 +113,9 @@ type SummaryOpts struct {
 	ConstLabels Labels
 
 	// Objectives defines the quantile rank estimates with their respective
-	// absolute error. The default value is DefObjectives.
+	// absolute error. If Objectives[q] = e, then the value reported
+	// for q will be the φ-quantile value for some φ between q-e and q+e.
+	// The default value is DefObjectives.
 	Objectives map[float64]float64
 
 	// MaxAge defines the duration for which an observation stays relevant
@@ -170,12 +173,12 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
 	}
 
 	for _, n := range desc.variableLabels {
-		if n == model.QuantileLabel {
+		if n == quantileLabel {
 			panic(errQuantileLabelNotAllowed)
 		}
 	}
 	for _, lp := range desc.constLabelPairs {
-		if lp.GetName() == model.QuantileLabel {
+		if lp.GetName() == quantileLabel {
 			panic(errQuantileLabelNotAllowed)
 		}
 	}

+ 1 - 1
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/untyped.go

@@ -21,7 +21,7 @@ import "hash/fnv"
 // An Untyped metric works the same as a Gauge. The only difference is that to
 // no type information is implied.
 //
-// To create Gauge instances, use NewUntyped.
+// To create Untyped instances, use NewUntyped.
 type Untyped interface {
 	Metric
 	Collector

+ 1 - 2
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/value.go

@@ -20,9 +20,8 @@ import (
 	"sort"
 	"sync/atomic"
 
-	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
-
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
+	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
 )
 
 // ValueType is an enumeration of metric types that represent a simple value.

+ 8 - 2
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/vec.go

@@ -58,6 +58,11 @@ func (m *MetricVec) Collect(ch chan<- Metric) {
 // GetMetricWithLabelValues returns the Metric for the given slice of label
 // values (same order as the VariableLabels in Desc). If that combination of
 // label values is accessed for the first time, a new Metric is created.
+//
+// It is possible to call this method without using the returned Metric to only
+// create the new Metric but leave it at its start value (e.g. a Summary or
+// Histogram without any observations). See also the SummaryVec example.
+//
 // Keeping the Metric for later use is possible (and should be considered if
 // performance is critical), but keep in mind that Reset, DeleteLabelValues and
 // Delete can be used to delete the Metric from the MetricVec. In that case, the
@@ -87,8 +92,9 @@ func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) {
 
 // GetMetricWith returns the Metric for the given Labels map (the label names
 // must match those of the VariableLabels in Desc). If that label map is
-// accessed for the first time, a new Metric is created. Implications of keeping
-// the Metric are the same as for GetMetricWithLabelValues.
+// accessed for the first time, a new Metric is created. Implications of
+// creating a Metric without using it and keeping the Metric for later use are
+// the same as for GetMetricWithLabelValues.
 //
 // An error is returned if the number and names of the Labels are inconsistent
 // with those of the VariableLabels in Desc.

+ 0 - 43
Godeps/_workspace/src/github.com/prometheus/client_golang/text/proto.go

@@ -1,43 +0,0 @@
-// Copyright 2014 The Prometheus Authors
-// 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.
-
-package text
-
-import (
-	"fmt"
-	"io"
-
-	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
-	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/matttproud/golang_protobuf_extensions/pbutil"
-
-	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
-)
-
-// WriteProtoDelimited writes the MetricFamily to the writer in delimited
-// protobuf format and returns the number of bytes written and any error
-// encountered.
-func WriteProtoDelimited(w io.Writer, p *dto.MetricFamily) (int, error) {
-	return pbutil.WriteDelimited(w, p)
-}
-
-// WriteProtoText writes the MetricFamily to the writer in text format and
-// returns the number of bytes written and any error encountered.
-func WriteProtoText(w io.Writer, p *dto.MetricFamily) (int, error) {
-	return fmt.Fprintf(w, "%s\n", proto.MarshalTextString(p))
-}
-
-// WriteProtoCompactText writes the MetricFamily to the writer in compact text
-// format and returns the number of bytes written and any error encountered.
-func WriteProtoCompactText(w io.Writer, p *dto.MetricFamily) (int, error) {
-	return fmt.Fprintf(w, "%s\n", p)
-}

BIN
Godeps/_workspace/src/github.com/prometheus/client_golang/text/testdata/protobuf


BIN
Godeps/_workspace/src/github.com/prometheus/client_golang/text/testdata/protobuf.gz


BIN
Godeps/_workspace/src/github.com/prometheus/client_golang/text/testdata/text.gz


+ 4 - 2
Godeps/_workspace/src/github.com/prometheus/client_golang/text/bench_test.go → Godeps/_workspace/src/github.com/prometheus/common/expfmt/bench_test.go

@@ -11,19 +11,21 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package text
+package expfmt
 
 import (
 	"bytes"
 	"compress/gzip"
-	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
 	"io"
 	"io/ioutil"
 	"testing"
 
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/matttproud/golang_protobuf_extensions/pbutil"
+	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
 )
 
+var parser TextParser
+
 // Benchmarks to show how much penalty text format parsing actually inflicts.
 //
 // Example results on Linux 3.13.0, Intel(R) Core(TM) i7-4700MQ CPU @ 2.40GHz, go1.4.

+ 410 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/decode.go

@@ -0,0 +1,410 @@
+// Copyright 2015 The Prometheus Authors
+// 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.
+
+package expfmt
+
+import (
+	"fmt"
+	"io"
+	"math"
+	"mime"
+	"net/http"
+
+	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/matttproud/golang_protobuf_extensions/pbutil"
+	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
+	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/common/model"
+)
+
+// Decoder types decode an input stream into metric families.
+type Decoder interface {
+	Decode(*dto.MetricFamily) error
+}
+
+type DecodeOptions struct {
+	// Timestamp is added to each value from the stream that has no explicit timestamp set.
+	Timestamp model.Time
+}
+
+// ResponseFormat extracts the correct format from a HTTP response header.
+// If no matching format can be found FormatUnknown is returned.
+func ResponseFormat(h http.Header) Format {
+	ct := h.Get(hdrContentType)
+
+	mediatype, params, err := mime.ParseMediaType(ct)
+	if err != nil {
+		return FmtUnknown
+	}
+
+	const (
+		textType = "text/plain"
+		jsonType = "application/json"
+	)
+
+	switch mediatype {
+	case ProtoType:
+		if p, ok := params["proto"]; ok && p != ProtoProtocol {
+			return FmtUnknown
+		}
+		if e, ok := params["encoding"]; ok && e != "delimited" {
+			return FmtUnknown
+		}
+		return FmtProtoDelim
+
+	case textType:
+		if v, ok := params["version"]; ok && v != TextVersion {
+			return FmtUnknown
+		}
+		return FmtText
+
+	case jsonType:
+		var prometheusAPIVersion string
+
+		if params["schema"] == "prometheus/telemetry" && params["version"] != "" {
+			prometheusAPIVersion = params["version"]
+		} else {
+			prometheusAPIVersion = h.Get("X-Prometheus-API-Version")
+		}
+
+		switch prometheusAPIVersion {
+		case "0.0.2", "":
+			return fmtJSON2
+		default:
+			return FmtUnknown
+		}
+	}
+
+	return FmtUnknown
+}
+
+// NewDecoder returns a new decoder based on the given input format.
+// If the input format does not imply otherwise, a text format decoder is returned.
+func NewDecoder(r io.Reader, format Format) Decoder {
+	switch format {
+	case FmtProtoDelim:
+		return &protoDecoder{r: r}
+	case fmtJSON2:
+		return newJSON2Decoder(r)
+	}
+	return &textDecoder{r: r}
+}
+
+// protoDecoder implements the Decoder interface for protocol buffers.
+type protoDecoder struct {
+	r io.Reader
+}
+
+// Decode implements the Decoder interface.
+func (d *protoDecoder) Decode(v *dto.MetricFamily) error {
+	_, err := pbutil.ReadDelimited(d.r, v)
+	return err
+}
+
+// textDecoder implements the Decoder interface for the text protcol.
+type textDecoder struct {
+	r    io.Reader
+	p    TextParser
+	fams []*dto.MetricFamily
+}
+
+// Decode implements the Decoder interface.
+func (d *textDecoder) Decode(v *dto.MetricFamily) error {
+	// TODO(fabxc): Wrap this as a line reader to make streaming safer.
+	if len(d.fams) == 0 {
+		// No cached metric families, read everything and parse metrics.
+		fams, err := d.p.TextToMetricFamilies(d.r)
+		if err != nil {
+			return err
+		}
+		if len(fams) == 0 {
+			return io.EOF
+		}
+		d.fams = make([]*dto.MetricFamily, 0, len(fams))
+		for _, f := range fams {
+			d.fams = append(d.fams, f)
+		}
+	}
+
+	*v = *d.fams[0]
+	d.fams = d.fams[1:]
+
+	return nil
+}
+
+type SampleDecoder struct {
+	Dec  Decoder
+	Opts *DecodeOptions
+
+	f dto.MetricFamily
+}
+
+func (sd *SampleDecoder) Decode(s *model.Vector) error {
+	if err := sd.Dec.Decode(&sd.f); err != nil {
+		return err
+	}
+	*s = extractSamples(&sd.f, sd.Opts)
+	return nil
+}
+
+// Extract samples builds a slice of samples from the provided metric families.
+func ExtractSamples(o *DecodeOptions, fams ...*dto.MetricFamily) model.Vector {
+	var all model.Vector
+	for _, f := range fams {
+		all = append(all, extractSamples(f, o)...)
+	}
+	return all
+}
+
+func extractSamples(f *dto.MetricFamily, o *DecodeOptions) model.Vector {
+	switch f.GetType() {
+	case dto.MetricType_COUNTER:
+		return extractCounter(o, f)
+	case dto.MetricType_GAUGE:
+		return extractGauge(o, f)
+	case dto.MetricType_SUMMARY:
+		return extractSummary(o, f)
+	case dto.MetricType_UNTYPED:
+		return extractUntyped(o, f)
+	case dto.MetricType_HISTOGRAM:
+		return extractHistogram(o, f)
+	}
+	panic("expfmt.extractSamples: unknown metric family type")
+}
+
+func extractCounter(o *DecodeOptions, f *dto.MetricFamily) model.Vector {
+	samples := make(model.Vector, 0, len(f.Metric))
+
+	for _, m := range f.Metric {
+		if m.Counter == nil {
+			continue
+		}
+
+		lset := make(model.LabelSet, len(m.Label)+1)
+		for _, p := range m.Label {
+			lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+		}
+		lset[model.MetricNameLabel] = model.LabelValue(f.GetName())
+
+		smpl := &model.Sample{
+			Metric: model.Metric(lset),
+			Value:  model.SampleValue(m.Counter.GetValue()),
+		}
+
+		if m.TimestampMs != nil {
+			smpl.Timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000)
+		} else {
+			smpl.Timestamp = o.Timestamp
+		}
+
+		samples = append(samples, smpl)
+	}
+
+	return samples
+}
+
+func extractGauge(o *DecodeOptions, f *dto.MetricFamily) model.Vector {
+	samples := make(model.Vector, 0, len(f.Metric))
+
+	for _, m := range f.Metric {
+		if m.Gauge == nil {
+			continue
+		}
+
+		lset := make(model.LabelSet, len(m.Label)+1)
+		for _, p := range m.Label {
+			lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+		}
+		lset[model.MetricNameLabel] = model.LabelValue(f.GetName())
+
+		smpl := &model.Sample{
+			Metric: model.Metric(lset),
+			Value:  model.SampleValue(m.Gauge.GetValue()),
+		}
+
+		if m.TimestampMs != nil {
+			smpl.Timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000)
+		} else {
+			smpl.Timestamp = o.Timestamp
+		}
+
+		samples = append(samples, smpl)
+	}
+
+	return samples
+}
+
+func extractUntyped(o *DecodeOptions, f *dto.MetricFamily) model.Vector {
+	samples := make(model.Vector, 0, len(f.Metric))
+
+	for _, m := range f.Metric {
+		if m.Untyped == nil {
+			continue
+		}
+
+		lset := make(model.LabelSet, len(m.Label)+1)
+		for _, p := range m.Label {
+			lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+		}
+		lset[model.MetricNameLabel] = model.LabelValue(f.GetName())
+
+		smpl := &model.Sample{
+			Metric: model.Metric(lset),
+			Value:  model.SampleValue(m.Untyped.GetValue()),
+		}
+
+		if m.TimestampMs != nil {
+			smpl.Timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000)
+		} else {
+			smpl.Timestamp = o.Timestamp
+		}
+
+		samples = append(samples, smpl)
+	}
+
+	return samples
+}
+
+func extractSummary(o *DecodeOptions, f *dto.MetricFamily) model.Vector {
+	samples := make(model.Vector, 0, len(f.Metric))
+
+	for _, m := range f.Metric {
+		if m.Summary == nil {
+			continue
+		}
+
+		timestamp := o.Timestamp
+		if m.TimestampMs != nil {
+			timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000)
+		}
+
+		for _, q := range m.Summary.Quantile {
+			lset := make(model.LabelSet, len(m.Label)+2)
+			for _, p := range m.Label {
+				lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+			}
+			// BUG(matt): Update other names to "quantile".
+			lset[model.LabelName(model.QuantileLabel)] = model.LabelValue(fmt.Sprint(q.GetQuantile()))
+			lset[model.MetricNameLabel] = model.LabelValue(f.GetName())
+
+			samples = append(samples, &model.Sample{
+				Metric:    model.Metric(lset),
+				Value:     model.SampleValue(q.GetValue()),
+				Timestamp: timestamp,
+			})
+		}
+
+		lset := make(model.LabelSet, len(m.Label)+1)
+		for _, p := range m.Label {
+			lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+		}
+		lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_sum")
+
+		samples = append(samples, &model.Sample{
+			Metric:    model.Metric(lset),
+			Value:     model.SampleValue(m.Summary.GetSampleSum()),
+			Timestamp: timestamp,
+		})
+
+		lset = make(model.LabelSet, len(m.Label)+1)
+		for _, p := range m.Label {
+			lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+		}
+		lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_count")
+
+		samples = append(samples, &model.Sample{
+			Metric:    model.Metric(lset),
+			Value:     model.SampleValue(m.Summary.GetSampleCount()),
+			Timestamp: timestamp,
+		})
+	}
+
+	return samples
+}
+
+func extractHistogram(o *DecodeOptions, f *dto.MetricFamily) model.Vector {
+	samples := make(model.Vector, 0, len(f.Metric))
+
+	for _, m := range f.Metric {
+		if m.Histogram == nil {
+			continue
+		}
+
+		timestamp := o.Timestamp
+		if m.TimestampMs != nil {
+			timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000)
+		}
+
+		infSeen := false
+
+		for _, q := range m.Histogram.Bucket {
+			lset := make(model.LabelSet, len(m.Label)+2)
+			for _, p := range m.Label {
+				lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+			}
+			lset[model.LabelName(model.BucketLabel)] = model.LabelValue(fmt.Sprint(q.GetUpperBound()))
+			lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_bucket")
+
+			if math.IsInf(q.GetUpperBound(), +1) {
+				infSeen = true
+			}
+
+			samples = append(samples, &model.Sample{
+				Metric:    model.Metric(lset),
+				Value:     model.SampleValue(q.GetCumulativeCount()),
+				Timestamp: timestamp,
+			})
+		}
+
+		lset := make(model.LabelSet, len(m.Label)+1)
+		for _, p := range m.Label {
+			lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+		}
+		lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_sum")
+
+		samples = append(samples, &model.Sample{
+			Metric:    model.Metric(lset),
+			Value:     model.SampleValue(m.Histogram.GetSampleSum()),
+			Timestamp: timestamp,
+		})
+
+		lset = make(model.LabelSet, len(m.Label)+1)
+		for _, p := range m.Label {
+			lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+		}
+		lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_count")
+
+		count := &model.Sample{
+			Metric:    model.Metric(lset),
+			Value:     model.SampleValue(m.Histogram.GetSampleCount()),
+			Timestamp: timestamp,
+		}
+		samples = append(samples, count)
+
+		if !infSeen {
+			// Append an infinity bucket sample.
+			lset := make(model.LabelSet, len(m.Label)+2)
+			for _, p := range m.Label {
+				lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+			}
+			lset[model.LabelName(model.BucketLabel)] = model.LabelValue("+Inf")
+			lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_bucket")
+
+			samples = append(samples, &model.Sample{
+				Metric:    model.Metric(lset),
+				Value:     count.Value,
+				Timestamp: timestamp,
+			})
+		}
+	}
+
+	return samples
+}

+ 356 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/decode_test.go

@@ -0,0 +1,356 @@
+// Copyright 2015 The Prometheus Authors
+// 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.
+
+package expfmt
+
+import (
+	"io"
+	"net/http"
+	"reflect"
+	"sort"
+	"strings"
+	"testing"
+
+	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/common/model"
+)
+
+func TestTextDecoder(t *testing.T) {
+	var (
+		ts = model.Now()
+		in = `
+# Only a quite simple scenario with two metric families.
+# More complicated tests of the parser itself can be found in the text package.
+# TYPE mf2 counter
+mf2 3
+mf1{label="value1"} -3.14 123456
+mf1{label="value2"} 42
+mf2 4
+`
+		out = model.Vector{
+			&model.Sample{
+				Metric: model.Metric{
+					model.MetricNameLabel: "mf1",
+					"label":               "value1",
+				},
+				Value:     -3.14,
+				Timestamp: 123456,
+			},
+			&model.Sample{
+				Metric: model.Metric{
+					model.MetricNameLabel: "mf1",
+					"label":               "value2",
+				},
+				Value:     42,
+				Timestamp: ts,
+			},
+			&model.Sample{
+				Metric: model.Metric{
+					model.MetricNameLabel: "mf2",
+				},
+				Value:     3,
+				Timestamp: ts,
+			},
+			&model.Sample{
+				Metric: model.Metric{
+					model.MetricNameLabel: "mf2",
+				},
+				Value:     4,
+				Timestamp: ts,
+			},
+		}
+	)
+
+	dec := &SampleDecoder{
+		Dec: &textDecoder{r: strings.NewReader(in)},
+		Opts: &DecodeOptions{
+			Timestamp: ts,
+		},
+	}
+	var all model.Vector
+	for {
+		var smpls model.Vector
+		err := dec.Decode(&smpls)
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			t.Fatal(err)
+		}
+		all = append(all, smpls...)
+	}
+	sort.Sort(all)
+	sort.Sort(out)
+	if !reflect.DeepEqual(all, out) {
+		t.Fatalf("output does not match")
+	}
+}
+
+func TestProtoDecoder(t *testing.T) {
+
+	var testTime = model.Now()
+
+	scenarios := []struct {
+		in       string
+		expected model.Vector
+	}{
+		{
+			in: "",
+		},
+		{
+			in: "\x8f\x01\n\rrequest_count\x12\x12Number of requests\x18\x00\"0\n#\n\x0fsome_label_name\x12\x10some_label_value\x1a\t\t\x00\x00\x00\x00\x00\x00E\xc0\"6\n)\n\x12another_label_name\x12\x13another_label_value\x1a\t\t\x00\x00\x00\x00\x00\x00U@",
+			expected: model.Vector{
+				&model.Sample{
+					Metric: model.Metric{
+						model.MetricNameLabel: "request_count",
+						"some_label_name":     "some_label_value",
+					},
+					Value:     -42,
+					Timestamp: testTime,
+				},
+				&model.Sample{
+					Metric: model.Metric{
+						model.MetricNameLabel: "request_count",
+						"another_label_name":  "another_label_value",
+					},
+					Value:     84,
+					Timestamp: testTime,
+				},
+			},
+		},
+		{
+			in: "\xb9\x01\n\rrequest_count\x12\x12Number of requests\x18\x02\"O\n#\n\x0fsome_label_name\x12\x10some_label_value\"(\x1a\x12\t\xaeG\xe1z\x14\xae\xef?\x11\x00\x00\x00\x00\x00\x00E\xc0\x1a\x12\t+\x87\x16\xd9\xce\xf7\xef?\x11\x00\x00\x00\x00\x00\x00U\xc0\"A\n)\n\x12another_label_name\x12\x13another_label_value\"\x14\x1a\x12\t\x00\x00\x00\x00\x00\x00\xe0?\x11\x00\x00\x00\x00\x00\x00$@",
+			expected: model.Vector{
+				&model.Sample{
+					Metric: model.Metric{
+						model.MetricNameLabel: "request_count_count",
+						"some_label_name":     "some_label_value",
+					},
+					Value:     0,
+					Timestamp: testTime,
+				},
+				&model.Sample{
+					Metric: model.Metric{
+						model.MetricNameLabel: "request_count_sum",
+						"some_label_name":     "some_label_value",
+					},
+					Value:     0,
+					Timestamp: testTime,
+				},
+				&model.Sample{
+					Metric: model.Metric{
+						model.MetricNameLabel: "request_count",
+						"some_label_name":     "some_label_value",
+						"quantile":            "0.99",
+					},
+					Value:     -42,
+					Timestamp: testTime,
+				},
+				&model.Sample{
+					Metric: model.Metric{
+						model.MetricNameLabel: "request_count",
+						"some_label_name":     "some_label_value",
+						"quantile":            "0.999",
+					},
+					Value:     -84,
+					Timestamp: testTime,
+				},
+				&model.Sample{
+					Metric: model.Metric{
+						model.MetricNameLabel: "request_count_count",
+						"another_label_name":  "another_label_value",
+					},
+					Value:     0,
+					Timestamp: testTime,
+				},
+				&model.Sample{
+					Metric: model.Metric{
+						model.MetricNameLabel: "request_count_sum",
+						"another_label_name":  "another_label_value",
+					},
+					Value:     0,
+					Timestamp: testTime,
+				},
+				&model.Sample{
+					Metric: model.Metric{
+						model.MetricNameLabel: "request_count",
+						"another_label_name":  "another_label_value",
+						"quantile":            "0.5",
+					},
+					Value:     10,
+					Timestamp: testTime,
+				},
+			},
+		},
+		{
+			in: "\x8d\x01\n\x1drequest_duration_microseconds\x12\x15The response latency.\x18\x04\"S:Q\b\x85\x15\x11\xcd\xcc\xccL\x8f\xcb:A\x1a\v\b{\x11\x00\x00\x00\x00\x00\x00Y@\x1a\f\b\x9c\x03\x11\x00\x00\x00\x00\x00\x00^@\x1a\f\b\xd0\x04\x11\x00\x00\x00\x00\x00\x00b@\x1a\f\b\xf4\v\x11\x9a\x99\x99\x99\x99\x99e@\x1a\f\b\x85\x15\x11\x00\x00\x00\x00\x00\x00\xf0\u007f",
+			expected: model.Vector{
+				&model.Sample{
+					Metric: model.Metric{
+						model.MetricNameLabel: "request_duration_microseconds_bucket",
+						"le": "100",
+					},
+					Value:     123,
+					Timestamp: testTime,
+				},
+				&model.Sample{
+					Metric: model.Metric{
+						model.MetricNameLabel: "request_duration_microseconds_bucket",
+						"le": "120",
+					},
+					Value:     412,
+					Timestamp: testTime,
+				},
+				&model.Sample{
+					Metric: model.Metric{
+						model.MetricNameLabel: "request_duration_microseconds_bucket",
+						"le": "144",
+					},
+					Value:     592,
+					Timestamp: testTime,
+				},
+				&model.Sample{
+					Metric: model.Metric{
+						model.MetricNameLabel: "request_duration_microseconds_bucket",
+						"le": "172.8",
+					},
+					Value:     1524,
+					Timestamp: testTime,
+				},
+				&model.Sample{
+					Metric: model.Metric{
+						model.MetricNameLabel: "request_duration_microseconds_bucket",
+						"le": "+Inf",
+					},
+					Value:     2693,
+					Timestamp: testTime,
+				},
+				&model.Sample{
+					Metric: model.Metric{
+						model.MetricNameLabel: "request_duration_microseconds_sum",
+					},
+					Value:     1756047.3,
+					Timestamp: testTime,
+				},
+				&model.Sample{
+					Metric: model.Metric{
+						model.MetricNameLabel: "request_duration_microseconds_count",
+					},
+					Value:     2693,
+					Timestamp: testTime,
+				},
+			},
+		},
+		{
+			// The metric type is unset in this protobuf, which needs to be handled
+			// correctly by the decoder.
+			in: "\x1c\n\rrequest_count\"\v\x1a\t\t\x00\x00\x00\x00\x00\x00\xf0?",
+			expected: model.Vector{
+				&model.Sample{
+					Metric: model.Metric{
+						model.MetricNameLabel: "request_count",
+					},
+					Value:     1,
+					Timestamp: testTime,
+				},
+			},
+		},
+	}
+
+	for i, scenario := range scenarios {
+		dec := &SampleDecoder{
+			Dec: &protoDecoder{r: strings.NewReader(scenario.in)},
+			Opts: &DecodeOptions{
+				Timestamp: testTime,
+			},
+		}
+
+		var all model.Vector
+		for {
+			var smpls model.Vector
+			err := dec.Decode(&smpls)
+			if err == io.EOF {
+				break
+			}
+			if err != nil {
+				t.Fatal(err)
+			}
+			all = append(all, smpls...)
+		}
+		sort.Sort(all)
+		sort.Sort(scenario.expected)
+		if !reflect.DeepEqual(all, scenario.expected) {
+			t.Fatalf("%d. output does not match, want: %#v, got %#v", i, scenario.expected, all)
+		}
+	}
+}
+
+func testDiscriminatorHTTPHeader(t testing.TB) {
+	var scenarios = []struct {
+		input  map[string]string
+		output Format
+		err    error
+	}{
+		{
+			input:  map[string]string{"Content-Type": `application/vnd.google.protobuf; proto="io.prometheus.client.MetricFamily"; encoding="delimited"`},
+			output: FmtProtoDelim,
+		},
+		{
+			input:  map[string]string{"Content-Type": `application/vnd.google.protobuf; proto="illegal"; encoding="delimited"`},
+			output: FmtUnknown,
+		},
+		{
+			input:  map[string]string{"Content-Type": `application/vnd.google.protobuf; proto="io.prometheus.client.MetricFamily"; encoding="illegal"`},
+			output: FmtUnknown,
+		},
+		{
+			input:  map[string]string{"Content-Type": `text/plain; version=0.0.4`},
+			output: FmtText,
+		},
+		{
+			input:  map[string]string{"Content-Type": `text/plain`},
+			output: FmtText,
+		},
+		{
+			input:  map[string]string{"Content-Type": `text/plain; version=0.0.3`},
+			output: FmtUnknown,
+		},
+	}
+
+	for i, scenario := range scenarios {
+		var header http.Header
+
+		if len(scenario.input) > 0 {
+			header = http.Header{}
+		}
+
+		for key, value := range scenario.input {
+			header.Add(key, value)
+		}
+
+		actual := ResponseFormat(header)
+
+		if scenario.output != actual {
+			t.Errorf("%d. expected %s, got %s", i, scenario.output, actual)
+		}
+	}
+}
+
+func TestDiscriminatorHTTPHeader(t *testing.T) {
+	testDiscriminatorHTTPHeader(t)
+}
+
+func BenchmarkDiscriminatorHTTPHeader(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		testDiscriminatorHTTPHeader(b)
+	}
+}

+ 87 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/encode.go

@@ -0,0 +1,87 @@
+// Copyright 2015 The Prometheus Authors
+// 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.
+
+package expfmt
+
+import (
+	"fmt"
+	"io"
+	"net/http"
+
+	"github.com/coreos/etcd/Godeps/_workspace/src/bitbucket.org/ww/goautoneg"
+	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
+	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/matttproud/golang_protobuf_extensions/pbutil"
+	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
+)
+
+// Encoder types encode metric families into an underlying wire protocol.
+type Encoder interface {
+	Encode(*dto.MetricFamily) error
+}
+
+type encoder func(*dto.MetricFamily) error
+
+func (e encoder) Encode(v *dto.MetricFamily) error {
+	return e(v)
+}
+
+// Negotiate returns the Content-Type based on the given Accept header.
+// If no appropriate accepted type is found, FmtText is returned.
+func Negotiate(h http.Header) Format {
+	for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) {
+		// Check for protocol buffer
+		if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol {
+			switch ac.Params["encoding"] {
+			case "delimited":
+				return FmtProtoDelim
+			case "text":
+				return FmtProtoText
+			case "compact-text":
+				return FmtProtoCompact
+			}
+		}
+		// Check for text format.
+		ver := ac.Params["version"]
+		if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") {
+			return FmtText
+		}
+	}
+	return FmtText
+}
+
+// NewEncoder returns a new encoder based on content type negotiation.
+func NewEncoder(w io.Writer, format Format) Encoder {
+	switch format {
+	case FmtProtoDelim:
+		return encoder(func(v *dto.MetricFamily) error {
+			_, err := pbutil.WriteDelimited(w, v)
+			return err
+		})
+	case FmtProtoCompact:
+		return encoder(func(v *dto.MetricFamily) error {
+			_, err := fmt.Fprintln(w, v.String())
+			return err
+		})
+	case FmtProtoText:
+		return encoder(func(v *dto.MetricFamily) error {
+			_, err := fmt.Fprintln(w, proto.MarshalTextString(v))
+			return err
+		})
+	case FmtText:
+		return encoder(func(v *dto.MetricFamily) error {
+			_, err := MetricFamilyToText(w, v)
+			return err
+		})
+	}
+	panic("expfmt.NewEncoder: unknown format")
+}

+ 40 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/expfmt.go

@@ -0,0 +1,40 @@
+// Copyright 2015 The Prometheus Authors
+// 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.
+
+// A package for reading and writing Prometheus metrics.
+package expfmt
+
+type Format string
+
+const (
+	TextVersion = "0.0.4"
+
+	ProtoType     = `application/vnd.google.protobuf`
+	ProtoProtocol = `io.prometheus.client.MetricFamily`
+	ProtoFmt      = ProtoType + "; proto=" + ProtoProtocol + ";"
+
+	// The Content-Type values for the different wire protocols.
+	FmtUnknown      Format = `<unknown>`
+	FmtText         Format = `text/plain; version=` + TextVersion
+	FmtProtoDelim   Format = ProtoFmt + ` encoding=delimited`
+	FmtProtoText    Format = ProtoFmt + ` encoding=text`
+	FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text`
+
+	// fmtJSON2 is hidden as it is deprecated.
+	fmtJSON2 Format = `application/json; version=0.0.2`
+)
+
+const (
+	hdrContentType = "Content-Type"
+	hdrAccept      = "Accept"
+)

+ 18 - 18
Godeps/_workspace/src/github.com/prometheus/client_golang/model/labelvalue.go → Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz.go

@@ -1,4 +1,4 @@
-// Copyright 2013 The Prometheus Authors
+// Copyright 2014 The Prometheus Authors
 // 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
@@ -11,26 +11,26 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package model
+// Build only when actually fuzzing
+// +build gofuzz
 
-import (
-	"sort"
-)
+package expfmt
 
-// A LabelValue is an associated value for a LabelName.
-type LabelValue string
+import "bytes"
 
-// LabelValues is a sortable LabelValue slice. It implements sort.Interface.
-type LabelValues []LabelValue
-
-func (l LabelValues) Len() int {
-	return len(l)
-}
+// Fuzz text metric parser with with github.com/dvyukov/go-fuzz:
+//
+//     go-fuzz-build github.com/prometheus/client_golang/text
+//     go-fuzz -bin text-fuzz.zip -workdir fuzz
+//
+// Further input samples should go in the folder fuzz/corpus.
+func Fuzz(in []byte) int {
+	parser := TextParser{}
+	_, err := parser.TextToMetricFamilies(bytes.NewReader(in))
 
-func (l LabelValues) Less(i, j int) bool {
-	return sort.StringsAreSorted([]string{string(l[i]), string(l[j])})
-}
+	if err != nil {
+		return 0
+	}
 
-func (l LabelValues) Swap(i, j int) {
-	l[i], l[j] = l[j], l[i]
+	return 1
 }

+ 2 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_0

@@ -0,0 +1,2 @@
+
+

+ 6 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_1

@@ -0,0 +1,6 @@
+
+minimal_metric 1.234
+another_metric -3e3 103948
+# Even that:
+no_labels{} 3
+# HELP line for non-existing metric will be ignored.

+ 12 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_2

@@ -0,0 +1,12 @@
+
+# A normal comment.
+#
+# TYPE name counter
+name{labelname="val1",basename="basevalue"} NaN
+name {labelname="val2",basename="base\"v\\al\nue"} 0.23 1234567890
+# HELP name two-line\n doc  str\\ing
+
+ # HELP  name2  	doc str"ing 2
+  #    TYPE    name2 gauge
+name2{labelname="val2"	,basename   =   "basevalue2"		} +Inf 54321
+name2{ labelname = "val1" , }-Inf

+ 22 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_3

@@ -0,0 +1,22 @@
+
+# TYPE my_summary summary
+my_summary{n1="val1",quantile="0.5"} 110
+decoy -1 -2
+my_summary{n1="val1",quantile="0.9"} 140 1
+my_summary_count{n1="val1"} 42
+# Latest timestamp wins in case of a summary.
+my_summary_sum{n1="val1"} 4711 2
+fake_sum{n1="val1"} 2001
+# TYPE another_summary summary
+another_summary_count{n2="val2",n1="val1"} 20
+my_summary_count{n2="val2",n1="val1"} 5 5
+another_summary{n1="val1",n2="val2",quantile=".3"} -1.2
+my_summary_sum{n1="val2"} 08 15
+my_summary{n1="val3", quantile="0.2"} 4711
+  my_summary{n1="val1",n2="val2",quantile="-12.34",} NaN
+# some
+# funny comments
+# HELP 
+# HELP
+# HELP my_summary
+# HELP my_summary 

+ 10 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_4

@@ -0,0 +1,10 @@
+
+# HELP request_duration_microseconds The response latency.
+# TYPE request_duration_microseconds histogram
+request_duration_microseconds_bucket{le="100"} 123
+request_duration_microseconds_bucket{le="120"} 412
+request_duration_microseconds_bucket{le="144"} 592
+request_duration_microseconds_bucket{le="172.8"} 1524
+request_duration_microseconds_bucket{le="+Inf"} 2693
+request_duration_microseconds_sum 1.7560473e+06
+request_duration_microseconds_count 2693

+ 1 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_0

@@ -0,0 +1 @@
+bla 3.14

+ 1 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_1

@@ -0,0 +1 @@
+metric{label="\t"} 3.14

+ 1 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_10

@@ -0,0 +1 @@
+metric{label="bla"} 3.14 2 3

+ 1 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_11

@@ -0,0 +1 @@
+metric{label="bla"} blubb

+ 3 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_12

@@ -0,0 +1,3 @@
+
+# HELP metric one
+# HELP metric two

+ 3 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_13

@@ -0,0 +1,3 @@
+
+# TYPE metric counter
+# TYPE metric untyped

+ 3 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_14

@@ -0,0 +1,3 @@
+
+metric 4.12
+# TYPE metric counter

+ 2 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_15

@@ -0,0 +1,2 @@
+
+# TYPE metric bla

+ 2 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_16

@@ -0,0 +1,2 @@
+
+# TYPE met-ric

+ 1 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_17

@@ -0,0 +1 @@
+@invalidmetric{label="bla"} 3.14 2

+ 1 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_18

@@ -0,0 +1 @@
+{label="bla"} 3.14 2

+ 3 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_19

@@ -0,0 +1,3 @@
+
+# TYPE metric histogram
+metric_bucket{le="bla"} 3.14

+ 3 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_2

@@ -0,0 +1,3 @@
+
+metric{label="new
+line"} 3.14

+ 1 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_3

@@ -0,0 +1 @@
+metric{@="bla"} 3.14

+ 1 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_4

@@ -0,0 +1 @@
+metric{__name__="bla"} 3.14

+ 1 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_5

@@ -0,0 +1 @@
+metric{label+="bla"} 3.14

+ 1 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_6

@@ -0,0 +1 @@
+metric{label=bla} 3.14

+ 3 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_7

@@ -0,0 +1,3 @@
+
+# TYPE metric summary
+metric{quantile="bla"} 3.14

+ 1 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_8

@@ -0,0 +1 @@
+metric{label="bla"+} 3.14

+ 1 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_9

@@ -0,0 +1 @@
+metric{label="bla"} 3.14 2.72

+ 1 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/minimal

@@ -0,0 +1 @@
+m{} 0

+ 161 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/json_decode.go

@@ -0,0 +1,161 @@
+// Copyright 2015 The Prometheus Authors
+// 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.
+
+package expfmt
+
+import (
+	"encoding/json"
+	"fmt"
+	"io"
+	"sort"
+
+	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
+	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
+	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/common/model"
+)
+
+type json2Decoder struct {
+	dec  *json.Decoder
+	fams []*dto.MetricFamily
+}
+
+func newJSON2Decoder(r io.Reader) Decoder {
+	return &json2Decoder{
+		dec: json.NewDecoder(r),
+	}
+}
+
+type histogram002 struct {
+	Labels model.LabelSet     `json:"labels"`
+	Values map[string]float64 `json:"value"`
+}
+
+type counter002 struct {
+	Labels model.LabelSet `json:"labels"`
+	Value  float64        `json:"value"`
+}
+
+func protoLabelSet(base, ext model.LabelSet) []*dto.LabelPair {
+	labels := base.Clone().Merge(ext)
+	delete(labels, model.MetricNameLabel)
+
+	names := make([]string, 0, len(labels))
+	for ln := range labels {
+		names = append(names, string(ln))
+	}
+	sort.Strings(names)
+
+	pairs := make([]*dto.LabelPair, 0, len(labels))
+
+	for _, ln := range names {
+		lv := labels[model.LabelName(ln)]
+
+		pairs = append(pairs, &dto.LabelPair{
+			Name:  proto.String(ln),
+			Value: proto.String(string(lv)),
+		})
+	}
+
+	return pairs
+}
+
+func (d *json2Decoder) more() error {
+	var entities []struct {
+		BaseLabels model.LabelSet `json:"baseLabels"`
+		Docstring  string         `json:"docstring"`
+		Metric     struct {
+			Type   string          `json:"type"`
+			Values json.RawMessage `json:"value"`
+		} `json:"metric"`
+	}
+
+	if err := d.dec.Decode(&entities); err != nil {
+		return err
+	}
+	for _, e := range entities {
+		f := &dto.MetricFamily{
+			Name:   proto.String(string(e.BaseLabels[model.MetricNameLabel])),
+			Help:   proto.String(e.Docstring),
+			Type:   dto.MetricType_UNTYPED.Enum(),
+			Metric: []*dto.Metric{},
+		}
+
+		d.fams = append(d.fams, f)
+
+		switch e.Metric.Type {
+		case "counter", "gauge":
+			var values []counter002
+
+			if err := json.Unmarshal(e.Metric.Values, &values); err != nil {
+				return fmt.Errorf("could not extract %s value: %s", e.Metric.Type, err)
+			}
+
+			for _, ctr := range values {
+				f.Metric = append(f.Metric, &dto.Metric{
+					Label: protoLabelSet(e.BaseLabels, ctr.Labels),
+					Untyped: &dto.Untyped{
+						Value: proto.Float64(ctr.Value),
+					},
+				})
+			}
+
+		case "histogram":
+			var values []histogram002
+
+			if err := json.Unmarshal(e.Metric.Values, &values); err != nil {
+				return fmt.Errorf("could not extract %s value: %s", e.Metric.Type, err)
+			}
+
+			for _, hist := range values {
+				quants := make([]string, 0, len(values))
+				for q := range hist.Values {
+					quants = append(quants, q)
+				}
+
+				sort.Strings(quants)
+
+				for _, q := range quants {
+					value := hist.Values[q]
+					// The correct label is "quantile" but to not break old expressions
+					// this remains "percentile"
+					hist.Labels["percentile"] = model.LabelValue(q)
+
+					f.Metric = append(f.Metric, &dto.Metric{
+						Label: protoLabelSet(e.BaseLabels, hist.Labels),
+						Untyped: &dto.Untyped{
+							Value: proto.Float64(value),
+						},
+					})
+				}
+			}
+
+		default:
+			return fmt.Errorf("unknown metric type %q", e.Metric.Type)
+		}
+	}
+	return nil
+}
+
+// Decode implements the Decoder interface.
+func (d *json2Decoder) Decode(v *dto.MetricFamily) error {
+	if len(d.fams) == 0 {
+		if err := d.more(); err != nil {
+			return err
+		}
+	}
+
+	*v = *d.fams[0]
+	d.fams = d.fams[1:]
+
+	return nil
+}

+ 124 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/json_decode_test.go

@@ -0,0 +1,124 @@
+// Copyright 2015 The Prometheus Authors
+// 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.
+
+package expfmt
+
+import (
+	"os"
+	"reflect"
+	"testing"
+
+	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
+	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
+)
+
+func TestJSON2Decode(t *testing.T) {
+	f, err := os.Open("testdata/json2")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer f.Close()
+
+	dec := newJSON2Decoder(f)
+
+	var v1 dto.MetricFamily
+	if err := dec.Decode(&v1); err != nil {
+		t.Fatal(err)
+	}
+
+	exp1 := dto.MetricFamily{
+		Type: dto.MetricType_UNTYPED.Enum(),
+		Help: proto.String("RPC calls."),
+		Name: proto.String("rpc_calls_total"),
+		Metric: []*dto.Metric{
+			{
+				Label: []*dto.LabelPair{
+					{
+						Name:  proto.String("job"),
+						Value: proto.String("batch_job"),
+					}, {
+						Name:  proto.String("service"),
+						Value: proto.String("zed"),
+					},
+				},
+				Untyped: &dto.Untyped{
+					Value: proto.Float64(25),
+				},
+			},
+			{
+				Label: []*dto.LabelPair{
+					{
+						Name:  proto.String("job"),
+						Value: proto.String("batch_job"),
+					}, {
+						Name:  proto.String("service"),
+						Value: proto.String("bar"),
+					},
+				},
+				Untyped: &dto.Untyped{
+					Value: proto.Float64(24),
+				},
+			},
+		},
+	}
+
+	if !reflect.DeepEqual(v1, exp1) {
+		t.Fatalf("Expected %v, got %v", exp1, v1)
+	}
+
+	var v2 dto.MetricFamily
+	if err := dec.Decode(&v2); err != nil {
+		t.Fatal(err)
+	}
+
+	exp2 := dto.MetricFamily{
+		Type: dto.MetricType_UNTYPED.Enum(),
+		Help: proto.String("RPC latency."),
+		Name: proto.String("rpc_latency_microseconds"),
+		Metric: []*dto.Metric{
+			{
+				Label: []*dto.LabelPair{
+					{
+						Name:  proto.String("percentile"),
+						Value: proto.String("0.010000"),
+					}, {
+						Name:  proto.String("service"),
+						Value: proto.String("foo"),
+					},
+				},
+				Untyped: &dto.Untyped{
+					Value: proto.Float64(15),
+				},
+			},
+			{
+				Label: []*dto.LabelPair{
+					{
+						Name:  proto.String("percentile"),
+						Value: proto.String("0.990000"),
+					}, {
+						Name:  proto.String("service"),
+						Value: proto.String("foo"),
+					},
+				},
+				Untyped: &dto.Untyped{
+					Value: proto.Float64(17),
+				},
+			},
+		},
+	}
+
+	if !reflect.DeepEqual(v2, exp2) {
+		t.Fatalf("Expected %v, got %v", exp2, v2)
+	}
+
+}

+ 46 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/json2

@@ -0,0 +1,46 @@
+[
+  {
+    "baseLabels": {
+      "__name__": "rpc_calls_total",
+      "job": "batch_job"
+    },
+    "docstring": "RPC calls.",
+    "metric": {
+      "type": "counter",
+      "value": [
+        {
+          "labels": {
+            "service": "zed"
+          },
+          "value": 25
+        },
+        {
+          "labels": {
+            "service": "bar"
+          },
+          "value": 24
+        }
+      ]
+    }
+  },
+  {
+    "baseLabels": {
+      "__name__": "rpc_latency_microseconds"
+    },
+    "docstring": "RPC latency.",
+    "metric": {
+      "type": "histogram",
+      "value": [
+        {
+          "labels": {
+            "service": "foo"
+          },
+          "value": {
+            "0.010000": 15,
+            "0.990000": 17
+          }
+        }
+      ]
+    }
+  }
+]

+ 516 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/protobuf

@@ -0,0 +1,516 @@
+fc08 0a22 6874 7470 5f72 6571 7565 7374
+5f64 7572 6174 696f 6e5f 6d69 6372 6f73
+6563 6f6e 6473 122b 5468 6520 4854 5450
+2072 6571 7565 7374 206c 6174 656e 6369
+6573 2069 6e20 6d69 6372 6f73 6563 6f6e
+6473 2e18 0222 570a 0c0a 0768 616e 646c
+6572 1201 2f22 4708 0011 0000 0000 0000
+0000 1a12 0900 0000 0000 00e0 3f11 0000
+0000 0000 0000 1a12 09cd cccc cccc ccec
+3f11 0000 0000 0000 0000 1a12 09ae 47e1
+7a14 aeef 3f11 0000 0000 0000 0000 225d
+0a12 0a07 6861 6e64 6c65 7212 072f 616c
+6572 7473 2247 0800 1100 0000 0000 0000
+001a 1209 0000 0000 0000 e03f 1100 0000
+0000 0000 001a 1209 cdcc cccc cccc ec3f
+1100 0000 0000 0000 001a 1209 ae47 e17a
+14ae ef3f 1100 0000 0000 0000 0022 620a
+170a 0768 616e 646c 6572 120c 2f61 7069
+2f6d 6574 7269 6373 2247 0800 1100 0000
+0000 0000 001a 1209 0000 0000 0000 e03f
+1100 0000 0000 0000 001a 1209 cdcc cccc
+cccc ec3f 1100 0000 0000 0000 001a 1209
+ae47 e17a 14ae ef3f 1100 0000 0000 0000
+0022 600a 150a 0768 616e 646c 6572 120a
+2f61 7069 2f71 7565 7279 2247 0800 1100
+0000 0000 0000 001a 1209 0000 0000 0000
+e03f 1100 0000 0000 0000 001a 1209 cdcc
+cccc cccc ec3f 1100 0000 0000 0000 001a
+1209 ae47 e17a 14ae ef3f 1100 0000 0000
+0000 0022 660a 1b0a 0768 616e 646c 6572
+1210 2f61 7069 2f71 7565 7279 5f72 616e
+6765 2247 0800 1100 0000 0000 0000 001a
+1209 0000 0000 0000 e03f 1100 0000 0000
+0000 001a 1209 cdcc cccc cccc ec3f 1100
+0000 0000 0000 001a 1209 ae47 e17a 14ae
+ef3f 1100 0000 0000 0000 0022 620a 170a
+0768 616e 646c 6572 120c 2f61 7069 2f74
+6172 6765 7473 2247 0800 1100 0000 0000
+0000 001a 1209 0000 0000 0000 e03f 1100
+0000 0000 0000 001a 1209 cdcc cccc cccc
+ec3f 1100 0000 0000 0000 001a 1209 ae47
+e17a 14ae ef3f 1100 0000 0000 0000 0022
+600a 150a 0768 616e 646c 6572 120a 2f63
+6f6e 736f 6c65 732f 2247 0800 1100 0000
+0000 0000 001a 1209 0000 0000 0000 e03f
+1100 0000 0000 0000 001a 1209 cdcc cccc
+cccc ec3f 1100 0000 0000 0000 001a 1209
+ae47 e17a 14ae ef3f 1100 0000 0000 0000
+0022 5c0a 110a 0768 616e 646c 6572 1206
+2f67 7261 7068 2247 0800 1100 0000 0000
+0000 001a 1209 0000 0000 0000 e03f 1100
+0000 0000 0000 001a 1209 cdcc cccc cccc
+ec3f 1100 0000 0000 0000 001a 1209 ae47
+e17a 14ae ef3f 1100 0000 0000 0000 0022
+5b0a 100a 0768 616e 646c 6572 1205 2f68
+6561 7022 4708 0011 0000 0000 0000 0000
+1a12 0900 0000 0000 00e0 3f11 0000 0000
+0000 0000 1a12 09cd cccc cccc ccec 3f11
+0000 0000 0000 0000 1a12 09ae 47e1 7a14
+aeef 3f11 0000 0000 0000 0000 225e 0a13
+0a07 6861 6e64 6c65 7212 082f 7374 6174
+6963 2f22 4708 0011 0000 0000 0000 0000
+1a12 0900 0000 0000 00e0 3f11 0000 0000
+0000 0000 1a12 09cd cccc cccc ccec 3f11
+0000 0000 0000 0000 1a12 09ae 47e1 7a14
+aeef 3f11 0000 0000 0000 0000 2260 0a15
+0a07 6861 6e64 6c65 7212 0a70 726f 6d65
+7468 6575 7322 4708 3b11 5b8f c2f5 083f
+f440 1a12 0900 0000 0000 00e0 3f11 e17a
+14ae c7af 9340 1a12 09cd cccc cccc ccec
+3f11 2fdd 2406 81f0 9640 1a12 09ae 47e1
+7a14 aeef 3f11 3d0a d7a3 b095 a740 e608
+0a17 6874 7470 5f72 6571 7565 7374 5f73
+697a 655f 6279 7465 7312 2054 6865 2048
+5454 5020 7265 7175 6573 7420 7369 7a65
+7320 696e 2062 7974 6573 2e18 0222 570a
+0c0a 0768 616e 646c 6572 1201 2f22 4708
+0011 0000 0000 0000 0000 1a12 0900 0000
+0000 00e0 3f11 0000 0000 0000 0000 1a12
+09cd cccc cccc ccec 3f11 0000 0000 0000
+0000 1a12 09ae 47e1 7a14 aeef 3f11 0000
+0000 0000 0000 225d 0a12 0a07 6861 6e64
+6c65 7212 072f 616c 6572 7473 2247 0800
+1100 0000 0000 0000 001a 1209 0000 0000
+0000 e03f 1100 0000 0000 0000 001a 1209
+cdcc cccc cccc ec3f 1100 0000 0000 0000
+001a 1209 ae47 e17a 14ae ef3f 1100 0000
+0000 0000 0022 620a 170a 0768 616e 646c
+6572 120c 2f61 7069 2f6d 6574 7269 6373
+2247 0800 1100 0000 0000 0000 001a 1209
+0000 0000 0000 e03f 1100 0000 0000 0000
+001a 1209 cdcc cccc cccc ec3f 1100 0000
+0000 0000 001a 1209 ae47 e17a 14ae ef3f
+1100 0000 0000 0000 0022 600a 150a 0768
+616e 646c 6572 120a 2f61 7069 2f71 7565
+7279 2247 0800 1100 0000 0000 0000 001a
+1209 0000 0000 0000 e03f 1100 0000 0000
+0000 001a 1209 cdcc cccc cccc ec3f 1100
+0000 0000 0000 001a 1209 ae47 e17a 14ae
+ef3f 1100 0000 0000 0000 0022 660a 1b0a
+0768 616e 646c 6572 1210 2f61 7069 2f71
+7565 7279 5f72 616e 6765 2247 0800 1100
+0000 0000 0000 001a 1209 0000 0000 0000
+e03f 1100 0000 0000 0000 001a 1209 cdcc
+cccc cccc ec3f 1100 0000 0000 0000 001a
+1209 ae47 e17a 14ae ef3f 1100 0000 0000
+0000 0022 620a 170a 0768 616e 646c 6572
+120c 2f61 7069 2f74 6172 6765 7473 2247
+0800 1100 0000 0000 0000 001a 1209 0000
+0000 0000 e03f 1100 0000 0000 0000 001a
+1209 cdcc cccc cccc ec3f 1100 0000 0000
+0000 001a 1209 ae47 e17a 14ae ef3f 1100
+0000 0000 0000 0022 600a 150a 0768 616e
+646c 6572 120a 2f63 6f6e 736f 6c65 732f
+2247 0800 1100 0000 0000 0000 001a 1209
+0000 0000 0000 e03f 1100 0000 0000 0000
+001a 1209 cdcc cccc cccc ec3f 1100 0000
+0000 0000 001a 1209 ae47 e17a 14ae ef3f
+1100 0000 0000 0000 0022 5c0a 110a 0768
+616e 646c 6572 1206 2f67 7261 7068 2247
+0800 1100 0000 0000 0000 001a 1209 0000
+0000 0000 e03f 1100 0000 0000 0000 001a
+1209 cdcc cccc cccc ec3f 1100 0000 0000
+0000 001a 1209 ae47 e17a 14ae ef3f 1100
+0000 0000 0000 0022 5b0a 100a 0768 616e
+646c 6572 1205 2f68 6561 7022 4708 0011
+0000 0000 0000 0000 1a12 0900 0000 0000
+00e0 3f11 0000 0000 0000 0000 1a12 09cd
+cccc cccc ccec 3f11 0000 0000 0000 0000
+1a12 09ae 47e1 7a14 aeef 3f11 0000 0000
+0000 0000 225e 0a13 0a07 6861 6e64 6c65
+7212 082f 7374 6174 6963 2f22 4708 0011
+0000 0000 0000 0000 1a12 0900 0000 0000
+00e0 3f11 0000 0000 0000 0000 1a12 09cd
+cccc cccc ccec 3f11 0000 0000 0000 0000
+1a12 09ae 47e1 7a14 aeef 3f11 0000 0000
+0000 0000 2260 0a15 0a07 6861 6e64 6c65
+7212 0a70 726f 6d65 7468 6575 7322 4708
+3b11 0000 0000 40c4 d040 1a12 0900 0000
+0000 00e0 3f11 0000 0000 0030 7240 1a12
+09cd cccc cccc ccec 3f11 0000 0000 0030
+7240 1a12 09ae 47e1 7a14 aeef 3f11 0000
+0000 0030 7240 7c0a 1368 7474 705f 7265
+7175 6573 7473 5f74 6f74 616c 1223 546f
+7461 6c20 6e75 6d62 6572 206f 6620 4854
+5450 2072 6571 7565 7374 7320 6d61 6465
+2e18 0022 3e0a 0b0a 0463 6f64 6512 0332
+3030 0a15 0a07 6861 6e64 6c65 7212 0a70
+726f 6d65 7468 6575 730a 0d0a 066d 6574
+686f 6412 0367 6574 1a09 0900 0000 0000
+804d 40e8 080a 1868 7474 705f 7265 7370
+6f6e 7365 5f73 697a 655f 6279 7465 7312
+2154 6865 2048 5454 5020 7265 7370 6f6e
+7365 2073 697a 6573 2069 6e20 6279 7465
+732e 1802 2257 0a0c 0a07 6861 6e64 6c65
+7212 012f 2247 0800 1100 0000 0000 0000
+001a 1209 0000 0000 0000 e03f 1100 0000
+0000 0000 001a 1209 cdcc cccc cccc ec3f
+1100 0000 0000 0000 001a 1209 ae47 e17a
+14ae ef3f 1100 0000 0000 0000 0022 5d0a
+120a 0768 616e 646c 6572 1207 2f61 6c65
+7274 7322 4708 0011 0000 0000 0000 0000
+1a12 0900 0000 0000 00e0 3f11 0000 0000
+0000 0000 1a12 09cd cccc cccc ccec 3f11
+0000 0000 0000 0000 1a12 09ae 47e1 7a14
+aeef 3f11 0000 0000 0000 0000 2262 0a17
+0a07 6861 6e64 6c65 7212 0c2f 6170 692f
+6d65 7472 6963 7322 4708 0011 0000 0000
+0000 0000 1a12 0900 0000 0000 00e0 3f11
+0000 0000 0000 0000 1a12 09cd cccc cccc
+ccec 3f11 0000 0000 0000 0000 1a12 09ae
+47e1 7a14 aeef 3f11 0000 0000 0000 0000
+2260 0a15 0a07 6861 6e64 6c65 7212 0a2f
+6170 692f 7175 6572 7922 4708 0011 0000
+0000 0000 0000 1a12 0900 0000 0000 00e0
+3f11 0000 0000 0000 0000 1a12 09cd cccc
+cccc ccec 3f11 0000 0000 0000 0000 1a12
+09ae 47e1 7a14 aeef 3f11 0000 0000 0000
+0000 2266 0a1b 0a07 6861 6e64 6c65 7212
+102f 6170 692f 7175 6572 795f 7261 6e67
+6522 4708 0011 0000 0000 0000 0000 1a12
+0900 0000 0000 00e0 3f11 0000 0000 0000
+0000 1a12 09cd cccc cccc ccec 3f11 0000
+0000 0000 0000 1a12 09ae 47e1 7a14 aeef
+3f11 0000 0000 0000 0000 2262 0a17 0a07
+6861 6e64 6c65 7212 0c2f 6170 692f 7461
+7267 6574 7322 4708 0011 0000 0000 0000
+0000 1a12 0900 0000 0000 00e0 3f11 0000
+0000 0000 0000 1a12 09cd cccc cccc ccec
+3f11 0000 0000 0000 0000 1a12 09ae 47e1
+7a14 aeef 3f11 0000 0000 0000 0000 2260
+0a15 0a07 6861 6e64 6c65 7212 0a2f 636f
+6e73 6f6c 6573 2f22 4708 0011 0000 0000
+0000 0000 1a12 0900 0000 0000 00e0 3f11
+0000 0000 0000 0000 1a12 09cd cccc cccc
+ccec 3f11 0000 0000 0000 0000 1a12 09ae
+47e1 7a14 aeef 3f11 0000 0000 0000 0000
+225c 0a11 0a07 6861 6e64 6c65 7212 062f
+6772 6170 6822 4708 0011 0000 0000 0000
+0000 1a12 0900 0000 0000 00e0 3f11 0000
+0000 0000 0000 1a12 09cd cccc cccc ccec
+3f11 0000 0000 0000 0000 1a12 09ae 47e1
+7a14 aeef 3f11 0000 0000 0000 0000 225b
+0a10 0a07 6861 6e64 6c65 7212 052f 6865
+6170 2247 0800 1100 0000 0000 0000 001a
+1209 0000 0000 0000 e03f 1100 0000 0000
+0000 001a 1209 cdcc cccc cccc ec3f 1100
+0000 0000 0000 001a 1209 ae47 e17a 14ae
+ef3f 1100 0000 0000 0000 0022 5e0a 130a
+0768 616e 646c 6572 1208 2f73 7461 7469
+632f 2247 0800 1100 0000 0000 0000 001a
+1209 0000 0000 0000 e03f 1100 0000 0000
+0000 001a 1209 cdcc cccc cccc ec3f 1100
+0000 0000 0000 001a 1209 ae47 e17a 14ae
+ef3f 1100 0000 0000 0000 0022 600a 150a
+0768 616e 646c 6572 120a 7072 6f6d 6574
+6865 7573 2247 083b 1100 0000 00e0 b4fc
+401a 1209 0000 0000 0000 e03f 1100 0000
+0000 349f 401a 1209 cdcc cccc cccc ec3f
+1100 0000 0000 08a0 401a 1209 ae47 e17a
+14ae ef3f 1100 0000 0000 0aa0 405c 0a19
+7072 6f63 6573 735f 6370 755f 7365 636f
+6e64 735f 746f 7461 6c12 3054 6f74 616c
+2075 7365 7220 616e 6420 7379 7374 656d
+2043 5055 2074 696d 6520 7370 656e 7420
+696e 2073 6563 6f6e 6473 2e18 0022 0b1a
+0909 a470 3d0a d7a3 d03f 4f0a 1270 726f
+6365 7373 5f67 6f72 6f75 7469 6e65 7312
+2a4e 756d 6265 7220 6f66 2067 6f72 6f75
+7469 6e65 7320 7468 6174 2063 7572 7265
+6e74 6c79 2065 7869 7374 2e18 0122 0b12
+0909 0000 0000 0000 5140 4a0a 0f70 726f
+6365 7373 5f6d 6178 5f66 6473 1228 4d61
+7869 6d75 6d20 6e75 6d62 6572 206f 6620
+6f70 656e 2066 696c 6520 6465 7363 7269
+7074 6f72 732e 1801 220b 1209 0900 0000
+0000 00c0 4043 0a10 7072 6f63 6573 735f
+6f70 656e 5f66 6473 1220 4e75 6d62 6572
+206f 6620 6f70 656e 2066 696c 6520 6465
+7363 7269 7074 6f72 732e 1801 220b 1209
+0900 0000 0000 003d 404e 0a1d 7072 6f63
+6573 735f 7265 7369 6465 6e74 5f6d 656d
+6f72 795f 6279 7465 7312 1e52 6573 6964
+656e 7420 6d65 6d6f 7279 2073 697a 6520
+696e 2062 7974 6573 2e18 0122 0b12 0909
+0000 0000 004b 8841 630a 1a70 726f 6365
+7373 5f73 7461 7274 5f74 696d 655f 7365
+636f 6e64 7312 3653 7461 7274 2074 696d
+6520 6f66 2074 6865 2070 726f 6365 7373
+2073 696e 6365 2075 6e69 7820 6570 6f63
+6820 696e 2073 6563 6f6e 6473 2e18 0122
+0b12 0909 3d0a 172d e831 d541 4c0a 1c70
+726f 6365 7373 5f76 6972 7475 616c 5f6d
+656d 6f72 795f 6279 7465 7312 1d56 6972
+7475 616c 206d 656d 6f72 7920 7369 7a65
+2069 6e20 6279 7465 732e 1801 220b 1209
+0900 0000 0020 12c0 415f 0a27 7072 6f6d
+6574 6865 7573 5f64 6e73 5f73 645f 6c6f
+6f6b 7570 5f66 6169 6c75 7265 735f 746f
+7461 6c12 2554 6865 206e 756d 6265 7220
+6f66 2044 4e53 2d53 4420 6c6f 6f6b 7570
+2066 6169 6c75 7265 732e 1800 220b 1a09
+0900 0000 0000 0000 004f 0a1f 7072 6f6d
+6574 6865 7573 5f64 6e73 5f73 645f 6c6f
+6f6b 7570 735f 746f 7461 6c12 1d54 6865
+206e 756d 6265 7220 6f66 2044 4e53 2d53
+4420 6c6f 6f6b 7570 732e 1800 220b 1a09
+0900 0000 0000 0008 40cf 010a 2a70 726f
+6d65 7468 6575 735f 6576 616c 7561 746f
+725f 6475 7261 7469 6f6e 5f6d 696c 6c69
+7365 636f 6e64 7312 2c54 6865 2064 7572
+6174 696f 6e20 666f 7220 616c 6c20 6576
+616c 7561 7469 6f6e 7320 746f 2065 7865
+6375 7465 2e18 0222 7122 6f08 0b11 0000
+0000 0000 2240 1a12 097b 14ae 47e1 7a84
+3f11 0000 0000 0000 0000 1a12 099a 9999
+9999 99a9 3f11 0000 0000 0000 0000 1a12
+0900 0000 0000 00e0 3f11 0000 0000 0000
+0000 1a12 09cd cccc cccc ccec 3f11 0000
+0000 0000 f03f 1a12 09ae 47e1 7a14 aeef
+3f11 0000 0000 0000 f03f a301 0a39 7072
+6f6d 6574 6865 7573 5f6c 6f63 616c 5f73
+746f 7261 6765 5f63 6865 636b 706f 696e
+745f 6475 7261 7469 6f6e 5f6d 696c 6c69
+7365 636f 6e64 7312 5754 6865 2064 7572
+6174 696f 6e20 2869 6e20 6d69 6c6c 6973
+6563 6f6e 6473 2920 6974 2074 6f6f 6b20
+746f 2063 6865 636b 706f 696e 7420 696e
+2d6d 656d 6f72 7920 6d65 7472 6963 7320
+616e 6420 6865 6164 2063 6875 6e6b 732e
+1801 220b 1209 0900 0000 0000 0000 00f2
+010a 2870 726f 6d65 7468 6575 735f 6c6f
+6361 6c5f 7374 6f72 6167 655f 6368 756e
+6b5f 6f70 735f 746f 7461 6c12 3354 6865
+2074 6f74 616c 206e 756d 6265 7220 6f66
+2063 6875 6e6b 206f 7065 7261 7469 6f6e
+7320 6279 2074 6865 6972 2074 7970 652e
+1800 221b 0a0e 0a04 7479 7065 1206 6372
+6561 7465 1a09 0900 0000 0000 b880 4022
+1c0a 0f0a 0474 7970 6512 0770 6572 7369
+7374 1a09 0900 0000 0000 c05b 4022 180a
+0b0a 0474 7970 6512 0370 696e 1a09 0900
+0000 0000 807b 4022 1e0a 110a 0474 7970
+6512 0974 7261 6e73 636f 6465 1a09 0900
+0000 0000 a06b 4022 1a0a 0d0a 0474 7970
+6512 0575 6e70 696e 1a09 0900 0000 0000
+807b 40c4 010a 3c70 726f 6d65 7468 6575
+735f 6c6f 6361 6c5f 7374 6f72 6167 655f
+696e 6465 7869 6e67 5f62 6174 6368 5f6c
+6174 656e 6379 5f6d 696c 6c69 7365 636f
+6e64 7312 3751 7561 6e74 696c 6573 2066
+6f72 2062 6174 6368 2069 6e64 6578 696e
+6720 6c61 7465 6e63 6965 7320 696e 206d
+696c 6c69 7365 636f 6e64 732e 1802 2249
+2247 0801 1100 0000 0000 0000 001a 1209
+0000 0000 0000 e03f 1100 0000 0000 0000
+001a 1209 cdcc cccc cccc ec3f 1100 0000
+0000 0000 001a 1209 ae47 e17a 14ae ef3f
+1100 0000 0000 0000 00bf 010a 2d70 726f
+6d65 7468 6575 735f 6c6f 6361 6c5f 7374
+6f72 6167 655f 696e 6465 7869 6e67 5f62
+6174 6368 5f73 697a 6573 1241 5175 616e
+7469 6c65 7320 666f 7220 696e 6465 7869
+6e67 2062 6174 6368 2073 697a 6573 2028
+6e75 6d62 6572 206f 6620 6d65 7472 6963
+7320 7065 7220 6261 7463 6829 2e18 0222
+4922 4708 0111 0000 0000 0000 0040 1a12
+0900 0000 0000 00e0 3f11 0000 0000 0000
+0040 1a12 09cd cccc cccc ccec 3f11 0000
+0000 0000 0040 1a12 09ae 47e1 7a14 aeef
+3f11 0000 0000 0000 0040 660a 3070 726f
+6d65 7468 6575 735f 6c6f 6361 6c5f 7374
+6f72 6167 655f 696e 6465 7869 6e67 5f71
+7565 7565 5f63 6170 6163 6974 7912 2354
+6865 2063 6170 6163 6974 7920 6f66 2074
+6865 2069 6e64 6578 696e 6720 7175 6575
+652e 1801 220b 1209 0900 0000 0000 00d0
+406d 0a2e 7072 6f6d 6574 6865 7573 5f6c
+6f63 616c 5f73 746f 7261 6765 5f69 6e64
+6578 696e 675f 7175 6575 655f 6c65 6e67
+7468 122c 5468 6520 6e75 6d62 6572 206f
+6620 6d65 7472 6963 7320 7761 6974 696e
+6720 746f 2062 6520 696e 6465 7865 642e
+1801 220b 1209 0900 0000 0000 0000 0067
+0a2f 7072 6f6d 6574 6865 7573 5f6c 6f63
+616c 5f73 746f 7261 6765 5f69 6e67 6573
+7465 645f 7361 6d70 6c65 735f 746f 7461
+6c12 2554 6865 2074 6f74 616c 206e 756d
+6265 7220 6f66 2073 616d 706c 6573 2069
+6e67 6573 7465 642e 1800 220b 1a09 0900
+0000 0080 27cd 40c3 010a 3770 726f 6d65
+7468 6575 735f 6c6f 6361 6c5f 7374 6f72
+6167 655f 696e 7661 6c69 645f 7072 656c
+6f61 645f 7265 7175 6573 7473 5f74 6f74
+616c 1279 5468 6520 746f 7461 6c20 6e75
+6d62 6572 206f 6620 7072 656c 6f61 6420
+7265 7175 6573 7473 2072 6566 6572 7269
+6e67 2074 6f20 6120 6e6f 6e2d 6578 6973
+7465 6e74 2073 6572 6965 732e 2054 6869
+7320 6973 2061 6e20 696e 6469 6361 7469
+6f6e 206f 6620 6f75 7464 6174 6564 206c
+6162 656c 2069 6e64 6578 6573 2e18 0022
+0b1a 0909 0000 0000 0000 0000 6f0a 2a70
+726f 6d65 7468 6575 735f 6c6f 6361 6c5f
+7374 6f72 6167 655f 6d65 6d6f 7279 5f63
+6875 6e6b 6465 7363 7312 3254 6865 2063
+7572 7265 6e74 206e 756d 6265 7220 6f66
+2063 6875 6e6b 2064 6573 6372 6970 746f
+7273 2069 6e20 6d65 6d6f 7279 2e18 0122
+0b12 0909 0000 0000 0020 8f40 9c01 0a26
+7072 6f6d 6574 6865 7573 5f6c 6f63 616c
+5f73 746f 7261 6765 5f6d 656d 6f72 795f
+6368 756e 6b73 1263 5468 6520 6375 7272
+656e 7420 6e75 6d62 6572 206f 6620 6368
+756e 6b73 2069 6e20 6d65 6d6f 7279 2c20
+6578 636c 7564 696e 6720 636c 6f6e 6564
+2063 6875 6e6b 7320 2869 2e65 2e20 6368
+756e 6b73 2077 6974 686f 7574 2061 2064
+6573 6372 6970 746f 7229 2e18 0122 0b12
+0909 0000 0000 00e8 8d40 600a 2670 726f
+6d65 7468 6575 735f 6c6f 6361 6c5f 7374
+6f72 6167 655f 6d65 6d6f 7279 5f73 6572
+6965 7312 2754 6865 2063 7572 7265 6e74
+206e 756d 6265 7220 6f66 2073 6572 6965
+7320 696e 206d 656d 6f72 792e 1801 220b
+1209 0900 0000 0000 807a 40b7 010a 3570
+726f 6d65 7468 6575 735f 6c6f 6361 6c5f
+7374 6f72 6167 655f 7065 7273 6973 745f
+6c61 7465 6e63 795f 6d69 6372 6f73 6563
+6f6e 6473 1231 4120 7375 6d6d 6172 7920
+6f66 206c 6174 656e 6369 6573 2066 6f72
+2070 6572 7369 7374 696e 6720 6561 6368
+2063 6875 6e6b 2e18 0222 4922 4708 6f11
+1c2f dd24 e68c cc40 1a12 0900 0000 0000
+00e0 3f11 8d97 6e12 8360 3e40 1a12 09cd
+cccc cccc ccec 3f11 0ad7 a370 3d62 6b40
+1a12 09ae 47e1 7a14 aeef 3f11 7b14 ae47
+e1b6 7240 6a0a 2f70 726f 6d65 7468 6575
+735f 6c6f 6361 6c5f 7374 6f72 6167 655f
+7065 7273 6973 745f 7175 6575 655f 6361
+7061 6369 7479 1228 5468 6520 746f 7461
+6c20 6361 7061 6369 7479 206f 6620 7468
+6520 7065 7273 6973 7420 7175 6575 652e
+1801 220b 1209 0900 0000 0000 0090 407a
+0a2d 7072 6f6d 6574 6865 7573 5f6c 6f63
+616c 5f73 746f 7261 6765 5f70 6572 7369
+7374 5f71 7565 7565 5f6c 656e 6774 6812
+3a54 6865 2063 7572 7265 6e74 206e 756d
+6265 7220 6f66 2063 6875 6e6b 7320 7761
+6974 696e 6720 696e 2074 6865 2070 6572
+7369 7374 2071 7565 7565 2e18 0122 0b12
+0909 0000 0000 0000 0000 ac01 0a29 7072
+6f6d 6574 6865 7573 5f6c 6f63 616c 5f73
+746f 7261 6765 5f73 6572 6965 735f 6f70
+735f 746f 7461 6c12 3454 6865 2074 6f74
+616c 206e 756d 6265 7220 6f66 2073 6572
+6965 7320 6f70 6572 6174 696f 6e73 2062
+7920 7468 6569 7220 7479 7065 2e18 0022
+1b0a 0e0a 0474 7970 6512 0663 7265 6174
+651a 0909 0000 0000 0000 0040 222a 0a1d
+0a04 7479 7065 1215 6d61 696e 7465 6e61
+6e63 655f 696e 5f6d 656d 6f72 791a 0909
+0000 0000 0000 1440 d601 0a2d 7072 6f6d
+6574 6865 7573 5f6e 6f74 6966 6963 6174
+696f 6e73 5f6c 6174 656e 6379 5f6d 696c
+6c69 7365 636f 6e64 7312 584c 6174 656e
+6379 2071 7561 6e74 696c 6573 2066 6f72
+2073 656e 6469 6e67 2061 6c65 7274 206e
+6f74 6966 6963 6174 696f 6e73 2028 6e6f
+7420 696e 636c 7564 696e 6720 6472 6f70
+7065 6420 6e6f 7469 6669 6361 7469 6f6e
+7329 2e18 0222 4922 4708 0011 0000 0000
+0000 0000 1a12 0900 0000 0000 00e0 3f11
+0000 0000 0000 0000 1a12 09cd cccc cccc
+ccec 3f11 0000 0000 0000 0000 1a12 09ae
+47e1 7a14 aeef 3f11 0000 0000 0000 0000
+680a 2770 726f 6d65 7468 6575 735f 6e6f
+7469 6669 6361 7469 6f6e 735f 7175 6575
+655f 6361 7061 6369 7479 122e 5468 6520
+6361 7061 6369 7479 206f 6620 7468 6520
+616c 6572 7420 6e6f 7469 6669 6361 7469
+6f6e 7320 7175 6575 652e 1801 220b 1209
+0900 0000 0000 0059 4067 0a25 7072 6f6d
+6574 6865 7573 5f6e 6f74 6966 6963 6174
+696f 6e73 5f71 7565 7565 5f6c 656e 6774
+6812 2f54 6865 206e 756d 6265 7220 6f66
+2061 6c65 7274 206e 6f74 6966 6963 6174
+696f 6e73 2069 6e20 7468 6520 7175 6575
+652e 1801 220b 1209 0900 0000 0000 0000
+009e 020a 3070 726f 6d65 7468 6575 735f
+7275 6c65 5f65 7661 6c75 6174 696f 6e5f
+6475 7261 7469 6f6e 5f6d 696c 6c69 7365
+636f 6e64 7312 2354 6865 2064 7572 6174
+696f 6e20 666f 7220 6120 7275 6c65 2074
+6f20 6578 6563 7574 652e 1802 2260 0a15
+0a09 7275 6c65 5f74 7970 6512 0861 6c65
+7274 696e 6722 4708 3711 0000 0000 0000
+2840 1a12 0900 0000 0000 00e0 3f11 0000
+0000 0000 0000 1a12 09cd cccc cccc ccec
+3f11 0000 0000 0000 0000 1a12 09ae 47e1
+7a14 aeef 3f11 0000 0000 0000 0840 2261
+0a16 0a09 7275 6c65 5f74 7970 6512 0972
+6563 6f72 6469 6e67 2247 0837 1100 0000
+0000 002e 401a 1209 0000 0000 0000 e03f
+1100 0000 0000 0000 001a 1209 cdcc cccc
+cccc ec3f 1100 0000 0000 0000 001a 1209
+ae47 e17a 14ae ef3f 1100 0000 0000 0008
+4069 0a29 7072 6f6d 6574 6865 7573 5f72
+756c 655f 6576 616c 7561 7469 6f6e 5f66
+6169 6c75 7265 735f 746f 7461 6c12 2d54
+6865 2074 6f74 616c 206e 756d 6265 7220
+6f66 2072 756c 6520 6576 616c 7561 7469
+6f6e 2066 6169 6c75 7265 732e 1800 220b
+1a09 0900 0000 0000 0000 0060 0a21 7072
+6f6d 6574 6865 7573 5f73 616d 706c 6573
+5f71 7565 7565 5f63 6170 6163 6974 7912
+2c43 6170 6163 6974 7920 6f66 2074 6865
+2071 7565 7565 2066 6f72 2075 6e77 7269
+7474 656e 2073 616d 706c 6573 2e18 0122
+0b12 0909 0000 0000 0000 b040 da01 0a1f
+7072 6f6d 6574 6865 7573 5f73 616d 706c
+6573 5f71 7565 7565 5f6c 656e 6774 6812
+a701 4375 7272 656e 7420 6e75 6d62 6572
+206f 6620 6974 656d 7320 696e 2074 6865
+2071 7565 7565 2066 6f72 2075 6e77 7269
+7474 656e 2073 616d 706c 6573 2e20 4561
+6368 2069 7465 6d20 636f 6d70 7269 7365
+7320 616c 6c20 7361 6d70 6c65 7320 6578
+706f 7365 6420 6279 206f 6e65 2074 6172
+6765 7420 6173 206f 6e65 206d 6574 7269
+6320 6661 6d69 6c79 2028 692e 652e 206d
+6574 7269 6373 206f 6620 7468 6520 7361
+6d65 206e 616d 6529 2e18 0122 0b12 0909
+0000 0000 0000 0000 d902 0a29 7072 6f6d
+6574 6865 7573 5f74 6172 6765 745f 696e
+7465 7276 616c 5f6c 656e 6774 685f 7365
+636f 6e64 7312 2141 6374 7561 6c20 696e
+7465 7276 616c 7320 6265 7477 6565 6e20
+7363 7261 7065 732e 1802 2282 010a 0f0a
+0869 6e74 6572 7661 6c12 0331 3573 226f
+0804 1100 0000 0000 804d 401a 1209 7b14
+ae47 e17a 843f 1100 0000 0000 002c 401a
+1209 9a99 9999 9999 a93f 1100 0000 0000
+002c 401a 1209 0000 0000 0000 e03f 1100
+0000 0000 002e 401a 1209 cdcc cccc cccc
+ec3f 1100 0000 0000 002e 401a 1209 ae47
+e17a 14ae ef3f 1100 0000 0000 002e 4022
+8101 0a0e 0a08 696e 7465 7276 616c 1202
+3173 226f 083a 1100 0000 0000 003c 401a
+1209 7b14 ae47 e17a 843f 1100 0000 0000
+0000 001a 1209 9a99 9999 9999 a93f 1100
+0000 0000 0000 001a 1209 0000 0000 0000
+e03f 1100 0000 0000 0000 001a 1209 cdcc
+cccc cccc ec3f 1100 0000 0000 00f0 3f1a
+1209 ae47 e17a 14ae ef3f 1100 0000 0000
+00f0 3f

+ 129 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/protobuf.gz

@@ -0,0 +1,129 @@
+1f8b 0808 efa0 c754 0003 7072 6f74 6f62
+7566 00ed 594d 8c1c c515 9eb1 8d3d 5b86
+6037 265e 8c4d ca03 c4bb ceee cc9a 9f58
+01cc f6ca 4424 041b 8837 21c8 24ed daee
+9a99 cef6 1f55 d578 c7e4 b004 0e39 8088
+8448 048a 124b 4442 9110 e110 25b9 c54a
+9072 01c5 9724 4a24 2472 413e 448a 8592
+1b87 bcea aeda eeea 99d9 3530 49a4 68e7
+b0bb 5355 fdde abf7 bef7 bdf7 7a3f 6ca0
+664f 88c4 61f4 8994 72e1 7829 23c2 8f23
+27f4 5d16 73ea c691 c7ad cf2d f628 fed2
+e2e2 c358 9dc3 0111 3472 7dca b11f e1f2
+d9d6 e496 e6a3 e86a b4a3 4722 2fa0 ccaa
+b79b f737 6abb 6bea b3cf 9ac8 ff78 6fbe
+bcf6 cedb f2f3 7763 ed8d fbff 766e cf1b
+ff28 d69a df44 5621 7847 9bc0 2fc1 c727
+7e09 ed2d c45f dd26 89df 0ea9 60be 3b46
+1d67 d0f5 850e 94e9 008f b2fe f834 74d0
+8d85 865d 8506 8791 a84b ffa3 de12 8475
+e938 2352 f116 208c c701 e563 84d4 e368
+77a1 617b bbcb 48d2 1b9f f4d3 6857 21fd
+aa76 8f92 647c c2bf 85ae 2b84 37da 5c40
+e6ba 6374 8de9 fc84 c590 0c3d 9aca f0de
+bdfb f40b bffd 5763 fe9f 7659 8314 f0fb
+9fbf 6897 35b4 dfbd 65fb d397 7f60 9735
+1c43 7f7e f5cd 975e b3df 6fa0 bd06 fb70
+ff1c 7596 fa82 720b 0f50 8edc cce8 263b
+b0c9 339b 3cb3 c933 5afa ff2f cfc8 13f6
+5b17 ed01 0d73 cc1e d090 af99 1a60 ed3b
+e8ba 32cd 7047 c482 04d6 cd8b f217 8ed2
+7089 321c 770c bae1 3824 1e6d 4dd6 9af7
+a29d 689b 1b7b d4da 7adb dcdc 085b d135
+68bb fc33 f6ac ad00 cd7d 13b9 b5ab 27ec
+4b0d 34a9 b4f3 0470 45cb 2c77 b0c4 72f9
+ee26 cd7d 02ec 6cd2 dc26 cd7d 6ce1 ff73
+9a7b ef17 1f0e d2dc 1d3f 19a4 b9c6 f941
+9a43 e7ed c7d1 0d20 d5a5 9c3b 6e92 3a6a
+2053 6437 9793 5dca 81ea c006 ccfb 5cd0
+101f 7ff8 6b58 f821 d04e 4223 2169 676d
+8eab 3577 028d fd34 91dd dac5 f987 90a5
+8577 6316 a7c2 8f80 bf0e 9f5c 23cf 6215
+8b1e 11d8 4d19 0391 411f d315 9f8b d664
+bdb9 d352 b458 7bc4 7e00 5dab e585 64c5
+e9c0 9439 7582 acf8 611a 9618 3906 ab70
+c70f 28f6 2877 999f 8898 7153 d405 fb38
+daa5 45c9 f399 2c7c f2a3 c838 669f 4407
+b40c 6062 df03 cb9d 9086 31e4 79ce d437
+7d55 2de3 7c39 e3e9 124d 97c4 7de5 7b0b
+2eda a7c5 018e 9870 a48f 7544 accf 9f92
+6bb9 dfc1 4040 0156 a741 6ae4 529c 46fe
+0aa6 49ec f68c 88e4 3a8e a1bd b397 8efc
+71e1 41b4 5feb 78d2 6722 2581 69f1 81af
+e7ab 1b1a 8cad 0b0b 0e3a 5420 d2f1 22b0
+db73 8238 5e4e 13a7 43fc 2005 af28 24dd
+2a6b 5611 a2fb 4e9e 9a3d 751f cecf 627d
+56c3 47a3 ff21 f499 51f2 b5dc 03eb c8ad
+c86b d87f a8a3 c325 81f4 4912 a404 025b
+7e81 1104 bef6 f88c 94ad b770 2786 1c08
+02ac 9e82 25c0 6c0c 38a5 6e2a a82c b94f
+34e3 c64e 95ba 4d99 6c4f ed91 e9f6 ac91
+e2af bc2c 3f3f 9bff 88f4 7079 7e90 1e2e
+cfbf 5a47 5f28 5d28 885d 8827 871b 912e
+75dc 1e75 9793 d88f c488 fb3d 6adc 6f2a
+7b27 536c 4f63 1fd0 068e 94b7 2c64 0118
+6615 3654 5dce 9801 58d5 8353 69b4 5cc9
+925a ed83 3a9a 5ac7 4878 0432 50c7 f376
+6993 a8b4 58d9 2199 924c f97d a92f f1ef
+332c fa49 d66e dd88 3e85 b6c9 2fd6 7697
+5122 a88e faaf 57ed e67e 74ad dadc 0122
+38f0 8ade bd70 da6e 4eca 4e2d dbdd 9af8
+d15a 0ff6 94dd bc09 ca52 be33 21a0 6e73
+d9ce e9fd f3cb 7673 1ff4 6ff9 fe55 6964
+3efb 561d dd33 f2ce 7ee4 01bb 455d 6789
+08b7 e7e4 6fc5 fa66 6c8e 3e92 9248 00ff
+f00c 78d9 49ac 1fac be48 2b9e 9330 fc32
+d486 fa58 aacf 6fea 68f6 4a6f 9175 a0d6
+8269 f69a c1b9 fd79 973a 5504 5623 08c2
+921f 991e b8c0 6071 cbd7 aa17 182c 6eb0
+d641 731b db0f 8d59 0a40 2409 717d d187
+061f 10a8 bf69 a65d bb48 76d8 44f8 453b
+44ad 2b55 13d0 a82b 7a39 b50c fae1 2cf1
+85d4 0219 b7a4 9452 af9a 4f5d d45e 475b
+17c6 10ea 399c 8449 60b2 6f35 abd4 11ac
+9f29 b3e5 eaa1 77ec dfd5 d1d1 7514 010d
+fa9e 9330 1ac4 c4ab 4e49 fd61 0ad5 d962
+5862 b443 1953 1726 388a a3d9 acec cb82
+092d 07e0 bb85 177b 3e98 2849 46fa c377
+73b2 9215 3a15 1ea4 8107 c9b0 4403 e5ac
+8112 121b 8c6f de41 15be 8c5d 6495 e7d6
+6d59 ecf3 1e64 807f 4a8d 4096 76d9 d346
+70f0 0bf6 8fea e8b3 57a4 905b ee3a ca4a
+1a66 a0c4 b841 ea49 37b9 411c 51cd b3c0
+d82d dad2 5fce fa30 47a6 02dc 58d8 396d
+5877 e979 fbcc c6c6 e57e b70e 0d37 2edf
+1d71 fdd5 73f6 afea e8ce 911a 14f9 9608
+aff4 df82 230b 98a7 6148 5896 7305 c149
+1a51 0f4a 0f50 023c 925d 5933 45bc 7b7f
+fbdd 5bde 7fee 6d83 299e ff61 643d 73e6
+5e83 29a0 254d 8e2d 2d1b 4c91 95e8 5f32
+fbdb eb24 95b6 bb42 1453 05c6 ab74 a19e
+18c6 16df b7cf ad43 aaa6 2a45 1677 ad0b
+14cd 1910 930d 54d7 6aaf d7d1 f448 dd79
+6c4b b5f8 8ea1 ac91 23e0 6315 6360 e4e6
+6174 406d 5e1f 12e8 2768 44a0 7905 3e51
+005c 3bbb c7fe 9359 7ea2 58f8 1d45 007c
+78d5 fcc6 83f9 2adc be5c 8638 8db2 f4c9
+de55 6043 0e54 a358 f634 3ac3 3c16 2709
+a498 7168 ad2a 8d67 a8eb 196d b379 ad0a
+c65a c38a d1b0 6b0c 09f7 6376 17dd ba81
+2285 b0b6 598e 8629 50f0 1a0a ab1f 6f31
+ea2c 4b03 ea14 6df2 88ee f3e6 c1ee 1acb
+272b 4db5 1c80 2732 8919 681a 996d 1029
+88c6 51e5 d1a9 613d c215 46a3 6137 09fa
+7459 c304 0303 9967 aa68 7d22 15be 9175
+55f7 5426 a5d9 6159 9739 a678 66e4 c474
+061d 2c69 d24d 4005 5433 c72b 80ca f6b3
+10a4 d159 e60b c821 dd1d 98a1 7ed3 fe6b
+dd98 c94c 0d0a 4daf d58f 0f90 952f 6868
+8268 843e fc45 c9f0 f238 76e3 3061 8017
+9ecd 5dba 5da1 2b09 140d 4fd2 0e14 439c
+bfee c284 67df f246 0adc 0350 ebab 02a9
+9b2b 7559 9003 5887 1fd3 5518 ff65 8b11
+a75c b223 398a 81e7 d5ed d6e6 f183 0b6e
+3628 eb7d 2042 2ace 5279 1597 9124 7f0b
+fbdd 3acc 1e0d 7dc4 da7a e44e 0e43 e2b6
+1c19 ab27 860c 8933 f6e0 9038 3304 7dad
+214d 706b 4813 dcb2 9b4f d781 900b 23b6
+1c91 36dc a5f6 eff9 af0c aaff 06f1 48e5
+4433 2000 00

+ 163 - 0
Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/test.gz

@@ -0,0 +1,163 @@
+1f8b 0808 2aa1 c754 0003 7465 7874 00b5
+5b5d 939b 3816 7def 5fa1 ea79 99a9 4d3c
+601b db3c f4c3 5426 55f3 309b ca6e 7ab7
+6a9e 281a d436 150c 04c4 a4bd 5df3 dff7
+4a88 361f 025d 094f 1e92 34e8 1cae 8ea4
+ab7b 04fd 03f9 ede3 ef9f c989 b122 28e9
+b79a 562c 88eb 3264 499e 05e7 242a f38a
+4679 1657 e4f1 44c9 6f8f 8f9f 896c 46d2
+90d1 2c4a 6845 928c 749b aeee 7e20 8f7f
+7cfe 8861 adea f339 2c2f 77fa a6af a730
+8b53 5a3e dcff 7cff ee5b 1d66 2c49 e9c3
+bdb3 f2ee ff22 ce12 027f 3101 9621 80ee
+7659 90a8 28af 3366 8eeb 2042 f887 558b
+7553 d158 a8a7 a4b1 d450 7259 2a69 84ee
+e28a e4e7 3365 6512 dd40 d429 2e1b 6527
+b96c e5ed 10da 6a6c 4c31 0043 cbf2 7213
+9915 4c96 22ab 9816 48dc d02d 10d8 8440
+050d ca30 3bd2 db89 ace2 5b22 b592 6fa9
+e092 74a9 ec46 3403 0216 9647 7a8b cc3c
+c565 29ba 9a6b 81e0 2de1 02b1 cd28 3a60
+f8b9 ca53 5a2d 2f1c 2698 2c44 9e62 b294
+f84a 6729 b029 4107 7a2c c3e2 b458 5a05
+8b85 ac2a 164b 491b 2a4b 394d c01d d889
+86c5 6225 c724 1642 2a48 2c75 144c 9632
+1a60 3ba8 8ac1 ed68 f96a 57f2 5868 a9e6
+b194 b325 b354 d40c 7e05 1665 0e45 dc89
+d68a bdca dd38 fbd5 7aef dd84 90cb e21e
+bcc3 6ab7 59df 8690 336e 9cc3 7eb5 396c
+8df5 eeb0 425c 7bff 70d8 ad3c 47fe 712d
+46a0 4fe8 fa60 96c7 16bc 4afe 4783 a70b
+a30a dfcd ef09 cf2d eeab cd76 07af 74d8
+d7fb 26b6 1a81 524c 6a0c 6a16 a675 cd9d
+a67a abac 0c07 e98f d158 ac0c 5827 3c29
+c694 819d 9144 0fb1 34ba 6604 6889 4c2c
+edb4 4e73 2674 4e2c 1cce cab1 9ac0 4dd4
+427a d359 ad26 fca4 4629 2d6a 81f5 3427
+31d6 0c6b 32f5 ca4d 5942 8c7e 7aac a587
+3423 3051 0fed 1667 959b f477 1ad5 1038
+2b33 6802 c7aa 6560 fb26 b59a b16a 334a
+a150 c6ae 0e0b c5ea 83f4 6f93 da4c f8ae
+195d b408 537b 8644 6215 c119 b149 41d4
+0e6a 460f 1dc0 c267 e1c1 5851 d08e 6a52
+9749 1f34 230d 0283 334c 6bdf b527 f017
+1368 1866 0cd0 66bb 3d1c b07a 619c 4e15
+b09c 8529 7914 7f67 f5f9 8996 247f ee39
+9e8a 9cc3 982a 8d4e 0b17 4fa6 e59d e2de
+6b94 c7d0 edb5 e3dc bf53 4ac3 ff93 c70f
+f7b0 8728 e3ac 0ac8 9c74 c292 3537 359e
+6ccc 3030 65a3 0638 5786 87f9 96b0 79dc
+8c31 1bb7 9d73 6673 1169 ad99 2918 ad85
+de9c e914 195b 2dbd 2e08 8cb1 3fb3 62c0
+eb84 7368 5ab1 d456 0ba1 1812 6868 d22c
+f046 9269 6d1a 46b0 91e3 c2c9 a587 5939
+356b 1673 e1f4 5e0d 2ddf d870 1988 8800
+1bdb 352b 0623 0911 860d 239f c279 e1a4
+c300 0d3d 9b05 1e2d 19ca b5e9 0453 1a30
+bd5c 3898 8171 33c4 a245 d25a 379d 4023
+27a6 1747 0fc1 bb37 3328 5a16 9d7f d3a9
+32f4 637a 51b4 0823 0b67 8c46 2b83 3071
+3a71 148e 4caf 0f06 84f4 71ce d65f 4021
+7c98 e31d 9650 341c bb2d 52b1 9e27 5b6f
+f79d 7758 5ae1 a6fc 1c5c 8f68 05cd 8b3a
+685f 7a75 5d5d 5d81 a703 1252 5d2a 46cf
+e4c3 e7ff 1096 9cc1 3515 3463 dc35 0d3f
+1c9d 666c 8dde 740b 1819 6f18 d931 2ff3
+9a25 1938 af4f 6f16 b373 919d 4246 a2ba
+2c21 9ef4 42e8 4b52 b151 309d f6c7 b03e
+d23b c58d bd33 7cf4 397c 099e e38a fc33
+7c49 cef5 b963 7173 e83d 7986 7124 31ad
+a232 2958 5e8e 2568 f1fd 47b6 570f aebf
+1e3e 91f3 8a9b 9f0c 1ff5 06ec 3feb edf2
+7a34 e230 6992 1834 0bce f49c 432d d498
+db7f cbab a4b9 2acc f1d8 1bcf 73f4 4350
+b7f1 569b c3de f1fc 35fd 87b3 1f86 068b
+bc64 019f 66ed fc20 5ff8 a566 e681 2630
+91db c610 6116 5152 67c9 0ba1 451e 9de6
+e6a4 82b8 1fac a281 bbda aed7 9bdd c1df
+1e36 3b88 7624 e49f 49c9 ea30 edf7 efbf
+cd45 9c8c 4a86 7e60 ca26 de6a eb6e f707
+dfe5 2a1e 3a71 c9a5 1ec4 1974 290e d23c
+ff5a 17c1 7398 a435 0c47 bbc0 41c4 eb8c
+fef5 d397 f75f 7e25 4d53 d236 ed86 8a22
+edac 7154 7b47 1735 225a 7d94 d8e8 da76
+7b45 54f4 cf30 ad43 587c dd4f 05d2 34e9
+7e63 dfde 21cf 3964 cd34 2512 0497 2051
+e590 9c68 5433 aa8a 5747 df9e 3ae1 21af
+ddbd c671 c596 698b f696 a017 81c5 2725
+d660 5334 df70 89bb 3641 8839 45d6 1bc5
+9449 f308 966c 05d8 f048 83e8 44a3 af45
+9e64 0c33 837e 14bf 9871 bdfb 1349 20ff
+c12c e5f3 e84a 0549 e5bd cc31 f218 45ec
+d650 46c6 d0aa cebe 2a17 8761 606f a9c8
+12af 5ae4 430a 0815 76ab ee6a 6783 6365
+d186 6f87 a55c 504f 17be 1124 2561 9742
+b9a6 e69f a148 06b3 8057 fe98 87fb a8a4
+21e3 8706 9e7f 30c5 42ec 1594 27e2 6ba4
+ad31 38c9 00e8 af1d 5320 2bc3 ace2 27e9
+00df ba9e 29bc ceae 4fd6 8d63 92c5 5080
+65c7 e029 64d1 2968 7ecd e8d2 9f0d ff92
+0bb4 1259 5234 242d 6ef8 8b49 5798 7e7c
+31cf 5664 5163 92f9 dcb6 8cce bf31 dd72
+3e91 1117 5234 29d2 359d 3dcd 8b99 fe74
+799b 28cd bc69 9afc 784d 126d 1284 95d6
+34f9 c978 e234 9ca6 3345 a046 5363 bd00
+ef2f c55b 1088 d136 c518 0fef b79a d690
+6dc2 228c 1276 11c9 feed 0759 ddbf 8db3
+686b 3086 036e cdd6 3505 7377 fc7b 53c3
+0ea5 343b b2d3 a052 6d27 e4f7 3061 bc3f
+b07b 3fc9 eed1 d8b8 5ff2 1166 bd92 204c
+f63e 5270 f971 5085 e722 a573 9bb1 6c41
+5a08 a627 4a72 ed2e 3c81 db38 dbbd bee6
+4a32 a8de 9238 284a 9ae6 613c 7a73 ade8
+996c 7a7d 815d d267 5a96 72ec 4292 e5d9
+7b71 c8c0 5d72 454b d8ab 5640 9480 16bc
+f6e2 439b 444d 0dc7 dd7b cd62 4889 316c
+6c4f 3495 e38e dacc 6603 47a8 368b d7cf
+0569 3445 49c0 0f1e 9af2 549e b38c aab2
+ced1 84d8 b805 58df cbf1 4334 337b 0c70
+1dcf 37ea cc6c 473a d1bf 03b7 16a5 75cc
+073e 4af3 8cb6 0535 94e6 2bba 6a7f f89e
+b013 0c32 4c8c ab06 883d a71f 9141 af79
+8f11 8598 8434 f373 a2c7 f2a6 f978 4920
+2e6a d978 bbd6 e753 591e 778a 88ce 6f9b
+ffd2 6ec9 3cf4 6b99 c88b 0289 e323 4543
+a80a 8450 fade cc3e 4ebb ffcf a147 75c0
+c659 6df6 fb1b 9035 47c6 9b95 b7f1 6fc1
+26e8 76eb dd6a bbdb d8f1 3515 8303 c3bb
+9af5 16b3 1cb2 82d8 e3a7 88a2 8490 9971
+5048 4800 b68e 98e0 d74c f509 14ac 54d3
+1e75 6a88 c914 d596 12b0 7017 f710 5750
+2831 fa24 d42c 7d8d ad97 f9c1 ded7 8f9e
+a2dd 1c87 88a1 b39f 2980 27a0 e730 8147
+6661 16f1 ad57 a63e f1a6 4521 5296 b3e4
+59d6 0895 daa7 fede 5c24 df7a e6a7 a299
+d88e c467 46a4 4703 1e28 e787 41ed 8e15
+9779 51c0 96d5 6ba4 dc97 10d1 2872 a11e
+356f 930d f123 1f6b 8ab7 2018 3b5f 04a6
+c964 aaa5 d107 232c 906a 9427 d7f8 2cfb
+6875 cfb6 761d 6cf8 4ac3 a30a 5b66 2aa3
+e8a7 32d3 4c5b 55dc 659d d2e0 7a0c 8f3e
+bc27 1ca8 39b3 c771 2b56 0f0a f82a 5a35
+f945 880a eb5a f5ae fff6 bca3 c572 2bde
+d189 048a 58bc 0557 91ff 3538 aac7 b135
+6fc6 27f8 fa25 8c71 bf4b b854 c67f c340
+4d10 2f1f a929 62f1 8bb7 8b87 eaca 0eda
+9a4b 3b1e ab1e a1eb 2116 bce2 ade7 b004
+114b fd0a 997d fba9 a157 d41e 1a84 2a69
+b547 1d83 ccfc 61b0 4388 db22 5dd5 d9f7
+3261 b01f b507 33aa d027 5847 1976 a2dd
+d6f1 77da 5865 26fe 30aa 5d13 46cf fd8d
+6022 70f2 915b 38de 1cc4 3c17 25cc 854a
+bc4b 6d8f 9ce8 4b01 c621 e665 22b8 72d2
+7c8e 48c2 4afc d41c b7c1 08c2 34ba 48a7
+de1e c149 d580 07f6 2bf8 4b59 0e29 bba3
+9168 66fb 69a2 0b78 7558 c214 904d df3e
+2ef8 2512 5f09 b4b7 a1f6 a5ec 3be5 6a44
+6558 a887 5143 a9d8 6ee6 11af edf5 877b
+d71b 7ca2 245e 1bbb db1b 9179 3724 f346
+19c5 9ecb bf25 9729 9948 997d 42fe 7ad0
+84a1 c992 238e b55d 8f54 53c0 b90d d568
+1fb4 a6ba 1dd3 e813 017b 2643 aae1 c8f3
+41f3 168d 7bf3 71df feee ff2d f9e8 431a
+5200 00

+ 0 - 0
Godeps/_workspace/src/github.com/prometheus/client_golang/text/testdata/text → Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/text


+ 8 - 18
Godeps/_workspace/src/github.com/prometheus/client_golang/text/create.go → Godeps/_workspace/src/github.com/prometheus/common/expfmt/text_create.go

@@ -11,14 +11,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Package text contains helper functions to parse and create text-based
-// exchange formats. The package currently supports (only) version 0.0.4 of the
-// exchange format. Should other versions be supported in the future, some
-// versioning scheme has to be applied. Possibilities include separate packages
-// or separate functions. The best way depends on the nature of future changes,
-// which is the reason why no versioning scheme has been applied prematurely
-// here.
-package text
+package expfmt
 
 import (
 	"bytes"
@@ -27,8 +20,8 @@ import (
 	"math"
 	"strings"
 
-	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_golang/model"
 	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
+	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/common/model"
 )
 
 // MetricFamilyToText converts a MetricFamily proto message into text format and
@@ -48,9 +41,6 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (int, error) {
 	if name == "" {
 		return written, fmt.Errorf("MetricFamily has no name: %s", in)
 	}
-	if in.Type == nil {
-		return written, fmt.Errorf("MetricFamily has no type: %s", in)
-	}
 
 	// Comments, first HELP, then TYPE.
 	if in.Help != nil {
@@ -79,7 +69,7 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (int, error) {
 		case dto.MetricType_COUNTER:
 			if metric.Counter == nil {
 				return written, fmt.Errorf(
-					"expected counter in metric %s", metric,
+					"expected counter in metric %s %s", name, metric,
 				)
 			}
 			n, err = writeSample(
@@ -90,7 +80,7 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (int, error) {
 		case dto.MetricType_GAUGE:
 			if metric.Gauge == nil {
 				return written, fmt.Errorf(
-					"expected gauge in metric %s", metric,
+					"expected gauge in metric %s %s", name, metric,
 				)
 			}
 			n, err = writeSample(
@@ -101,7 +91,7 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (int, error) {
 		case dto.MetricType_UNTYPED:
 			if metric.Untyped == nil {
 				return written, fmt.Errorf(
-					"expected untyped in metric %s", metric,
+					"expected untyped in metric %s %s", name, metric,
 				)
 			}
 			n, err = writeSample(
@@ -112,7 +102,7 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (int, error) {
 		case dto.MetricType_SUMMARY:
 			if metric.Summary == nil {
 				return written, fmt.Errorf(
-					"expected summary in metric %s", metric,
+					"expected summary in metric %s %s", name, metric,
 				)
 			}
 			for _, q := range metric.Summary.Quantile {
@@ -144,7 +134,7 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (int, error) {
 		case dto.MetricType_HISTOGRAM:
 			if metric.Histogram == nil {
 				return written, fmt.Errorf(
-					"expected summary in metric %s", metric,
+					"expected histogram in metric %s %s", name, metric,
 				)
 			}
 			infSeen := false
@@ -191,7 +181,7 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (int, error) {
 			)
 		default:
 			return written, fmt.Errorf(
-				"unexpected type in metric %s", metric,
+				"unexpected type in metric %s %s", name, metric,
 			)
 		}
 		written += n

+ 20 - 17
Godeps/_workspace/src/github.com/prometheus/client_golang/text/create_test.go → Godeps/_workspace/src/github.com/prometheus/common/expfmt/text_create_test.go

@@ -11,7 +11,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package text
+package expfmt
 
 import (
 	"bytes"
@@ -311,6 +311,24 @@ request_duration_microseconds_bucket{le="172.8"} 1524
 request_duration_microseconds_bucket{le="+Inf"} 2693
 request_duration_microseconds_sum 1.7560473e+06
 request_duration_microseconds_count 2693
+`,
+		},
+		// 6: No metric type, should result in default type Counter.
+		{
+			in: &dto.MetricFamily{
+				Name: proto.String("name"),
+				Help: proto.String("doc string"),
+				Metric: []*dto.Metric{
+					&dto.Metric{
+						Counter: &dto.Counter{
+							Value: proto.Float64(math.Inf(-1)),
+						},
+					},
+				},
+			},
+			out: `# HELP name doc string
+# TYPE name counter
+name -Inf
 `,
 		},
 	}
@@ -378,22 +396,7 @@ func testCreateError(t testing.TB) {
 			},
 			err: "MetricFamily has no name",
 		},
-		// 2: No metric type.
-		{
-			in: &dto.MetricFamily{
-				Name: proto.String("name"),
-				Help: proto.String("doc string"),
-				Metric: []*dto.Metric{
-					&dto.Metric{
-						Untyped: &dto.Untyped{
-							Value: proto.Float64(math.Inf(-1)),
-						},
-					},
-				},
-			},
-			err: "MetricFamily has no type",
-		},
-		// 3: Wrong type.
+		// 2: Wrong type.
 		{
 			in: &dto.MetricFamily{
 				Name: proto.String("name"),

+ 36 - 30
Godeps/_workspace/src/github.com/prometheus/client_golang/text/parse.go → Godeps/_workspace/src/github.com/prometheus/common/expfmt/text_parse.go

@@ -11,7 +11,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package text
+package expfmt
 
 import (
 	"bufio"
@@ -22,10 +22,9 @@ import (
 	"strconv"
 	"strings"
 
-	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
-
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
-	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_golang/model"
+	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
+	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/common/model"
 )
 
 // A stateFn is a function that represents a state in a state machine. By
@@ -46,9 +45,9 @@ func (e ParseError) Error() string {
 	return fmt.Sprintf("text format parsing error in line %d: %s", e.Line, e.Msg)
 }
 
-// Parser is used to parse the simple and flat text-based exchange format. Its
+// TextParser is used to parse the simple and flat text-based exchange format. Its
 // nil value is ready to use.
-type Parser struct {
+type TextParser struct {
 	metricFamiliesByName map[string]*dto.MetricFamily
 	buf                  *bufio.Reader // Where the parsed input is read through.
 	err                  error         // Most recent error.
@@ -83,14 +82,21 @@ type Parser struct {
 // and exactly the same label set), the resulting MetricFamily will contain
 // duplicate Metric proto messages. Similar is true for duplicate label
 // names. Checks for duplicates have to be performed separately, if required.
+// Also note that neither the metrics within each MetricFamily are sorted nor
+// the label pairs within each Metric. Sorting is not required for the most
+// frequent use of this method, which is sample ingestion in the Prometheus
+// server. However, for presentation purposes, you might want to sort the
+// metrics, and in some cases, you must sort the labels, e.g. for consumption by
+// the metric family injection hook of the Prometheus registry.
 //
-// Summaries are a rather special beast. You would probably not use them in the
-// simple text format anyway. This method can deal with summaries if they are
-// presented in exactly the way the text.Create function creates them.
+// Summaries and histograms are rather special beasts. You would probably not
+// use them in the simple text format anyway. This method can deal with
+// summaries and histograms if they are presented in exactly the way the
+// text.Create function creates them.
 //
 // This method must not be called concurrently. If you want to parse different
 // input concurrently, instantiate a separate Parser for each goroutine.
-func (p *Parser) TextToMetricFamilies(in io.Reader) (map[string]*dto.MetricFamily, error) {
+func (p *TextParser) TextToMetricFamilies(in io.Reader) (map[string]*dto.MetricFamily, error) {
 	p.reset(in)
 	for nextState := p.startOfLine; nextState != nil; nextState = nextState() {
 		// Magic happens here...
@@ -104,7 +110,7 @@ func (p *Parser) TextToMetricFamilies(in io.Reader) (map[string]*dto.MetricFamil
 	return p.metricFamiliesByName, p.err
 }
 
-func (p *Parser) reset(in io.Reader) {
+func (p *TextParser) reset(in io.Reader) {
 	p.metricFamiliesByName = map[string]*dto.MetricFamily{}
 	if p.buf == nil {
 		p.buf = bufio.NewReader(in)
@@ -125,7 +131,7 @@ func (p *Parser) reset(in io.Reader) {
 
 // startOfLine represents the state where the next byte read from p.buf is the
 // start of a line (or whitespace leading up to it).
-func (p *Parser) startOfLine() stateFn {
+func (p *TextParser) startOfLine() stateFn {
 	p.lineCount++
 	if p.skipBlankTab(); p.err != nil {
 		// End of input reached. This is the only case where
@@ -144,7 +150,7 @@ func (p *Parser) startOfLine() stateFn {
 
 // startComment represents the state where the next byte read from p.buf is the
 // start of a comment (or whitespace leading up to it).
-func (p *Parser) startComment() stateFn {
+func (p *TextParser) startComment() stateFn {
 	if p.skipBlankTab(); p.err != nil {
 		return nil // Unexpected end of input.
 	}
@@ -205,7 +211,7 @@ func (p *Parser) startComment() stateFn {
 
 // readingMetricName represents the state where the last byte read (now in
 // p.currentByte) is the first byte of a metric name.
-func (p *Parser) readingMetricName() stateFn {
+func (p *TextParser) readingMetricName() stateFn {
 	if p.readTokenAsMetricName(); p.err != nil {
 		return nil
 	}
@@ -232,7 +238,7 @@ func (p *Parser) readingMetricName() stateFn {
 // readingLabels represents the state where the last byte read (now in
 // p.currentByte) is either the first byte of the label set (i.e. a '{'), or the
 // first byte of the value (otherwise).
-func (p *Parser) readingLabels() stateFn {
+func (p *TextParser) readingLabels() stateFn {
 	// Summaries/histograms are special. We have to reset the
 	// currentLabels map, currentQuantile and currentBucket before starting to
 	// read labels.
@@ -250,7 +256,7 @@ func (p *Parser) readingLabels() stateFn {
 
 // startLabelName represents the state where the next byte read from p.buf is
 // the start of a label name (or whitespace leading up to it).
-func (p *Parser) startLabelName() stateFn {
+func (p *TextParser) startLabelName() stateFn {
 	if p.skipBlankTab(); p.err != nil {
 		return nil // Unexpected end of input.
 	}
@@ -290,7 +296,7 @@ func (p *Parser) startLabelName() stateFn {
 
 // startLabelValue represents the state where the next byte read from p.buf is
 // the start of a (quoted) label value (or whitespace leading up to it).
-func (p *Parser) startLabelValue() stateFn {
+func (p *TextParser) startLabelValue() stateFn {
 	if p.skipBlankTab(); p.err != nil {
 		return nil // Unexpected end of input.
 	}
@@ -348,7 +354,7 @@ func (p *Parser) startLabelValue() stateFn {
 
 // readingValue represents the state where the last byte read (now in
 // p.currentByte) is the first byte of the sample value (i.e. a float).
-func (p *Parser) readingValue() stateFn {
+func (p *TextParser) readingValue() stateFn {
 	// When we are here, we have read all the labels, so for the
 	// special case of a summary/histogram, we can finally find out
 	// if the metric already exists.
@@ -436,7 +442,7 @@ func (p *Parser) readingValue() stateFn {
 
 // startTimestamp represents the state where the next byte read from p.buf is
 // the start of the timestamp (or whitespace leading up to it).
-func (p *Parser) startTimestamp() stateFn {
+func (p *TextParser) startTimestamp() stateFn {
 	if p.skipBlankTab(); p.err != nil {
 		return nil // Unexpected end of input.
 	}
@@ -462,7 +468,7 @@ func (p *Parser) startTimestamp() stateFn {
 
 // readingHelp represents the state where the last byte read (now in
 // p.currentByte) is the first byte of the docstring after 'HELP'.
-func (p *Parser) readingHelp() stateFn {
+func (p *TextParser) readingHelp() stateFn {
 	if p.currentMF.Help != nil {
 		p.parseError(fmt.Sprintf("second HELP line for metric name %q", p.currentMF.GetName()))
 		return nil
@@ -477,7 +483,7 @@ func (p *Parser) readingHelp() stateFn {
 
 // readingType represents the state where the last byte read (now in
 // p.currentByte) is the first byte of the type hint after 'HELP'.
-func (p *Parser) readingType() stateFn {
+func (p *TextParser) readingType() stateFn {
 	if p.currentMF.Type != nil {
 		p.parseError(fmt.Sprintf("second TYPE line for metric name %q, or TYPE reported after samples", p.currentMF.GetName()))
 		return nil
@@ -497,7 +503,7 @@ func (p *Parser) readingType() stateFn {
 
 // parseError sets p.err to a ParseError at the current line with the given
 // message.
-func (p *Parser) parseError(msg string) {
+func (p *TextParser) parseError(msg string) {
 	p.err = ParseError{
 		Line: p.lineCount,
 		Msg:  msg,
@@ -506,7 +512,7 @@ func (p *Parser) parseError(msg string) {
 
 // skipBlankTab reads (and discards) bytes from p.buf until it encounters a byte
 // that is neither ' ' nor '\t'. That byte is left in p.currentByte.
-func (p *Parser) skipBlankTab() {
+func (p *TextParser) skipBlankTab() {
 	for {
 		if p.currentByte, p.err = p.buf.ReadByte(); p.err != nil || !isBlankOrTab(p.currentByte) {
 			return
@@ -516,7 +522,7 @@ func (p *Parser) skipBlankTab() {
 
 // skipBlankTabIfCurrentBlankTab works exactly as skipBlankTab but doesn't do
 // anything if p.currentByte is neither ' ' nor '\t'.
-func (p *Parser) skipBlankTabIfCurrentBlankTab() {
+func (p *TextParser) skipBlankTabIfCurrentBlankTab() {
 	if isBlankOrTab(p.currentByte) {
 		p.skipBlankTab()
 	}
@@ -526,7 +532,7 @@ func (p *Parser) skipBlankTabIfCurrentBlankTab() {
 // first byte considered is the byte already read (now in p.currentByte).  The
 // first whitespace byte encountered is still copied into p.currentByte, but not
 // into p.currentToken.
-func (p *Parser) readTokenUntilWhitespace() {
+func (p *TextParser) readTokenUntilWhitespace() {
 	p.currentToken.Reset()
 	for p.err == nil && !isBlankOrTab(p.currentByte) && p.currentByte != '\n' {
 		p.currentToken.WriteByte(p.currentByte)
@@ -540,7 +546,7 @@ func (p *Parser) readTokenUntilWhitespace() {
 // p.currentToken. If recognizeEscapeSequence is true, two escape sequences are
 // recognized: '\\' tranlates into '\', and '\n' into a line-feed character. All
 // other escape sequences are invalid and cause an error.
-func (p *Parser) readTokenUntilNewline(recognizeEscapeSequence bool) {
+func (p *TextParser) readTokenUntilNewline(recognizeEscapeSequence bool) {
 	p.currentToken.Reset()
 	escaped := false
 	for p.err == nil {
@@ -573,7 +579,7 @@ func (p *Parser) readTokenUntilNewline(recognizeEscapeSequence bool) {
 // The first byte considered is the byte already read (now in p.currentByte).
 // The first byte not part of a metric name is still copied into p.currentByte,
 // but not into p.currentToken.
-func (p *Parser) readTokenAsMetricName() {
+func (p *TextParser) readTokenAsMetricName() {
 	p.currentToken.Reset()
 	if !isValidMetricNameStart(p.currentByte) {
 		return
@@ -591,7 +597,7 @@ func (p *Parser) readTokenAsMetricName() {
 // The first byte considered is the byte already read (now in p.currentByte).
 // The first byte not part of a label name is still copied into p.currentByte,
 // but not into p.currentToken.
-func (p *Parser) readTokenAsLabelName() {
+func (p *TextParser) readTokenAsLabelName() {
 	p.currentToken.Reset()
 	if !isValidLabelNameStart(p.currentByte) {
 		return
@@ -610,7 +616,7 @@ func (p *Parser) readTokenAsLabelName() {
 // last read byte in p.currentByte, this method ignores p.currentByte and starts
 // with reading a new byte from p.buf. The first byte not part of a label value
 // is still copied into p.currentByte, but not into p.currentToken.
-func (p *Parser) readTokenAsLabelValue() {
+func (p *TextParser) readTokenAsLabelValue() {
 	p.currentToken.Reset()
 	escaped := false
 	for {
@@ -644,7 +650,7 @@ func (p *Parser) readTokenAsLabelValue() {
 	}
 }
 
-func (p *Parser) setOrCreateCurrentMF() {
+func (p *TextParser) setOrCreateCurrentMF() {
 	p.currentIsSummaryCount = false
 	p.currentIsSummarySum = false
 	p.currentIsHistogramCount = false

+ 10 - 12
Godeps/_workspace/src/github.com/prometheus/client_golang/text/parse_test.go → Godeps/_workspace/src/github.com/prometheus/common/expfmt/text_parse_test.go

@@ -11,7 +11,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package text
+package expfmt
 
 import (
 	"math"
@@ -22,9 +22,7 @@ import (
 	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
 )
 
-var parser Parser
-
-func testParse(t testing.TB) {
+func testTextParse(t testing.TB) {
 	var scenarios = []struct {
 		in  string
 		out []*dto.MetricFamily
@@ -419,17 +417,17 @@ request_duration_microseconds_count 2693
 	}
 }
 
-func TestParse(t *testing.T) {
-	testParse(t)
+func TestTextParse(t *testing.T) {
+	testTextParse(t)
 }
 
-func BenchmarkParse(b *testing.B) {
+func BenchmarkTextParse(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		testParse(b)
+		testTextParse(b)
 	}
 }
 
-func testParseError(t testing.TB) {
+func testTextParseError(t testing.TB) {
 	var scenarios = []struct {
 		in  string
 		err string
@@ -577,12 +575,12 @@ metric_bucket{le="bla"} 3.14
 
 }
 
-func TestParseError(t *testing.T) {
-	testParseError(t)
+func TestTextParseError(t *testing.T) {
+	testTextParseError(t)
 }
 
 func BenchmarkParseError(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		testParseError(b)
+		testTextParseError(b)
 	}
 }

+ 109 - 0
Godeps/_workspace/src/github.com/prometheus/common/model/alert.go

@@ -0,0 +1,109 @@
+// Copyright 2013 The Prometheus Authors
+// 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.
+
+package model
+
+import (
+	"fmt"
+	"time"
+)
+
+type AlertStatus string
+
+const (
+	AlertFiring   AlertStatus = "firing"
+	AlertResolved AlertStatus = "resolved"
+)
+
+// Alert is a generic representation of an alert in the Prometheus eco-system.
+type Alert struct {
+	// Label value pairs for purpose of aggregation, matching, and disposition
+	// dispatching. This must minimally include an "alertname" label.
+	Labels LabelSet `json:"labels"`
+
+	// Extra key/value information which does not define alert identity.
+	Annotations LabelSet `json:"annotations"`
+
+	// The known time range for this alert. Both ends are optional.
+	StartsAt time.Time `json:"startsAt,omitempty"`
+	EndsAt   time.Time `json:"endsAt,omitempty"`
+}
+
+// Name returns the name of the alert. It is equivalent to the "alertname" label.
+func (a *Alert) Name() string {
+	return string(a.Labels[AlertNameLabel])
+}
+
+// Fingerprint returns a unique hash for the alert. It is equivalent to
+// the fingerprint of the alert's label set.
+func (a *Alert) Fingerprint() Fingerprint {
+	return a.Labels.Fingerprint()
+}
+
+func (a *Alert) String() string {
+	s := fmt.Sprintf("%s[%s]", a.Name(), a.Fingerprint().String()[:7])
+	if a.Resolved() {
+		return s + "[resolved]"
+	}
+	return s + "[active]"
+}
+
+// Resolved returns true iff the activity interval ended in the past.
+func (a *Alert) Resolved() bool {
+	if a.EndsAt.IsZero() {
+		return false
+	}
+	return !a.EndsAt.After(time.Now())
+}
+
+// Status returns the status of the alert.
+func (a *Alert) Status() AlertStatus {
+	if a.Resolved() {
+		return AlertResolved
+	}
+	return AlertFiring
+}
+
+// Alert is a list of alerts that can be sorted in chronological order.
+type Alerts []*Alert
+
+func (as Alerts) Len() int      { return len(as) }
+func (as Alerts) Swap(i, j int) { as[i], as[j] = as[j], as[i] }
+
+func (as Alerts) Less(i, j int) bool {
+	if as[i].StartsAt.Before(as[j].StartsAt) {
+		return true
+	}
+	if as[i].EndsAt.Before(as[j].EndsAt) {
+		return true
+	}
+	return as[i].Fingerprint() < as[j].Fingerprint()
+}
+
+// HasFiring returns true iff one of the alerts is not resolved.
+func (as Alerts) HasFiring() bool {
+	for _, a := range as {
+		if !a.Resolved() {
+			return true
+		}
+	}
+	return false
+}
+
+// Status returns StatusFiring iff at least one of the alerts is firing.
+func (as Alerts) Status() AlertStatus {
+	if as.HasFiring() {
+		return AlertFiring
+	}
+	return AlertResolved
+}

+ 12 - 17
Godeps/_workspace/src/github.com/prometheus/client_golang/model/fingerprinting.go → Godeps/_workspace/src/github.com/prometheus/common/model/fingerprinting.go

@@ -22,28 +22,23 @@ import (
 // For our purposes, FNV-1A 64-bit is used.
 type Fingerprint uint64
 
-func (f Fingerprint) String() string {
-	return fmt.Sprintf("%016x", uint64(f))
-}
-
-// Less implements sort.Interface.
-func (f Fingerprint) Less(o Fingerprint) bool {
-	return f < o
-}
-
-// Equal implements sort.Interface.
-func (f Fingerprint) Equal(o Fingerprint) bool {
-	return f == o
+// FingerprintFromString transforms a string representation into a Fingerprint.
+func FingerprintFromString(s string) (Fingerprint, error) {
+	num, err := strconv.ParseUint(s, 16, 64)
+	return Fingerprint(num), err
 }
 
-// LoadFromString transforms a string representation into a Fingerprint.
-func (f *Fingerprint) LoadFromString(s string) error {
+// ParseFingerprint parses the input string into a fingerprint.
+func ParseFingerprint(s string) (Fingerprint, error) {
 	num, err := strconv.ParseUint(s, 16, 64)
 	if err != nil {
-		return err
+		return 0, err
 	}
-	*f = Fingerprint(num)
-	return nil
+	return Fingerprint(num), nil
+}
+
+func (f Fingerprint) String() string {
+	return fmt.Sprintf("%016x", uint64(f))
 }
 
 // Fingerprints represents a collection of Fingerprint subject to a given

+ 94 - 10
Godeps/_workspace/src/github.com/prometheus/client_golang/model/labelname.go → Godeps/_workspace/src/github.com/prometheus/common/model/labels.go

@@ -14,27 +14,36 @@
 package model
 
 import (
+	"encoding/json"
 	"fmt"
 	"regexp"
+	"sort"
 	"strings"
 )
 
 const (
-	// ExporterLabelPrefix is the label name prefix to prepend if a
-	// synthetic label is already present in the exported metrics.
-	ExporterLabelPrefix LabelName = "exporter_"
+	// AlertNameLabel is the name of the label containing the an alert's name.
+	AlertNameLabel = "alertname"
+
+	// ExportedLabelPrefix is the prefix to prepend to the label names present in
+	// exported metrics if a label of the same name is added by the server.
+	ExportedLabelPrefix = "exported_"
 
 	// MetricNameLabel is the label name indicating the metric name of a
 	// timeseries.
-	MetricNameLabel LabelName = "__name__"
+	MetricNameLabel = "__name__"
+
+	// SchemeLabel is the name of the label that holds the scheme on which to
+	// scrape a target.
+	SchemeLabel = "__scheme__"
 
 	// AddressLabel is the name of the label that holds the address of
 	// a scrape target.
-	AddressLabel LabelName = "__address__"
+	AddressLabel = "__address__"
 
 	// MetricsPathLabel is the name of the label that holds the path on which to
 	// scrape a target.
-	MetricsPathLabel LabelName = "__metrics_path__"
+	MetricsPathLabel = "__metrics_path__"
 
 	// ReservedLabelPrefix is a prefix which is not legal in user-supplied
 	// label names.
@@ -45,12 +54,22 @@ const (
 	// will not be attached to time series.
 	MetaLabelPrefix = "__meta_"
 
+	// TmpLabelPrefix is a prefix for temporary labels as part of relabelling.
+	// Labels with this prefix are used for intermediate label processing and
+	// will not be attached to time series. This is reserved for use in
+	// Prometheus configuration files by users.
+	TmpLabelPrefix = "__tmp_"
+
+	// ParamLabelPrefix is a prefix for labels that provide URL parameters
+	// used to scrape a target.
+	ParamLabelPrefix = "__param_"
+
 	// JobLabel is the label name indicating the job from which a timeseries
 	// was scraped.
-	JobLabel LabelName = "job"
+	JobLabel = "job"
 
 	// InstanceLabel is the label name used for the instance label.
-	InstanceLabel LabelName = "instance"
+	InstanceLabel = "instance"
 
 	// BucketLabel is used for the label that defines the upper bound of a
 	// bucket of a histogram ("le" -> "less or equal").
@@ -61,7 +80,8 @@ const (
 	QuantileLabel = "quantile"
 )
 
-var labelNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$")
+// LabelNameRE is a regular expression matching valid label names.
+var LabelNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$")
 
 // A LabelName is a key for a LabelSet or Metric.  It has a value associated
 // therewith.
@@ -73,7 +93,20 @@ func (ln *LabelName) UnmarshalYAML(unmarshal func(interface{}) error) error {
 	if err := unmarshal(&s); err != nil {
 		return err
 	}
-	if !labelNameRE.MatchString(s) {
+	if !LabelNameRE.MatchString(s) {
+		return fmt.Errorf("%q is not a valid label name", s)
+	}
+	*ln = LabelName(s)
+	return nil
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+func (ln *LabelName) UnmarshalJSON(b []byte) error {
+	var s string
+	if err := json.Unmarshal(b, &s); err != nil {
+		return err
+	}
+	if !LabelNameRE.MatchString(s) {
 		return fmt.Errorf("%q is not a valid label name", s)
 	}
 	*ln = LabelName(s)
@@ -102,3 +135,54 @@ func (l LabelNames) String() string {
 	}
 	return strings.Join(labelStrings, ", ")
 }
+
+// A LabelValue is an associated value for a LabelName.
+type LabelValue string
+
+// LabelValues is a sortable LabelValue slice. It implements sort.Interface.
+type LabelValues []LabelValue
+
+func (l LabelValues) Len() int {
+	return len(l)
+}
+
+func (l LabelValues) Less(i, j int) bool {
+	return sort.StringsAreSorted([]string{string(l[i]), string(l[j])})
+}
+
+func (l LabelValues) Swap(i, j int) {
+	l[i], l[j] = l[j], l[i]
+}
+
+// LabelPair pairs a name with a value.
+type LabelPair struct {
+	Name  LabelName
+	Value LabelValue
+}
+
+// LabelPairs is a sortable slice of LabelPair pointers. It implements
+// sort.Interface.
+type LabelPairs []*LabelPair
+
+func (l LabelPairs) Len() int {
+	return len(l)
+}
+
+func (l LabelPairs) Less(i, j int) bool {
+	switch {
+	case l[i].Name > l[j].Name:
+		return false
+	case l[i].Name < l[j].Name:
+		return true
+	case l[i].Value > l[j].Value:
+		return false
+	case l[i].Value < l[j].Value:
+		return true
+	default:
+		return false
+	}
+}
+
+func (l LabelPairs) Swap(i, j int) {
+	l[i], l[j] = l[j], l[i]
+}

+ 36 - 0
Godeps/_workspace/src/github.com/prometheus/client_golang/model/labelvalue_test.go → Godeps/_workspace/src/github.com/prometheus/common/model/labels_test.go

@@ -18,6 +18,42 @@ import (
 	"testing"
 )
 
+func testLabelNames(t testing.TB) {
+	var scenarios = []struct {
+		in  LabelNames
+		out LabelNames
+	}{
+		{
+			in:  LabelNames{"ZZZ", "zzz"},
+			out: LabelNames{"ZZZ", "zzz"},
+		},
+		{
+			in:  LabelNames{"aaa", "AAA"},
+			out: LabelNames{"AAA", "aaa"},
+		},
+	}
+
+	for i, scenario := range scenarios {
+		sort.Sort(scenario.in)
+
+		for j, expected := range scenario.out {
+			if expected != scenario.in[j] {
+				t.Errorf("%d.%d expected %s, got %s", i, j, expected, scenario.in[j])
+			}
+		}
+	}
+}
+
+func TestLabelNames(t *testing.T) {
+	testLabelNames(t)
+}
+
+func BenchmarkLabelNames(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		testLabelNames(b)
+	}
+}
+
 func testLabelValues(t testing.TB) {
 	var scenarios = []struct {
 		in  LabelValues

+ 153 - 0
Godeps/_workspace/src/github.com/prometheus/common/model/labelset.go

@@ -0,0 +1,153 @@
+// Copyright 2013 The Prometheus Authors
+// 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.
+
+package model
+
+import (
+	"encoding/json"
+	"fmt"
+	"sort"
+	"strings"
+)
+
+// A LabelSet is a collection of LabelName and LabelValue pairs.  The LabelSet
+// may be fully-qualified down to the point where it may resolve to a single
+// Metric in the data store or not.  All operations that occur within the realm
+// of a LabelSet can emit a vector of Metric entities to which the LabelSet may
+// match.
+type LabelSet map[LabelName]LabelValue
+
+func (ls LabelSet) Equal(o LabelSet) bool {
+	if len(ls) != len(o) {
+		return false
+	}
+	for ln, lv := range ls {
+		olv, ok := o[ln]
+		if !ok {
+			return false
+		}
+		if olv != lv {
+			return false
+		}
+	}
+	return true
+}
+
+// Before compares the metrics, using the following criteria:
+//
+// If m has fewer labels than o, it is before o. If it has more, it is not.
+//
+// If the number of labels is the same, the superset of all label names is
+// sorted alphanumerically. The first differing label pair found in that order
+// determines the outcome: If the label does not exist at all in m, then m is
+// before o, and vice versa. Otherwise the label value is compared
+// alphanumerically.
+//
+// If m and o are equal, the method returns false.
+func (ls LabelSet) Before(o LabelSet) bool {
+	if len(ls) < len(o) {
+		return true
+	}
+	if len(ls) > len(o) {
+		return false
+	}
+
+	lns := make(LabelNames, 0, len(ls)+len(o))
+	for ln := range ls {
+		lns = append(lns, ln)
+	}
+	for ln := range o {
+		lns = append(lns, ln)
+	}
+	// It's probably not worth it to de-dup lns.
+	sort.Sort(lns)
+	for _, ln := range lns {
+		mlv, ok := ls[ln]
+		if !ok {
+			return true
+		}
+		olv, ok := o[ln]
+		if !ok {
+			return false
+		}
+		if mlv < olv {
+			return true
+		}
+		if mlv > olv {
+			return false
+		}
+	}
+	return false
+}
+
+func (ls LabelSet) Clone() LabelSet {
+	lsn := make(LabelSet, len(ls))
+	for ln, lv := range ls {
+		lsn[ln] = lv
+	}
+	return lsn
+}
+
+// Merge is a helper function to non-destructively merge two label sets.
+func (l LabelSet) Merge(other LabelSet) LabelSet {
+	result := make(LabelSet, len(l))
+
+	for k, v := range l {
+		result[k] = v
+	}
+
+	for k, v := range other {
+		result[k] = v
+	}
+
+	return result
+}
+
+func (l LabelSet) String() string {
+	lstrs := make([]string, 0, len(l))
+	for l, v := range l {
+		lstrs = append(lstrs, fmt.Sprintf("%s=%q", l, v))
+	}
+
+	sort.Strings(lstrs)
+	return fmt.Sprintf("{%s}", strings.Join(lstrs, ", "))
+}
+
+// Fingerprint returns the LabelSet's fingerprint.
+func (ls LabelSet) Fingerprint() Fingerprint {
+	return labelSetToFingerprint(ls)
+}
+
+// FastFingerprint returns the LabelSet's Fingerprint calculated by a faster hashing
+// algorithm, which is, however, more susceptible to hash collisions.
+func (ls LabelSet) FastFingerprint() Fingerprint {
+	return labelSetToFastFingerprint(ls)
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+func (l *LabelSet) UnmarshalJSON(b []byte) error {
+	var m map[LabelName]LabelValue
+	if err := json.Unmarshal(b, &m); err != nil {
+		return err
+	}
+	// encoding/json only unmarshals maps of the form map[string]T. It treats
+	// LabelName as a string and does not call its UnmarshalJSON method.
+	// Thus, we have to replicate the behavior here.
+	for ln := range m {
+		if !LabelNameRE.MatchString(string(ln)) {
+			return fmt.Errorf("%q is not a valid label name", ln)
+		}
+	}
+	*l = LabelSet(m)
+	return nil
+}

+ 81 - 0
Godeps/_workspace/src/github.com/prometheus/common/model/metric.go

@@ -0,0 +1,81 @@
+// Copyright 2013 The Prometheus Authors
+// 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.
+
+package model
+
+import (
+	"fmt"
+	"sort"
+	"strings"
+)
+
+var separator = []byte{0}
+
+// A Metric is similar to a LabelSet, but the key difference is that a Metric is
+// a singleton and refers to one and only one stream of samples.
+type Metric LabelSet
+
+// Equal compares the metrics.
+func (m Metric) Equal(o Metric) bool {
+	return LabelSet(m).Equal(LabelSet(o))
+}
+
+// Before compares the metrics' underlying label sets.
+func (m Metric) Before(o Metric) bool {
+	return LabelSet(m).Before(LabelSet(o))
+}
+
+// Clone returns a copy of the Metric.
+func (m Metric) Clone() Metric {
+	clone := Metric{}
+	for k, v := range m {
+		clone[k] = v
+	}
+	return clone
+}
+
+func (m Metric) String() string {
+	metricName, hasName := m[MetricNameLabel]
+	numLabels := len(m) - 1
+	if !hasName {
+		numLabels = len(m)
+	}
+	labelStrings := make([]string, 0, numLabels)
+	for label, value := range m {
+		if label != MetricNameLabel {
+			labelStrings = append(labelStrings, fmt.Sprintf("%s=%q", label, value))
+		}
+	}
+
+	switch numLabels {
+	case 0:
+		if hasName {
+			return string(metricName)
+		}
+		return "{}"
+	default:
+		sort.Strings(labelStrings)
+		return fmt.Sprintf("%s{%s}", metricName, strings.Join(labelStrings, ", "))
+	}
+}
+
+// Fingerprint returns a Metric's Fingerprint.
+func (m Metric) Fingerprint() Fingerprint {
+	return LabelSet(m).Fingerprint()
+}
+
+// FastFingerprint returns a Metric's Fingerprint calculated by a faster hashing
+// algorithm, which is, however, more susceptible to hash collisions.
+func (m Metric) FastFingerprint() Fingerprint {
+	return LabelSet(m).FastFingerprint()
+}

+ 12 - 59
Godeps/_workspace/src/github.com/prometheus/client_golang/model/metric_test.go → Godeps/_workspace/src/github.com/prometheus/common/model/metric_test.go

@@ -17,17 +17,17 @@ import "testing"
 
 func testMetric(t testing.TB) {
 	var scenarios = []struct {
-		input           Metric
+		input           LabelSet
 		fingerprint     Fingerprint
 		fastFingerprint Fingerprint
 	}{
 		{
-			input:           Metric{},
+			input:           LabelSet{},
 			fingerprint:     14695981039346656037,
 			fastFingerprint: 14695981039346656037,
 		},
 		{
-			input: Metric{
+			input: LabelSet{
 				"first_name":   "electro",
 				"occupation":   "robot",
 				"manufacturer": "westinghouse",
@@ -36,14 +36,14 @@ func testMetric(t testing.TB) {
 			fastFingerprint: 11310079640881077873,
 		},
 		{
-			input: Metric{
+			input: LabelSet{
 				"x": "y",
 			},
 			fingerprint:     8241431561484471700,
 			fastFingerprint: 13948396922932177635,
 		},
 		{
-			input: Metric{
+			input: LabelSet{
 				"a": "bb",
 				"b": "c",
 			},
@@ -51,7 +51,7 @@ func testMetric(t testing.TB) {
 			fastFingerprint: 3198632812309449502,
 		},
 		{
-			input: Metric{
+			input: LabelSet{
 				"a":  "b",
 				"bb": "c",
 			},
@@ -61,11 +61,13 @@ func testMetric(t testing.TB) {
 	}
 
 	for i, scenario := range scenarios {
-		if scenario.fingerprint != scenario.input.Fingerprint() {
-			t.Errorf("%d. expected %d, got %d", i, scenario.fingerprint, scenario.input.Fingerprint())
+		input := Metric(scenario.input)
+
+		if scenario.fingerprint != input.Fingerprint() {
+			t.Errorf("%d. expected %d, got %d", i, scenario.fingerprint, input.Fingerprint())
 		}
-		if scenario.fastFingerprint != scenario.input.FastFingerprint() {
-			t.Errorf("%d. expected %d, got %d", i, scenario.fastFingerprint, scenario.input.FastFingerprint())
+		if scenario.fastFingerprint != input.FastFingerprint() {
+			t.Errorf("%d. expected %d, got %d", i, scenario.fastFingerprint, input.FastFingerprint())
 		}
 	}
 }
@@ -79,52 +81,3 @@ func BenchmarkMetric(b *testing.B) {
 		testMetric(b)
 	}
 }
-
-func TestCOWMetric(t *testing.T) {
-	testMetric := Metric{
-		"to_delete": "test1",
-		"to_change": "test2",
-	}
-
-	scenarios := []struct {
-		fn  func(*COWMetric)
-		out Metric
-	}{
-		{
-			fn: func(cm *COWMetric) {
-				cm.Delete("to_delete")
-			},
-			out: Metric{
-				"to_change": "test2",
-			},
-		},
-		{
-			fn: func(cm *COWMetric) {
-				cm.Set("to_change", "changed")
-			},
-			out: Metric{
-				"to_delete": "test1",
-				"to_change": "changed",
-			},
-		},
-	}
-
-	for i, s := range scenarios {
-		orig := testMetric.Clone()
-		cm := &COWMetric{
-			Metric: orig,
-		}
-
-		s.fn(cm)
-
-		// Test that the original metric was not modified.
-		if !orig.Equal(testMetric) {
-			t.Fatalf("%d. original metric changed; expected %v, got %v", i, testMetric, orig)
-		}
-
-		// Test that the new metric has the right changes.
-		if !cm.Metric.Equal(s.out) {
-			t.Fatalf("%d. copied metric doesn't contain expected changes; expected %v, got %v", i, s.out, cm.Metric)
-		}
-	}
-}

+ 2 - 1
Godeps/_workspace/src/github.com/prometheus/client_golang/model/model.go → Godeps/_workspace/src/github.com/prometheus/common/model/model.go

@@ -11,5 +11,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Package model contains core representation of Prometheus client primitives.
+// Package model contains common data structures that are shared across
+// Prometheus componenets and libraries.
 package model

+ 12 - 12
Godeps/_workspace/src/github.com/prometheus/client_golang/model/signature.go → Godeps/_workspace/src/github.com/prometheus/common/model/signature.go

@@ -80,15 +80,15 @@ func LabelsToSignature(labels map[string]string) uint64 {
 	return hb.h.Sum64()
 }
 
-// metricToFingerprint works exactly as LabelsToSignature but takes a Metric as
+// labelSetToFingerprint works exactly as LabelsToSignature but takes a LabelSet as
 // parameter (rather than a label map) and returns a Fingerprint.
-func metricToFingerprint(m Metric) Fingerprint {
-	if len(m) == 0 {
+func labelSetToFingerprint(ls LabelSet) Fingerprint {
+	if len(ls) == 0 {
 		return Fingerprint(emptyLabelSignature)
 	}
 
-	labelNames := make(LabelNames, 0, len(m))
-	for labelName := range m {
+	labelNames := make(LabelNames, 0, len(ls))
+	for labelName := range ls {
 		labelNames = append(labelNames, labelName)
 	}
 	sort.Sort(labelNames)
@@ -99,7 +99,7 @@ func metricToFingerprint(m Metric) Fingerprint {
 	for _, labelName := range labelNames {
 		hb.b.WriteString(string(labelName))
 		hb.b.WriteByte(SeparatorByte)
-		hb.b.WriteString(string(m[labelName]))
+		hb.b.WriteString(string(ls[labelName]))
 		hb.b.WriteByte(SeparatorByte)
 		hb.h.Write(hb.b.Bytes())
 		hb.b.Reset()
@@ -107,11 +107,11 @@ func metricToFingerprint(m Metric) Fingerprint {
 	return Fingerprint(hb.h.Sum64())
 }
 
-// metricToFastFingerprint works similar to metricToFingerprint but uses a
+// labelSetToFastFingerprint works similar to labelSetToFingerprint but uses a
 // faster and less allocation-heavy hash function, which is more susceptible to
 // create hash collisions. Therefore, collision detection should be applied.
-func metricToFastFingerprint(m Metric) Fingerprint {
-	if len(m) == 0 {
+func labelSetToFastFingerprint(ls LabelSet) Fingerprint {
+	if len(ls) == 0 {
 		return Fingerprint(emptyLabelSignature)
 	}
 
@@ -119,7 +119,7 @@ func metricToFastFingerprint(m Metric) Fingerprint {
 	hb := getHashAndBuf()
 	defer putHashAndBuf(hb)
 
-	for labelName, labelValue := range m {
+	for labelName, labelValue := range ls {
 		hb.b.WriteString(string(labelName))
 		hb.b.WriteByte(SeparatorByte)
 		hb.b.WriteString(string(labelValue))
@@ -135,12 +135,12 @@ func metricToFastFingerprint(m Metric) Fingerprint {
 // parameter (rather than a label map) and only includes the labels with the
 // specified LabelNames into the signature calculation. The labels passed in
 // will be sorted by this function.
-func SignatureForLabels(m Metric, labels LabelNames) uint64 {
+func SignatureForLabels(m Metric, labels ...LabelName) uint64 {
 	if len(m) == 0 || len(labels) == 0 {
 		return emptyLabelSignature
 	}
 
-	sort.Sort(labels)
+	sort.Sort(LabelNames(labels))
 
 	hb := getHashAndBuf()
 	defer putHashAndBuf(hb)

+ 30 - 30
Godeps/_workspace/src/github.com/prometheus/client_golang/model/signature_test.go → Godeps/_workspace/src/github.com/prometheus/common/model/signature_test.go

@@ -45,21 +45,21 @@ func TestLabelsToSignature(t *testing.T) {
 
 func TestMetricToFingerprint(t *testing.T) {
 	var scenarios = []struct {
-		in  Metric
+		in  LabelSet
 		out Fingerprint
 	}{
 		{
-			in:  Metric{},
+			in:  LabelSet{},
 			out: 14695981039346656037,
 		},
 		{
-			in:  Metric{"name": "garland, briggs", "fear": "love is not enough"},
+			in:  LabelSet{"name": "garland, briggs", "fear": "love is not enough"},
 			out: 5799056148416392346,
 		},
 	}
 
 	for i, scenario := range scenarios {
-		actual := metricToFingerprint(scenario.in)
+		actual := labelSetToFingerprint(scenario.in)
 
 		if actual != scenario.out {
 			t.Errorf("%d. expected %d, got %d", i, scenario.out, actual)
@@ -69,21 +69,21 @@ func TestMetricToFingerprint(t *testing.T) {
 
 func TestMetricToFastFingerprint(t *testing.T) {
 	var scenarios = []struct {
-		in  Metric
+		in  LabelSet
 		out Fingerprint
 	}{
 		{
-			in:  Metric{},
+			in:  LabelSet{},
 			out: 14695981039346656037,
 		},
 		{
-			in:  Metric{"name": "garland, briggs", "fear": "love is not enough"},
+			in:  LabelSet{"name": "garland, briggs", "fear": "love is not enough"},
 			out: 12952432476264840823,
 		},
 	}
 
 	for i, scenario := range scenarios {
-		actual := metricToFastFingerprint(scenario.in)
+		actual := labelSetToFastFingerprint(scenario.in)
 
 		if actual != scenario.out {
 			t.Errorf("%d. expected %d, got %d", i, scenario.out, actual)
@@ -125,7 +125,7 @@ func TestSignatureForLabels(t *testing.T) {
 	}
 
 	for i, scenario := range scenarios {
-		actual := SignatureForLabels(scenario.in, scenario.labels)
+		actual := SignatureForLabels(scenario.in, scenario.labels...)
 
 		if actual != scenario.out {
 			t.Errorf("%d. expected %d, got %d", i, scenario.out, actual)
@@ -199,10 +199,10 @@ func BenchmarkLabelToSignatureTriple(b *testing.B) {
 	benchmarkLabelToSignature(b, map[string]string{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 13843036195897128121)
 }
 
-func benchmarkMetricToFingerprint(b *testing.B, m Metric, e Fingerprint) {
+func benchmarkMetricToFingerprint(b *testing.B, ls LabelSet, e Fingerprint) {
 	for i := 0; i < b.N; i++ {
-		if a := metricToFingerprint(m); a != e {
-			b.Fatalf("expected signature of %d for %s, got %d", e, m, a)
+		if a := labelSetToFingerprint(ls); a != e {
+			b.Fatalf("expected signature of %d for %s, got %d", e, ls, a)
 		}
 	}
 }
@@ -212,21 +212,21 @@ func BenchmarkMetricToFingerprintScalar(b *testing.B) {
 }
 
 func BenchmarkMetricToFingerprintSingle(b *testing.B) {
-	benchmarkMetricToFingerprint(b, Metric{"first-label": "first-label-value"}, 5146282821936882169)
+	benchmarkMetricToFingerprint(b, LabelSet{"first-label": "first-label-value"}, 5146282821936882169)
 }
 
 func BenchmarkMetricToFingerprintDouble(b *testing.B) {
-	benchmarkMetricToFingerprint(b, Metric{"first-label": "first-label-value", "second-label": "second-label-value"}, 3195800080984914717)
+	benchmarkMetricToFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value"}, 3195800080984914717)
 }
 
 func BenchmarkMetricToFingerprintTriple(b *testing.B) {
-	benchmarkMetricToFingerprint(b, Metric{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 13843036195897128121)
+	benchmarkMetricToFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 13843036195897128121)
 }
 
-func benchmarkMetricToFastFingerprint(b *testing.B, m Metric, e Fingerprint) {
+func benchmarkMetricToFastFingerprint(b *testing.B, ls LabelSet, e Fingerprint) {
 	for i := 0; i < b.N; i++ {
-		if a := metricToFastFingerprint(m); a != e {
-			b.Fatalf("expected signature of %d for %s, got %d", e, m, a)
+		if a := labelSetToFastFingerprint(ls); a != e {
+			b.Fatalf("expected signature of %d for %s, got %d", e, ls, a)
 		}
 	}
 }
@@ -236,18 +236,18 @@ func BenchmarkMetricToFastFingerprintScalar(b *testing.B) {
 }
 
 func BenchmarkMetricToFastFingerprintSingle(b *testing.B) {
-	benchmarkMetricToFastFingerprint(b, Metric{"first-label": "first-label-value"}, 5147259542624943964)
+	benchmarkMetricToFastFingerprint(b, LabelSet{"first-label": "first-label-value"}, 5147259542624943964)
 }
 
 func BenchmarkMetricToFastFingerprintDouble(b *testing.B) {
-	benchmarkMetricToFastFingerprint(b, Metric{"first-label": "first-label-value", "second-label": "second-label-value"}, 18269973311206963528)
+	benchmarkMetricToFastFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value"}, 18269973311206963528)
 }
 
 func BenchmarkMetricToFastFingerprintTriple(b *testing.B) {
-	benchmarkMetricToFastFingerprint(b, Metric{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676)
+	benchmarkMetricToFastFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676)
 }
 
-func TestEmptyLabelSignature(t *testing.T) {
+func BenchmarkEmptyLabelSignature(b *testing.B) {
 	input := []map[string]string{nil, {}}
 
 	var ms runtime.MemStats
@@ -262,11 +262,11 @@ func TestEmptyLabelSignature(t *testing.T) {
 	runtime.ReadMemStats(&ms)
 
 	if got := ms.Alloc; alloc != got {
-		t.Fatal("expected LabelsToSignature with empty labels not to perform allocations")
+		b.Fatal("expected LabelsToSignature with empty labels not to perform allocations")
 	}
 }
 
-func benchmarkMetricToFastFingerprintConc(b *testing.B, m Metric, e Fingerprint, concLevel int) {
+func benchmarkMetricToFastFingerprintConc(b *testing.B, ls LabelSet, e Fingerprint, concLevel int) {
 	var start, end sync.WaitGroup
 	start.Add(1)
 	end.Add(concLevel)
@@ -275,8 +275,8 @@ func benchmarkMetricToFastFingerprintConc(b *testing.B, m Metric, e Fingerprint,
 		go func() {
 			start.Wait()
 			for j := b.N / concLevel; j >= 0; j-- {
-				if a := metricToFastFingerprint(m); a != e {
-					b.Fatalf("expected signature of %d for %s, got %d", e, m, a)
+				if a := labelSetToFastFingerprint(ls); a != e {
+					b.Fatalf("expected signature of %d for %s, got %d", e, ls, a)
 				}
 			}
 			end.Done()
@@ -288,17 +288,17 @@ func benchmarkMetricToFastFingerprintConc(b *testing.B, m Metric, e Fingerprint,
 }
 
 func BenchmarkMetricToFastFingerprintTripleConc1(b *testing.B) {
-	benchmarkMetricToFastFingerprintConc(b, Metric{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 1)
+	benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 1)
 }
 
 func BenchmarkMetricToFastFingerprintTripleConc2(b *testing.B) {
-	benchmarkMetricToFastFingerprintConc(b, Metric{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 2)
+	benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 2)
 }
 
 func BenchmarkMetricToFastFingerprintTripleConc4(b *testing.B) {
-	benchmarkMetricToFastFingerprintConc(b, Metric{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 4)
+	benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 4)
 }
 
 func BenchmarkMetricToFastFingerprintTripleConc8(b *testing.B) {
-	benchmarkMetricToFastFingerprintConc(b, Metric{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 8)
+	benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 8)
 }

+ 60 - 0
Godeps/_workspace/src/github.com/prometheus/common/model/silence.go

@@ -0,0 +1,60 @@
+// Copyright 2015 The Prometheus Authors
+// 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.
+
+package model
+
+import (
+	"encoding/json"
+	"fmt"
+	"regexp"
+	"time"
+)
+
+// Matcher describes a matches the value of a given label.
+type Matcher struct {
+	Name    LabelName `json:"name"`
+	Value   string    `json:"value"`
+	IsRegex bool      `json:"isRegex"`
+}
+
+func (m *Matcher) UnmarshalJSON(b []byte) error {
+	type plain Matcher
+	if err := json.Unmarshal(b, (*plain)(m)); err != nil {
+		return err
+	}
+
+	if len(m.Name) == 0 {
+		return fmt.Errorf("label name in matcher must not be empty")
+	}
+	if m.IsRegex {
+		if _, err := regexp.Compile(m.Value); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// Silence defines the representation of a silence definiton
+// in the Prometheus eco-system.
+type Silence struct {
+	ID uint64 `json:"id,omitempty"`
+
+	Matchers []*Matcher `json:"matchers"`
+
+	StartsAt time.Time `json:"startsAt"`
+	EndsAt   time.Time `json:"endsAt"`
+
+	CreatedAt time.Time `json:"createdAt,omitempty"`
+	CreatedBy string    `json:"createdBy"`
+	Comment   string    `json:"comment,omitempty"`
+}

+ 230 - 0
Godeps/_workspace/src/github.com/prometheus/common/model/time.go

@@ -0,0 +1,230 @@
+// Copyright 2013 The Prometheus Authors
+// 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.
+
+package model
+
+import (
+	"fmt"
+	"math"
+	"regexp"
+	"strconv"
+	"strings"
+	"time"
+)
+
+const (
+	// MinimumTick is the minimum supported time resolution. This has to be
+	// at least time.Second in order for the code below to work.
+	minimumTick = time.Millisecond
+	// second is the Time duration equivalent to one second.
+	second = int64(time.Second / minimumTick)
+	// The number of nanoseconds per minimum tick.
+	nanosPerTick = int64(minimumTick / time.Nanosecond)
+
+	// Earliest is the earliest Time representable. Handy for
+	// initializing a high watermark.
+	Earliest = Time(math.MinInt64)
+	// Latest is the latest Time representable. Handy for initializing
+	// a low watermark.
+	Latest = Time(math.MaxInt64)
+)
+
+// Time is the number of milliseconds since the epoch
+// (1970-01-01 00:00 UTC) excluding leap seconds.
+type Time int64
+
+// Interval describes and interval between two timestamps.
+type Interval struct {
+	Start, End Time
+}
+
+// Now returns the current time as a Time.
+func Now() Time {
+	return TimeFromUnixNano(time.Now().UnixNano())
+}
+
+// TimeFromUnix returns the Time equivalent to the Unix Time t
+// provided in seconds.
+func TimeFromUnix(t int64) Time {
+	return Time(t * second)
+}
+
+// TimeFromUnixNano returns the Time equivalent to the Unix Time
+// t provided in nanoseconds.
+func TimeFromUnixNano(t int64) Time {
+	return Time(t / nanosPerTick)
+}
+
+// Equal reports whether two Times represent the same instant.
+func (t Time) Equal(o Time) bool {
+	return t == o
+}
+
+// Before reports whether the Time t is before o.
+func (t Time) Before(o Time) bool {
+	return t < o
+}
+
+// After reports whether the Time t is after o.
+func (t Time) After(o Time) bool {
+	return t > o
+}
+
+// Add returns the Time t + d.
+func (t Time) Add(d time.Duration) Time {
+	return t + Time(d/minimumTick)
+}
+
+// Sub returns the Duration t - o.
+func (t Time) Sub(o Time) time.Duration {
+	return time.Duration(t-o) * minimumTick
+}
+
+// Time returns the time.Time representation of t.
+func (t Time) Time() time.Time {
+	return time.Unix(int64(t)/second, (int64(t)%second)*nanosPerTick)
+}
+
+// Unix returns t as a Unix time, the number of seconds elapsed
+// since January 1, 1970 UTC.
+func (t Time) Unix() int64 {
+	return int64(t) / second
+}
+
+// UnixNano returns t as a Unix time, the number of nanoseconds elapsed
+// since January 1, 1970 UTC.
+func (t Time) UnixNano() int64 {
+	return int64(t) * nanosPerTick
+}
+
+// The number of digits after the dot.
+var dotPrecision = int(math.Log10(float64(second)))
+
+// String returns a string representation of the Time.
+func (t Time) String() string {
+	return strconv.FormatFloat(float64(t)/float64(second), 'f', -1, 64)
+}
+
+// MarshalJSON implements the json.Marshaler interface.
+func (t Time) MarshalJSON() ([]byte, error) {
+	return []byte(t.String()), nil
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+func (t *Time) UnmarshalJSON(b []byte) error {
+	p := strings.Split(string(b), ".")
+	switch len(p) {
+	case 1:
+		v, err := strconv.ParseInt(string(p[0]), 10, 64)
+		if err != nil {
+			return err
+		}
+		*t = Time(v * second)
+
+	case 2:
+		v, err := strconv.ParseInt(string(p[0]), 10, 64)
+		if err != nil {
+			return err
+		}
+		v *= second
+
+		prec := dotPrecision - len(p[1])
+		if prec < 0 {
+			p[1] = p[1][:dotPrecision]
+		} else if prec > 0 {
+			p[1] = p[1] + strings.Repeat("0", prec)
+		}
+
+		va, err := strconv.ParseInt(p[1], 10, 32)
+		if err != nil {
+			return err
+		}
+
+		*t = Time(v + va)
+
+	default:
+		return fmt.Errorf("invalid time %q", string(b))
+	}
+	return nil
+}
+
+// Duration wraps time.Duration. It is used to parse the custom duration format
+// from YAML.
+// This type should not propagate beyond the scope of input/output processing.
+type Duration time.Duration
+
+// StringToDuration parses a string into a time.Duration, assuming that a year
+// a day always has 24h.
+func ParseDuration(durationStr string) (Duration, error) {
+	matches := durationRE.FindStringSubmatch(durationStr)
+	if len(matches) != 3 {
+		return 0, fmt.Errorf("not a valid duration string: %q", durationStr)
+	}
+	durSeconds, _ := strconv.Atoi(matches[1])
+	dur := time.Duration(durSeconds) * time.Second
+	unit := matches[2]
+	switch unit {
+	case "d":
+		dur *= 60 * 60 * 24
+	case "h":
+		dur *= 60 * 60
+	case "m":
+		dur *= 60
+	case "s":
+		dur *= 1
+	default:
+		return 0, fmt.Errorf("invalid time unit in duration string: %q", unit)
+	}
+	return Duration(dur), nil
+}
+
+var durationRE = regexp.MustCompile("^([0-9]+)([ywdhms]+)$")
+
+func (d Duration) String() string {
+	seconds := int64(time.Duration(d) / time.Second)
+	factors := map[string]int64{
+		"d": 60 * 60 * 24,
+		"h": 60 * 60,
+		"m": 60,
+		"s": 1,
+	}
+	unit := "s"
+	switch int64(0) {
+	case seconds % factors["d"]:
+		unit = "d"
+	case seconds % factors["h"]:
+		unit = "h"
+	case seconds % factors["m"]:
+		unit = "m"
+	}
+	return fmt.Sprintf("%v%v", seconds/factors[unit], unit)
+}
+
+// MarshalYAML implements the yaml.Marshaler interface.
+func (d Duration) MarshalYAML() (interface{}, error) {
+	return d.String(), nil
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (d *Duration) UnmarshalYAML(unmarshal func(interface{}) error) error {
+	var s string
+	if err := unmarshal(&s); err != nil {
+		return err
+	}
+	dur, err := ParseDuration(s)
+	if err != nil {
+		return err
+	}
+	*d = dur
+	return nil
+}

+ 13 - 13
Godeps/_workspace/src/github.com/prometheus/client_golang/model/timestamp_test.go → Godeps/_workspace/src/github.com/prometheus/common/model/time_test.go

@@ -15,13 +15,13 @@ package model
 
 import (
 	"testing"
-	native_time "time"
+	"time"
 )
 
 func TestComparators(t *testing.T) {
-	t1a := TimestampFromUnix(0)
-	t1b := TimestampFromUnix(0)
-	t2 := TimestampFromUnix(2*second - 1)
+	t1a := TimeFromUnix(0)
+	t1b := TimeFromUnix(0)
+	t2 := TimeFromUnix(2*second - 1)
 
 	if !t1a.Equal(t1b) {
 		t.Fatalf("Expected %s to be equal to %s", t1a, t1b)
@@ -45,21 +45,21 @@ func TestComparators(t *testing.T) {
 	}
 }
 
-func TestTimestampConversions(t *testing.T) {
+func TestTimeConversions(t *testing.T) {
 	unixSecs := int64(1136239445)
 	unixNsecs := int64(123456789)
-	unixNano := unixSecs*1000000000 + unixNsecs
+	unixNano := unixSecs*1e9 + unixNsecs
 
-	t1 := native_time.Unix(unixSecs, unixNsecs-unixNsecs%nanosPerTick)
-	t2 := native_time.Unix(unixSecs, unixNsecs)
+	t1 := time.Unix(unixSecs, unixNsecs-unixNsecs%nanosPerTick)
+	t2 := time.Unix(unixSecs, unixNsecs)
 
-	ts := TimestampFromUnixNano(unixNano)
+	ts := TimeFromUnixNano(unixNano)
 	if !ts.Time().Equal(t1) {
 		t.Fatalf("Expected %s, got %s", t1, ts.Time())
 	}
 
 	// Test available precision.
-	ts = TimestampFromTime(t2)
+	ts = TimeFromUnixNano(t2.UnixNano())
 	if !ts.Time().Equal(t1) {
 		t.Fatalf("Expected %s, got %s", t1, ts.Time())
 	}
@@ -70,10 +70,10 @@ func TestTimestampConversions(t *testing.T) {
 }
 
 func TestDuration(t *testing.T) {
-	duration := native_time.Second + native_time.Minute + native_time.Hour
-	goTime := native_time.Unix(1136239445, 0)
+	duration := time.Second + time.Minute + time.Hour
+	goTime := time.Unix(1136239445, 0)
 
-	ts := TimestampFromTime(goTime)
+	ts := TimeFromUnix(goTime.Unix())
 	if !goTime.Add(duration).Equal(ts.Add(duration).Time()) {
 		t.Fatalf("Expected %s to be equal to %s", goTime.Add(duration), ts.Add(duration))
 	}

+ 395 - 0
Godeps/_workspace/src/github.com/prometheus/common/model/value.go

@@ -0,0 +1,395 @@
+// Copyright 2013 The Prometheus Authors
+// 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.
+
+package model
+
+import (
+	"encoding/json"
+	"fmt"
+	"sort"
+	"strconv"
+	"strings"
+)
+
+// A SampleValue is a representation of a value for a given sample at a given
+// time.
+type SampleValue float64
+
+// MarshalJSON implements json.Marshaler.
+func (v SampleValue) MarshalJSON() ([]byte, error) {
+	return json.Marshal(v.String())
+}
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (v *SampleValue) UnmarshalJSON(b []byte) error {
+	if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
+		return fmt.Errorf("sample value must be a quoted string")
+	}
+	f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64)
+	if err != nil {
+		return err
+	}
+	*v = SampleValue(f)
+	return nil
+}
+
+func (v SampleValue) Equal(o SampleValue) bool {
+	return v == o
+}
+
+func (v SampleValue) String() string {
+	return strconv.FormatFloat(float64(v), 'f', -1, 64)
+}
+
+// SamplePair pairs a SampleValue with a Timestamp.
+type SamplePair struct {
+	Timestamp Time
+	Value     SampleValue
+}
+
+// MarshalJSON implements json.Marshaler.
+func (s SamplePair) MarshalJSON() ([]byte, error) {
+	t, err := json.Marshal(s.Timestamp)
+	if err != nil {
+		return nil, err
+	}
+	v, err := json.Marshal(s.Value)
+	if err != nil {
+		return nil, err
+	}
+	return []byte(fmt.Sprintf("[%s,%s]", t, v)), nil
+}
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (s *SamplePair) UnmarshalJSON(b []byte) error {
+	v := [...]json.Unmarshaler{&s.Timestamp, &s.Value}
+	return json.Unmarshal(b, &v)
+}
+
+// Equal returns true if this SamplePair and o have equal Values and equal
+// Timestamps.
+func (s *SamplePair) Equal(o *SamplePair) bool {
+	return s == o || (s.Value == o.Value && s.Timestamp.Equal(o.Timestamp))
+}
+
+func (s SamplePair) String() string {
+	return fmt.Sprintf("%s @[%s]", s.Value, s.Timestamp)
+}
+
+// Sample is a sample pair associated with a metric.
+type Sample struct {
+	Metric    Metric      `json:"metric"`
+	Value     SampleValue `json:"value"`
+	Timestamp Time        `json:"timestamp"`
+}
+
+// Equal compares first the metrics, then the timestamp, then the value.
+func (s *Sample) Equal(o *Sample) bool {
+	if s == o {
+		return true
+	}
+
+	if !s.Metric.Equal(o.Metric) {
+		return false
+	}
+	if !s.Timestamp.Equal(o.Timestamp) {
+		return false
+	}
+	if s.Value != o.Value {
+		return false
+	}
+
+	return true
+}
+
+func (s Sample) String() string {
+	return fmt.Sprintf("%s => %s", s.Metric, SamplePair{
+		Timestamp: s.Timestamp,
+		Value:     s.Value,
+	})
+}
+
+// MarshalJSON implements json.Marshaler.
+func (s Sample) MarshalJSON() ([]byte, error) {
+	v := struct {
+		Metric Metric     `json:"metric"`
+		Value  SamplePair `json:"value"`
+	}{
+		Metric: s.Metric,
+		Value: SamplePair{
+			Timestamp: s.Timestamp,
+			Value:     s.Value,
+		},
+	}
+
+	return json.Marshal(&v)
+}
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (s *Sample) UnmarshalJSON(b []byte) error {
+	v := struct {
+		Metric Metric     `json:"metric"`
+		Value  SamplePair `json:"value"`
+	}{
+		Metric: s.Metric,
+		Value: SamplePair{
+			Timestamp: s.Timestamp,
+			Value:     s.Value,
+		},
+	}
+
+	if err := json.Unmarshal(b, &v); err != nil {
+		return err
+	}
+
+	s.Metric = v.Metric
+	s.Timestamp = v.Value.Timestamp
+	s.Value = v.Value.Value
+
+	return nil
+}
+
+// Samples is a sortable Sample slice. It implements sort.Interface.
+type Samples []*Sample
+
+func (s Samples) Len() int {
+	return len(s)
+}
+
+// Less compares first the metrics, then the timestamp.
+func (s Samples) Less(i, j int) bool {
+	switch {
+	case s[i].Metric.Before(s[j].Metric):
+		return true
+	case s[j].Metric.Before(s[i].Metric):
+		return false
+	case s[i].Timestamp.Before(s[j].Timestamp):
+		return true
+	default:
+		return false
+	}
+}
+
+func (s Samples) Swap(i, j int) {
+	s[i], s[j] = s[j], s[i]
+}
+
+// Equal compares two sets of samples and returns true if they are equal.
+func (s Samples) Equal(o Samples) bool {
+	if len(s) != len(o) {
+		return false
+	}
+
+	for i, sample := range s {
+		if !sample.Equal(o[i]) {
+			return false
+		}
+	}
+	return true
+}
+
+// SampleStream is a stream of Values belonging to an attached COWMetric.
+type SampleStream struct {
+	Metric Metric       `json:"metric"`
+	Values []SamplePair `json:"values"`
+}
+
+func (ss SampleStream) String() string {
+	vals := make([]string, len(ss.Values))
+	for i, v := range ss.Values {
+		vals[i] = v.String()
+	}
+	return fmt.Sprintf("%s =>\n%s", ss.Metric, strings.Join(vals, "\n"))
+}
+
+// Value is a generic interface for values resulting from a query evaluation.
+type Value interface {
+	Type() ValueType
+	String() string
+}
+
+func (Matrix) Type() ValueType  { return ValMatrix }
+func (Vector) Type() ValueType  { return ValVector }
+func (*Scalar) Type() ValueType { return ValScalar }
+func (*String) Type() ValueType { return ValString }
+
+type ValueType int
+
+const (
+	ValNone ValueType = iota
+	ValScalar
+	ValVector
+	ValMatrix
+	ValString
+)
+
+// MarshalJSON implements json.Marshaler.
+func (et ValueType) MarshalJSON() ([]byte, error) {
+	return json.Marshal(et.String())
+}
+
+func (et *ValueType) UnmarshalJSON(b []byte) error {
+	var s string
+	if err := json.Unmarshal(b, &s); err != nil {
+		return err
+	}
+	switch s {
+	case "<ValNone>":
+		*et = ValNone
+	case "scalar":
+		*et = ValScalar
+	case "vector":
+		*et = ValVector
+	case "matrix":
+		*et = ValMatrix
+	case "string":
+		*et = ValString
+	default:
+		return fmt.Errorf("unknown value type %q", s)
+	}
+	return nil
+}
+
+func (e ValueType) String() string {
+	switch e {
+	case ValNone:
+		return "<ValNone>"
+	case ValScalar:
+		return "scalar"
+	case ValVector:
+		return "vector"
+	case ValMatrix:
+		return "matrix"
+	case ValString:
+		return "string"
+	}
+	panic("ValueType.String: unhandled value type")
+}
+
+// Scalar is a scalar value evaluated at the set timestamp.
+type Scalar struct {
+	Value     SampleValue `json:"value"`
+	Timestamp Time        `json:"timestamp"`
+}
+
+func (s Scalar) String() string {
+	return fmt.Sprintf("scalar: %v @[%v]", s.Value, s.Timestamp)
+}
+
+// MarshalJSON implements json.Marshaler.
+func (s Scalar) MarshalJSON() ([]byte, error) {
+	v := strconv.FormatFloat(float64(s.Value), 'f', -1, 64)
+	return json.Marshal([...]interface{}{s.Timestamp, string(v)})
+}
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (s *Scalar) UnmarshalJSON(b []byte) error {
+	var f string
+	v := [...]interface{}{&s.Timestamp, &f}
+
+	if err := json.Unmarshal(b, &v); err != nil {
+		return err
+	}
+
+	value, err := strconv.ParseFloat(f, 64)
+	if err != nil {
+		return fmt.Errorf("error parsing sample value: %s", err)
+	}
+	s.Value = SampleValue(value)
+	return nil
+}
+
+// String is a string value evaluated at the set timestamp.
+type String struct {
+	Value     string `json:"value"`
+	Timestamp Time   `json:"timestamp"`
+}
+
+func (s *String) String() string {
+	return s.Value
+}
+
+// MarshalJSON implements json.Marshaler.
+func (s String) MarshalJSON() ([]byte, error) {
+	return json.Marshal([]interface{}{s.Timestamp, s.Value})
+}
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (s *String) UnmarshalJSON(b []byte) error {
+	v := [...]interface{}{&s.Timestamp, &s.Value}
+	return json.Unmarshal(b, &v)
+}
+
+// Vector is basically only an alias for Samples, but the
+// contract is that in a Vector, all Samples have the same timestamp.
+type Vector []*Sample
+
+func (vec Vector) String() string {
+	entries := make([]string, len(vec))
+	for i, s := range vec {
+		entries[i] = s.String()
+	}
+	return strings.Join(entries, "\n")
+}
+
+func (vec Vector) Len() int      { return len(vec) }
+func (vec Vector) Swap(i, j int) { vec[i], vec[j] = vec[j], vec[i] }
+
+// Less compares first the metrics, then the timestamp.
+func (vec Vector) Less(i, j int) bool {
+	switch {
+	case vec[i].Metric.Before(vec[j].Metric):
+		return true
+	case vec[j].Metric.Before(vec[i].Metric):
+		return false
+	case vec[i].Timestamp.Before(vec[j].Timestamp):
+		return true
+	default:
+		return false
+	}
+}
+
+// Equal compares two sets of samples and returns true if they are equal.
+func (vec Vector) Equal(o Vector) bool {
+	if len(vec) != len(o) {
+		return false
+	}
+
+	for i, sample := range vec {
+		if !sample.Equal(o[i]) {
+			return false
+		}
+	}
+	return true
+}
+
+// Matrix is a list of time series.
+type Matrix []*SampleStream
+
+func (m Matrix) Len() int           { return len(m) }
+func (m Matrix) Less(i, j int) bool { return m[i].Metric.Before(m[j].Metric) }
+func (m Matrix) Swap(i, j int)      { m[i], m[j] = m[j], m[i] }
+
+func (mat Matrix) String() string {
+	matCp := make(Matrix, len(mat))
+	copy(matCp, mat)
+	sort.Sort(matCp)
+
+	strs := make([]string, len(matCp))
+
+	for i, ss := range matCp {
+		strs[i] = ss.String()
+	}
+
+	return strings.Join(strs, "\n")
+}

+ 362 - 0
Godeps/_workspace/src/github.com/prometheus/common/model/value_test.go

@@ -0,0 +1,362 @@
+// Copyright 2013 The Prometheus Authors
+// 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.
+
+package model
+
+import (
+	"encoding/json"
+	"math"
+	"reflect"
+	"sort"
+	"testing"
+)
+
+func TestSamplePairJSON(t *testing.T) {
+	input := []struct {
+		plain string
+		value SamplePair
+	}{
+		{
+			plain: `[1234.567,"123.1"]`,
+			value: SamplePair{
+				Value:     123.1,
+				Timestamp: 1234567,
+			},
+		},
+	}
+
+	for _, test := range input {
+		b, err := json.Marshal(test.value)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		if string(b) != test.plain {
+			t.Errorf("encoding error: expected %q, got %q", test.plain, b)
+			continue
+		}
+
+		var sp SamplePair
+		err = json.Unmarshal(b, &sp)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		if sp != test.value {
+			t.Errorf("decoding error: expected %v, got %v", test.value, sp)
+		}
+	}
+}
+
+func TestSampleJSON(t *testing.T) {
+	input := []struct {
+		plain string
+		value Sample
+	}{
+		{
+			plain: `{"metric":{"__name__":"test_metric"},"value":[1234.567,"123.1"]}`,
+			value: Sample{
+				Metric: Metric{
+					MetricNameLabel: "test_metric",
+				},
+				Value:     123.1,
+				Timestamp: 1234567,
+			},
+		},
+	}
+
+	for _, test := range input {
+		b, err := json.Marshal(test.value)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		if string(b) != test.plain {
+			t.Errorf("encoding error: expected %q, got %q", test.plain, b)
+			continue
+		}
+
+		var sv Sample
+		err = json.Unmarshal(b, &sv)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		if !reflect.DeepEqual(sv, test.value) {
+			t.Errorf("decoding error: expected %v, got %v", test.value, sv)
+		}
+	}
+}
+
+func TestVectorJSON(t *testing.T) {
+	input := []struct {
+		plain string
+		value Vector
+	}{
+		{
+			plain: `[]`,
+			value: Vector{},
+		},
+		{
+			plain: `[{"metric":{"__name__":"test_metric"},"value":[1234.567,"123.1"]}]`,
+			value: Vector{&Sample{
+				Metric: Metric{
+					MetricNameLabel: "test_metric",
+				},
+				Value:     123.1,
+				Timestamp: 1234567,
+			}},
+		},
+		{
+			plain: `[{"metric":{"__name__":"test_metric"},"value":[1234.567,"123.1"]},{"metric":{"foo":"bar"},"value":[1.234,"+Inf"]}]`,
+			value: Vector{
+				&Sample{
+					Metric: Metric{
+						MetricNameLabel: "test_metric",
+					},
+					Value:     123.1,
+					Timestamp: 1234567,
+				},
+				&Sample{
+					Metric: Metric{
+						"foo": "bar",
+					},
+					Value:     SampleValue(math.Inf(1)),
+					Timestamp: 1234,
+				},
+			},
+		},
+	}
+
+	for _, test := range input {
+		b, err := json.Marshal(test.value)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		if string(b) != test.plain {
+			t.Errorf("encoding error: expected %q, got %q", test.plain, b)
+			continue
+		}
+
+		var vec Vector
+		err = json.Unmarshal(b, &vec)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		if !reflect.DeepEqual(vec, test.value) {
+			t.Errorf("decoding error: expected %v, got %v", test.value, vec)
+		}
+	}
+}
+
+func TestScalarJSON(t *testing.T) {
+	input := []struct {
+		plain string
+		value Scalar
+	}{
+		{
+			plain: `[123.456,"456"]`,
+			value: Scalar{
+				Timestamp: 123456,
+				Value:     456,
+			},
+		},
+		{
+			plain: `[123123.456,"+Inf"]`,
+			value: Scalar{
+				Timestamp: 123123456,
+				Value:     SampleValue(math.Inf(1)),
+			},
+		},
+		{
+			plain: `[123123.456,"-Inf"]`,
+			value: Scalar{
+				Timestamp: 123123456,
+				Value:     SampleValue(math.Inf(-1)),
+			},
+		},
+	}
+
+	for _, test := range input {
+		b, err := json.Marshal(test.value)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		if string(b) != test.plain {
+			t.Errorf("encoding error: expected %q, got %q", test.plain, b)
+			continue
+		}
+
+		var sv Scalar
+		err = json.Unmarshal(b, &sv)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		if sv != test.value {
+			t.Errorf("decoding error: expected %v, got %v", test.value, sv)
+		}
+	}
+}
+
+func TestStringJSON(t *testing.T) {
+	input := []struct {
+		plain string
+		value String
+	}{
+		{
+			plain: `[123.456,"test"]`,
+			value: String{
+				Timestamp: 123456,
+				Value:     "test",
+			},
+		},
+		{
+			plain: `[123123.456,"台北"]`,
+			value: String{
+				Timestamp: 123123456,
+				Value:     "台北",
+			},
+		},
+	}
+
+	for _, test := range input {
+		b, err := json.Marshal(test.value)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		if string(b) != test.plain {
+			t.Errorf("encoding error: expected %q, got %q", test.plain, b)
+			continue
+		}
+
+		var sv String
+		err = json.Unmarshal(b, &sv)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		if sv != test.value {
+			t.Errorf("decoding error: expected %v, got %v", test.value, sv)
+		}
+	}
+}
+
+func TestVectorSort(t *testing.T) {
+	input := Vector{
+		&Sample{
+			Metric: Metric{
+				MetricNameLabel: "A",
+			},
+			Timestamp: 1,
+		},
+		&Sample{
+			Metric: Metric{
+				MetricNameLabel: "A",
+			},
+			Timestamp: 2,
+		},
+		&Sample{
+			Metric: Metric{
+				MetricNameLabel: "C",
+			},
+			Timestamp: 1,
+		},
+		&Sample{
+			Metric: Metric{
+				MetricNameLabel: "C",
+			},
+			Timestamp: 2,
+		},
+		&Sample{
+			Metric: Metric{
+				MetricNameLabel: "B",
+			},
+			Timestamp: 1,
+		},
+		&Sample{
+			Metric: Metric{
+				MetricNameLabel: "B",
+			},
+			Timestamp: 2,
+		},
+	}
+
+	expected := Vector{
+		&Sample{
+			Metric: Metric{
+				MetricNameLabel: "A",
+			},
+			Timestamp: 1,
+		},
+		&Sample{
+			Metric: Metric{
+				MetricNameLabel: "A",
+			},
+			Timestamp: 2,
+		},
+		&Sample{
+			Metric: Metric{
+				MetricNameLabel: "B",
+			},
+			Timestamp: 1,
+		},
+		&Sample{
+			Metric: Metric{
+				MetricNameLabel: "B",
+			},
+			Timestamp: 2,
+		},
+		&Sample{
+			Metric: Metric{
+				MetricNameLabel: "C",
+			},
+			Timestamp: 1,
+		},
+		&Sample{
+			Metric: Metric{
+				MetricNameLabel: "C",
+			},
+			Timestamp: 2,
+		},
+	}
+
+	sort.Sort(input)
+
+	for i, actual := range input {
+		actualFp := actual.Metric.Fingerprint()
+		expectedFp := expected[i].Metric.Fingerprint()
+
+		if actualFp != expectedFp {
+			t.Fatalf("%d. Incorrect fingerprint. Got %s; want %s", i, actualFp.String(), expectedFp.String())
+		}
+
+		if actual.Timestamp != expected[i].Timestamp {
+			t.Fatalf("%d. Incorrect timestamp. Got %s; want %s", i, actual.Timestamp, expected[i].Timestamp)
+		}
+	}
+}

+ 2 - 0
Godeps/_workspace/src/github.com/prometheus/procfs/.travis.yml

@@ -1,5 +1,7 @@
+sudo: false
 language: go
 go:
     - 1.3
     - 1.4
+    - 1.5
     - tip

+ 8 - 0
Godeps/_workspace/src/github.com/prometheus/procfs/AUTHORS.md

@@ -8,5 +8,13 @@ Maintainers of this repository:
 The following individuals have contributed code to this repository
 (listed in alphabetical order):
 
+* Armen Baghumian <abaghumian@noggin.com.au>
+* Bjoern Rabenstein <beorn@soundcloud.com>
+* David Cournapeau <cournape@gmail.com>
 * Ji-Hoon, Seol <jihoon.seol@gmail.com>
+* Jonas Große Sundrup <cherti@letopolis.de>
+* Julius Volz <julius@soundcloud.com>
+* Matthias Rampke <mr@soundcloud.com>
+* Nicky Gerritsen <nicky@streamone.nl>
+* Rémi Audebert <contact@halfr.net>
 * Tobias Schmidt <tobidt@gmail.com>

+ 6 - 0
Godeps/_workspace/src/github.com/prometheus/procfs/Makefile

@@ -0,0 +1,6 @@
+ci:
+	go fmt
+	go vet
+	go test -v ./...
+	go get github.com/golang/lint/golint
+	golint *.go

+ 0 - 0
Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/0


+ 1 - 0
Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/0

@@ -0,0 +1 @@
+../../symlinktargets/abc

+ 0 - 0
Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/1


+ 1 - 0
Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/1

@@ -0,0 +1 @@
+../../symlinktargets/def

+ 1 - 0
Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/10

@@ -0,0 +1 @@
+../../symlinktargets/xyz

+ 0 - 0
Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/2


+ 1 - 0
Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/2

@@ -0,0 +1 @@
+../../symlinktargets/ghi

+ 0 - 0
Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/3


+ 1 - 0
Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/3

@@ -0,0 +1 @@
+../../symlinktargets/uvw

+ 0 - 0
Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26232/fd/0


Some files were not shown because too many files changed in this diff