-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Bill Prin
committed
Jun 30, 2016
1 parent
d958f74
commit 1f59346
Showing
7 changed files
with
322 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Error Reporting Client | ||
======================= | ||
|
||
.. automodule:: gcloud.error_reporting.client | ||
:members: | ||
:show-inheritance: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
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 <gcloud.logging.client.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) | ||
|
||
Error Reporting associates errors with a service, which is an identifier for an executable, | ||
App Engine module, or job. The default service is "python", but a default can be specified | ||
for the client on construction time. | ||
|
||
.. doctest:: | ||
|
||
>>> from gcloud import error_reporting | ||
>>> client = error_reporting.Client(project='my-project', service="login_service") | ||
|
||
|
||
Reporting an exception | ||
----------------------- | ||
|
||
Report a stacktrace to Stackdriver Error Reporting after an exception | ||
|
||
.. doctest:: | ||
|
||
>>> from gcloud import error_reporting | ||
>>> client = error_reporting.Client() | ||
>>> try: | ||
>>> raise NameError | ||
>>> except Exception: | ||
>>> client.report_error(message="Something went wrong") | ||
|
||
|
||
By default, the client will report the error using the service specified in the client's | ||
constructor, or the default service of "python". The service can also be manually specified | ||
in the parameters: | ||
|
||
.. doctest:: | ||
|
||
>>> try: | ||
>>> raise NameError | ||
>>> except Exception: | ||
>>> client.report_error(message="Something went wrong", service="login_service") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
#!/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 | ||
|
||
|
||
class Client(object): | ||
"""Error Reporting client. Currently Error Reporting is done by creating | ||
a Logging client. | ||
:type project: string | ||
:param project: the project which the client acts on behalf of. If not | ||
passed falls back to the default inferred from the | ||
environment. | ||
:type credentials: :class:`oauth2client.client.OAuth2Credentials` or | ||
:class:`NoneType` | ||
:param credentials: The OAuth2 Credentials to use for the connection | ||
owned by this client. If not passed (and if no ``http`` | ||
object is passed), falls back to the default inferred | ||
from the environment. | ||
:type http: :class:`httplib2.Http` or class that defines ``request()``. | ||
:param http: An optional HTTP object to make requests. If not passed, an | ||
``http`` object is created that is bound to the | ||
``credentials`` for the current object. | ||
: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. | ||
:raises: :class:`ValueError` if the project is neither passed in nor | ||
set in the environment. | ||
""" | ||
|
||
def __init__(self, project=None, | ||
credentials=None, | ||
http=None, | ||
service=None): | ||
self.logging_client = gcloud.logging.client.Client( | ||
project, credentials, http) | ||
self.service = service | ||
|
||
DEFAULT_SERVICE = 'python' | ||
|
||
def _get_default_service(self): | ||
"""Returns the service to use on method calls that don't specify an | ||
override. | ||
:rtype: string | ||
:returns: The default service for error reporting calls | ||
""" | ||
if self.service: | ||
return self.service | ||
else: | ||
return self.DEFAULT_SERVICE | ||
|
||
def report_error(self, message="", service=None): | ||
""" 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!") | ||
""" | ||
if not service: | ||
service = self._get_default_service() | ||
payload = { | ||
'serviceContext': {'service': service}, | ||
'message': '{0} : {1}'.format(message, traceback.format_exc()) | ||
} | ||
logger = self.logging_client.logger('errors') | ||
logger.log_struct(payload) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
#!/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) | ||
|
||
PROJECT = 'PROJECT' | ||
SERVICE = 'SERVICE' | ||
|
||
def test_ctor(self): | ||
CREDENTIALS = _Credentials() | ||
target = self._makeOne(project=self.PROJECT, | ||
credentials=CREDENTIALS) | ||
self.assertEquals(target._get_default_service(), | ||
target.DEFAULT_SERVICE) | ||
|
||
def test_ctor_service(self): | ||
CREDENTIALS = _Credentials() | ||
target = self._makeOne(project=self.PROJECT, | ||
credentials=CREDENTIALS, | ||
service=self.SERVICE) | ||
self.assertEquals(target.service, self.SERVICE) | ||
self.assertEquals(target._get_default_service(), self.SERVICE) | ||
|
||
def test_report_error(self): | ||
CREDENTIALS = _Credentials() | ||
target = self._makeOne(project=self.PROJECT, | ||
credentials=CREDENTIALS) | ||
MESSAGE = 'hello world' | ||
|
||
logger = _Logger() | ||
target.logging_client.logger = lambda _: logger | ||
|
||
try: | ||
raise NameError | ||
except NameError: | ||
target.report_error(MESSAGE) | ||
|
||
payload = logger.log_struct_called_with | ||
self.assertEquals(payload['serviceContext'], { | ||
'service': target.DEFAULT_SERVICE | ||
}) | ||
self.assertIn(MESSAGE, payload['message']) | ||
self.assertIn('test_report_error', payload['message']) | ||
self.assertIn('test_client.py', payload['message']) | ||
|
||
def test_report_error_specify_service(self): | ||
CREDENTIALS = _Credentials() | ||
target = self._makeOne(project=self.PROJECT, | ||
credentials=CREDENTIALS) | ||
MESSAGE = 'hello world' | ||
SERVICE = "notdefault" | ||
|
||
logger = _Logger() | ||
target.logging_client.logger = lambda _: logger | ||
|
||
try: | ||
raise NameError | ||
except NameError: | ||
target.report_error(MESSAGE, service=SERVICE) | ||
|
||
payload = logger.log_struct_called_with | ||
self.assertEquals(payload['serviceContext'], { | ||
'service': SERVICE | ||
}) | ||
self.assertIn(MESSAGE, payload['message']) | ||
self.assertIn('test_report_error', payload['message']) | ||
self.assertIn('test_client.py', payload['message']) | ||
|
||
|
||
class _Credentials(object): | ||
|
||
_scopes = None | ||
|
||
@staticmethod | ||
def create_scoped_required(): | ||
return True | ||
|
||
def create_scoped(self, scope): | ||
self._scopes = scope | ||
return self | ||
|
||
|
||
class _Logger(object): | ||
|
||
def log_struct(self, payload, # pylint: disable=unused-argument | ||
client=None, # pylint: disable=unused-argument | ||
labels=None, # pylint: disable=unused-argument | ||
insert_id=None, # pylint: disable=unused-argument | ||
severity=None, # pylint: disable=unused-argument | ||
http_request=None): # pylint: disable=unused-argument | ||
self.log_struct_called_with = payload |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters