diff --git a/exporter/prometheus/prometheus.go b/exporter/prometheus/prometheus.go index a3924b550..1496c3f5c 100644 --- a/exporter/prometheus/prometheus.go +++ b/exporter/prometheus/prometheus.go @@ -239,6 +239,8 @@ func (c *collector) toMetric(desc *prometheus.Desc, v *view.View, row *view.Row) return prometheus.NewConstHistogram(desc, uint64(data.Count), data.Sum(), points, tagValues(row.Tags)...) case *view.SumData: return prometheus.NewConstMetric(desc, prometheus.UntypedValue, float64(*data), tagValues(row.Tags)...) + case *view.LastValueData: + return prometheus.NewConstMetric(desc, prometheus.UntypedValue, data.Value, tagValues(row.Tags)...) default: return nil, fmt.Errorf("aggregation %T is not yet supported", v.Aggregation) } diff --git a/exporter/stackdriver/stats.go b/exporter/stackdriver/stats.go index a3c7f0f9a..43475d6b1 100644 --- a/exporter/stackdriver/stats.go +++ b/exporter/stackdriver/stats.go @@ -263,6 +263,8 @@ func (e *statsExporter) createMeasure(ctx context.Context, vd *view.Data) error } case view.AggTypeDistribution: valueType = metricpb.MetricDescriptor_DISTRIBUTION + case view.AggTypeLastValue: + valueType = metricpb.MetricDescriptor_DOUBLE default: return fmt.Errorf("unsupported aggregation type: %s", agg.Type.String()) } @@ -348,6 +350,10 @@ func newTypedValue(vd *view.View, r *view.Row) *monitoringpb.TypedValue { BucketCounts: v.CountPerBucket, }, }} + case *view.LastValueData: + return &monitoringpb.TypedValue{Value: &monitoringpb.TypedValue_DoubleValue{ + DoubleValue: v.Value, + }} } return nil } diff --git a/exporter/stackdriver/stats_test.go b/exporter/stackdriver/stats_test.go index d39473dce..814dd6813 100644 --- a/exporter/stackdriver/stats_test.go +++ b/exporter/stackdriver/stats_test.go @@ -97,6 +97,8 @@ func TestExporter_makeReq(t *testing.T) { count2 := view.CountData(16) sum1 := view.SumData(5.5) sum2 := view.SumData(-11.1) + last1 := view.LastValueData{Value: 100} + last2 := view.LastValueData{Value: 200} taskValue := getTaskValue() tests := []struct { @@ -241,6 +243,74 @@ func TestExporter_makeReq(t *testing.T) { }, }}, }, + { + name: "last value agg", + projID: "proj-id", + vd: newTestViewData(v, start, end, &last1, &last2), + want: []*monitoringpb.CreateTimeSeriesRequest{{ + Name: monitoring.MetricProjectPath("proj-id"), + TimeSeries: []*monitoringpb.TimeSeries{ + { + Metric: &metricpb.Metric{ + Type: "custom.googleapis.com/opencensus/testview", + Labels: map[string]string{ + "test_key": "test-value-1", + opencensusTaskKey: taskValue, + }, + }, + Resource: &monitoredrespb.MonitoredResource{ + Type: "global", + }, + Points: []*monitoringpb.Point{ + { + Interval: &monitoringpb.TimeInterval{ + StartTime: ×tamp.Timestamp{ + Seconds: start.Unix(), + Nanos: int32(start.Nanosecond()), + }, + EndTime: ×tamp.Timestamp{ + Seconds: end.Unix(), + Nanos: int32(end.Nanosecond()), + }, + }, + Value: &monitoringpb.TypedValue{Value: &monitoringpb.TypedValue_DoubleValue{ + DoubleValue: 100, + }}, + }, + }, + }, + { + Metric: &metricpb.Metric{ + Type: "custom.googleapis.com/opencensus/testview", + Labels: map[string]string{ + "test_key": "test-value-2", + opencensusTaskKey: taskValue, + }, + }, + Resource: &monitoredrespb.MonitoredResource{ + Type: "global", + }, + Points: []*monitoringpb.Point{ + { + Interval: &monitoringpb.TimeInterval{ + StartTime: ×tamp.Timestamp{ + Seconds: start.Unix(), + Nanos: int32(start.Nanosecond()), + }, + EndTime: ×tamp.Timestamp{ + Seconds: end.Unix(), + Nanos: int32(end.Nanosecond()), + }, + }, + Value: &monitoringpb.TypedValue{Value: &monitoringpb.TypedValue_DoubleValue{ + DoubleValue: 200, + }}, + }, + }, + }, + }, + }}, + }, { name: "dist agg + time window", projID: "proj-id",