Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 1.8k
Add Error Reporting GAPIC as dependency#2894
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
28f4c98df26d80e2eb576e92e17d128cc3aa51d687e6c3547de8daaa4b9c8fa602e31388873ba3d956a5fa382b358b1e76File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| # 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. | ||
| """GAX wrapper for Error Reporting API requests.""" | ||
| from google.cloud._helpers import make_secure_channel | ||
| from google.cloud._http import DEFAULT_USER_AGENT | ||
| from google.cloud.gapic.errorreporting.v1beta1 import ( | ||
| report_errors_service_client) | ||
| from google.cloud.grpc.devtools.clouderrorreporting.v1beta1 import ( | ||
| report_errors_service_pb2) | ||
| from google.protobuf.json_format import ParseDict | ||
| def make_report_error_api(client): | ||
| """Create an instance of the GAX Logging API. | ||
| :type client::class:`google.cloud.error_reporting.Client` | ||
| :param client: Error Reporting client. | ||
| :rtype: :class:_ErrorReportingGaxApi | ||
| :returns: An Error Reporting API instance. | ||
| """ | ||
| channel = make_secure_channel( | ||
| client._connection.credentials, | ||
| DEFAULT_USER_AGENT, | ||
| report_errors_service_client.ReportErrorsServiceClient.SERVICE_ADDRESS) | ||
| gax_client = report_errors_service_client.ReportErrorsServiceClient( | ||
| channel=channel) | ||
| return _ErrorReportingGaxApi(gax_client, client.project) | ||
| class _ErrorReportingGaxApi(object): | ||
| """Helper mapping Error Reporting-related APIs | ||
| :type gax_api: | ||
| :class:`v1beta1.report_errors_service_client.ReportErrorsServiceClient` | ||
| :param gax_api: API object used to make GAX requests. | ||
| :type project: str | ||
| :param project: Google Cloud Project ID | ||
| """ | ||
| def __init__(self, gax_api, project): | ||
| self._gax_api = gax_api | ||
| self._project = project | ||
| def report_error_event(self, error_report): | ||
| """Uses the GAX client to report the error. | ||
| :type error_report: dict | ||
| :param error_report: | ||
| payload of the error report formatted according to | ||
| https://cloud.google.com/error-reporting/docs/formatting-error-messages | ||
| This object should be built using | ||
| Use | ||
| :meth:~`google.cloud.error_reporting.client._build_error_report` | ||
| """ | ||
| project_name = self._gax_api.project_path(self._project) | ||
| error_report_payload = report_errors_service_pb2.ReportedErrorEvent() | ||
| ParseDict(error_report, error_report_payload) | ||
| self._gax_api.report_error_event(project_name, error_report_payload) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| # 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. | ||
| """Interact with Stackdriver Error Reporting via Logging API. | ||
| It's possible to report Stackdriver Error Reporting errors by formatting | ||
| structured log messages in Stackdriver Logging in a given format. This | ||
| client provides a mechanism to report errors using that technique. | ||
| """ | ||
| import google.cloud.logging.client | ||
| class _ErrorReportingLoggingAPI(object): | ||
| """Report to Stackdriver Error Reporting via Logging API | ||
| :type project: str | ||
| :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. | ||
| """ | ||
| def __init__(self, project, credentials=None, http=None): | ||
| self.logging_client = google.cloud.logging.client.Client( | ||
| project, credentials, http) | ||
| def report_error_event(self, error_report): | ||
| """Report error payload. | ||
| :type error_report: dict | ||
| :param: error_report: | ||
| dict payload of the error report formatted according to | ||
| https://cloud.google.com/error-reporting/docs/formatting-error-messages | ||
| This object should be built using | ||
| :meth:~`google.cloud.error_reporting.client._build_error_report` | ||
| """ | ||
| logger = self.logging_client.logger('errors') | ||
| logger.log_struct(error_report) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -12,13 +12,26 @@ | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
| """Client for interacting with the Stackdriver Logging API""" | ||
| """Client for interacting with the Stackdriver Error Reporting API""" | ||
| import os | ||
| import traceback | ||
| import google.cloud.logging.client | ||
| try: | ||
This comment was marked as spam.Sorry, something went wrong. Uh oh!There was an error while loading. Please reload this page.
This comment was marked as spam.Sorry, something went wrong. Uh oh!There was an error while loading. Please reload this page.
This comment was marked as spam.Sorry, something went wrong. Uh oh!There was an error while loading. Please reload this page.
This comment was marked as spam.Sorry, something went wrong. Uh oh!There was an error while loading. Please reload this page.
This comment was marked as spam.Sorry, something went wrong. Uh oh!There was an error while loading. Please reload this page.
This comment was marked as spam.Sorry, something went wrong. Uh oh!There was an error while loading. Please reload this page. | ||
| from google.cloud.error_reporting._gax import make_report_error_api | ||
| _HAVE_GAX = True | ||
| except ImportError: # pragma: NO COVER | ||
| _HAVE_GAX = False | ||
| from google.cloud._helpers import _determine_default_project | ||
| from google.cloud.error_reporting._logging import _ErrorReportingLoggingAPI | ||
| from google.cloud.environment_vars import DISABLE_GRPC | ||
| import six | ||
| _DISABLE_GAX = os.getenv(DISABLE_GRPC, False) | ||
| _USE_GAX = _HAVE_GAX and not _DISABLE_GAX | ||
| class HTTPContext(object): | ||
| """HTTPContext defines an object that captures the parameter for the | ||
| @@ -96,6 +109,12 @@ class Client(object): | ||
| SHA-1 hash, for example. If the developer did not provide | ||
| a version, the value is set to default. | ||
| :type use_gax: bool | ||
| :param use_gax: (Optional) Explicitly specifies whether | ||
| to use the gRPC transport (via GAX) or HTTP. If unset, | ||
| falls back to the ``GOOGLE_CLOUD_DISABLE_GRPC`` environment | ||
| variable. | ||
| :raises: :class:`ValueError` if the project is neither passed in nor | ||
| set in the environment. | ||
| """ | ||
| @@ -104,24 +123,56 @@ def __init__(self, project=None, | ||
| credentials=None, | ||
| http=None, | ||
| service=None, | ||
| version=None): | ||
| self.logging_client = google.cloud.logging.client.Client( | ||
| project, credentials, http) | ||
| version=None, | ||
| use_gax=None): | ||
| if project is None: | ||
| self._project = _determine_default_project() | ||
| else: | ||
| self._project = project | ||
| self._credentials = credentials | ||
| self._http = http | ||
| self._report_errors_api = None | ||
| self.service = service if service else self.DEFAULT_SERVICE | ||
| self.version = version | ||
| if use_gax is None: | ||
| self._use_gax = _USE_GAX | ||
| else: | ||
| self._use_gax = use_gax | ||
| DEFAULT_SERVICE = 'python' | ||
| def _send_error_report(self, message, | ||
| report_location=None, http_context=None, user=None): | ||
| """Makes the call to the Error Reporting API via the log stream. | ||
| @property | ||
| def report_errors_api(self): | ||
| """Helper for logging-related API calls. | ||
| This is the lower-level interface to build the payload, generally | ||
| users will use either report() or report_exception() to automatically | ||
| gather the parameters for this method. | ||
| See: | ||
| https://cloud.google.com/logging/docs/api/reference/rest/v2/entries | ||
| https://cloud.google.com/logging/docs/api/reference/rest/v2/projects.logs | ||
| Currently this method sends the Error Report by formatting a structured | ||
| log message according to | ||
| :rtype: | ||
| :class:`_gax._ErrorReportingGaxApi` | ||
| or | ||
| :class:`._logging._ErrorReportingLoggingAPI` | ||
| :returns: A class that implements the report errors API. | ||
| """ | ||
| if self._report_errors_api is None: | ||
| if self._use_gax: | ||
| self._report_errors_api = make_report_error_api(self._project) | ||
| else: | ||
| self._report_errors_api = _ErrorReportingLoggingAPI( | ||
| self._project, self._credentials, self._http) | ||
| return self._report_errors_api | ||
| def _build_error_report(self, | ||
| message, | ||
| report_location=None, | ||
| http_context=None, | ||
| user=None): | ||
| """Builds the Error Reporting object to report. | ||
| This builds the object according to | ||
| https://cloud.google.com/error-reporting/docs/formatting-error-messages | ||
| @@ -151,7 +202,10 @@ def _send_error_report(self, message, | ||
| logged in. In this case the Error Reporting system will | ||
| use other data, such as remote IP address, | ||
| to distinguish affected users. | ||
| """ | ||
| :rtype: dict | ||
| :returns: A dict payload ready to be serialized to JSON and sent to | ||
| the API. | ||
| """ | ||
| payload = { | ||
| 'serviceContext': { | ||
| 'service': self.service, | ||
| @@ -178,9 +232,49 @@ def _send_error_report(self, message, | ||
| if user: | ||
| payload['context']['user'] = user | ||
| return payload | ||
| def _send_error_report(self, | ||
| message, | ||
| report_location=None, | ||
| http_context=None, | ||
| user=None): | ||
| """Makes the call to the Error Reporting API. | ||
| This is the lower-level interface to build and send the payload, | ||
| generally users will use either report() or report_exception() to | ||
| automatically gather the parameters for this method. | ||
| logger = self.logging_client.logger('errors') | ||
| logger.log_struct(payload) | ||
| :type message: str | ||
| :param message: The stack trace that was reported or logged by the | ||
| service. | ||
| :type report_location: dict | ||
| :param report_location: The location in the source code where the | ||
| decision was made to report the error, usually the place | ||
| where it was logged. For a logged exception this would be the | ||
| source line where the exception is logged, usually close to | ||
| the place where it was caught. | ||
| This should be a Python dict that contains the keys 'filePath', | ||
| 'lineNumber', and 'functionName' | ||
| :type http_context: :class`google.cloud.error_reporting.HTTPContext` | ||
| :param http_context: The HTTP request which was processed when the | ||
| error was triggered. | ||
| :type user: str | ||
| :param user: The user who caused or was affected by the crash. This can | ||
| be a user ID, an email address, or an arbitrary token that | ||
| uniquely identifies the user. When sending an error | ||
| report, leave this field empty if the user was not | ||
| logged in. In this case the Error Reporting system will | ||
| use other data, such as remote IP address, | ||
| to distinguish affected users. | ||
| """ | ||
| error_report = self._build_error_report(message, report_location, | ||
| http_context, user) | ||
| self.report_errors_api.report_error_event(error_report) | ||
| def report(self, message, http_context=None, user=None): | ||
| """ Reports a message to Stackdriver Error Reporting | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| # Copyright 2017 Google Inc. | ||
| # | ||
| # 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 unittest | ||
| import mock | ||
| class Test_make_report_error_api(unittest.TestCase): | ||
| def test_make_report_error_api(self): | ||
| from google.cloud.error_reporting._gax import make_report_error_api | ||
| client = mock.Mock() | ||
| client.project = mock.Mock() | ||
| report_error_client = make_report_error_api(client) | ||
| self.assertEqual(report_error_client._project, client.project) | ||
| class Test_ErrorReportingGaxApi(unittest.TestCase): | ||
| PROJECT = 'PROJECT' | ||
| def _call_fut(self, gax_api, project): | ||
| from google.cloud.error_reporting._gax import _ErrorReportingGaxApi | ||
| return _ErrorReportingGaxApi(gax_api, project) | ||
| def test_constructor(self): | ||
| gax_api = mock.Mock() | ||
| gax_client_wrapper = self._call_fut(gax_api, self.PROJECT) | ||
| self.assertEqual(gax_client_wrapper._project, self.PROJECT) | ||
| self.assertEqual(gax_client_wrapper._gax_api, gax_api) | ||
| @mock.patch("google.cloud.error_reporting._gax.ParseDict") | ||
| def test_report_error_event(self, _): | ||
| gax_api = mock.Mock() | ||
| gax_client_wrapper = self._call_fut(gax_api, self.PROJECT) | ||
| mock_error_report = mock.Mock() | ||
| gax_client_wrapper.report_error_event(mock_error_report) | ||
| self.assertTrue(gax_api.report_error_event.called_with, | ||
| mock_error_report) |
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.