Eliminate a number of style-guide violations.

Change-Id: Iedcd611e5c7ad24c84c004d8d6c551d1734e443c
This commit is contained in:
Bjoern Rabenstein 2014-04-25 12:50:18 +02:00
parent 00816363e4
commit 9da2fbcce3
19 changed files with 125 additions and 82 deletions

View File

@ -80,3 +80,17 @@ ensure that all tests pass by running the following from the project root:
The use of gocheck is summarily being phased out; however, old tests that use it The use of gocheck is summarily being phased out; however, old tests that use it
still exist. still exist.
# Contributing
Same as for the `prometheus/prometheus` repository, we are using
Gerrit to manage reviews of pull-requests for this repository. See
[`CONTRIBUTING.md`](https://github.com/prometheus/prometheus/blob/master/CONTRIBUTING.md)
in the `prometheus/prometheus` repository for details (but replace the
`prometheus` repository name by `client_golang`).
Please try to avoid warnings flagged by [`go
vet`](https://godoc.org/code.google.com/p/go.tools/cmd/vet) and by
[`golint`](https://github.com/golang/lint), and pay attention to the
[Go Code Review
Comments](https://code.google.com/p/go-wiki/wiki/CodeReviewComments).

View File

@ -14,6 +14,7 @@
package extraction package extraction
import ( import (
"errors"
"fmt" "fmt"
"mime" "mime"
"net/http" "net/http"
@ -24,20 +25,20 @@ import (
// Processor can be found, an error is returned. // Processor can be found, an error is returned.
func ProcessorForRequestHeader(header http.Header) (Processor, error) { func ProcessorForRequestHeader(header http.Header) (Processor, error) {
if header == nil { if header == nil {
return nil, fmt.Errorf("Received illegal and nil header.") return nil, errors.New("received illegal and nil header")
} }
mediatype, params, err := mime.ParseMediaType(header.Get("Content-Type")) mediatype, params, err := mime.ParseMediaType(header.Get("Content-Type"))
if err != nil { if err != nil {
return nil, fmt.Errorf("Invalid Content-Type header %q: %s", header.Get("Content-Type"), err) return nil, fmt.Errorf("invalid Content-Type header %q: %s", header.Get("Content-Type"), err)
} }
switch mediatype { switch mediatype {
case "application/vnd.google.protobuf": case "application/vnd.google.protobuf":
if params["proto"] != "io.prometheus.client.MetricFamily" { if params["proto"] != "io.prometheus.client.MetricFamily" {
return nil, fmt.Errorf("Unrecognized Protocol Message %s", params["proto"]) return nil, fmt.Errorf("unrecognized protocol message %s", params["proto"])
} }
if params["encoding"] != "delimited" { if params["encoding"] != "delimited" {
return nil, fmt.Errorf("Unsupported Encoding %s", params["encoding"]) return nil, fmt.Errorf("unsupported encoding %s", params["encoding"])
} }
return MetricFamilyProcessor, nil return MetricFamilyProcessor, nil
case "text/plain": case "text/plain":
@ -48,26 +49,26 @@ func ProcessorForRequestHeader(header http.Header) (Processor, error) {
// Fallback: most recent version. // Fallback: most recent version.
return Processor004, nil return Processor004, nil
default: default:
return nil, fmt.Errorf("Unrecognized API version %s", params["version"]) return nil, fmt.Errorf("unrecognized API version %s", params["version"])
} }
case "application/json": case "application/json":
var prometheusApiVersion string var prometheusAPIVersion string
if params["schema"] == "prometheus/telemetry" && params["version"] != "" { if params["schema"] == "prometheus/telemetry" && params["version"] != "" {
prometheusApiVersion = params["version"] prometheusAPIVersion = params["version"]
} else { } else {
prometheusApiVersion = header.Get("X-Prometheus-API-Version") prometheusAPIVersion = header.Get("X-Prometheus-API-Version")
} }
switch prometheusApiVersion { switch prometheusAPIVersion {
case "0.0.2": case "0.0.2":
return Processor002, nil return Processor002, nil
case "0.0.1": case "0.0.1":
return Processor001, nil return Processor001, nil
default: default:
return nil, fmt.Errorf("Unrecognized API version %s", prometheusApiVersion) return nil, fmt.Errorf("unrecognized API version %s", prometheusAPIVersion)
} }
default: default:
return nil, fmt.Errorf("Unsupported media type %q, expected %q", mediatype, "application/json") return nil, fmt.Errorf("unsupported media type %q, expected %q", mediatype, "application/json")
} }
} }

View File

@ -14,14 +14,14 @@
package extraction package extraction
import ( import (
"fmt" "errors"
"net/http" "net/http"
"testing" "testing"
"github.com/prometheus/client_golang/test" "github.com/prometheus/client_golang/test"
) )
func testDiscriminatorHttpHeader(t test.Tester) { func testDiscriminatorHTTPHeader(t test.Tester) {
var scenarios = []struct { var scenarios = []struct {
input map[string]string input map[string]string
output Processor output Processor
@ -29,12 +29,12 @@ func testDiscriminatorHttpHeader(t test.Tester) {
}{ }{
{ {
output: nil, output: nil,
err: fmt.Errorf("Received illegal and nil header."), err: errors.New("received illegal and nil header"),
}, },
{ {
input: map[string]string{"Content-Type": "application/json", "X-Prometheus-API-Version": "0.0.0"}, input: map[string]string{"Content-Type": "application/json", "X-Prometheus-API-Version": "0.0.0"},
output: nil, output: nil,
err: fmt.Errorf("Unrecognized API version 0.0.0"), err: errors.New("unrecognized API version 0.0.0"),
}, },
{ {
input: map[string]string{"Content-Type": "application/json", "X-Prometheus-API-Version": "0.0.1"}, input: map[string]string{"Content-Type": "application/json", "X-Prometheus-API-Version": "0.0.1"},
@ -44,7 +44,7 @@ func testDiscriminatorHttpHeader(t test.Tester) {
{ {
input: map[string]string{"Content-Type": `application/json; schema="prometheus/telemetry"; version=0.0.0`}, input: map[string]string{"Content-Type": `application/json; schema="prometheus/telemetry"; version=0.0.0`},
output: nil, output: nil,
err: fmt.Errorf("Unrecognized API version 0.0.0"), err: errors.New("unrecognized API version 0.0.0"),
}, },
{ {
input: map[string]string{"Content-Type": `application/json; schema="prometheus/telemetry"; version=0.0.1`}, input: map[string]string{"Content-Type": `application/json; schema="prometheus/telemetry"; version=0.0.1`},
@ -64,12 +64,12 @@ func testDiscriminatorHttpHeader(t test.Tester) {
{ {
input: map[string]string{"Content-Type": `application/vnd.google.protobuf; proto="illegal"; encoding="delimited"`}, input: map[string]string{"Content-Type": `application/vnd.google.protobuf; proto="illegal"; encoding="delimited"`},
output: nil, output: nil,
err: fmt.Errorf("Unrecognized Protocol Message illegal"), err: errors.New("unrecognized protocol message illegal"),
}, },
{ {
input: map[string]string{"Content-Type": `application/vnd.google.protobuf; proto="io.prometheus.client.MetricFamily"; encoding="illegal"`}, input: map[string]string{"Content-Type": `application/vnd.google.protobuf; proto="io.prometheus.client.MetricFamily"; encoding="illegal"`},
output: nil, output: nil,
err: fmt.Errorf("Unsupported Encoding illegal"), err: errors.New("unsupported encoding illegal"),
}, },
{ {
input: map[string]string{"Content-Type": `text/plain; version=0.0.4`}, input: map[string]string{"Content-Type": `text/plain; version=0.0.4`},
@ -84,7 +84,7 @@ func testDiscriminatorHttpHeader(t test.Tester) {
{ {
input: map[string]string{"Content-Type": `text/plain; version=0.0.3`}, input: map[string]string{"Content-Type": `text/plain; version=0.0.3`},
output: nil, output: nil,
err: fmt.Errorf("Unrecognized API version 0.0.3"), err: errors.New("unrecognized API version 0.0.3"),
}, },
} }
@ -117,12 +117,12 @@ func testDiscriminatorHttpHeader(t test.Tester) {
} }
} }
func TestDiscriminatorHttpHeader(t *testing.T) { func TestDiscriminatorHTTPHeader(t *testing.T) {
testDiscriminatorHttpHeader(t) testDiscriminatorHTTPHeader(t)
} }
func BenchmarkDiscriminatorHttpHeader(b *testing.B) { func BenchmarkDiscriminatorHTTPHeader(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
testDiscriminatorHttpHeader(b) testDiscriminatorHTTPHeader(b)
} }
} }

View File

@ -35,9 +35,9 @@ const (
percentile001 = "percentile" percentile001 = "percentile"
) )
// Processor002 is responsible for decoding payloads from protocol version // Processor001 is responsible for decoding payloads from protocol version
// 0.0.1. // 0.0.1.
var Processor001 Processor = &processor001{} var Processor001 = &processor001{}
// processor001 is responsible for handling API version 0.0.1. // processor001 is responsible for handling API version 0.0.1.
type processor001 struct{} type processor001 struct{}
@ -77,7 +77,7 @@ func (p *processor001) ProcessSingle(in io.Reader, out Ingester, o *ProcessOptio
case gauge001, counter001: case gauge001, counter001:
sampleValue, ok := value.Value.(float64) sampleValue, ok := value.Value.(float64)
if !ok { if !ok {
err = fmt.Errorf("Could not convert value from %s %s to float64.", entity, value) err = fmt.Errorf("could not convert value from %s %s to float64", entity, value)
if err := out.Ingest(&Result{Err: err}); err != nil { if err := out.Ingest(&Result{Err: err}); err != nil {
return err return err
} }
@ -95,7 +95,7 @@ func (p *processor001) ProcessSingle(in io.Reader, out Ingester, o *ProcessOptio
case histogram001: case histogram001:
sampleValue, ok := value.Value.(map[string]interface{}) sampleValue, ok := value.Value.(map[string]interface{})
if !ok { if !ok {
err = fmt.Errorf("Could not convert value from %q to a map[string]interface{}.", value.Value) err = fmt.Errorf("could not convert value from %q to a map[string]interface{}", value.Value)
if err := out.Ingest(&Result{Err: err}); err != nil { if err := out.Ingest(&Result{Err: err}); err != nil {
return err return err
} }
@ -105,7 +105,7 @@ func (p *processor001) ProcessSingle(in io.Reader, out Ingester, o *ProcessOptio
for percentile, percentileValue := range sampleValue { for percentile, percentileValue := range sampleValue {
individualValue, ok := percentileValue.(float64) individualValue, ok := percentileValue.(float64)
if !ok { if !ok {
err = fmt.Errorf("Could not convert value from %q to a float64.", percentileValue) err = fmt.Errorf("could not convert value from %q to a float64", percentileValue)
if err := out.Ingest(&Result{Err: err}); err != nil { if err := out.Ingest(&Result{Err: err}); err != nil {
return err return err
} }

View File

@ -14,7 +14,7 @@
package extraction package extraction
import ( import (
"fmt" "errors"
"os" "os"
"path" "path"
"sort" "sort"
@ -68,7 +68,7 @@ func testProcessor001Process(t test.Tester) {
var scenarios = []testProcessor001ProcessScenario{ var scenarios = []testProcessor001ProcessScenario{
{ {
in: "empty.json", in: "empty.json",
err: fmt.Errorf("unexpected end of JSON input"), err: errors.New("unexpected end of JSON input"),
}, },
{ {
in: "test0_0_1-0_0_2.json", in: "test0_0_1-0_0_2.json",

View File

@ -23,7 +23,7 @@ import (
// Processor002 is responsible for decoding payloads from protocol version // Processor002 is responsible for decoding payloads from protocol version
// 0.0.2. // 0.0.2.
var Processor002 = new(processor002) var Processor002 = &processor002{}
type histogram002 struct { type histogram002 struct {
Labels map[string]string `json:"labels"` Labels map[string]string `json:"labels"`
@ -60,7 +60,7 @@ func (p *processor002) ProcessSingle(in io.Reader, out Ingester, o *ProcessOptio
var values []counter002 var values []counter002
if err := json.Unmarshal(entity.Metric.Values, &values); err != nil { if err := json.Unmarshal(entity.Metric.Values, &values); err != nil {
err := fmt.Errorf("Could not extract %s value: %s", entity.Metric.Type, err) err := fmt.Errorf("could not extract %s value: %s", entity.Metric.Type, err)
if err := out.Ingest(&Result{Err: err}); err != nil { if err := out.Ingest(&Result{Err: err}); err != nil {
return err return err
} }
@ -81,7 +81,7 @@ func (p *processor002) ProcessSingle(in io.Reader, out Ingester, o *ProcessOptio
var values []histogram002 var values []histogram002
if err := json.Unmarshal(entity.Metric.Values, &values); err != nil { if err := json.Unmarshal(entity.Metric.Values, &values); err != nil {
err := fmt.Errorf("Could not extract %s value: %s", entity.Metric.Type, err) err := fmt.Errorf("could not extract %s value: %s", entity.Metric.Type, err)
if err := out.Ingest(&Result{Err: err}); err != nil { if err := out.Ingest(&Result{Err: err}); err != nil {
return err return err
} }
@ -102,7 +102,7 @@ func (p *processor002) ProcessSingle(in io.Reader, out Ingester, o *ProcessOptio
} }
default: default:
err := fmt.Errorf("Unknown metric type %q", entity.Metric.Type) err := fmt.Errorf("unknown metric type %q", entity.Metric.Type)
if err := out.Ingest(&Result{Err: err}); err != nil { if err := out.Ingest(&Result{Err: err}); err != nil {
return err return err
} }

View File

@ -14,7 +14,7 @@
package extraction package extraction
import ( import (
"fmt" "errors"
"os" "os"
"path" "path"
"runtime" "runtime"
@ -69,7 +69,7 @@ func testProcessor002Process(t test.Tester) {
var scenarios = []testProcessor002ProcessScenario{ var scenarios = []testProcessor002ProcessScenario{
{ {
in: "empty.json", in: "empty.json",
err: fmt.Errorf("EOF"), err: errors.New("EOF"),
}, },
{ {
in: "test0_0_1-0_0_2.json", in: "test0_0_1-0_0_2.json",

View File

@ -36,6 +36,8 @@ func (f *Fingerprint) String() string {
return strings.Join([]string{fmt.Sprintf("%020d", f.Hash), f.FirstCharacterOfFirstLabelName, fmt.Sprint(f.LabelMatterLength), f.LastCharacterOfLastLabelValue}, "-") return strings.Join([]string{fmt.Sprintf("%020d", f.Hash), f.FirstCharacterOfFirstLabelName, fmt.Sprint(f.LabelMatterLength), f.LastCharacterOfLastLabelValue}, "-")
} }
// Less compares first the Hash, then the FirstCharacterOfFirstLabelName, then
// the LabelMatterLength, then the LastCharacterOfLastLabelValue.
func (f *Fingerprint) Less(o *Fingerprint) bool { func (f *Fingerprint) Less(o *Fingerprint) bool {
if f.Hash < o.Hash { if f.Hash < o.Hash {
return true return true
@ -67,6 +69,7 @@ func (f *Fingerprint) Less(o *Fingerprint) bool {
return false return false
} }
// Equal uses the same semantics as Less.
func (f *Fingerprint) Equal(o *Fingerprint) bool { func (f *Fingerprint) Equal(o *Fingerprint) bool {
if f.Hash != o.Hash { if f.Hash != o.Hash {
return false return false
@ -146,8 +149,8 @@ func (f *Fingerprint) LoadFromMetric(m Metric) {
f.LastCharacterOfLastLabelValue = lastCharacterOfLastLabelValue f.LastCharacterOfLastLabelValue = lastCharacterOfLastLabelValue
} }
// Represents a collection of Fingerprint subject to a given natural sorting // Fingerprints represents a collection of Fingerprint subject to a given
// scheme. // natural sorting scheme. It implements sort.Interface.
type Fingerprints []*Fingerprint type Fingerprints []*Fingerprint
func (f Fingerprints) Len() int { func (f Fingerprints) Len() int {
@ -162,8 +165,10 @@ func (f Fingerprints) Swap(i, j int) {
f[i], f[j] = f[j], f[i] f[i], f[j] = f[j], f[i]
} }
type FingerprintSet map[Fingerprint]bool // FingerprintSet is a set of Fingerprints.
type FingerprintSet map[Fingerprint]struct{}
// Equal returns true if both sets contain the same elements (and not more).
func (s FingerprintSet) Equal(o FingerprintSet) bool { func (s FingerprintSet) Equal(o FingerprintSet) bool {
if len(s) != len(o) { if len(s) != len(o) {
return false return false
@ -178,6 +183,7 @@ func (s FingerprintSet) Equal(o FingerprintSet) bool {
return true return true
} }
// Intersection returns the elements contained in both sets.
func (s FingerprintSet) Intersection(o FingerprintSet) FingerprintSet { func (s FingerprintSet) Intersection(o FingerprintSet) FingerprintSet {
myLength, otherLength := len(s), len(o) myLength, otherLength := len(s), len(o)
if myLength == 0 || otherLength == 0 { if myLength == 0 || otherLength == 0 {
@ -196,7 +202,7 @@ func (s FingerprintSet) Intersection(o FingerprintSet) FingerprintSet {
for k := range subSet { for k := range subSet {
if _, ok := superSet[k]; ok { if _, ok := superSet[k]; ok {
out[k] = true out[k] = struct{}{}
} }
} }

View File

@ -18,18 +18,20 @@ import (
) )
const ( const (
// The label name prefix to prepend if a synthetic label is already present // ExporterLabelPrefix is the label name prefix to prepend if a
// in the exported metrics. // synthetic label is already present in the exported metrics.
ExporterLabelPrefix LabelName = "exporter_" ExporterLabelPrefix LabelName = "exporter_"
// The label name indicating the metric name of a timeseries. // MetricNameLabel is the label name indicating the metric name of a
// timeseries.
MetricNameLabel LabelName = "__name__" MetricNameLabel LabelName = "__name__"
// ReservedLabelPrefix is a prefix which is not legal in user-supplied label // ReservedLabelPrefix is a prefix which is not legal in user-supplied
// names. // label names.
ReservedLabelPrefix = "__" ReservedLabelPrefix = "__"
// The label name indicating the job from which a timeseries was scraped. // JobLabel is the label name indicating the job from which a timeseries
// was scraped.
JobLabel LabelName = "job" JobLabel LabelName = "job"
) )
@ -37,6 +39,7 @@ const (
// therewith. // therewith.
type LabelName string type LabelName string
// LabelNames is a sortable LabelName slice. In implements sort.Interface.
type LabelNames []LabelName type LabelNames []LabelName
func (l LabelNames) Len() int { func (l LabelNames) Len() int {

View File

@ -26,7 +26,7 @@ import (
// match. // match.
type LabelSet map[LabelName]LabelValue type LabelSet map[LabelName]LabelValue
// Helper function to non-destructively merge two label sets. // Merge is a helper function to non-destructively merge two label sets.
func (l LabelSet) Merge(other LabelSet) LabelSet { func (l LabelSet) Merge(other LabelSet) LabelSet {
result := make(LabelSet, len(l)) result := make(LabelSet, len(l))
@ -56,6 +56,7 @@ func (l LabelSet) String() string {
} }
} }
// MergeFromMetric merges Metric into this LabelSet.
func (l LabelSet) MergeFromMetric(m Metric) { func (l LabelSet) MergeFromMetric(m Metric) {
for k, v := range m { for k, v := range m {
l[k] = v l[k] = v

View File

@ -20,6 +20,7 @@ import (
// A LabelValue is an associated value for a LabelName. // A LabelValue is an associated value for a LabelName.
type LabelValue string type LabelValue string
// LabelValues is a sortable LabelValue slice. It implements sort.Interface.
type LabelValues []LabelValue type LabelValues []LabelValue
func (l LabelValues) Len() int { func (l LabelValues) Len() int {

View File

@ -23,6 +23,7 @@ import (
// a singleton and refers to one and only one stream of samples. // a singleton and refers to one and only one stream of samples.
type Metric map[LabelName]LabelValue type Metric map[LabelName]LabelValue
// Equal compares the fingerprints of both metrics.
func (m Metric) Equal(o Metric) bool { func (m Metric) Equal(o Metric) bool {
lFingerprint := &Fingerprint{} lFingerprint := &Fingerprint{}
rFingerprint := &Fingerprint{} rFingerprint := &Fingerprint{}
@ -33,6 +34,7 @@ func (m Metric) Equal(o Metric) bool {
return lFingerprint.Equal(rFingerprint) return lFingerprint.Equal(rFingerprint)
} }
// Before compares the fingerprints of both metrics.
func (m Metric) Before(o Metric) bool { func (m Metric) Before(o Metric) bool {
lFingerprint := &Fingerprint{} lFingerprint := &Fingerprint{}
rFingerprint := &Fingerprint{} rFingerprint := &Fingerprint{}
@ -64,6 +66,8 @@ func (m Metric) String() string {
} }
} }
// 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) { func (m Metric) MergeFromLabelSet(labels LabelSet, collisionPrefix LabelName) {
for k, v := range labels { for k, v := range labels {
if collisionPrefix != "" { if collisionPrefix != "" {

View File

@ -13,12 +13,14 @@
package model package model
// Sample is a sample value with a timestamp and a metric.
type Sample struct { type Sample struct {
Metric Metric Metric Metric
Value SampleValue Value SampleValue
Timestamp Timestamp Timestamp Timestamp
} }
// Equal compares first the metrics, then the timestamp, then the value.
func (s *Sample) Equal(o *Sample) bool { func (s *Sample) Equal(o *Sample) bool {
if s == o { if s == o {
return true return true
@ -37,12 +39,14 @@ func (s *Sample) Equal(o *Sample) bool {
return true return true
} }
// Samples is a sortable Sample slice. It implements sort.Interface.
type Samples []*Sample type Samples []*Sample
func (s Samples) Len() int { func (s Samples) Len() int {
return len(s) return len(s)
} }
// Less compares first the metrics, then the timestamp.
func (s Samples) Less(i, j int) bool { func (s Samples) Less(i, j int) bool {
switch { switch {
case s[i].Metric.Before(s[j].Metric): case s[i].Metric.Before(s[j].Metric):

View File

@ -21,10 +21,12 @@ import (
// time. // time.
type SampleValue float64 type SampleValue float64
// Equal does a straight v==o.
func (v SampleValue) Equal(o SampleValue) bool { func (v SampleValue) Equal(o SampleValue) bool {
return v == o return v == o
} }
// MarshalJSON implements json.Marshaler.
func (v SampleValue) MarshalJSON() ([]byte, error) { func (v SampleValue) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"%f"`, v)), nil return []byte(fmt.Sprintf(`"%f"`, v)), nil
} }

View File

@ -23,14 +23,15 @@ import (
// methods below, so it will be easy to change this later // methods below, so it will be easy to change this later
// without requiring significant user code changes. // without requiring significant user code changes.
// Time in seconds since the epoch (January 1, 1970 UTC). // Timestamp is the number of seconds since the epoch (1970-01-01 00:00 UTC)
// without leap seconds.
type Timestamp int64 type Timestamp int64
const ( const (
// The minimum supported time resolution. This has to be at least // MinimumTick is the minimum supported time resolution. This has to be
// native_time.Second in order for the code below to work. // at least native_time.Second in order for the code below to work.
MinimumTick = native_time.Second MinimumTick = native_time.Second
// The timestamp duration equivalent to one second. // second is the timestamp duration equivalent to one second.
second = int64(native_time.Second / MinimumTick) second = int64(native_time.Second / MinimumTick)
) )
@ -44,7 +45,7 @@ func (t Timestamp) Before(o Timestamp) bool {
return t < o return t < o
} }
// Before reports whether the timestamp t is after o. // After reports whether the timestamp t is after o.
func (t Timestamp) After(o Timestamp) bool { func (t Timestamp) After(o Timestamp) bool {
return t > o return t > o
} }

View File

@ -72,12 +72,12 @@ func TestDuration(t *testing.T) {
ts := TimestampFromTime(goTime) ts := TimestampFromTime(goTime)
if !goTime.Add(duration).Equal(ts.Add(duration).Time()) { if !goTime.Add(duration).Equal(ts.Add(duration).Time()) {
t.Fatalf("%d. Expected %s to be equal to %s", goTime.Add(duration), ts.Add(duration)) t.Fatalf("Expected %s to be equal to %s", goTime.Add(duration), ts.Add(duration))
} }
earlier := ts.Add(-duration) earlier := ts.Add(-duration)
delta := ts.Sub(earlier) delta := ts.Sub(earlier)
if delta != duration { if delta != duration {
t.Fatalf("%d. Expected %s to be equal to %s", delta, duration) t.Fatalf("Expected %s to be equal to %s", delta, duration)
} }
} }

View File

@ -8,30 +8,35 @@ package prometheus
var ( var (
// NilLabels is a nil set of labels merely for end-user convenience. // NilLabels is a nil set of labels merely for end-user convenience.
NilLabels map[string]string = nil NilLabels map[string]string
// The default http.Handler for exposing telemetric data over a web services // DefaultHandler is the default http.Handler for exposing telemetric
// interface. // data over a web services interface.
DefaultHandler = DefaultRegistry.Handler() DefaultHandler = DefaultRegistry.Handler()
// This is the default registry with which Metric objects are associated. // DefaultRegistry with which Metric objects are associated.
DefaultRegistry = NewRegistry() DefaultRegistry = NewRegistry()
) )
const ( const (
// A prefix to be used to namespace instrumentation flags from others. // FlagNamespace is a prefix to be used to namespace instrumentation
// flags from others.
FlagNamespace = "telemetry." FlagNamespace = "telemetry."
// The format of the exported data. This will match this library's version, // APIVersion is the version of the format of the exported data. This
// which subscribes to the Semantic Versioning scheme. // will match this library's version, which subscribes to the Semantic
// Versioning scheme.
APIVersion = "0.0.2" APIVersion = "0.0.2"
// The content type and schema information set on telemetry data responses. // TelemetryContentType is the content type and schema information set
// on telemetry data responses.
TelemetryContentType = `application/json; schema="prometheus/telemetry"; version=` + APIVersion TelemetryContentType = `application/json; schema="prometheus/telemetry"; version=` + APIVersion
// The content type and schema information set on telemetry data responses. // DelimitedTelemetryContentType is the content type and schema
// information set on telemetry data responses.
DelimitedTelemetryContentType = `application/vnd.google.protobuf; proto="io.prometheus.client.MetricFamily"; encoding="delimited"` DelimitedTelemetryContentType = `application/vnd.google.protobuf; proto="io.prometheus.client.MetricFamily"; encoding="delimited"`
// The customary web services endpoint on which telemetric data is exposed. // ExpositionResource is the customary web services endpoint on which
// telemetric data is exposed.
ExpositionResource = "/metrics" ExpositionResource = "/metrics"
baseLabelsKey = "baseLabels" baseLabelsKey = "baseLabels"

View File

@ -7,9 +7,10 @@
package prometheus package prometheus
import ( import (
. "github.com/matttproud/gocheck"
"math" "math"
"reflect" "reflect"
. "github.com/matttproud/gocheck"
) )
type isNaNChecker struct { type isNaNChecker struct {
@ -18,7 +19,7 @@ type isNaNChecker struct {
// This piece provides a simple tester for the gocheck testing library to // This piece provides a simple tester for the gocheck testing library to
// ascertain if a value is not-a-number. // ascertain if a value is not-a-number.
var IsNaN Checker = &isNaNChecker{ var IsNaN = &isNaNChecker{
&CheckerInfo{Name: "IsNaN", Params: []string{"value"}}, &CheckerInfo{Name: "IsNaN", Params: []string{"value"}},
} }
@ -43,7 +44,7 @@ type valueEqualsChecker struct {
*CheckerInfo *CheckerInfo
} }
var ValueEquals Checker = &valueEqualsChecker{ var ValueEquals = &valueEqualsChecker{
&CheckerInfo{Name: "IsValue", Params: []string{"obtained", "expected"}}, &CheckerInfo{Name: "IsValue", Params: []string{"obtained", "expected"}},
} }

View File

@ -98,15 +98,15 @@ type Registry interface {
YieldExporter() http.HandlerFunc YieldExporter() http.HandlerFunc
} }
// This builds a new metric registry. It is not needed in the majority of // NewRegistry builds a new metric registry. It is not needed in the majority
// cases. // of cases.
func NewRegistry() Registry { func NewRegistry() Registry {
return &registry{ return &registry{
signatureContainers: make(map[uint64]*container), signatureContainers: make(map[uint64]*container),
} }
} }
// Associate a Metric with the DefaultRegistry. // Register associates a Metric with the DefaultRegistry.
func Register(name, docstring string, baseLabels map[string]string, metric Metric) error { func Register(name, docstring string, baseLabels map[string]string, metric Metric) error {
return DefaultRegistry.Register(name, docstring, baseLabels, metric) return DefaultRegistry.Register(name, docstring, baseLabels, metric)
} }
@ -116,7 +116,7 @@ func (r *registry) SetMetricFamilyInjectionHook(hook func() []*dto.MetricFamily)
r.metricFamilyInjectionHook = hook r.metricFamilyInjectionHook = hook
} }
// Implements json.Marshaler // MarshalJSON implements json.Marshaler.
func (r *registry) MarshalJSON() ([]byte, error) { func (r *registry) MarshalJSON() ([]byte, error) {
containers := make(containers, 0, len(r.signatureContainers)) containers := make(containers, 0, len(r.signatureContainers))
@ -218,12 +218,12 @@ func (r *registry) Register(name, docstring string, baseLabels map[string]string
// YieldBasicAuthExporter creates a http.HandlerFunc that is protected by HTTP's // YieldBasicAuthExporter creates a http.HandlerFunc that is protected by HTTP's
// basic authentication. // basic authentication.
func (register *registry) YieldBasicAuthExporter(username, password string) http.HandlerFunc { func (r *registry) YieldBasicAuthExporter(username, password string) http.HandlerFunc {
// XXX: Work with Daniel to get this removed from the library, as it is really // XXX: Work with Daniel to get this removed from the library, as it is really
// superfluous and can be much more elegantly accomplished via // superfluous and can be much more elegantly accomplished via
// delegation. // delegation.
log.Println("Registry.YieldBasicAuthExporter is deprecated.") log.Println("Registry.YieldBasicAuthExporter is deprecated.")
exporter := register.YieldExporter() exporter := r.YieldExporter()
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authenticated := false authenticated := false
@ -261,10 +261,10 @@ func decorateWriter(request *http.Request, writer http.ResponseWriter) io.Writer
return gziper return gziper
} }
func (registry *registry) YieldExporter() http.HandlerFunc { func (r *registry) YieldExporter() http.HandlerFunc {
log.Println("Registry.YieldExporter is deprecated in favor of Registry.Handler.") log.Println("Registry.YieldExporter is deprecated in favor of Registry.Handler.")
return registry.Handler() return r.Handler()
} }
func (r *registry) dumpDelimitedPB(w io.Writer) { func (r *registry) dumpDelimitedPB(w io.Writer) {
@ -311,20 +311,20 @@ func (r *registry) dumpDelimitedExternalPB(w io.Writer) {
} }
} }
func (registry *registry) Handler() http.HandlerFunc { func (r *registry) Handler() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, req *http.Request) {
defer requestLatencyAccumulator(time.Now()) defer requestLatencyAccumulator(time.Now())
requestCount.Increment(nil) requestCount.Increment(nil)
header := w.Header() header := w.Header()
writer := decorateWriter(r, w) writer := decorateWriter(req, w)
if closer, ok := writer.(io.Closer); ok { if closer, ok := writer.(io.Closer); ok {
defer closer.Close() defer closer.Close()
} }
accepts := goautoneg.ParseAccept(r.Header.Get("Accept")) accepts := goautoneg.ParseAccept(req.Header.Get("Accept"))
for _, accept := range accepts { for _, accept := range accepts {
if accept.Type != "application" { if accept.Type != "application" {
continue continue
@ -339,14 +339,14 @@ func (registry *registry) Handler() http.HandlerFunc {
} }
header.Set(contentTypeHeader, DelimitedTelemetryContentType) header.Set(contentTypeHeader, DelimitedTelemetryContentType)
registry.dumpDelimitedPB(writer) r.dumpDelimitedPB(writer)
registry.dumpDelimitedExternalPB(writer) r.dumpDelimitedExternalPB(writer)
return return
} }
} }
header.Set(contentTypeHeader, TelemetryContentType) header.Set(contentTypeHeader, TelemetryContentType)
json.NewEncoder(writer).Encode(registry) json.NewEncoder(writer).Encode(r)
} }
} }