Skip to content

Commit bc6e36c

Browse files
extract part of monitoring lib to x/lib/gcm.
The main purpose is to let allocatord to use those functions to retrieve data from GCM to render dashboard. MultiPart: 2/2 Change-Id: I2aed93cb8f93a9334280bf4bd909d4d72f7deba8
1 parent 3ea1783 commit bc6e36c

File tree

4 files changed

+337
-0
lines changed

4 files changed

+337
-0
lines changed

gcm/.api

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pkg gcm, func Authenticate(string) (*cloudmonitoring.Service, error)
2+
pkg gcm, func GetMetric(string, string) (*cloudmonitoring.MetricDescriptor, error)
3+
pkg gcm, func GetSortedMetricNames() []string

gcm/.godepcop

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<godepcop>
2+
<pkg allow="golang.org/x/oauth2/..."/>
3+
<pkg allow="golang.org/x/net/..."/>
4+
<pkg allow="google.golang.org/api/..."/>
5+
<pkg allow="google.golang.org/cloud/..."/>
6+
</godepcop>

gcm/gcm.go

+206
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
// Copyright 2016 The Vanadium 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.
4+
5+
package gcm
6+
7+
import (
8+
"fmt"
9+
"io/ioutil"
10+
"net/http"
11+
"sort"
12+
13+
"golang.org/x/oauth2"
14+
"golang.org/x/oauth2/google"
15+
cloudmonitoring "google.golang.org/api/monitoring/v3"
16+
)
17+
18+
const (
19+
customMetricPrefix = "custom.googleapis.com"
20+
)
21+
22+
type labelData struct {
23+
key string
24+
description string
25+
}
26+
27+
var aggLabelData = []labelData{
28+
labelData{
29+
key: "aggregation",
30+
description: "The aggregation type (min, max, avg, sum, count)",
31+
},
32+
}
33+
34+
// customMetricDescriptors is a map from metric's short names to their
35+
// MetricDescriptor definitions.
36+
var customMetricDescriptors = map[string]*cloudmonitoring.MetricDescriptor{
37+
// Custom metrics for recording stats of cloud syncbase instances.
38+
"cloud-syncbase": createMetric("cloud-syncbase", "Stats of cloud syncbase instances.", "double", false, []labelData{
39+
labelData{
40+
key: "mounted_name",
41+
description: "The relative mounted name of the instance",
42+
},
43+
}),
44+
"cloud-syncbase-agg": createMetric("cloud-syncbase-agg", "The aggregated stats of cloud syncbase instances.", "double", false, aggLabelData),
45+
46+
// Custom metrics for recording check latency and its aggregation
47+
// of vanadium production services.
48+
"service-latency": createMetric("service/latency", "The check latency (ms) of vanadium production services.", "double", true, nil),
49+
"service-latency-agg": createMetric("service/latency-agg", "The aggregated check latency (ms) of vanadium production services.", "double", false, aggLabelData),
50+
51+
// Custom metric for recording per-method rpc latency and its aggregation
52+
// for a service.
53+
"service-permethod-latency": createMetric("service/latency/method", "Service latency (ms) per method.", "double", true, []labelData{
54+
labelData{
55+
key: "method_name",
56+
description: "The method name",
57+
},
58+
}),
59+
"service-permethod-latency-agg": createMetric("service/latency/method-agg", "Aggregated service latency (ms) per method.", "double", false, []labelData{
60+
labelData{
61+
key: "method_name",
62+
description: "The method name",
63+
},
64+
aggLabelData[0],
65+
}),
66+
67+
// Custom metric for recording various counters and their aggregations
68+
// of vanadium production services.
69+
"service-counters": createMetric("service/counters", "Various counters of vanadium production services.", "double", true, nil),
70+
"service-counters-agg": createMetric("service/counters-agg", "Aggregated counters of vanadium production services.", "double", false, aggLabelData),
71+
72+
// Custom metric for recording service metadata and its aggregation
73+
// of vanadium production services.
74+
"service-metadata": createMetric("service/metadata", "Various metadata of vanadium production services.", "double", true, []labelData{
75+
labelData{
76+
key: "metadata_name",
77+
description: "The metadata name",
78+
},
79+
}),
80+
"service-metadata-agg": createMetric("service/metadata-agg", "Aggregated metadata of vanadium production services.", "double", false, []labelData{
81+
labelData{
82+
key: "metadata_name",
83+
description: "The metadata name",
84+
},
85+
aggLabelData[0],
86+
}),
87+
88+
// Custom metric for recording total rpc qps and its aggregation for a service.
89+
"service-qps-total": createMetric("service/qps/total", "Total service QPS.", "double", true, nil),
90+
"service-qps-total-agg": createMetric("service/qps/total-agg", "Aggregated total service QPS.", "double", false, aggLabelData),
91+
92+
// Custom metric for recording per-method rpc qps for a service.
93+
"service-qps-method": createMetric("service/qps/method", "Service QPS per method.", "double", true, []labelData{
94+
labelData{
95+
key: "method_name",
96+
description: "The method name",
97+
},
98+
}),
99+
"service-qps-method-agg": createMetric("service/qps/method-agg", "Aggregated service QPS per method.", "double", false, []labelData{
100+
labelData{
101+
key: "method_name",
102+
description: "The method name",
103+
},
104+
aggLabelData[0],
105+
}),
106+
107+
// Custom metric for recording gce instance stats.
108+
"gce-instance": createMetric("gce-instance/stats", "Various stats for GCE instances.", "double", true, nil),
109+
110+
// Custom metric for recording nginx stats.
111+
"nginx": createMetric("nginx/stats", "Various stats for Nginx server.", "double", true, nil),
112+
113+
// Custom metric for rpc load tests.
114+
"rpc-load-test": createMetric("rpc-load-test", "Results of rpc load test.", "double", false, nil),
115+
116+
// Custom metric for recording jenkins related data.
117+
"jenkins": createMetric("jenkins", "Jenkins related data.", "double", false, nil),
118+
}
119+
120+
func createMetric(metricType, description, valueType string, includeGCELabels bool, extraLabels []labelData) *cloudmonitoring.MetricDescriptor {
121+
labels := []*cloudmonitoring.LabelDescriptor{}
122+
if includeGCELabels {
123+
labels = append(labels, &cloudmonitoring.LabelDescriptor{
124+
Key: "gce_instance",
125+
Description: "The name of the GCE instance associated with this metric.",
126+
ValueType: "string",
127+
}, &cloudmonitoring.LabelDescriptor{
128+
Key: "gce_zone",
129+
Description: "The zone of the GCE instance associated with this metric.",
130+
ValueType: "string",
131+
})
132+
}
133+
labels = append(labels, &cloudmonitoring.LabelDescriptor{
134+
Key: "metric_name",
135+
Description: "The name of the metric.",
136+
ValueType: "string",
137+
})
138+
if extraLabels != nil {
139+
for _, data := range extraLabels {
140+
labels = append(labels, &cloudmonitoring.LabelDescriptor{
141+
Key: fmt.Sprintf("%s", data.key),
142+
Description: data.description,
143+
ValueType: "string",
144+
})
145+
}
146+
}
147+
148+
return &cloudmonitoring.MetricDescriptor{
149+
Type: fmt.Sprintf("%s/vanadium/%s", customMetricPrefix, metricType),
150+
Description: description,
151+
MetricKind: "gauge",
152+
ValueType: valueType,
153+
Labels: labels,
154+
}
155+
}
156+
157+
// GetMetric gets the custom metric descriptor with the given name and project.
158+
func GetMetric(name, project string) (*cloudmonitoring.MetricDescriptor, error) {
159+
md, ok := customMetricDescriptors[name]
160+
if !ok {
161+
return nil, fmt.Errorf("metric %q doesn't exist", name)
162+
}
163+
md.Name = fmt.Sprintf("projects/%s/metricDescriptors/%s", project, md.Type)
164+
return md, nil
165+
}
166+
167+
// GetSortedMetricNames gets the sorted metric names.
168+
func GetSortedMetricNames() []string {
169+
names := []string{}
170+
for n := range customMetricDescriptors {
171+
names = append(names, n)
172+
}
173+
sort.Strings(names)
174+
return names
175+
}
176+
177+
func createClient(keyFilePath string) (*http.Client, error) {
178+
if len(keyFilePath) > 0 {
179+
data, err := ioutil.ReadFile(keyFilePath)
180+
if err != nil {
181+
return nil, err
182+
}
183+
conf, err := google.JWTConfigFromJSON(data, cloudmonitoring.MonitoringScope)
184+
if err != nil {
185+
return nil, fmt.Errorf("failed to create JWT config file: %v", err)
186+
}
187+
return conf.Client(oauth2.NoContext), nil
188+
}
189+
190+
return google.DefaultClient(oauth2.NoContext, cloudmonitoring.MonitoringScope)
191+
}
192+
193+
// Authenticate authenticates with the given JSON credentials file (or the
194+
// default client if the file is not provided). If successful, it returns a
195+
// service object that can be used in GCM API calls.
196+
func Authenticate(keyFilePath string) (*cloudmonitoring.Service, error) {
197+
c, err := createClient(keyFilePath)
198+
if err != nil {
199+
return nil, err
200+
}
201+
s, err := cloudmonitoring.New(c)
202+
if err != nil {
203+
return nil, fmt.Errorf("New() failed: %v", err)
204+
}
205+
return s, nil
206+
}

