Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 8e457f4

Browse filesBrowse files
author
Bill Prin
committed
Add Custom Metric Examples
1 parent fdbe26d commit 8e457f4
Copy full SHA for 8e457f4

File tree

Expand file treeCollapse file tree

5 files changed

+385
-1
lines changed
Filter options
Expand file treeCollapse file tree

5 files changed

+385
-1
lines changed

‎monitoring/api/auth.py

Copy file name to clipboardExpand all lines: monitoring/api/auth.py
+4-1Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616

1717
"""Sample command-line program for retrieving Google Cloud Monitoring API data.
1818
19+
Prerequisites: To run locally, download a Service Account JSON file from
20+
your project and point GOOGLE_APPLICATION_CREDENTIALS to the file.
21+
22+
1923
This sample is used on this page:
2024
2125
https://cloud.google.com/monitoring/api/authentication
@@ -30,7 +34,6 @@
3034
from googleapiclient.discovery import build
3135
from oauth2client.client import GoogleCredentials
3236

33-
3437
METRIC = 'compute.googleapis.com/instance/disk/read_ops_count'
3538
YOUNGEST = '2015-01-01T00:00:00Z'
3639

+197Lines 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)
+31Lines 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)
+124Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
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+
"""Writes and reads a lightweight custom metric.
19+
20+
This is an example of how to use the Google Cloud Monitoring API to write
21+
and read a lightweight custom metric. Lightweight custom metrics have no
22+
labels and you do not need to create a metric descriptor for them.
23+
24+
Prerequisites: To run locally, download a Service Account JSON file from
25+
your project and point GOOGLE_APPLICATION_CREDENTIALS to the file.
26+
27+
From App Engine or a GCE instance with the correct scope, the Service
28+
Account step is not required.
29+
30+
Typical usage: Run the following shell commands on the instance:
31+
32+
python lightweight_custom_metric.py --project_id=<YOUR-PROJECT-ID>
33+
"""
34+
35+
import argparse
36+
import datetime
37+
import os
38+
import time
39+
40+
from googleapiclient import discovery
41+
from oauth2client.client import GoogleCredentials
42+
43+
CUSTOM_METRIC_NAME = "custom.cloudmonitoring.googleapis.com/pid"
44+
45+
46+
def format_rfc3339(datetime_instance=None):
47+
"""Formats a datetime per RFC 3339.
48+
:param datetime_instance: Datetime instanec to format, defaults to utcnow
49+
"""
50+
return datetime_instance.isoformat("T") + "Z"
51+
52+
53+
def get_now_rfc3339():
54+
return format_rfc3339(datetime.datetime.utcnow())
55+
56+
57+
def get_client():
58+
"""Builds an http client authenticated with the service account
59+
credentials."""
60+
credentials = GoogleCredentials.get_application_default()
61+
client = discovery.build(
62+
'cloudmonitoring', 'v2beta2',
63+
credentials=credentials)
64+
return client
65+
66+
67+
def main(project_id):
68+
# Set up the write request.
69+
client = get_client()
70+
now = get_now_rfc3339()
71+
desc = {"project": project_id,
72+
"metric": CUSTOM_METRIC_NAME}
73+
point = {"start": now,
74+
"end": now,
75+
"doubleValue": os.getpid()}
76+
print("Writing {} at {}".format(point["doubleValue"], now))
77+
78+
# Write a new data point.
79+
try:
80+
write_request = client.timeseries().write(
81+
project=project_id,
82+
body={"timeseries": [{"timeseriesDesc": desc, "point": point}]})
83+
write_request.execute() # Ignore the response.
84+
except Exception as e:
85+
print("Failed to write custom metric data: exception={}".format(e))
86+
raise
87+
88+
# Read all data points from the time series.
89+
# When a custom metric is created, it may take a few seconds
90+
# to propagate throughout the system. Retry a few times.
91+
print("Reading data from custom metric timeseries...")
92+
read_request = client.timeseries().list(
93+
project=project_id,
94+
metric=CUSTOM_METRIC_NAME,
95+
youngest=now)
96+
start = time.time()
97+
while True:
98+
try:
99+
read_response = read_request.execute()
100+
for point in read_response["timeseries"][0]["points"]:
101+
print("Point: {}: {}".format(
102+
point["end"], point["doubleValue"]))
103+
break
104+
except Exception as e:
105+
if time.time() < start + 20:
106+
print("Failed to read custom metric data, retrying...")
107+
time.sleep(3)
108+
else:
109+
print("Failed to read custom metric data, aborting: "
110+
"exception={}".format(e))
111+
raise
112+
113+
114+
if __name__ == '__main__':
115+
parser = argparse.ArgumentParser(
116+
description=__doc__,
117+
formatter_class=argparse.RawDescriptionHelpFormatter
118+
)
119+
120+
parser.add_argument(
121+
'--project_id', help='Project ID you want to access.', required=True)
122+
123+
args = parser.parse_args()
124+
main(args.project_id)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.