forked from census-instrumentation/opencensus-go
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add metric API (census-instrumentation#975)
- Loading branch information
Ramon Nogueira
committed
Nov 20, 2018
1 parent
91a0276
commit a91cf18
Showing
9 changed files
with
497 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Copyright 2018, OpenCensus 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 metric contains a data model and exporter support for metrics. | ||
package metric // import "go.opencensus.io/metric" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// Copyright 2018, OpenCensus 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 metric | ||
|
||
import ( | ||
"time" | ||
|
||
"go.opencensus.io/resource" | ||
) | ||
|
||
// LabelValue represents the value of a label. A missing value (nil) is distinct | ||
// from an empty string value. | ||
type LabelValue *string | ||
|
||
// NewLabelValue creates a new non-nil LabelValue that represents the given string. | ||
func NewLabelValue(val string) LabelValue { | ||
return &val | ||
} | ||
|
||
// Descriptor holds metadata about a metric. | ||
type Descriptor struct { | ||
Name string // full name of the metric | ||
Description string // human-readable description | ||
Unit Unit // units for the measure | ||
Type Type // type of measure | ||
LabelKeys []string // label keys | ||
} | ||
|
||
// Metric represents a quantity measured against a resource with different | ||
// label value combinations. | ||
type Metric struct { | ||
Descriptor Descriptor // metric descriptor | ||
Resource *resource.Resource // resource against which this was measured | ||
TimeSeries []*TimeSeries // one time series for each combination of label values | ||
} | ||
|
||
// TimeSeries is a sequence of points associated with a combination of label | ||
// values. | ||
type TimeSeries struct { | ||
LabelValues []LabelValue // label values, same order as keys in the metric descriptor | ||
Points []Point // points sequence | ||
StartTime time.Time // time we started recording this time series | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,239 @@ | ||
// Copyright 2018, OpenCensus 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 metric | ||
|
||
import ( | ||
"time" | ||
|
||
"go.opencensus.io/exemplar" | ||
) | ||
|
||
// Point is a single data point of a time series. | ||
type Point struct { | ||
// Time is the point in time that this point represents in a time series. | ||
Time time.Time | ||
// ValueType is the type of value held in this point. | ||
ValueType ValueType | ||
// Value is the value of this point. Prefer using ReadValue to switching on | ||
// the value type, since new value types might be added. | ||
Value interface{} | ||
} | ||
|
||
//go:generate stringer -type ValueType | ||
|
||
// ValueType is the type of value held in a point. | ||
type ValueType int | ||
|
||
// Value types. New value types may be added. | ||
const ( | ||
ValueTypeFloat64 ValueType = iota | ||
ValueTypeInt64 | ||
ValueTypeDistribution | ||
ValueTypeSummary | ||
) | ||
|
||
// NewFloat64Point creates a new Point holding a float64 value. | ||
func NewFloat64Point(t time.Time, val float64) Point { | ||
return Point{ | ||
ValueType: ValueTypeFloat64, | ||
Value: val, | ||
Time: t, | ||
} | ||
} | ||
|
||
// NewInt64Point creates a new Point holding an int64 value. | ||
func NewInt64Point(t time.Time, val int64) Point { | ||
return Point{ | ||
ValueType: ValueTypeInt64, | ||
Value: val, | ||
Time: t, | ||
} | ||
} | ||
|
||
// NewDistributionPoint creates a new Point holding a Distribution value. | ||
func NewDistributionPoint(t time.Time, val *Distribution) Point { | ||
return Point{ | ||
ValueType: ValueTypeDistribution, | ||
Value: val, | ||
Time: t, | ||
} | ||
} | ||
|
||
// NewSummaryPoint creates a new Point holding a Summary value. | ||
func NewSummaryPoint(t time.Time, val *Summary) Point { | ||
return Point{ | ||
ValueType: ValueTypeSummary, | ||
Value: val, | ||
Time: t, | ||
} | ||
} | ||
|
||
// ValueVisitor allows reading the value of a point. | ||
type ValueVisitor interface { | ||
VisitFloat64Value(float64) | ||
VisitInt64Value(int64) | ||
VisitDistributionValue(*Distribution) | ||
VisitSummaryValue(*Summary) | ||
} | ||
|
||
// ReadValue accepts a ValueVisitor and calls the appropriate method with the | ||
// value of this point. | ||
// Consumers of Point should use this in preference to switching on the type | ||
// of the value directly, since new value types may be added. | ||
func (p Point) ReadValue(vv ValueVisitor) { | ||
switch v := p.Value.(type) { | ||
case int64: | ||
vv.VisitInt64Value(v) | ||
case float64: | ||
vv.VisitFloat64Value(v) | ||
case *Distribution: | ||
vv.VisitDistributionValue(v) | ||
case *Summary: | ||
vv.VisitSummaryValue(v) | ||
default: | ||
panic("unexpected value type") | ||
} | ||
} | ||
|
||
// Distribution contains summary statistics for a population of values. It | ||
// optionally contains a histogram representing the distribution of those | ||
// values across a set of buckets. | ||
type Distribution struct { | ||
// Count is the number of values in the population. Must be non-negative. This value | ||
// must equal the sum of the values in bucket_counts if a histogram is | ||
// provided. | ||
Count int64 | ||
// Sum is the sum of the values in the population. If count is zero then this field | ||
// must be zero. | ||
Sum float64 | ||
// SumOfSquaredDeviation is the sum of squared deviations from the mean of the values in the | ||
// population. For values x_i this is: | ||
// | ||
// Sum[i=1..n]((x_i - mean)^2) | ||
// | ||
// Knuth, "The Art of Computer Programming", Vol. 2, page 323, 3rd edition | ||
// describes Welford's method for accumulating this sum in one pass. | ||
// | ||
// If count is zero then this field must be zero. | ||
SumOfSquaredDeviation float64 | ||
// BucketOptions describes the bounds of the histogram buckets in this | ||
// distribution. | ||
// | ||
// A Distribution may optionally contain a histogram of the values in the | ||
// population. | ||
// | ||
// If nil, there is no associated histogram. | ||
BucketOptions *BucketOptions | ||
// Bucket If the distribution does not have a histogram, then omit this field. | ||
// If there is a histogram, then the sum of the values in the Bucket counts | ||
// must equal the value in the count field of the distribution. | ||
Buckets []Bucket | ||
} | ||
|
||
// BucketOptions describes the bounds of the histogram buckets in this | ||
// distribution. | ||
type BucketOptions struct { | ||
// Bounds specifies a set of buckets with arbitrary upper-bounds. | ||
// This defines len(bounds) + 1 (= N) buckets. The boundaries for bucket | ||
// index i are: | ||
// | ||
// [0, Bounds[i]) for i == 0 | ||
// [Bounds[i-1], Bounds[i]) for 0 < i < N-1 | ||
// [Bounds[i-1], +infinity) for i == N-1 | ||
Bounds []float64 | ||
} | ||
|
||
// Bucket represents a single bucket (value range) in a distribution. | ||
type Bucket struct { | ||
// Count is the number of values in each bucket of the histogram, as described in | ||
// bucket_bounds. | ||
Count int64 | ||
// Exemplar associated with this bucket (if any). | ||
Exemplar *exemplar.Exemplar | ||
} | ||
|
||
// Summary is a representation of percentiles. | ||
type Summary struct { | ||
// Count is the cumulative count (if available). | ||
Count int64 | ||
// Sum is the cumulative sum of values (if available). | ||
Sum float64 | ||
// HasCountAndSum is true if Count and Sum are available. | ||
HasCountAndSum bool | ||
// Snapshot represents percentiles calculated over an arbitrary time window. | ||
// The values in this struct can be reset at arbitrary unknown times, with | ||
// the requirement that all of them are reset at the same time. | ||
Snapshot Snapshot | ||
} | ||
|
||
// Snapshot represents percentiles over an arbitrary time. | ||
// The values in this struct can be reset at arbitrary unknown times, with | ||
// the requirement that all of them are reset at the same time. | ||
type Snapshot struct { | ||
// Count is the number of values in the snapshot. Optional since some systems don't | ||
// expose this. Set to 0 if not available. | ||
Count int64 | ||
// Sum is the sum of values in the snapshot. Optional since some systems don't | ||
// expose this. If count is 0 then this field must be zero. | ||
Sum float64 | ||
// Percentiles is a map from percentile (range (0-100.0]) to the value of | ||
// the percentile. | ||
Percentiles map[float64]float64 | ||
} | ||
|
||
//go:generate stringer -type Type | ||
|
||
// Type is the overall type of metric, including its value type and whether it | ||
// represents a cumulative total (since the start time) or if it represents a | ||
// gauge value. | ||
type Type int | ||
|
||
// Metric types. | ||
const ( | ||
TypeGaugeInt64 Type = iota | ||
TypeGaugeFloat64 | ||
TypeGaugeDistribution | ||
TypeCumulativeInt64 | ||
TypeCumulativeFloat64 | ||
TypeCumulativeDistribution | ||
TypeSummary | ||
) | ||
|
||
// IsGuage returns true if the metric type represents a gauge-type value. | ||
func (t Type) IsGuage() bool { | ||
switch t { | ||
case TypeGaugeInt64, TypeGaugeFloat64, TypeGaugeDistribution: | ||
return true | ||
default: | ||
return false | ||
} | ||
} | ||
|
||
// ValueType returns the type of value of the points of metrics of the receiver | ||
// type. | ||
func (t Type) ValueType() ValueType { | ||
switch t { | ||
case TypeGaugeFloat64, TypeCumulativeFloat64: | ||
return ValueTypeFloat64 | ||
case TypeGaugeDistribution, TypeCumulativeDistribution: | ||
return ValueTypeDistribution | ||
case TypeGaugeInt64, TypeCumulativeInt64: | ||
return ValueTypeInt64 | ||
case TypeSummary: | ||
return ValueTypeSummary | ||
default: | ||
panic("unexpected metric.Type value") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// Copyright 2018, OpenCensus 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 metric | ||
|
||
import ( | ||
"sync" | ||
) | ||
|
||
// Producer is a source of metrics. | ||
type Producer interface { | ||
// Read should return the current values of all metrics supported by this | ||
// metric provider. | ||
// The returned metrics should be unique for each combination of name and | ||
// resource. | ||
Read() []*Metric | ||
} | ||
|
||
// Registry maintains a set of metric producers for exporting. Most users will | ||
// rely on the DefaultRegistry. | ||
type Registry struct { | ||
mu sync.RWMutex | ||
sources map[*uintptr]Producer | ||
ind uint64 | ||
} | ||
|
||
var _ Producer = (*Registry)(nil) | ||
|
||
// NewRegistry creates a new Registry. | ||
func NewRegistry() *Registry { | ||
m := &Registry{ | ||
sources: make(map[*uintptr]Producer), | ||
ind: 0, | ||
} | ||
return m | ||
} | ||
|
||
// Read returns all the metrics from all the metric produces in this registry. | ||
func (m *Registry) Read() []*Metric { | ||
m.mu.RLock() | ||
defer m.mu.RUnlock() | ||
ms := make([]*Metric, 0, len(m.sources)) | ||
for _, s := range m.sources { | ||
ms = append(ms, s.Read()...) | ||
} | ||
return ms | ||
} | ||
|
||
// AddProducer adds a producer to this registry. | ||
func (m *Registry) AddProducer(source Producer) (remove func()) { | ||
m.mu.Lock() | ||
defer m.mu.Unlock() | ||
if source == m { | ||
panic("attempt to add registry to itself") | ||
} | ||
tok := new(uintptr) | ||
m.sources[tok] = source | ||
return func() { | ||
m.mu.Lock() | ||
defer m.mu.Unlock() | ||
delete(m.sources, tok) | ||
} | ||
} | ||
|
||
var defaultReg = NewRegistry() | ||
|
||
// DefaultRegistry returns the default, global metric registry for the current | ||
// process. | ||
// Most applications will rely on this registry but libraries should not assume | ||
// the default registry is used. | ||
func DefaultRegistry() *Registry { | ||
return defaultReg | ||
} |
Oops, something went wrong.