gcm/gcm_test.go

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// Copyright 2015 The Vanadium 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.
4+
5+
package gcm
6+
7+
import (
8+
"fmt"
9+
"reflect"
10+
"testing"
11+
12+
cloudmonitoring "google.golang.org/api/monitoring/v3"
13+
)
14+
15+
func TestCreateMetric(t *testing.T) {
16+
type testCase struct {
17+
metricType string
18+
description string
19+
valueType string
20+
includeGCELabels bool
21+
extraLabels []labelData
22+
expectedMetric *cloudmonitoring.MetricDescriptor
23+
}
24+
testCases := []testCase{
25+
testCase{
26+
metricType: "test",
27+
description: "this is a test",
28+
valueType: "double",
29+
includeGCELabels: false,
30+
extraLabels: nil,
31+
expectedMetric: &cloudmonitoring.MetricDescriptor{
32+
Type: fmt.Sprintf("%s/vanadium/test", customMetricPrefix),
33+
Description: "this is a test",
34+
MetricKind: "gauge",
35+
ValueType: "double",
36+
Labels: []*cloudmonitoring.LabelDescriptor{
37+
&cloudmonitoring.LabelDescriptor{
38+
Key: "metric_name",
39+
Description: "The name of the metric.",
40+
ValueType: "string",
41+
},
42+
},
43+
},
44+
},
45+
testCase{
46+
metricType: "test2",
47+
description: "this is a test2",
48+
valueType: "string",
49+
includeGCELabels: true,
50+
extraLabels: nil,
51+
expectedMetric: &cloudmonitoring.MetricDescriptor{
52+
Type: fmt.Sprintf("%s/vanadium/test2", customMetricPrefix),
53+
Description: "this is a test2",
54+
MetricKind: "gauge",
55+
ValueType: "string",
56+
Labels: []*cloudmonitoring.LabelDescriptor{
57+
&cloudmonitoring.LabelDescriptor{
58+
Key: "gce_instance",
59+
Description: "The name of the GCE instance associated with this metric.",
60+
ValueType: "string",
61+
},
62+
&cloudmonitoring.LabelDescriptor{
63+
Key: "gce_zone",
64+
Description: "The zone of the GCE instance associated with this metric.",
65+
ValueType: "string",
66+
},
67+
&cloudmonitoring.LabelDescriptor{
68+
Key: "metric_name",
69+
Description: "The name of the metric.",
70+
ValueType: "string",
71+
},
72+
},
73+
},
74+
},
75+
testCase{
76+
metricType: "test3",
77+
description: "this is a test3",
78+
valueType: "double",
79+
includeGCELabels: true,
80+
extraLabels: []labelData{
81+
labelData{
82+
key: "extraLabel",
83+
description: "this is an extra label",
84+
},
85+
},
86+
expectedMetric: &cloudmonitoring.MetricDescriptor{
87+
Type: fmt.Sprintf("%s/vanadium/test3", customMetricPrefix),
88+
Description: "this is a test3",
89+
MetricKind: "gauge",
90+
ValueType: "double",
91+
Labels: []*cloudmonitoring.LabelDescriptor{
92+
&cloudmonitoring.LabelDescriptor{
93+
Key: "gce_instance",
94+
Description: "The name of the GCE instance associated with this metric.",
95+
ValueType: "string",
96+
},
97+
&cloudmonitoring.LabelDescriptor{
98+
Key: "gce_zone",
99+
Description: "The zone of the GCE instance associated with this metric.",
100+
ValueType: "string",
101+
},
102+
&cloudmonitoring.LabelDescriptor{
103+
Key: "metric_name",
104+
Description: "The name of the metric.",
105+
ValueType: "string",
106+
},
107+
&cloudmonitoring.LabelDescriptor{
108+
Key: "extraLabel",
109+
Description: "this is an extra label",
110+
ValueType: "string",
111+
},
112+
},
113+
},
114+
},
115+
}
116+
for _, test := range testCases {
117+
got := createMetric(test.metricType, test.description, test.valueType, test.includeGCELabels, test.extraLabels)
118+
if !reflect.DeepEqual(got, test.expectedMetric) {
119+
t.Fatalf("want %#v, got %#v", test.expectedMetric, got)
120+
}
121+
}
122+
}

0 commit comments

Comments
 (0)