Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Monitoring v3 Samples #223

Merged
merged 2 commits into from
Mar 16, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
47 changes: 47 additions & 0 deletions monitoring/api/v3/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Cloud Monitoring v3 Sample

Sample command-line programs for retrieving Google Monitoring API V3 data.

`list_resources.py` is a simple command-line program to demonstrate connecting to the Google
Monitoring API to retrieve API data and print out some of the resources.

`custom_metric.py` demonstrates how to create a custom metric and write a TimeSeries
value to it.

## Prerequisites to run locally:

* [pip](https://pypi.python.org/pypi/pip)

Go to the [Google Cloud Console](https://console.cloud.google.com).

* Go to API Manager -> Credentials
* Click 'New Credentials', and create a Service Account or [click here](https://console.cloud.google
.com/project/_/apiui/credential/serviceaccount)
Download the JSON for this service account, and set the `GOOGLE_APPLICATION_CREDENTIALS`
environment variable to point to the file containing the JSON credentials.


export GOOGLE_APPLICATION_CREDENTIALS=~/Downloads/<project-id>-0123456789abcdef.json


# Set Up Your Local Dev Environment
To install, run the following commands. If you want to use [virtualenv](https://virtualenv.readthedocs.org/en/latest/)
(recommended), run the commands within a virtualenv.

* pip install -r requirements.txt

To run locally:

python list_resources.py --project_id=<YOUR-PROJECT-ID>
python custom_metric.py --project_id=<YOUR-PROJECT-ID


## Contributing changes

* See [CONTRIBUTING.md](CONTRIBUTING.md)

## Licensing

* See [LICENSE](LICENSE)


202 changes: 202 additions & 0 deletions monitoring/api/v3/custom_metric.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
#!/usr/bin/env python
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

""" Sample command-line program for writing and reading Google Monitoring API
V3 custom metrics.

Simple command-line program to demonstrate connecting to the Google
Monitoring API to write custom metrics and read them back.

See README.md for instructions on setting up your development environment.

This example creates a custom metric based on a hypothetical GAUGE measurement.

To run locally:

python custom_metric.py --project_id=<YOUR-PROJECT-ID>

"""

# [START all]
import argparse
import datetime
import pprint
import random
import time

import list_resources


def format_rfc3339(datetime_instance=None):
"""Formats a datetime per RFC 3339.
:param datetime_instance: Datetime instanec to format, defaults to utcnow
"""
return datetime_instance.isoformat("T") + "Z"


def get_start_time():
# Return now- 5 minutes
start_time = datetime.datetime.utcnow() - datetime.timedelta(minutes=5)
return format_rfc3339(start_time)


def get_now_rfc3339():
# Return now
return format_rfc3339(datetime.datetime.utcnow())


def create_custom_metric(client, project_id,
custom_metric_name, metric_kind):
"""Create custom metric descriptor"""
metrics_descriptor = {
"name": "projects/{}/metricDescriptors/{}".format(
project_id, custom_metric_name),
"type": custom_metric_name,
"labels": [
{
"key": "environment",
"valueType": "STRING",
"description": "An abritrary measurement"
}
],
"metricKind": metric_kind,
"valueType": "INT64",
"unit": "items",
"description": "An arbitrary measurement.",
"displayName": "Custom Metric"
}

client.projects().metricDescriptors().create(
name=project_id, body=metrics_descriptor).execute()


def get_custom_metric(client, project_id, custom_metric_name):
"""Retrieve the custom metric we created"""
request = client.projects().metricDescriptors().list(
name=project_id,
filter='metric.type=starts_with("{}")'.format(custom_metric_name))
response = request.execute()
print('ListCustomMetrics response:')
pprint.pprint(response)
try:
return response['metricDescriptors']
except KeyError:
return None


def get_custom_data_point():
"""Dummy method to return a mock measurement for demonstration purposes.
Returns a random number between 0 and 10"""
length = random.randint(0, 10)
print("reporting timeseries value {}".format(str(length)))
return length


def write_timeseries_value(client, project_resource,
custom_metric_name, instance_id, metric_kind):
"""Write the custom metric obtained by get_custom_data_point at a point in
time."""
# Specify a new data point for the time series.
now = get_now_rfc3339()
timeseries_data = {
"metric": {
"type": custom_metric_name,
"labels": {
"environment": "STAGING"
}
},
"resource": {
"type": 'gce_instance',
"labels": {
'instance_id': instance_id,
'zone': 'us-central1-f'
}
},
"metricKind": metric_kind,
"valueType": "INT64",
"points": [
{
"interval": {
"startTime": now,
"endTime": now
},
"value": {
"int64Value": get_custom_data_point()
}
}
]
}

request = client.projects().timeSeries().create(
name=project_resource, body={"timeSeries": [timeseries_data]})
request.execute()


def read_timeseries(client, project_resource, custom_metric_name):
"""Reads all of the CUSTOM_METRICS that we have written between START_TIME
and END_TIME
:param project_resource: Resource of the project to read the timeseries
from.
:param custom_metric_name: The name of the timeseries we want to read.
"""
request = client.projects().timeSeries().list(
name=project_resource,
filter='metric.type="{0}"'.format(custom_metric_name),
pageSize=3,
interval_startTime=get_start_time(),
interval_endTime=get_now_rfc3339())
response = request.execute()
return response


def main(project_id):
# This is the namespace for all custom metrics
CUSTOM_METRIC_DOMAIN = "custom.googleapis.com"
# This is our specific metric name
CUSTOM_METRIC_NAME = "{}/custom_measurement".format(CUSTOM_METRIC_DOMAIN)
INSTANCE_ID = "test_instance"
METRIC_KIND = "GAUGE"

project_resource = "projects/{0}".format(project_id)
client = list_resources.get_client()
create_custom_metric(client, project_resource,
CUSTOM_METRIC_NAME, METRIC_KIND)
custom_metric = None
while not custom_metric:
# wait until it's created
time.sleep(1)
custom_metric = get_custom_metric(
client, project_resource, CUSTOM_METRIC_NAME)

write_timeseries_value(client, project_resource,
CUSTOM_METRIC_NAME, INSTANCE_ID, METRIC_KIND)
# Sometimes on new metric descriptors, writes have a delay in being read
# back. 3 seconds should be enough to make sure our read call picks up the
# write
time.sleep(3)
timeseries = read_timeseries(client, project_resource, CUSTOM_METRIC_NAME)
print('read_timeseries response:\n{}'.format(pprint.pformat(timeseries)))


if __name__ == '__main__':
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument(
'--project_id', help='Project ID you want to access.', required=True)

args = parser.parse_args()
main(args.project_id)

# [END all]
82 changes: 82 additions & 0 deletions monitoring/api/v3/custom_metric_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/usr/bin/env python
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mind converting these over to py.test? Should be relatively easy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

""" Integration test for custom_metric.py

GOOGLE_APPLICATION_CREDENTIALS must be set to a Service Account for a project
that has enabled the Monitoring API.

Currently the TEST_PROJECT_ID is hard-coded to run using the project created
for this test, but it could be changed to a different project.
"""

import random
import time

from custom_metric import create_custom_metric, get_custom_metric
from custom_metric import read_timeseries, write_timeseries_value
import list_resources

""" Change this to run against other prjoects
GOOGLE_APPLICATION_CREDENTIALS must be the service account for this project
"""

# temporarily hard code to whitelisted project
TEST_PROJECT_ID = 'cloud-monitoring-dev'
# TEST_PROJECT_ID = os.getenv("GCLOUD_PROJECT", 'cloud-monitoring-dev')

""" Custom metric domain for all cusotm metrics"""
CUSTOM_METRIC_DOMAIN = "custom.googleapis.com"

PROJECT_RESOURCE = "projects/{}".format(TEST_PROJECT_ID)

METRIC = 'compute.googleapis.com/instance/cpu/usage_time'
METRIC_NAME = ''.join(
random.choice('0123456789ABCDEF') for i in range(16))
METRIC_RESOURCE = "{}/{}".format(
CUSTOM_METRIC_DOMAIN, METRIC_NAME)


def test_custom_metric():
client = list_resources.get_client()
# Use a constant seed so psuedo random number is known ahead of time
random.seed(1)
pseudo_random_value = random.randint(0, 10)
# Reseed it
random.seed(1)

INSTANCE_ID = "test_instance"
METRIC_KIND = "GAUGE"

create_custom_metric(
client, PROJECT_RESOURCE, METRIC_RESOURCE, METRIC_KIND)
custom_metric = None
# wait until metric has been created, use the get call to wait until
# a response comes back with the new metric
while not custom_metric:
time.sleep(1)
custom_metric = get_custom_metric(
client, PROJECT_RESOURCE, METRIC_RESOURCE)

write_timeseries_value(client, PROJECT_RESOURCE,
METRIC_RESOURCE, INSTANCE_ID,
METRIC_KIND)
# Sometimes on new metric descriptors, writes have a delay in being
# read back. 3 seconds should be enough to make sure our read call
# picks up the write
time.sleep(3)
response = read_timeseries(client, PROJECT_RESOURCE, METRIC_RESOURCE)
value = int(
response['timeSeries'][0]['points'][0]['value']['int64Value'])
# using seed of 1 will create a value of 1
assert value == pseudo_random_value
Loading