diff --git a/contrib/opencensus-ext-stackdriver/opencensus/ext/stackdriver/stats_exporter/__init__.py b/contrib/opencensus-ext-stackdriver/opencensus/ext/stackdriver/stats_exporter/__init__.py index bf692095f..39f911eb5 100644 --- a/contrib/opencensus-ext-stackdriver/opencensus/ext/stackdriver/stats_exporter/__init__.py +++ b/contrib/opencensus-ext-stackdriver/opencensus/ext/stackdriver/stats_exporter/__init__.py @@ -22,6 +22,7 @@ from google.api_core.gapic_v1 import client_info from google.cloud import monitoring_v3 +import google.auth from opencensus.common import utils from opencensus.common.monitored_resource import monitored_resource @@ -365,12 +366,16 @@ def get_user_agent_slug(): return "opencensus-python/{}".format(__version__) -def new_stats_exporter(options, interval=None): +def new_stats_exporter(options=None, interval=None): """Get a stats exporter and running transport thread. Create a new `StackdriverStatsExporter` with the given options and start periodically exporting stats to stackdriver in the background. + Fall back to default auth if `options` is null. This will raise + `google.auth.exceptions.DefaultCredentialsError` if default credentials + aren't configured. + See `opencensus.metrics.transport.get_exporter_thread` for details on the transport thread. @@ -380,9 +385,12 @@ def new_stats_exporter(options, interval=None): :type interval: int or float :param interval: Seconds between export calls. - :rtype: :class:`StackdriverStatsExporter` and :class:`PeriodicTask` - :return: A tuple of the exporter and transport thread. + :rtype: :class:`StackdriverStatsExporter` + :return: The newly-created exporter. """ + if options is None: + _, project_id = google.auth.default() + options = Options(project_id=project_id) if str(options.project_id).strip() == "": raise ValueError(ERROR_BLANK_PROJECT_ID) diff --git a/contrib/opencensus-ext-stackdriver/tests/test_stackdriver_stats.py b/contrib/opencensus-ext-stackdriver/tests/test_stackdriver_stats.py index 8fbaeb95f..9f8cb6c8c 100644 --- a/contrib/opencensus-ext-stackdriver/tests/test_stackdriver_stats.py +++ b/contrib/opencensus-ext-stackdriver/tests/test_stackdriver_stats.py @@ -17,6 +17,7 @@ import unittest from google.cloud import monitoring_v3 +import google.auth from opencensus.common import utils from opencensus.common.version import __version__ @@ -115,6 +116,32 @@ def test_constructor_param(self): default_monitoring_labels=default_labels)) self.assertEqual(exporter.options.project_id, project_id) + def test_null_options(self): + # Check that we don't suppress auth errors + auth_error = google.auth.exceptions.DefaultCredentialsError + mock_auth_error = mock.Mock() + mock_auth_error.side_effect = auth_error + with mock.patch('opencensus.ext.stackdriver.stats_exporter' + '.google.auth.default', mock_auth_error): + with self.assertRaises(auth_error): + stackdriver.new_stats_exporter() + + # Check that we get the default credentials' project ID + mock_auth_ok = mock.Mock() + mock_auth_ok.return_value = (None, 123) + with mock.patch('opencensus.ext.stackdriver.stats_exporter' + '.google.auth.default', mock_auth_ok): + sdse = stackdriver.new_stats_exporter() + self.assertEqual(sdse.options.project_id, 123) + + # Check that we raise if auth works but the project is empty + mock_auth_no_project = mock.Mock() + mock_auth_no_project.return_value = (None, '') + with mock.patch('opencensus.ext.stackdriver.stats_exporter' + '.google.auth.default', mock_auth_no_project): + with self.assertRaises(ValueError): + stackdriver.new_stats_exporter() + def test_blank_project(self): self.assertRaises(ValueError, stackdriver.new_stats_exporter, stackdriver.Options(project_id=""))