mirror of
https://github.com/golang/go
synced 2024-11-19 11:44:45 -07:00
be03d4f470
This change attaches start timestamps to timeseries and end timestamps to the points in each timeseries. Int64Data, Float64Data, HistogramInt64Data, and HistogramFloat64Data have also had an EndTime field added to keep track of the last time the metric was updated. What works: * Start and end timestamps will now be attached to timeseries. What does not work yet: * MetricDescriptors will not have a unit attached. * No labels will be attached to timeseries. * Distributions will not have SumOfSquaredDeviation attached. Updates golang/go#33819 Change-Id: I692e1676bb1e31de26c1f799b96428fc9a55d6c7 Reviewed-on: https://go-review.googlesource.com/c/tools/+/203060 Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
215 lines
5.4 KiB
Go
215 lines
5.4 KiB
Go
// Copyright 2019 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package ocagent
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"golang.org/x/tools/internal/telemetry"
|
|
"golang.org/x/tools/internal/telemetry/export/ocagent/wire"
|
|
"golang.org/x/tools/internal/telemetry/metric"
|
|
)
|
|
|
|
// dataToMetricDescriptor return a *wire.MetricDescriptor based on data.
|
|
func dataToMetricDescriptor(data telemetry.MetricData) *wire.MetricDescriptor {
|
|
if data == nil {
|
|
return nil
|
|
}
|
|
descriptor := &wire.MetricDescriptor{
|
|
Name: data.Handle(),
|
|
Description: getDescription(data),
|
|
// TODO: Unit?
|
|
Type: dataToMetricDescriptorType(data),
|
|
LabelKeys: getLabelKeys(data),
|
|
}
|
|
|
|
return descriptor
|
|
}
|
|
|
|
// getDescription returns the description of data.
|
|
func getDescription(data telemetry.MetricData) string {
|
|
switch d := data.(type) {
|
|
case *metric.Int64Data:
|
|
return d.Info.Description
|
|
|
|
case *metric.Float64Data:
|
|
return d.Info.Description
|
|
|
|
case *metric.HistogramInt64Data:
|
|
return d.Info.Description
|
|
|
|
case *metric.HistogramFloat64Data:
|
|
return d.Info.Description
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
// getLabelKeys returns a slice of *wire.LabelKeys based on the keys
|
|
// in data.
|
|
func getLabelKeys(data telemetry.MetricData) []*wire.LabelKey {
|
|
switch d := data.(type) {
|
|
case *metric.Int64Data:
|
|
return infoKeysToLabelKeys(d.Info.Keys)
|
|
|
|
case *metric.Float64Data:
|
|
return infoKeysToLabelKeys(d.Info.Keys)
|
|
|
|
case *metric.HistogramInt64Data:
|
|
return infoKeysToLabelKeys(d.Info.Keys)
|
|
|
|
case *metric.HistogramFloat64Data:
|
|
return infoKeysToLabelKeys(d.Info.Keys)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// dataToMetricDescriptorType returns a wire.MetricDescriptor_Type based on the
|
|
// underlying type of data.
|
|
func dataToMetricDescriptorType(data telemetry.MetricData) wire.MetricDescriptor_Type {
|
|
switch d := data.(type) {
|
|
case *metric.Int64Data:
|
|
if d.IsGauge {
|
|
return wire.MetricDescriptor_GAUGE_INT64
|
|
}
|
|
return wire.MetricDescriptor_CUMULATIVE_INT64
|
|
|
|
case *metric.Float64Data:
|
|
if d.IsGauge {
|
|
return wire.MetricDescriptor_GAUGE_DOUBLE
|
|
}
|
|
return wire.MetricDescriptor_CUMULATIVE_DOUBLE
|
|
|
|
case *metric.HistogramInt64Data:
|
|
return wire.MetricDescriptor_CUMULATIVE_DISTRIBUTION
|
|
|
|
case *metric.HistogramFloat64Data:
|
|
return wire.MetricDescriptor_CUMULATIVE_DISTRIBUTION
|
|
}
|
|
|
|
return wire.MetricDescriptor_UNSPECIFIED
|
|
}
|
|
|
|
// dataToTimeseries returns a slice of *wire.TimeSeries based on the
|
|
// points in data.
|
|
func dataToTimeseries(data telemetry.MetricData, start time.Time) []*wire.TimeSeries {
|
|
if data == nil {
|
|
return nil
|
|
}
|
|
|
|
numRows := numRows(data)
|
|
startTimestamp := convertTimestamp(start)
|
|
timeseries := make([]*wire.TimeSeries, 0, numRows)
|
|
|
|
for i := 0; i < numRows; i++ {
|
|
timeseries = append(timeseries, &wire.TimeSeries{
|
|
StartTimestamp: &startTimestamp,
|
|
// TODO: labels?
|
|
Points: dataToPoints(data, i),
|
|
})
|
|
}
|
|
|
|
return timeseries
|
|
}
|
|
|
|
// numRows returns the number of rows in data.
|
|
func numRows(data telemetry.MetricData) int {
|
|
switch d := data.(type) {
|
|
case *metric.Int64Data:
|
|
return len(d.Rows)
|
|
case *metric.Float64Data:
|
|
return len(d.Rows)
|
|
case *metric.HistogramInt64Data:
|
|
return len(d.Rows)
|
|
case *metric.HistogramFloat64Data:
|
|
return len(d.Rows)
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
// dataToPoints returns an array of *wire.Points based on the point(s)
|
|
// in data at index i.
|
|
func dataToPoints(data telemetry.MetricData, i int) []*wire.Point {
|
|
switch d := data.(type) {
|
|
case *metric.Int64Data:
|
|
timestamp := convertTimestamp(*d.EndTime)
|
|
return []*wire.Point{
|
|
{
|
|
Value: wire.PointInt64Value{
|
|
Int64Value: d.Rows[i],
|
|
},
|
|
Timestamp: ×tamp,
|
|
},
|
|
}
|
|
case *metric.Float64Data:
|
|
timestamp := convertTimestamp(*d.EndTime)
|
|
return []*wire.Point{
|
|
{
|
|
Value: wire.PointDoubleValue{
|
|
DoubleValue: d.Rows[i],
|
|
},
|
|
Timestamp: ×tamp,
|
|
},
|
|
}
|
|
case *metric.HistogramInt64Data:
|
|
row := d.Rows[i]
|
|
bucketBounds := make([]float64, len(d.Info.Buckets))
|
|
for i, val := range d.Info.Buckets {
|
|
bucketBounds[i] = float64(val)
|
|
}
|
|
return distributionToPoints(row.Values, row.Count, float64(row.Sum), bucketBounds, *d.EndTime)
|
|
case *metric.HistogramFloat64Data:
|
|
row := d.Rows[i]
|
|
return distributionToPoints(row.Values, row.Count, row.Sum, d.Info.Buckets, *d.EndTime)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// distributionToPoints returns an array of *wire.Points containing a
|
|
// wire.PointDistributionValue representing a distribution with the
|
|
// supplied counts, count, and sum.
|
|
func distributionToPoints(counts []int64, count int64, sum float64, bucketBounds []float64, end time.Time) []*wire.Point {
|
|
buckets := make([]*wire.Bucket, len(counts))
|
|
for i := 0; i < len(counts); i++ {
|
|
buckets[i] = &wire.Bucket{
|
|
Count: counts[i],
|
|
}
|
|
}
|
|
timestamp := convertTimestamp(end)
|
|
return []*wire.Point{
|
|
{
|
|
Value: wire.PointDistributionValue{
|
|
DistributionValue: &wire.DistributionValue{
|
|
Count: count,
|
|
Sum: sum,
|
|
// TODO: SumOfSquaredDeviation?
|
|
Buckets: buckets,
|
|
BucketOptions: wire.BucketOptionsExplicit{
|
|
Bounds: bucketBounds,
|
|
},
|
|
},
|
|
},
|
|
Timestamp: ×tamp,
|
|
},
|
|
}
|
|
}
|
|
|
|
// infoKeysToLabelKeys returns an array of *wire.LabelKeys containing the
|
|
// string values of the elements of labelKeys.
|
|
func infoKeysToLabelKeys(infoKeys []interface{}) []*wire.LabelKey {
|
|
labelKeys := make([]*wire.LabelKey, 0, len(infoKeys))
|
|
for _, key := range infoKeys {
|
|
labelKeys = append(labelKeys, &wire.LabelKey{
|
|
Key: fmt.Sprintf("%v", key),
|
|
})
|
|
}
|
|
|
|
return labelKeys
|
|
}
|