From 7851c8ddc1d614ddd3440d163c9b54624f1b15dc Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Wed, 22 Feb 2017 08:22:41 -0800 Subject: [PATCH] Add gccl metrics header to Spanner. (#3045) --- spanner/google/cloud/spanner/__init__.py | 4 ++ spanner/google/cloud/spanner/client.py | 11 +++++- spanner/google/cloud/spanner/database.py | 4 +- spanner/setup.py | 2 +- spanner/unit_tests/test_client.py | 49 +++++++++++++++++++++++- spanner/unit_tests/test_database.py | 7 +++- 6 files changed, 70 insertions(+), 7 deletions(-) diff --git a/spanner/google/cloud/spanner/__init__.py b/spanner/google/cloud/spanner/__init__.py index 6c5f790366b9..25e8ec04c238 100644 --- a/spanner/google/cloud/spanner/__init__.py +++ b/spanner/google/cloud/spanner/__init__.py @@ -15,6 +15,10 @@ """Cloud Spanner API package.""" +import pkg_resources +__version__ = pkg_resources.get_distribution('google-cloud-spanner').version + + from google.cloud.spanner.client import Client from google.cloud.spanner.keyset import KeyRange diff --git a/spanner/google/cloud/spanner/client.py b/spanner/google/cloud/spanner/client.py index 95e5bac86f5a..61fa05a0f961 100644 --- a/spanner/google/cloud/spanner/client.py +++ b/spanner/google/cloud/spanner/client.py @@ -38,6 +38,7 @@ from google.cloud.client import _ClientProjectMixin from google.cloud.credentials import get_credentials from google.cloud.iterator import GAXIterator +from google.cloud.spanner import __version__ from google.cloud.spanner._helpers import _options_with_prefix from google.cloud.spanner.instance import DEFAULT_NODE_COUNT from google.cloud.spanner.instance import Instance @@ -152,14 +153,20 @@ def project_name(self): def instance_admin_api(self): """Helper for session-related API calls.""" if self._instance_admin_api is None: - self._instance_admin_api = InstanceAdminClient() + self._instance_admin_api = InstanceAdminClient( + lib_name='gccl', + lib_version=__version__, + ) return self._instance_admin_api @property def database_admin_api(self): """Helper for session-related API calls.""" if self._database_admin_api is None: - self._database_admin_api = DatabaseAdminClient() + self._database_admin_api = DatabaseAdminClient( + lib_name='gccl', + lib_version=__version__, + ) return self._database_admin_api def copy(self): diff --git a/spanner/google/cloud/spanner/database.py b/spanner/google/cloud/spanner/database.py index 16864b4b0c78..fef8594cae4b 100644 --- a/spanner/google/cloud/spanner/database.py +++ b/spanner/google/cloud/spanner/database.py @@ -30,6 +30,7 @@ from google.cloud.exceptions import Conflict from google.cloud.exceptions import NotFound from google.cloud.operation import register_type +from google.cloud.spanner import __version__ from google.cloud.spanner._helpers import _options_with_prefix from google.cloud.spanner.batch import Batch from google.cloud.spanner.session import Session @@ -179,7 +180,8 @@ def ddl_statements(self): def spanner_api(self): """Helper for session-related API calls.""" if self._spanner_api is None: - self._spanner_api = SpannerClient() + self._spanner_api = SpannerClient( + lib_name='gccl', lib_version=__version__) return self._spanner_api def __eq__(self, other): diff --git a/spanner/setup.py b/spanner/setup.py index e864c977f415..2cac3d85a5e8 100644 --- a/spanner/setup.py +++ b/spanner/setup.py @@ -59,7 +59,7 @@ setup( name='google-cloud-spanner', - version='0.23.1', + version='0.23.2', description='Python Client for Cloud Spanner', long_description=README, namespace_packages=[ diff --git a/spanner/unit_tests/test_client.py b/spanner/unit_tests/test_client.py index 9383471f7fdb..0b0bafd4a967 100644 --- a/spanner/unit_tests/test_client.py +++ b/spanner/unit_tests/test_client.py @@ -106,6 +106,45 @@ def test_constructor_credentials_wo_create_scoped(self): expected_scopes = None self._constructor_test_helper(expected_scopes, creds) + def test_admin_api_lib_name(self): + from google.cloud.spanner import __version__ + from google.cloud.gapic.spanner_admin_database import v1 as db + from google.cloud.gapic.spanner_admin_instance import v1 as inst + + # Get the actual admin client classes. + DatabaseAdminClient = db.database_admin_client.DatabaseAdminClient + InstanceAdminClient = inst.instance_admin_client.InstanceAdminClient + + # Test that the DatabaseAdminClient is called with the gccl library + # name and version. + with mock.patch.object(DatabaseAdminClient, '__init__') as mock_dac: + mock_dac.return_value = None + client = self._make_one( + credentials=_make_credentials(), + project='foo', + ) + self.assertIsInstance(client.database_admin_api, + DatabaseAdminClient) + mock_dac.assert_called_once() + self.assertEqual(mock_dac.mock_calls[0][2]['lib_name'], 'gccl') + self.assertEqual(mock_dac.mock_calls[0][2]['lib_version'], + __version__) + + # Test that the InstanceAdminClient is called with the gccl library + # name and version. + with mock.patch.object(InstanceAdminClient, '__init__') as mock_iac: + mock_iac.return_value = None + client = self._make_one( + credentials=_make_credentials(), + project='foo', + ) + self.assertIsInstance(client.instance_admin_api, + InstanceAdminClient) + mock_iac.assert_called_once() + self.assertEqual(mock_iac.mock_calls[0][2]['lib_name'], 'gccl') + self.assertEqual(mock_iac.mock_calls[0][2]['lib_version'], + __version__) + def test_instance_admin_api(self): from google.cloud._testing import _Monkey from google.cloud.spanner import client as MUT @@ -114,7 +153,9 @@ def test_instance_admin_api(self): client = self._make_one(project=self.PROJECT, credentials=creds) class _Client(object): - pass + def __init__(self, *args, **kwargs): + self.args = args + self.kwargs = kwargs with _Monkey(MUT, InstanceAdminClient=_Client): api = client.instance_admin_api @@ -122,6 +163,7 @@ class _Client(object): self.assertTrue(isinstance(api, _Client)) again = client.instance_admin_api self.assertTrue(again is api) + self.assertEqual(api.kwargs['lib_name'], 'gccl') def test_database_admin_api(self): from google.cloud._testing import _Monkey @@ -131,7 +173,9 @@ def test_database_admin_api(self): client = self._make_one(project=self.PROJECT, credentials=creds) class _Client(object): - pass + def __init__(self, *args, **kwargs): + self.args = args + self.kwargs = kwargs with _Monkey(MUT, DatabaseAdminClient=_Client): api = client.database_admin_api @@ -139,6 +183,7 @@ class _Client(object): self.assertTrue(isinstance(api, _Client)) again = client.database_admin_api self.assertTrue(again is api) + self.assertEqual(api.kwargs['lib_name'], 'gccl') def test_copy(self): credentials = _Credentials('value') diff --git a/spanner/unit_tests/test_database.py b/spanner/unit_tests/test_database.py index 9d36e6635509..a7a2a174116c 100644 --- a/spanner/unit_tests/test_database.py +++ b/spanner/unit_tests/test_database.py @@ -17,6 +17,8 @@ import mock +from google.cloud.spanner import __version__ + from google.cloud._testing import _GAXBaseAPI @@ -188,7 +190,10 @@ def test_spanner_api_property(self): _client = object() _clients = [_client] - def _mock_spanner_client(): + def _mock_spanner_client(*args, **kwargs): + self.assertIsInstance(args, tuple) + self.assertEqual(kwargs['lib_name'], 'gccl') + self.assertEqual(kwargs['lib_version'], __version__) return _clients.pop(0) with _Monkey(MUT, SpannerClient=_mock_spanner_client):