1 // Copyright 2019 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
10 "golang.org/x/tools/internal/event/export/metric"
11 "golang.org/x/tools/internal/event/export/ocagent/wire"
12 "golang.org/x/tools/internal/event/label"
15 // dataToMetricDescriptor return a *wire.MetricDescriptor based on data.
16 func dataToMetricDescriptor(data metric.Data) *wire.MetricDescriptor {
20 descriptor := &wire.MetricDescriptor{
22 Description: getDescription(data),
24 Type: dataToMetricDescriptorType(data),
25 LabelKeys: getLabelKeys(data),
31 // getDescription returns the description of data.
32 func getDescription(data metric.Data) string {
33 switch d := data.(type) {
34 case *metric.Int64Data:
35 return d.Info.Description
37 case *metric.Float64Data:
38 return d.Info.Description
40 case *metric.HistogramInt64Data:
41 return d.Info.Description
43 case *metric.HistogramFloat64Data:
44 return d.Info.Description
50 // getLabelKeys returns a slice of *wire.LabelKeys based on the keys
52 func getLabelKeys(data metric.Data) []*wire.LabelKey {
53 switch d := data.(type) {
54 case *metric.Int64Data:
55 return infoKeysToLabelKeys(d.Info.Keys)
57 case *metric.Float64Data:
58 return infoKeysToLabelKeys(d.Info.Keys)
60 case *metric.HistogramInt64Data:
61 return infoKeysToLabelKeys(d.Info.Keys)
63 case *metric.HistogramFloat64Data:
64 return infoKeysToLabelKeys(d.Info.Keys)
70 // dataToMetricDescriptorType returns a wire.MetricDescriptor_Type based on the
71 // underlying type of data.
72 func dataToMetricDescriptorType(data metric.Data) wire.MetricDescriptor_Type {
73 switch d := data.(type) {
74 case *metric.Int64Data:
76 return wire.MetricDescriptor_GAUGE_INT64
78 return wire.MetricDescriptor_CUMULATIVE_INT64
80 case *metric.Float64Data:
82 return wire.MetricDescriptor_GAUGE_DOUBLE
84 return wire.MetricDescriptor_CUMULATIVE_DOUBLE
86 case *metric.HistogramInt64Data:
87 return wire.MetricDescriptor_CUMULATIVE_DISTRIBUTION
89 case *metric.HistogramFloat64Data:
90 return wire.MetricDescriptor_CUMULATIVE_DISTRIBUTION
93 return wire.MetricDescriptor_UNSPECIFIED
96 // dataToTimeseries returns a slice of *wire.TimeSeries based on the
98 func dataToTimeseries(data metric.Data, start time.Time) []*wire.TimeSeries {
103 numRows := numRows(data)
104 startTimestamp := convertTimestamp(start)
105 timeseries := make([]*wire.TimeSeries, 0, numRows)
107 for i := 0; i < numRows; i++ {
108 timeseries = append(timeseries, &wire.TimeSeries{
109 StartTimestamp: &startTimestamp,
111 Points: dataToPoints(data, i),
118 // numRows returns the number of rows in data.
119 func numRows(data metric.Data) int {
120 switch d := data.(type) {
121 case *metric.Int64Data:
123 case *metric.Float64Data:
125 case *metric.HistogramInt64Data:
127 case *metric.HistogramFloat64Data:
134 // dataToPoints returns an array of *wire.Points based on the point(s)
135 // in data at index i.
136 func dataToPoints(data metric.Data, i int) []*wire.Point {
137 switch d := data.(type) {
138 case *metric.Int64Data:
139 timestamp := convertTimestamp(d.EndTime)
140 return []*wire.Point{
142 Value: wire.PointInt64Value{
143 Int64Value: d.Rows[i],
145 Timestamp: ×tamp,
148 case *metric.Float64Data:
149 timestamp := convertTimestamp(d.EndTime)
150 return []*wire.Point{
152 Value: wire.PointDoubleValue{
153 DoubleValue: d.Rows[i],
155 Timestamp: ×tamp,
158 case *metric.HistogramInt64Data:
160 bucketBounds := make([]float64, len(d.Info.Buckets))
161 for i, val := range d.Info.Buckets {
162 bucketBounds[i] = float64(val)
164 return distributionToPoints(row.Values, row.Count, float64(row.Sum), bucketBounds, d.EndTime)
165 case *metric.HistogramFloat64Data:
167 return distributionToPoints(row.Values, row.Count, row.Sum, d.Info.Buckets, d.EndTime)
173 // distributionToPoints returns an array of *wire.Points containing a
174 // wire.PointDistributionValue representing a distribution with the
175 // supplied counts, count, and sum.
176 func distributionToPoints(counts []int64, count int64, sum float64, bucketBounds []float64, end time.Time) []*wire.Point {
177 buckets := make([]*wire.Bucket, len(counts))
178 for i := 0; i < len(counts); i++ {
179 buckets[i] = &wire.Bucket{
183 timestamp := convertTimestamp(end)
184 return []*wire.Point{
186 Value: wire.PointDistributionValue{
187 DistributionValue: &wire.DistributionValue{
190 // TODO: SumOfSquaredDeviation?
192 BucketOptions: &wire.BucketOptionsExplicit{
193 Bounds: bucketBounds,
197 Timestamp: ×tamp,
202 // infoKeysToLabelKeys returns an array of *wire.LabelKeys containing the
203 // string values of the elements of labelKeys.
204 func infoKeysToLabelKeys(infoKeys []label.Key) []*wire.LabelKey {
205 labelKeys := make([]*wire.LabelKey, 0, len(infoKeys))
206 for _, key := range infoKeys {
207 labelKeys = append(labelKeys, &wire.LabelKey{