Skip to content

Commit

Permalink
Add Monitoring v3 Samples
Browse files Browse the repository at this point in the history
Refactor v2 samples in to separate directory
Add v3 Samples
Renamed auth to list_env
  • Loading branch information
Bill Prin committed Mar 16, 2016
1 parent 1034b81 commit 2c52c6e
Show file tree
Hide file tree
Showing 14 changed files with 525 additions and 0 deletions.
File renamed without changes.
File renamed without changes.
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]
81 changes: 81 additions & 0 deletions monitoring/api/v3/custom_metric_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/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.

""" 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)
client = list_resources.get_client()
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():
# 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

0 comments on commit 2c52c6e

Please sign in to comment.