-
Notifications
You must be signed in to change notification settings - Fork 328
Add metric API #975
Add metric API #975
Conversation
The follow-ups are here: https://github.com/ramonza/opencensus-go/pulls |
@rakyll split up the PR, PTAL |
func NewRegistry() *Registry { | ||
m := &Registry{ | ||
sources: make(map[*uintptr]Producer), | ||
ind: 0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused remainder from before the uintptr
trick :)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few high level comments.
metric/doc.go
Outdated
|
||
// Package metric contains a data model and exporter support for metrics. | ||
// The data model is derived from the metric protocol buffers: | ||
// https://github.com/census-instrumentation/opencensus-proto/blob/master/src/opencensus/proto/metrics/v1/metrics.proto |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
User doesn't have to know about the proto, please remove this.
|
||
// LabelValue represents the value of a label. A missing value (nil) is distinct | ||
// from an empty string value. | ||
type LabelValue *string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a unlikely type. Why not simply type LabelValue { Value string }
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The intention here is to be able to represent no value (nil) and empty string value distinctly. The protobuf does this, so we need to as well to be compatible. Using a type like you suggest would not allow us to represent these two distinctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Protobuf types are not an idiomatic due to the limitations and code-generation nature of the problem. In handcrafted libraries, we are doing better than proto.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We proposed to replace with this with struct { Value string, HasValue bool }
to differentiate between "missing" and an empty string value.
// from an empty string value. | ||
type LabelValue *string | ||
|
||
// NewLabelValue creates a new non-nil LabelValue that represents the given string. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This becomes if the type changes.
LabelValue{ Value: "val" } would just work.
metric/point.go
Outdated
// [0, bucket_bounds[i]) for i == 0 | ||
// [bucket_bounds[i-1], bucket_bounds[i]) for 0 < i < N-1 | ||
// [bucket_bounds[i-1], +infinity) for i == N-1 | ||
ExplicitBoundaries []float64 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just Boundaries?
metric/point.go
Outdated
) | ||
|
||
// NewDoublePoint creates a new Point holding a float64 value. | ||
func NewDoublePoint(t time.Time, val float64) Point { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NewFloat64Point
m.mu.Lock() | ||
defer m.mu.Unlock() | ||
if source == m { | ||
panic("attempt to add registry to itself") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this statically possible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*Registry implements Producer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The question is it might be broken to make Registry implementing Read() []*Metric.
Can't we make it implement ReadAll() []*Metric to differentiate it from the producers? Otherwise, we should introduce a MultiProducer a la io.MultiReader instead of this type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will rename
metric/metric.go
Outdated
// Metric represents a quantity measured against a resource with different | ||
// label value combinations. | ||
type Metric struct { | ||
Descriptor *Descriptor // metric descriptor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Descriptor Descriptor
No need for a pointer.
// 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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this something that exporters would use? If yes, maybe we shouldn't have it in this package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is. This whole package is mostly for use by exporters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any end to end example usage for the new APIs here? It is not clear what the package is for. If it is mainly for the exporters, we shouldn't use a top-level package like "metric" where we would like to put the developer-facing APIs to.
@@ -0,0 +1,11 @@ | |||
package metric |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing license.
@@ -0,0 +1,29 @@ | |||
package metric |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing license.
LGTM |
This reverts commit a91cf18. The API was merged without an API review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reverted this change because they are open issues, and left some more comments. 296c89c
Please provide a few end to end examples so we can see the call sites. We can discuss the APIs on a design doc if it works better.
|
||
// LabelValue represents the value of a label. A missing value (nil) is distinct | ||
// from an empty string value. | ||
type LabelValue *string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Protobuf types are not an idiomatic due to the limitations and code-generation nature of the problem. In handcrafted libraries, we are doing better than proto.
m.mu.Lock() | ||
defer m.mu.Unlock() | ||
if source == m { | ||
panic("attempt to add registry to itself") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The question is it might be broken to make Registry implementing Read() []*Metric.
Can't we make it implement ReadAll() []*Metric to differentiate it from the producers? Otherwise, we should introduce a MultiProducer a la io.MultiReader instead of this type.
// rely on the DefaultRegistry. | ||
type Registry struct { | ||
mu sync.RWMutex | ||
sources map[*uintptr]Producer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In what case? Also why a pointer to uintptr?
// 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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any end to end example usage for the new APIs here? It is not clear what the package is for. If it is mainly for the exporters, we shouldn't use a top-level package like "metric" where we would like to put the developer-facing APIs to.
No description provided.