Add Custom Metric Examples · ericbolo/python-docs-samples@8e457f4 · GitHub
Skip to content

Commit 8e457f4

Browse files
author
Bill Prin
committed
Add Custom Metric Examples
1 parent fdbe26d commit 8e457f4

5 files changed

Lines changed: 385 additions & 1 deletion

File tree

monitoring/api/auth.py

Lines changed: 4 additions & 1 deletion
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
#!/usr/bin/env python
2+
3+
# Copyright 2015 Google Inc. All rights reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
18+
"""Creates, writes, and reads a labeled custom metric.
19+
20+
This is an example of how to use the Google Cloud Monitoring API to create,
21+
write, and read a labeled custom metric.
22+
The metric has two labels: color and size, and the data points represent
23+
the number of shirts of the given color and size in inventory.
24+
25+
Prerequisites: To run locally, download a Service Account JSON file from
26+
your project and point GOOGLE_APPLICATION_CREDENTIALS to the file.
27+
28+
From App Engine or a GCE instance with the correct scope, the Service
29+
Account step is not required.
30+
31+
Typical usage: Run the following shell commands on the instance:
32+
python labeled_custom_metric.py --project_id <project_id> /
33+
--color yellow --size large --count 10
34+
"""
35+
36+
import argparse
37+
import datetime
38+
import time
39+
40+
from googleapiclient import discovery
41+
from oauth2client.client import GoogleCredentials
42+
43+
CUSTOM_METRIC_DOMAIN = "custom.cloudmonitoring.googleapis.com"
44+
CUSTOM_METRIC_NAME = "{}/shirt_inventory".format(CUSTOM_METRIC_DOMAIN)
45+
46+
47+
def format_rfc3339(datetime_instance=None):
48+
"""Formats a datetime per RFC 3339.
49+
:param datetime_instance: Datetime instance to format, defaults to utcnow
50+
"""
51+
return datetime_instance.isoformat("T") + "Z"
52+
53+
54+
def get_now_rfc3339():
55+
return format_rfc3339(datetime.datetime.utcnow())
56+
57+
58+
def create_custom_metric(client, project_id):
59+
"""Create metric descriptor for the custom metric and send it to the
60+
API."""
61+
# You need to execute this operation only once. The operation is
62+
# idempotent, so, for simplicity, this sample code calls it each time
63+
64+
# Create a label descriptor for each of the metric labels. The
65+
# "description" field should be more meaningful for your metrics.
66+
label_descriptors = []
67+
for label in ["color", "size", ]:
68+
label_descriptors.append({"key": "/{}".format(label),
69+
"description": "The {}.".format(label)})
70+
71+
# Create the metric descriptor for the custom metric.
72+
metric_descriptor = {
73+
"name": CUSTOM_METRIC_NAME,
74+
"project": project_id,
75+
"typeDescriptor": {
76+
"metricType": "gauge",
77+
"valueType": "int64",
78+
},
79+
"labels": label_descriptors,
80+
"description": "The size of my shirt inventory.",
81+
}
82+
# Submit the custom metric creation request.
83+
try:
84+
request = client.metricDescriptors().create(
85+
project=project_id, body=metric_descriptor)
86+
request.execute() # ignore the response
87+
except Exception as e:
88+
print("Failed to create custom metric: exception={})".format(e))
89+
raise
90+
91+
92+
def write_custom_metric(client, project_id, now_rfc3339, color, size, count):
93+
"""Write a data point to a single time series of the custom metric."""
94+
# Identify the particular time series to which to write the data by
95+
# specifying the metric and values for each label.
96+
timeseries_descriptor = {
97+
"project": project_id,
98+
"metric": CUSTOM_METRIC_NAME,
99+
"labels": {
100+
"{}/color".format(CUSTOM_METRIC_DOMAIN): color,
101+
"{}/size".format(CUSTOM_METRIC_DOMAIN): size,
102+
}
103+
}
104+
105+
# Specify a new data point for the time series.
106+
timeseries_data = {
107+
"timeseriesDesc": timeseries_descriptor,
108+
"point": {
109+
"start": now_rfc3339,
110+
"end": now_rfc3339,
111+
"int64Value": count,
112+
}
113+
}
114+
115+
# Submit the write request.
116+
request = client.timeseries().write(
117+
project=project_id, body={"timeseries": [timeseries_data, ]})
118+
try:
119+
request.execute() # ignore the response
120+
except Exception as e:
121+
print("Failed to write data to custom metric: exception={}".format(e))
122+
raise
123+
124+
125+
def read_custom_metric(client, project_id, now_rfc3339, color, size):
126+
"""Read all the timeseries data points for a given set of label values."""
127+
# To identify a time series, specify values for in label as a list.
128+
labels = ["{}/color=={}".format(CUSTOM_METRIC_DOMAIN, color),
129+
"{}/size=={}".format(CUSTOM_METRIC_DOMAIN, size), ]
130+
131+
# Submit the read request.
132+
request = client.timeseries().list(
133+
project=project_id,
134+
metric=CUSTOM_METRIC_NAME,
135+
youngest=now_rfc3339,
136+
labels=labels)
137+
138+
# When a custom metric is created, it may take a few seconds
139+
# to propagate throughout the system. Retry a few times.
140+
start = time.time()
141+
while True:
142+
try:
143+
response = request.execute()
144+
for point in response["timeseries"][0]["points"]:
145+
print("{}: {}".format(point["end"], point["int64Value"]))
146+
break
147+
except Exception as e:
148+
if time.time() < start + 20:
149+
print("Failed to read custom metric data, retrying...")
150+
time.sleep(3)
151+
else:
152+
print("Failed to read custom metric data, aborting: "
153+
"exception={}".format(e))
154+
raise
155+
156+
157+
def get_client():
158+
"""Builds an http client authenticated with the application default
159+
credentials."""
160+
credentials = GoogleCredentials.get_application_default()
161+
client = discovery.build(
162+
'cloudmonitoring', 'v2beta2',
163+
credentials=credentials)
164+
return client
165+
166+
167+
def main(project_id, color, size, count):
168+
now_rfc3339 = get_now_rfc3339()
169+
170+
client = get_client()
171+
172+
print ("Labels: color: {}, size: {}.".format(color, size))
173+
print ("Creating custom metric...")
174+
create_custom_metric(client, project_id)
175+
time.sleep(2)
176+
print ("Writing new data to custom metric timeseries...")
177+
write_custom_metric(client, project_id, now_rfc3339,
178+
color, size, count)
179+
print ("Reading data from custom metric timeseries...")
180+
write_custom_metric(client, project_id, now_rfc3339, color,
181+
size, count)
182+
183+
184+
if __name__ == '__main__':
185+
parser = argparse.ArgumentParser(
186+
description=__doc__,
187+
formatter_class=argparse.RawDescriptionHelpFormatter,
188+
)
189+
190+
parser.add_argument(
191+
'--project_id', help='Project ID you want to access.', required=True)
192+
parser.add_argument("--color", required=True)
193+
parser.add_argument("--size", required=True)
194+
parser.add_argument("--count", required=True)
195+
196+
args = parser.parse_args()
197+
main(args.project_id, args.color, args.size, args.count)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/usr/bin/env python
2+
3+
# Copyright 2015 Google Inc. All rights reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
import re
18+
19+
import labeled_custom_metric
20+
21+
22+
def test_main(cloud_config, capsys):
23+
labeled_custom_metric.main(cloud_config.project, "yellow", "large", "10")
24+
output, _ = capsys.readouterr()
25+
26+
assert re.search(
27+
re.compile(
28+
r'.*Creating.*'
29+
r'Writing.*'
30+
r'Reading.*', flags=re.DOTALL),
31+
output)
Lines changed: 124 additions & 0 deletions

0 commit comments

Comments
 (0)