func MakeLabelValue(value string) *metricspb.LabelValue {
	return &metricspb.LabelValue{
		Value:    value,
		HasValue: true,
	}
}
MakeLabelValue generates a proto representation of a metric label with value as its value.
package metricgenerator
import (
	"math"
	"time"
	timestamp "google.golang.org/protobuf/types/known/timestamppb"
	metricspb "github.com/census-instrumentation/opencensus-proto/gen-go/metrics/v1"
)
func MakeInt64TimeSeries(val int64, startTime, now time.Time, labels []*metricspb.LabelValue) *metricspb.TimeSeries {
	return &metricspb.TimeSeries{
		StartTimestamp: timestamp.New(startTime),
		LabelValues:    labels,
		Points:         []*metricspb.Point{{Timestamp: timestamp.New(now), Value: &metricspb.Point_Int64Value{Int64Value: val}}},
	}
}
func MakeDoubleTimeSeries(val float64, startTime, now time.Time, labels []*metricspb.LabelValue) *metricspb.TimeSeries {
	return &metricspb.TimeSeries{
		StartTimestamp: timestamp.New(startTime),
		LabelValues:    labels,
		Points:         []*metricspb.Point{{Timestamp: timestamp.New(now), Value: &metricspb.Point_DoubleValue{DoubleValue: val}}},
	}
}
func MakeExponentialBucketOptions(boundsBase, maxExponent float64) *metricspb.DistributionValue_BucketOptions {
	bounds := make([]float64, 0, int(maxExponent))
	for i := float64(0); i <= maxExponent; i++ {
		bounds = append(bounds, math.Pow(boundsBase, i))
	}
	return &metricspb.DistributionValue_BucketOptions{
		Type: &metricspb.DistributionValue_BucketOptions_Explicit_{
			Explicit: &metricspb.DistributionValue_BucketOptions_Explicit{
				Bounds: bounds,
			},
		},
	}
}
func FormatBucketOptions(bounds []float64) *metricspb.DistributionValue_BucketOptions {
	return &metricspb.DistributionValue_BucketOptions{
		Type: &metricspb.DistributionValue_BucketOptions_Explicit_{
			Explicit: &metricspb.DistributionValue_BucketOptions_Explicit{
				Bounds: bounds,
			},
		},
	}
}
func MakeBuckets(values, bounds []float64) []*metricspb.DistributionValue_Bucket {
	buckets := make([]*metricspb.DistributionValue_Bucket, len(bounds)+1, len(bounds)+1)
	for i := 0; i <= len(bounds); i++ {
		buckets[i] = &metricspb.DistributionValue_Bucket{}
	}
	for _, val := range values {
		index := getBucketIndex(val, bounds)
		buckets[index].Count++
	}
	return buckets
}
func getBucketIndex(val float64, bounds []float64) int {
	if val < bounds[0] {
		return 0
	}
	for i, lowerBound := range bounds {
		if i < len(bounds)-1 && val >= lowerBound && val < bounds[i+1] {
			return i + 1
		}
	}
	return len(bounds)
}
func formatBuckets(distribution []int64) []*metricspb.DistributionValue_Bucket {
	buckets := make([]*metricspb.DistributionValue_Bucket, len(distribution), len(distribution))
	for i := 0; i < len(distribution); i++ {
		buckets[i] = &metricspb.DistributionValue_Bucket{
			Count: distribution[i],
		}
	}
	return buckets
}