From b57cb2dccaa60483451081fac074d5ea67100719 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Sat, 20 Feb 2021 06:57:11 +0100 Subject: [PATCH 1/7] chore(deps): update dependency google-cloud-monitoring to v2.0.1 (#85) --- samples/snippets/v3/alerts-client/requirements.txt | 2 +- samples/snippets/v3/cloud-client/requirements.txt | 2 +- samples/snippets/v3/uptime-check-client/requirements.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/snippets/v3/alerts-client/requirements.txt b/samples/snippets/v3/alerts-client/requirements.txt index 4db0730a..d5c9844e 100644 --- a/samples/snippets/v3/alerts-client/requirements.txt +++ b/samples/snippets/v3/alerts-client/requirements.txt @@ -1,2 +1,2 @@ -google-cloud-monitoring==2.0.0 +google-cloud-monitoring==2.0.1 tabulate==0.8.7 diff --git a/samples/snippets/v3/cloud-client/requirements.txt b/samples/snippets/v3/cloud-client/requirements.txt index e664e634..2155b357 100644 --- a/samples/snippets/v3/cloud-client/requirements.txt +++ b/samples/snippets/v3/cloud-client/requirements.txt @@ -1 +1 @@ -google-cloud-monitoring==2.0.0 +google-cloud-monitoring==2.0.1 diff --git a/samples/snippets/v3/uptime-check-client/requirements.txt b/samples/snippets/v3/uptime-check-client/requirements.txt index 4db0730a..d5c9844e 100644 --- a/samples/snippets/v3/uptime-check-client/requirements.txt +++ b/samples/snippets/v3/uptime-check-client/requirements.txt @@ -1,2 +1,2 @@ -google-cloud-monitoring==2.0.0 +google-cloud-monitoring==2.0.1 tabulate==0.8.7 From aa56521990e070ea96f48baaa714ed362309b229 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 22 Feb 2021 17:05:05 +0100 Subject: [PATCH 2/7] chore(deps): update dependency tabulate to v0.8.9 (#84) --- samples/snippets/v3/alerts-client/requirements.txt | 2 +- samples/snippets/v3/uptime-check-client/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/snippets/v3/alerts-client/requirements.txt b/samples/snippets/v3/alerts-client/requirements.txt index d5c9844e..71e5cabc 100644 --- a/samples/snippets/v3/alerts-client/requirements.txt +++ b/samples/snippets/v3/alerts-client/requirements.txt @@ -1,2 +1,2 @@ google-cloud-monitoring==2.0.1 -tabulate==0.8.7 +tabulate==0.8.9 diff --git a/samples/snippets/v3/uptime-check-client/requirements.txt b/samples/snippets/v3/uptime-check-client/requirements.txt index d5c9844e..71e5cabc 100644 --- a/samples/snippets/v3/uptime-check-client/requirements.txt +++ b/samples/snippets/v3/uptime-check-client/requirements.txt @@ -1,2 +1,2 @@ google-cloud-monitoring==2.0.1 -tabulate==0.8.7 +tabulate==0.8.9 From 811f9aa409ec922402cb83a6753812518b7a0d4b Mon Sep 17 00:00:00 2001 From: Vinay B S Date: Tue, 2 Mar 2021 16:12:04 -0500 Subject: [PATCH 3/7] feat: Adding labels to the metric descriptor in the snippets.py (#88) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helps understand how to add labels for custom metrics [1]. [1] https://cloud.google.com/monitoring/custom-metrics/creating-metrics#create-metric-desc Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [x] Make sure to open an issue as a [bug/issue](https://github.com/googleapis/python-monitoring/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [x] Ensure the tests and linter pass - [ ] Code coverage does not decrease (if any source code was changed) - [ ] Appropriate docs were updated (if necessary) Fixes #86 🦕 --- samples/snippets/v3/cloud-client/snippets.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/samples/snippets/v3/cloud-client/snippets.py b/samples/snippets/v3/cloud-client/snippets.py index 1c0407a2..19654e32 100644 --- a/samples/snippets/v3/cloud-client/snippets.py +++ b/samples/snippets/v3/cloud-client/snippets.py @@ -19,6 +19,7 @@ import uuid from google.api import metric_pb2 as ga_metric +from google.api import label_pb2 as ga_label from google.cloud import monitoring_v3 @@ -34,6 +35,13 @@ def create_metric_descriptor(project_id): descriptor.metric_kind = ga_metric.MetricDescriptor.MetricKind.GAUGE descriptor.value_type = ga_metric.MetricDescriptor.ValueType.DOUBLE descriptor.description = "This is a simple example of a custom metric." + + labels = ga_label.LabelDescriptor() + labels.key = "TestLabel" + labels.value_type = ga_label.LabelDescriptor.ValueType.STRING + labels.description = "This is a test label" + descriptor.labels.append(labels) + descriptor = client.create_metric_descriptor( name=project_name, metric_descriptor=descriptor ) From fe57446bef8c4c11dbe7e5948ff25030b7275715 Mon Sep 17 00:00:00 2001 From: Bu Sun Kim <8822365+busunkim96@users.noreply.github.com> Date: Sat, 6 Mar 2021 05:30:02 -0700 Subject: [PATCH 4/7] chore: require samples checks (#63) Make samples kokoro sessions required --- .github/sync-repo-settings.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/sync-repo-settings.yaml diff --git a/.github/sync-repo-settings.yaml b/.github/sync-repo-settings.yaml new file mode 100644 index 00000000..af599353 --- /dev/null +++ b/.github/sync-repo-settings.yaml @@ -0,0 +1,13 @@ +# https://github.com/googleapis/repo-automation-bots/tree/master/packages/sync-repo-settings +# Rules for master branch protection +branchProtectionRules: +# Identifies the protection rule pattern. Name of the branch to be protected. +# Defaults to `master` +- pattern: master + requiredStatusCheckContexts: + - 'Kokoro' + - 'cla/google' + - 'Samples - Lint' + - 'Samples - Python 3.6' + - 'Samples - Python 3.7' + - 'Samples - Python 3.8' From 4cdb1ff439154409c94e347dd5f3b6e2bc40e998 Mon Sep 17 00:00:00 2001 From: Bu Sun Kim <8822365+busunkim96@users.noreply.github.com> Date: Sat, 6 Mar 2021 05:38:02 -0700 Subject: [PATCH 5/7] docs: remove code snippet and 'Stackdriver' (#71) Remove the code snippet which is untested. Fixes #70. Also remove 'Stackdriver' from the README. --- README.rst | 39 +++++++-------------------------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/README.rst b/README.rst index 210b4875..ca17b563 100644 --- a/README.rst +++ b/README.rst @@ -1,10 +1,10 @@ -Python Client for Stackdriver Monitoring API +Python Client for Cloud Monitoring API ======================================================= |ga| |pypi| |versions| -`Stackdriver Monitoring API`_: Manages your Stackdriver Monitoring data and -configurations. Most projects must be associated with a Stackdriver account, +`Cloud Monitoring API`_: Manages your Cloud Monitoring data and +configurations. Most projects must be associated with a Google Cloud account, with a few exceptions as noted on the individual method pages. - `Client Library Documentation`_ @@ -16,7 +16,7 @@ with a few exceptions as noted on the individual method pages. :target: https://pypi.org/project/google-cloud-monitoring/ .. |versions| image:: https://img.shields.io/pypi/pyversions/google-cloud-monitoring.svg :target: https://pypi.org/project/google-cloud-monitoring/ -.. _Stackdriver Monitoring API: https://cloud.google.com/monitoring/api/ref_v3/rest/ +.. _Cloud Monitoring API: https://cloud.google.com/monitoring/api/ref_v3/rest/ .. _Client Library Documentation: https://googleapis.dev/python/monitoring/latest .. _Product Documentation: https://cloud.google.com/monitoring/docs @@ -27,12 +27,12 @@ In order to use this library, you first need to go through the following steps: 1. `Select or create a Cloud Platform project.`_ 2. `Enable billing for your project.`_ -3. `Enable the Stackdriver Monitoring API.`_ +3. `Enable the Cloud Monitoring API.`_ 4. `Setup Authentication.`_ .. _Select or create a Cloud Platform project.: https://console.cloud.google.com/project .. _Enable billing for your project.: https://cloud.google.com/billing/docs/how-to/modify-project#enable_billing_for_a_project -.. _Enable the Stackdriver Monitoring API.: https://cloud.google.com/monitoring/api/enable-api +.. _Enable the Cloud Monitoring API.: https://cloud.google.com/monitoring/api/enable-api .. _Setup Authentication.: https://googleapis.dev/python/google-api-core/latest/auth.html Installation @@ -81,37 +81,12 @@ Windows \Scripts\activate \Scripts\pip.exe install google-cloud-monitoring -Preview -~~~~~~~ - -MetricServiceClient -^^^^^^^^^^^^^^^^^^^ - -.. code:: py - - from google.cloud import monitoring_v3 - - client = monitoring_v3.MetricServiceClient() - - name = client.project_path('[PROJECT]') - - - # Iterate over all results - for element in client.list_monitored_resource_descriptors(name): - # process element - pass - - # Or iterate over results one page at a time - for page in client.list_monitored_resource_descriptors(name).pages: - for element in page: - # process element - pass Next Steps ~~~~~~~~~~ -- Read the `Client Library Documentation`_ for Stackdriver Monitoring API +- Read the `Client Library Documentation`_ for Cloud Monitoring API to see other available methods on the client. - Read the `Product documentation`_ to learn more about the product and see How-to Guides. From f135202f1dd7866c4be2d709b522beb2710f5cda Mon Sep 17 00:00:00 2001 From: Bu Sun Kim <8822365+busunkim96@users.noreply.github.com> Date: Thu, 11 Mar 2021 17:42:19 -0700 Subject: [PATCH 6/7] fix: fix `as_dataframe` (#91) --- google/cloud/monitoring_v3/_dataframe.py | 18 ++++++---- noxfile.py | 36 ++++++++++++++++--- samples/snippets/v3/cloud-client/snippets.py | 6 ++-- synth.py | 7 ++-- tests/unit/test__dataframe.py | 38 ++++++++++---------- 5 files changed, 71 insertions(+), 34 deletions(-) diff --git a/google/cloud/monitoring_v3/_dataframe.py b/google/cloud/monitoring_v3/_dataframe.py index 5bedb39b..9210fbea 100644 --- a/google/cloud/monitoring_v3/_dataframe.py +++ b/google/cloud/monitoring_v3/_dataframe.py @@ -21,14 +21,15 @@ except ImportError: # pragma: NO COVER pandas = None -from google.cloud.monitoring_v3.types import TimeSeries +from google.cloud import monitoring_v3 + TOP_RESOURCE_LABELS = ("project_id", "aws_account", "location", "region", "zone") def _extract_header(time_series): """Return a copy of time_series with the points removed.""" - return TimeSeries( + return monitoring_v3.TimeSeries( metric=time_series.metric, resource=time_series.resource, metric_kind=time_series.metric_kind, @@ -46,15 +47,19 @@ def _extract_labels(time_series): def _extract_value(typed_value): """Extract the value from a TypedValue.""" - value_type = typed_value.WhichOneof("value") - return typed_value.__getattribute__(value_type) + # There is no equivalent of WhichOneOf in proto-plus + # This may break if the field names have been altered in the + # proto-plus representation + # https://github.com/googleapis/proto-plus-python/issues/137 + value_type = monitoring_v3.TypedValue.pb(typed_value).WhichOneof("value") + return getattr(typed_value, value_type) def _build_dataframe(time_series_iterable, label=None, labels=None): # pragma: NO COVER """Build a :mod:`pandas` dataframe out of time series. :type time_series_iterable: - iterable over :class:`~google.cloud.monitoring_v3.types.TimeSeries` + iterable over :class:`~google.cloud.monitoring_v3.TimeSeries` :param time_series_iterable: An iterable (e.g., a query object) yielding time series. @@ -95,7 +100,8 @@ def _build_dataframe(time_series_iterable, label=None, labels=None): # pragma: pandas_series = pandas.Series( data=[_extract_value(point.value) for point in time_series.points], index=[ - point.interval.end_time.ToNanoseconds() for point in time_series.points + point.interval.end_time.timestamp_pb().ToNanoseconds() + for point in time_series.points ], ) columns.append(pandas_series) diff --git a/noxfile.py b/noxfile.py index 41eeb037..bc06683c 100644 --- a/noxfile.py +++ b/noxfile.py @@ -30,6 +30,17 @@ SYSTEM_TEST_PYTHON_VERSIONS = ["3.8"] UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9"] +# 'docfx' is excluded since it only needs to run in 'docs-presubmit' +nox.options.sessions = [ + "unit", + "system", + "cover", + "lint", + "lint_setup_py", + "blacken", + "docs", +] + @nox.session(python=DEFAULT_PYTHON_VERSION) def lint(session): @@ -75,12 +86,14 @@ def default(session): session.install( "mock", "pytest", "pytest-cov", ) - session.install("-e", ".") + + session.install("-e", ".[pandas]") # Run py.test against the unit tests. session.run( "py.test", "--quiet", + f"--junitxml=unit_{session.python}_sponge_log.xml", "--cov=google/cloud", "--cov=tests/unit", "--cov-append", @@ -110,6 +123,9 @@ def system(session): # Sanity check: Only run tests if the environment variable is set. if not os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", ""): session.skip("Credentials must be set via environment variable") + # Install pyopenssl for mTLS testing. + if os.environ.get("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true": + session.install("pyopenssl") system_test_exists = os.path.exists(system_test_path) system_test_folder_exists = os.path.exists(system_test_folder_path) @@ -125,13 +141,25 @@ def system(session): session.install( "mock", "pytest", "google-cloud-testutils", ) - session.install("-e", ".") + session.install("-e", ".[pandas]") # Run py.test against the system tests. if system_test_exists: - session.run("py.test", "--quiet", system_test_path, *session.posargs) + session.run( + "py.test", + "--quiet", + f"--junitxml=system_{session.python}_sponge_log.xml", + system_test_path, + *session.posargs, + ) if system_test_folder_exists: - session.run("py.test", "--quiet", system_test_folder_path, *session.posargs) + session.run( + "py.test", + "--quiet", + f"--junitxml=system_{session.python}_sponge_log.xml", + system_test_folder_path, + *session.posargs, + ) @nox.session(python=DEFAULT_PYTHON_VERSION) diff --git a/samples/snippets/v3/cloud-client/snippets.py b/samples/snippets/v3/cloud-client/snippets.py index 19654e32..9b47e5da 100644 --- a/samples/snippets/v3/cloud-client/snippets.py +++ b/samples/snippets/v3/cloud-client/snippets.py @@ -18,8 +18,8 @@ import time import uuid -from google.api import metric_pb2 as ga_metric from google.api import label_pb2 as ga_label +from google.api import metric_pb2 as ga_metric from google.cloud import monitoring_v3 @@ -35,13 +35,13 @@ def create_metric_descriptor(project_id): descriptor.metric_kind = ga_metric.MetricDescriptor.MetricKind.GAUGE descriptor.value_type = ga_metric.MetricDescriptor.ValueType.DOUBLE descriptor.description = "This is a simple example of a custom metric." - + labels = ga_label.LabelDescriptor() labels.key = "TestLabel" labels.value_type = ga_label.LabelDescriptor.ValueType.STRING labels.description = "This is a test label" descriptor.labels.append(labels) - + descriptor = client.create_metric_descriptor( name=project_name, metric_descriptor=descriptor ) diff --git a/synth.py b/synth.py index 5486781a..919fe7b6 100644 --- a/synth.py +++ b/synth.py @@ -93,16 +93,19 @@ templated_files = common.py_library( samples=True, # set to True only if there are samples microgenerator=True, + unit_test_extras=["pandas"], + system_test_extras=["pandas"], cov_level=99 ) s.move(templated_files, excludes=[".coveragerc"]) # microgenerator has a good .coveragerc file +# Don't treat docs (sphinx) warnings as errors. +s.replace("noxfile.py", '[\"\']-W[\"\']', '# "-W"') + # ---------------------------------------------------------------------------- # Samples templates # ---------------------------------------------------------------------------- python.py_samples(skip_readmes=True) -# Don't treat warnings as errors. -s.replace("noxfile.py", '[\"\']-W[\"\']', '# "-W"') s.shell.run(["nox", "-s", "blacken"], hide_output=False) diff --git a/tests/unit/test__dataframe.py b/tests/unit/test__dataframe.py index 5626dcaa..8613831b 100644 --- a/tests/unit/test__dataframe.py +++ b/tests/unit/test__dataframe.py @@ -12,15 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -try: - import pandas -except ImportError: - HAVE_PANDAS = False -else: - HAVE_PANDAS = True # pragma: NO COVER +import pandas import unittest +from google.api import metric_pb2 +from google.api import monitored_resource_pb2 +from google.api_core import datetime_helpers +from google.cloud import monitoring_v3 +from google.cloud.monitoring_v3 import _dataframe + PROJECT = "my-project" @@ -58,20 +59,22 @@ def parse_timestamps(): def generate_query_results(): - from google.cloud.monitoring_v3 import types - def P(timestamp, value): - interval = types.TimeInterval() - interval.start_time.FromJsonString(timestamp) - interval.end_time.FromJsonString(timestamp) - return types.Point(interval=interval, value={"double_value": value}) + interval = monitoring_v3.TimeInterval() + interval.start_time = datetime_helpers.from_rfc3339(timestamp).replace( + tzinfo=None + ) + interval.end_time = datetime_helpers.from_rfc3339(timestamp).replace( + tzinfo=None + ) + return monitoring_v3.Point(interval=interval, value={"double_value": value}) for metric_labels, resource_labels, value in zip( METRIC_LABELS, RESOURCE_LABELS, VALUES ): - yield types.TimeSeries( - metric=types.Metric(type=METRIC_TYPE, labels=metric_labels), - resource=types.MonitoredResource( + yield monitoring_v3.TimeSeries( + metric=metric_pb2.Metric(type=METRIC_TYPE, labels=metric_labels), + resource=monitored_resource_pb2.MonitoredResource( type=RESOURCE_TYPE, labels=resource_labels ), metric_kind=METRIC_KIND, @@ -80,12 +83,9 @@ def P(timestamp, value): ) -@unittest.skipUnless(HAVE_PANDAS, "No pandas") class Test__build_dataframe(unittest.TestCase): def _call_fut(self, *args, **kwargs): - from google.cloud.monitoring_v3._dataframe import _build_dataframe - - return _build_dataframe(*args, **kwargs) + return _dataframe._build_dataframe(*args, **kwargs) def test_both_label_and_labels_illegal(self): with self.assertRaises(ValueError): From d8d09ab2a2da37ce64012c20e971afb61ef36fad Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 11 Mar 2021 18:00:20 -0700 Subject: [PATCH 7/7] chore: release 2.1.0 (#89) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- CHANGELOG.md | 17 +++++++++++++++++ setup.py | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b7a6bae..5c0a4b4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,23 @@ [1]: https://pypi.org/project/google-cloud-monitoring/#history +## [2.1.0](https://www.github.com/googleapis/python-monitoring/compare/v2.0.1...v2.1.0) (2021-03-12) + + +### Features + +* Adding labels to the metric descriptor in the snippets.py ([#88](https://www.github.com/googleapis/python-monitoring/issues/88)) ([811f9aa](https://www.github.com/googleapis/python-monitoring/commit/811f9aa409ec922402cb83a6753812518b7a0d4b)) + + +### Bug Fixes + +* fix `as_dataframe` ([#91](https://www.github.com/googleapis/python-monitoring/issues/91)) ([f135202](https://www.github.com/googleapis/python-monitoring/commit/f135202f1dd7866c4be2d709b522beb2710f5cda)) + + +### Documentation + +* remove code snippet and 'Stackdriver' ([#71](https://www.github.com/googleapis/python-monitoring/issues/71)) ([4cdb1ff](https://www.github.com/googleapis/python-monitoring/commit/4cdb1ff439154409c94e347dd5f3b6e2bc40e998)) + ### [2.0.1](https://www.github.com/googleapis/python-monitoring/compare/v2.0.0...v2.0.1) (2021-02-18) diff --git a/setup.py b/setup.py index 84c7d5d3..ae90de3d 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ name = "google-cloud-monitoring" description = "Stackdriver Monitoring API client library" -version = "2.0.1" +version = "2.1.0" # Should be one of: # 'Development Status :: 3 - Alpha' # 'Development Status :: 4 - Beta'