blob: 14ed25b4bbefb9c475408eed0576aaebe9d71663 [file] [log] [blame]
// Copyright 2017 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 metrics enumerates the set of Stackdriver metrics
// used by the Go build system.
package metrics
import (
"errors"
"fmt"
monapi "cloud.google.com/go/monitoring/apiv3"
"google.golang.org/genproto/googleapis/api/label"
metpb "google.golang.org/genproto/googleapis/api/metric"
monpb "google.golang.org/genproto/googleapis/monitoring/v3"
)
// Metric defines a custom metric type used by Go build system.
type Metric struct {
Name string
Descriptor *metpb.MetricDescriptor
}
// ReverseCount is the Stackdriver metric for monitoring
// the number of reverse buildlets up at any given moment.
var ReverseCount = &Metric{
Name: "reverse/count",
Descriptor: &metpb.MetricDescriptor{
Type: "custom.googleapis.com/reverse/count",
Labels: []*label.LabelDescriptor{
{
Key: "hosttype",
ValueType: label.LabelDescriptor_STRING,
},
},
MetricKind: metpb.MetricDescriptor_GAUGE,
ValueType: metpb.MetricDescriptor_INT64,
},
}
// Metrics is the set of all Stackdriver metrics being used
// to monitor the Go build system.
var Metrics = []*Metric{
ReverseCount,
}
// DescriptorPath returns the unique path for this metric among all
// GCP resources in all projects.
// See cloud.google.com/monitoring/custom-metrics/creating-metrics
// for details.
func (m *Metric) DescriptorPath(project string) string {
return monapi.MetricMetricDescriptorPath(project, m.Descriptor.Type)
}
// Labels populates the set of labels with the given label values.
// The labels should be passed in the same order as defined in the metric
// descriptor. All labels listed in the Descriptor must be assigned values.
func (m *Metric) Labels(labels ...string) (map[string]string, error) {
if len(m.Descriptor.Labels) != len(labels) {
return nil, errors.New("mismatch metric labels")
}
lm := make(map[string]string)
for i, l := range m.Descriptor.Labels {
lm[l.Key] = labels[i]
}
return lm, nil
}
// TypedValue returns the cooresponding *monpb.TypedValue based on
// the metric descriptor's value type.
func (m *Metric) TypedValue(v interface{}) (*monpb.TypedValue, error) {
var tv monpb.TypedValue
switch m.Descriptor.ValueType {
case metpb.MetricDescriptor_BOOL:
if vt, ok := v.(bool); ok {
tv.Value = &monpb.TypedValue_BoolValue{
BoolValue: vt,
}
} else {
return nil, fmt.Errorf("wrong value type (%T) for BOOL", v)
}
case metpb.MetricDescriptor_INT64:
if vt, ok := v.(int); ok {
tv.Value = &monpb.TypedValue_Int64Value{
Int64Value: int64(vt),
}
} else {
return nil, fmt.Errorf("wrong value type (%T) for INT64", v)
}
case metpb.MetricDescriptor_DOUBLE:
if vt, ok := v.(float64); ok {
tv.Value = &monpb.TypedValue_DoubleValue{
DoubleValue: float64(vt),
}
} else {
return nil, fmt.Errorf("wrong value type (%T) for DOUBLE", v)
}
case metpb.MetricDescriptor_STRING:
if vt, ok := v.(string); ok {
tv.Value = &monpb.TypedValue_StringValue{
StringValue: string(vt),
}
} else {
return nil, fmt.Errorf("wrong value type (%T) for STRING", v)
}
case metpb.MetricDescriptor_DISTRIBUTION, metpb.MetricDescriptor_MONEY:
return nil, errors.New("unused metric descriptor value type")
}
return &tv, nil
}