Skip to content

Commit

Permalink
Merge pull request #1584 from tseaver/logging-metric_create
Browse files Browse the repository at this point in the history
Add 'metric.Metric' class and its 'create' API wrapper.
  • Loading branch information
tseaver committed Mar 12, 2016
2 parents a8cdf27 + 5baba70 commit f2d8ad6
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
Client <logging-client>
logging-logger
logging-entries
logging-metric
logging-sink

.. toctree::
Expand Down
7 changes: 7 additions & 0 deletions docs/logging-metric.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Metrics
=======

.. automodule:: gcloud.logging.metric
:members:
:undoc-members:
:show-inheritance:
95 changes: 95 additions & 0 deletions gcloud/logging/metric.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Copyright 2016 Google Inc. All rights reserved.
#
# 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.

"""Define Logging API Metrics."""


class Metric(object):
"""Metrics represent named filters for log entries.
See:
https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/projects.metrics
:type name: string
:param name: the name of the metric
:type filter_: string
:param filter_: the advanced logs filter expression defining the entries
tracked by the metric.
:type client: :class:`gcloud.logging.client.Client`
:param client: A client which holds credentials and project configuration
for the metric (which requires a project).
:type description: string
:param description: an optional description of the metric
"""
def __init__(self, name, filter_, client, description=''):
self.name = name
self._client = client
self.filter_ = filter_
self.description = description

@property
def client(self):
"""Clent bound to the logger."""
return self._client

@property
def project(self):
"""Project bound to the logger."""
return self._client.project

@property
def full_name(self):
"""Fully-qualified name used in metric APIs"""
return 'projects/%s/metrics/%s' % (self.project, self.name)

@property
def path(self):
"""URL path for the metric's APIs"""
return '/%s' % (self.full_name,)

def _require_client(self, client):
"""Check client or verify over-ride.
:type client: :class:`gcloud.logging.client.Client` or ``NoneType``
:param client: the client to use. If not passed, falls back to the
``client`` stored on the current metric.
:rtype: :class:`gcloud.logging.client.Client`
:returns: The client passed in or the currently bound client.
"""
if client is None:
client = self._client
return client

def create(self, client=None):
"""API call: create the metric via a PUT request
See:
https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/projects.metrics/create
:type client: :class:`gcloud.logging.client.Client` or ``NoneType``
:param client: the client to use. If not passed, falls back to the
``client`` stored on the current metric.
"""
client = self._require_client(client)
data = {
'name': self.name,
'filter': self.filter_,
}
if self.description:
data['description'] = self.description
client.connection.api_request(method='PUT', path=self.path, data=data)
119 changes: 119 additions & 0 deletions gcloud/logging/test_metric.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Copyright 2016 Google Inc. All rights reserved.
#
# 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.

import unittest2


class TestMetric(unittest2.TestCase):

PROJECT = 'test-project'
METRIC_NAME = 'metric-name'
FILTER = 'logName:syslog AND severity>=ERROR'
DESCRIPTION = 'DESCRIPTION'

def _getTargetClass(self):
from gcloud.logging.metric import Metric
return Metric

def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)

def test_ctor_defaults(self):
FULL = 'projects/%s/metrics/%s' % (self.PROJECT, self.METRIC_NAME)
conn = _Connection()
client = _Client(self.PROJECT, conn)
metric = self._makeOne(self.METRIC_NAME, self.FILTER, client=client)
self.assertEqual(metric.name, self.METRIC_NAME)
self.assertEqual(metric.filter_, self.FILTER)
self.assertEqual(metric.description, '')
self.assertTrue(metric.client is client)
self.assertEqual(metric.project, self.PROJECT)
self.assertEqual(metric.full_name, FULL)
self.assertEqual(metric.path, '/%s' % (FULL,))

def test_ctor_explicit(self):
FULL = 'projects/%s/metrics/%s' % (self.PROJECT, self.METRIC_NAME)
conn = _Connection()
client = _Client(self.PROJECT, conn)
metric = self._makeOne(self.METRIC_NAME, self.FILTER,
client=client, description=self.DESCRIPTION)
self.assertEqual(metric.name, self.METRIC_NAME)
self.assertEqual(metric.filter_, self.FILTER)
self.assertEqual(metric.description, self.DESCRIPTION)
self.assertTrue(metric.client is client)
self.assertEqual(metric.project, self.PROJECT)
self.assertEqual(metric.full_name, FULL)
self.assertEqual(metric.path, '/%s' % (FULL,))

def test_create_w_bound_client(self):
FULL = 'projects/%s/metrics/%s' % (self.PROJECT, self.METRIC_NAME)
RESOURCE = {
'name': self.METRIC_NAME,
'filter': self.FILTER,
}
conn = _Connection({'name': FULL})
client = _Client(project=self.PROJECT, connection=conn)
metric = self._makeOne(self.METRIC_NAME, self.FILTER, client=client)
metric.create()
self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'PUT')
self.assertEqual(req['path'], '/%s' % FULL)
self.assertEqual(req['data'], RESOURCE)

def test_create_w_alternate_client(self):
FULL = 'projects/%s/metrics/%s' % (self.PROJECT, self.METRIC_NAME)
RESOURCE = {
'name': self.METRIC_NAME,
'filter': self.FILTER,
'description': self.DESCRIPTION,
}
conn1 = _Connection({'name': FULL})
client1 = _Client(project=self.PROJECT, connection=conn1)
conn2 = _Connection({'name': FULL})
client2 = _Client(project=self.PROJECT, connection=conn2)
metric = self._makeOne(self.METRIC_NAME, self.FILTER, client=client1,
description=self.DESCRIPTION)
metric.create(client=client2)
self.assertEqual(len(conn1._requested), 0)
self.assertEqual(len(conn2._requested), 1)
req = conn2._requested[0]
self.assertEqual(req['method'], 'PUT')
self.assertEqual(req['path'], '/%s' % FULL)
self.assertEqual(req['data'], RESOURCE)


class _Connection(object):

def __init__(self, *responses):
self._responses = responses
self._requested = []

def api_request(self, **kw):
from gcloud.exceptions import NotFound
self._requested.append(kw)

try:
response, self._responses = self._responses[0], self._responses[1:]
except: # pragma: NO COVER
raise NotFound('miss')
else:
return response


class _Client(object):

def __init__(self, project, connection=None):
self.project = project
self.connection = connection

0 comments on commit f2d8ad6

Please sign in to comment.