From e982bf07680968ec68621bf32f88b571b669d4db Mon Sep 17 00:00:00 2001 From: Bill Prin Date: Wed, 29 Jun 2016 17:42:24 -0700 Subject: [PATCH] Add Error Reporting Client --- docs/error-reporting-client.rst | 7 ++++ docs/error-reporting-usage.rst | 46 +++++++++++++++++++++ docs/index.rst | 8 ++++ gcloud/error_reporting/__init__.py | 18 ++++++++ gcloud/error_reporting/client.py | 59 +++++++++++++++++++++++++++ gcloud/error_reporting/test_client.py | 52 +++++++++++++++++++++++ scripts/verify_included_modules.py | 1 + 7 files changed, 191 insertions(+) create mode 100644 docs/error-reporting-client.rst create mode 100644 docs/error-reporting-usage.rst create mode 100644 gcloud/error_reporting/__init__.py create mode 100644 gcloud/error_reporting/client.py create mode 100644 gcloud/error_reporting/test_client.py diff --git a/docs/error-reporting-client.rst b/docs/error-reporting-client.rst new file mode 100644 index 0000000000000..55092baa08806 --- /dev/null +++ b/docs/error-reporting-client.rst @@ -0,0 +1,7 @@ +Error Reporting Client +======================= + +.. automodule:: gcloud.error_reporting.client + :members: + :show-inheritance: + diff --git a/docs/error-reporting-usage.rst b/docs/error-reporting-usage.rst new file mode 100644 index 0000000000000..dc93c161936a6 --- /dev/null +++ b/docs/error-reporting-usage.rst @@ -0,0 +1,46 @@ +Using the API +============= + + +Authentication and Configuration +-------------------------------- + +- For an overview of authentication in ``gcloud-python``, + see :doc:`gcloud-auth`. + +- In addition to any authentication configuration, you should also set the + :envvar:`GCLOUD_PROJECT` environment variable for the project you'd like + to interact with. If you are Google App Engine or Google Compute Engine + this will be detected automatically. + +- After configuring your environment, create a + :class:`Client ` + + .. doctest:: + + >>> from gcloud import error_reporting + >>> client = error_reporting.Client() + + or pass in ``credentials`` and ``project`` explicitly + + .. doctest:: + + >>> from gcloud import error_reporting + >>> client = error_reporting.Client(project='my-project', credentials=creds) + + +Reporting an exception +----------------------- + +Report a stacktrace to Stackdriver Error Reporting after an exception + +.. doctest:: + + >>> from gcloud import error_reporting + >>> from + >>> client = error_reporting.Client() + >>> try: + >>> raise NameError + >>> except Exception: + >>> client.report_error(message="Something went wrong") + diff --git a/docs/index.rst b/docs/index.rst index b263dba705319..2f6849db40f1c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -111,6 +111,14 @@ logging-metric logging-sink +.. toctree:: + :maxdepth: 0 + :hidden: + :caption: Stackdriver Error Reporting + + error-reporting-usage + Client + .. toctree:: :maxdepth: 0 :hidden: diff --git a/gcloud/error_reporting/__init__.py b/gcloud/error_reporting/__init__.py new file mode 100644 index 0000000000000..6d62d44dc36bf --- /dev/null +++ b/gcloud/error_reporting/__init__.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python +# 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. + +"""Client library for Stackdriver Error Reporting""" + +from gcloud.error_reporting.client import Client diff --git a/gcloud/error_reporting/client.py b/gcloud/error_reporting/client.py new file mode 100644 index 0000000000000..66217dbf57a95 --- /dev/null +++ b/gcloud/error_reporting/client.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# 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. + +"""Client for interacting with the Stackdriver Logging API""" + +import traceback + +import gcloud.logging.client + +DEFAULT_SERVICE = 'python' + + +class Client(gcloud.logging.client.Client): + """Error Reporting client. Currently Error Reporting is done via the + Logging Client so it just subclasses that.""" + + def report_error(self, message="", service=DEFAULT_SERVICE): + """ Reports the details of the latest exceptions to Stackdriver Error + Reporting. + + https://cloud.google.com/error-reporting/docs/formatting-error-messages + + :type message: str + :param message: An optional message to include with the exception + detail + + :type service: str + :param service: An identifier of the service, such as the name of + the executable, job, or Google App Engine module + name. This field is expected to have a low number + of values that are relatively stable over time, + as opposed to version, which can be changed + whenever new code is deployed. + + Example:: + + >>> try: + >>> raise NameError + >>> except Exception: + >>> client.report_error("Something went wrong!") + """ + payload = { + 'serviceContext': {'service': service}, + 'message': '{0} : {1}'.format(message, traceback.format_exc()) + } + logger = self.logger('errors') + logger.log_struct(payload) diff --git a/gcloud/error_reporting/test_client.py b/gcloud/error_reporting/test_client.py new file mode 100644 index 0000000000000..524561c71c5fd --- /dev/null +++ b/gcloud/error_reporting/test_client.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +# 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 TestClient(unittest2.TestCase): + + def _getTargetClass(self): + from gcloud.error_reporting.client import Client + return Client + + def _makeOne(self, *args, **kw): + return self._getTargetClass()(*args, **kw) + + def test_report_error(self): + target = self._makeOne() + MESSAGE = 'hello world' + + logger = _Logger() + target.logger = lambda _: logger + + try: + raise NameError + except NameError: + target.report_error(MESSAGE) + + payload = logger.log_struct_called_with + self.assertEquals(payload['serviceContext'], { + 'service': 'python' + }) + self.assertIn(MESSAGE, payload['message']) + self.assertIn('test_report_error', payload['message']) + self.assertIn('test_client.py', payload['message']) + + +class _Logger(object): + def log_struct(self, payload): + self.log_struct_called_with = payload diff --git a/scripts/verify_included_modules.py b/scripts/verify_included_modules.py index 15d3875064844..1172c0eb303d4 100644 --- a/scripts/verify_included_modules.py +++ b/scripts/verify_included_modules.py @@ -35,6 +35,7 @@ 'gcloud.bigtable.__init__', 'gcloud.datastore.__init__', 'gcloud.dns.__init__', + 'gcloud.error_reporting.__init__', 'gcloud.iterator', 'gcloud.logging.__init__', 'gcloud.monitoring.__init__',