-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Metrics proposal for Go #2
Conversation
Invalid Type = iota | ||
Gauge // Supports Set() | ||
Cumulative // Supports Inc(): only positive values | ||
Additive // Supports Add(): positive or negative |
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.
Additive and Gauge can be unified.
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.
They could be. I was hoping to make there be a 1:1 mapping between measured value and the interpretation. If we decide to keep a Stats API (i.e., reject RFC 0003), then I feel strongly that the Metrics API should be layered on top of the Stats API, so there should be a 1:1 mapping from a metrics update into a lower-level stats measurement. If we combine Additive and Gauge, for example, then I need to know the kind of operation in order to interpret a statistic. By allowing the Additive and Gauge to be separate metric types, I can layer Metrics on top of Stats, because each Measure has only one kind. I.e., there's not a mixture of Set() and Add() calls in the same stream of measurements.
Cumulative // Supports Inc() | ||
Invalid Type = iota | ||
Gauge // Supports Set() | ||
Cumulative // Supports Inc(): only positive values |
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.
Cumulative also needs a set, because the classic example for this is CPU usage. If you want to report a CPU usage it is always going up (unless you do a CumulativeGauge that remembers the previous value and Inc delta).
SUM | ||
COUNT | ||
MIN | ||
MAX |
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 min/max? Where is this used?
MIN | ||
MAX | ||
LAST_VALUE | ||
DISTRIBUTION |
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.
For a distribution if a histogram is used user requires to also configure the buckets. If a summary is used user requires to configure the percentiles. So I cannot see how this is used.
return "unknown" | ||
// WithAggregation applies a user-recommended aggregation to this | ||
// metric, useful particularly for Measure type metrics. | ||
func WithAggregation(aggr aggregation.Operator) Option { |
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 not compatible with OpenCensus stats which is a primary requirement for this, because we need to not allow the instrumentation plugin to define the aggregation.
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 not a definition. This is a recommendation. The SDK is not bound to follow this advice. If this value is not set, the default aggregation for MeasureMetrics is None
. I like this because the application programmer can suggest None
as a good aggregation for measure metrics, but could also suggest Distribution
.
@@ -25,10 +25,16 @@ var ( | |||
) | |||
|
|||
func SetCurrentSpan(ctx context.Context, span Span) context.Context { | |||
if ctx == nil { |
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 these changes?
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 my exporter, I want to know the current span in order to annotate the span data with accumulated metrics, grouped by span_id. I want this to happen for all callers, without the programmer having to do anything. So this check avoids a crash when you ask for the current span and there's no context.
) | ||
|
||
type Meter interface { | ||
// TODO more Metric types | ||
GetFloat64Gauge(ctx context.Context, gauge *Float64GaugeHandle, labels ...core.KeyValue) Float64Gauge | ||
GetFloat64Gauge(context.Context, *Float64GaugeHandle, ...core.KeyValue) Float64Gauge |
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 a context in this case?
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 allows context tags to be recorded, in case the SDK wants to do that. In addition, it allows us to associate the current active span with the measurement, which means we can reflect this metric update in the recorded span data, for example.
type Float64Measure interface { | ||
Record(ctx context.Context, value float64, labels ...core.KeyValue) | ||
} | ||
|
||
type Handle struct { |
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.
What is a Handle? why does this exist?
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.
A handle is a common base type for any of the metrics. In this proposal, the only API difference between the metric types is the verb they use, the interpretation is left to the SDK. So the Handle
is a thing that describes the metric independently of its verb or metric type. The properties of a metric are: variable (name), type (gauge, additive, cumulative, or measure), keys (recommended), and aggregation (recommended).
Invalid Type = iota | ||
Gauge // Supports Set() | ||
Cumulative // Supports Inc(): only positive values | ||
Additive // Supports Add(): positive or negative |
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.
They could be. I was hoping to make there be a 1:1 mapping between measured value and the interpretation. If we decide to keep a Stats API (i.e., reject RFC 0003), then I feel strongly that the Metrics API should be layered on top of the Stats API, so there should be a 1:1 mapping from a metrics update into a lower-level stats measurement. If we combine Additive and Gauge, for example, then I need to know the kind of operation in order to interpret a statistic. By allowing the Additive and Gauge to be separate metric types, I can layer Metrics on top of Stats, because each Measure has only one kind. I.e., there's not a mixture of Set() and Add() calls in the same stream of measurements.
) | ||
|
||
type Meter interface { | ||
// TODO more Metric types | ||
GetFloat64Gauge(ctx context.Context, gauge *Float64GaugeHandle, labels ...core.KeyValue) Float64Gauge | ||
GetFloat64Gauge(context.Context, *Float64GaugeHandle, ...core.KeyValue) Float64Gauge |
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 allows context tags to be recorded, in case the SDK wants to do that. In addition, it allows us to associate the current active span with the measurement, which means we can reflect this metric update in the recorded span data, for example.
type Float64Measure interface { | ||
Record(ctx context.Context, value float64, labels ...core.KeyValue) | ||
} | ||
|
||
type Handle struct { |
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.
A handle is a common base type for any of the metrics. In this proposal, the only API difference between the metric types is the verb they use, the interpretation is left to the SDK. So the Handle
is a thing that describes the metric independently of its verb or metric type. The properties of a metric are: variable (name), type (gauge, additive, cumulative, or measure), keys (recommended), and aggregation (recommended).
return "unknown" | ||
// WithAggregation applies a user-recommended aggregation to this | ||
// metric, useful particularly for Measure type metrics. | ||
func WithAggregation(aggr aggregation.Operator) Option { |
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 not a definition. This is a recommendation. The SDK is not bound to follow this advice. If this value is not set, the default aggregation for MeasureMetrics is None
. I like this because the application programmer can suggest None
as a good aggregation for measure metrics, but could also suggest Distribution
.
@@ -25,10 +25,16 @@ var ( | |||
) | |||
|
|||
func SetCurrentSpan(ctx context.Context, span Span) context.Context { | |||
if ctx == nil { |
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 my exporter, I want to know the current span in order to annotate the span data with accumulated metrics, grouped by span_id. I want this to happen for all callers, without the programmer having to do anything. So this check avoids a crash when you ask for the current span and there's no context.
read.Type = event.Type | ||
|
||
if event.Context != nil { | ||
span := trace.CurrentSpan(event.Context) |
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.
Here, this is where the metric update is associated with a current span. This would be a nil
context if for some reason the programmer passed a nil to the metrics APIs.
* Add MinMaxSumCount stress test * Reimplement MinMaxSumCount using StateLocker * Address PR comments * Round #2 of PR comments Co-authored-by: Rahul Patel <rahulpa@google.com>
* Add ExportTimeout option * Adjust tests * Update CHANGELOG * Beef up the exporter timeout test * Beef up exporter test - attempt #2 Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>
This implements a proof-of-concept for https://github.com/open-telemetry/rfcs/pull/4}
See examples/grpc/metrics.go for how the gRPC metrics translate from
https://github.com/census-instrumentation/opencensus-specs/blob/master/stats/gRPC.md