Skip to content
This repository was archived by the owner on Sep 17, 2025. It is now read-only.

Commit 15b126a

Browse files
authored
upgrade opencensus-ext-stackdriver to use google-cloud-monitoring v2 library (#1060)
1 parent e693d50 commit 15b126a

File tree

5 files changed

+72
-41
lines changed

5 files changed

+72
-41
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,6 @@ jobs:
3939
with:
4040
path: .tox
4141
# bump version prefix to fully reset caches
42-
key: v1-tox-${{ matrix.python-version }}-${{ hashFiles('tox.ini') }}
42+
key: v1-tox-${{ matrix.python-version }}-${{ hashFiles('tox.ini', '**/setup.py') }}
4343
- name: run tox
4444
run: tox -f ${{ matrix.python-version }}

contrib/opencensus-ext-stackdriver/opencensus/ext/stackdriver/stats_exporter/__init__.py

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121
from datetime import datetime
2222

2323
import google.auth
24+
from google.api import metric_pb2
2425
from google.api_core.gapic_v1 import client_info
2526
from google.cloud import monitoring_v3
27+
from google.protobuf import timestamp_pb2
2628

2729
from opencensus.common import utils
2830
from opencensus.common.monitored_resource import (
@@ -51,20 +53,20 @@
5153
# OC metric descriptor type to SD metric kind and value type
5254
OC_MD_TO_SD_TYPE = {
5355
metric_descriptor.MetricDescriptorType.CUMULATIVE_INT64:
54-
(monitoring_v3.enums.MetricDescriptor.MetricKind.CUMULATIVE,
55-
monitoring_v3.enums.MetricDescriptor.ValueType.INT64),
56+
(metric_pb2.MetricDescriptor.MetricKind.CUMULATIVE,
57+
metric_pb2.MetricDescriptor.ValueType.INT64),
5658
metric_descriptor.MetricDescriptorType.CUMULATIVE_DOUBLE:
57-
(monitoring_v3.enums.MetricDescriptor.MetricKind.CUMULATIVE,
58-
monitoring_v3.enums.MetricDescriptor.ValueType.DOUBLE),
59+
(metric_pb2.MetricDescriptor.MetricKind.CUMULATIVE,
60+
metric_pb2.MetricDescriptor.ValueType.DOUBLE),
5961
metric_descriptor.MetricDescriptorType.CUMULATIVE_DISTRIBUTION:
60-
(monitoring_v3.enums.MetricDescriptor.MetricKind.CUMULATIVE,
61-
monitoring_v3.enums.MetricDescriptor.ValueType.DISTRIBUTION),
62+
(metric_pb2.MetricDescriptor.MetricKind.CUMULATIVE,
63+
metric_pb2.MetricDescriptor.ValueType.DISTRIBUTION),
6264
metric_descriptor.MetricDescriptorType.GAUGE_INT64:
63-
(monitoring_v3.enums.MetricDescriptor.MetricKind.GAUGE,
64-
monitoring_v3.enums.MetricDescriptor.ValueType.INT64),
65+
(metric_pb2.MetricDescriptor.MetricKind.GAUGE,
66+
metric_pb2.MetricDescriptor.ValueType.INT64),
6567
metric_descriptor.MetricDescriptorType.GAUGE_DOUBLE:
66-
(monitoring_v3.enums.MetricDescriptor.MetricKind.GAUGE,
67-
monitoring_v3.enums.MetricDescriptor.ValueType.DOUBLE)
68+
(metric_pb2.MetricDescriptor.MetricKind.GAUGE,
69+
metric_pb2.MetricDescriptor.ValueType.DOUBLE)
6870
}
6971

7072

@@ -158,7 +160,9 @@ def export_metrics(self, metrics):
158160
ts_batches = self.create_batched_time_series(metrics)
159161
for ts_batch in ts_batches:
160162
self.client.create_time_series(
161-
self.client.project_path(self.options.project_id), ts_batch)
163+
name=self.client.common_project_path(self.options.project_id),
164+
time_series=ts_batch,
165+
)
162166

163167
def create_batched_time_series(self, metrics,
164168
batch_size=MAX_TIME_SERIES_PER_UPLOAD):
@@ -173,7 +177,7 @@ def create_time_series_list(self, metric):
173177

174178
def _convert_series(self, metric, ts):
175179
"""Convert an OC timeseries to a SD series."""
176-
series = monitoring_v3.types.TimeSeries()
180+
series = monitoring_v3.TimeSeries()
177181
series.metric.type = self.get_metric_type(metric.descriptor)
178182

179183
for lk, lv in self.options.default_monitoring_labels.items():
@@ -187,9 +191,10 @@ def _convert_series(self, metric, ts):
187191
set_monitored_resource(series, self.options.resource)
188192

189193
for point in ts.points:
190-
sd_point = series.points.add()
194+
sd_point = monitoring_v3.Point()
191195
# this just modifies points, no return
192196
self._convert_point(metric, ts, point, sd_point)
197+
series.points.append(sd_point)
193198
return series
194199

195200
def _convert_point(self, metric, ts, point, sd_point):
@@ -245,14 +250,17 @@ def _convert_point(self, metric, ts, point, sd_point):
245250
timestamp_start = (start - EPOCH_DATETIME).total_seconds()
246251
timestamp_end = (end - EPOCH_DATETIME).total_seconds()
247252

248-
sd_point.interval.end_time.seconds = int(timestamp_end)
249-
250-
secs = sd_point.interval.end_time.seconds
251-
sd_point.interval.end_time.nanos = int((timestamp_end - secs) * 1e9)
253+
end_time_pb = timestamp_pb2.Timestamp()
254+
end_time_pb.seconds = int(timestamp_end)
255+
end_time_pb.nanos = int((timestamp_end - end_time_pb.seconds) * 1e9)
256+
sd_point.interval.end_time = end_time_pb
252257

253-
start_time = sd_point.interval.start_time
254-
start_time.seconds = int(timestamp_start)
255-
start_time.nanos = int((timestamp_start - start_time.seconds) * 1e9)
258+
start_time_pb = timestamp_pb2.Timestamp()
259+
start_time_pb.seconds = int(timestamp_start)
260+
start_time_pb.nanos = int(
261+
(timestamp_start - start_time_pb.seconds) * 1e9,
262+
)
263+
sd_point.interval.start_time = start_time_pb
256264

257265
def get_metric_type(self, oc_md):
258266
"""Get a SD metric type for an OC metric descriptor."""
@@ -273,7 +281,7 @@ def get_metric_descriptor(self, oc_md):
273281
desc_labels = new_label_descriptors(
274282
self.options.default_monitoring_labels, oc_md.label_keys)
275283

276-
descriptor = monitoring_v3.types.MetricDescriptor(labels=desc_labels)
284+
descriptor = metric_pb2.MetricDescriptor(labels=desc_labels)
277285
metric_type = self.get_metric_type(oc_md)
278286
descriptor.type = metric_type
279287
descriptor.metric_kind = metric_kind
@@ -295,8 +303,10 @@ def register_metric_descriptor(self, oc_md):
295303
return self._md_cache[metric_type]
296304

297305
descriptor = self.get_metric_descriptor(oc_md)
298-
project_name = self.client.project_path(self.options.project_id)
299-
sd_md = self.client.create_metric_descriptor(project_name, descriptor)
306+
project_name = self.client.common_project_path(self.options.project_id)
307+
sd_md = self.client.create_metric_descriptor(
308+
name=project_name, metric_descriptor=descriptor
309+
)
300310
with self._md_lock:
301311
self._md_cache[metric_type] = sd_md
302312
return sd_md

contrib/opencensus-ext-stackdriver/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
include_package_data=True,
3838
long_description=open('README.rst').read(),
3939
install_requires=[
40-
'google-cloud-monitoring >= 0.30.0, < 1.0.0',
40+
'google-cloud-monitoring ~= 2.0',
4141
'google-cloud-trace >= 0.20.0, < 1.0.0',
4242
'rsa <= 4.0; python_version<="3.4"',
4343
'opencensus >= 0.8.dev0, < 1.0.0',

contrib/opencensus-ext-stackdriver/tests/test_stackdriver_stats.py

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313
# limitations under the License.
1414

1515
import unittest
16-
from datetime import datetime
16+
from datetime import datetime, timedelta
1717

1818
import google.auth
1919
import mock
20+
from google.api import metric_pb2
2021
from google.cloud import monitoring_v3
2122

2223
from opencensus.common import utils
@@ -433,12 +434,12 @@ def test_get_metric_descriptor(self):
433434
sd_md = exporter.get_metric_descriptor(oc_md)
434435
self.assertEqual(
435436
sd_md.metric_kind,
436-
monitoring_v3.enums.MetricDescriptor.MetricKind.GAUGE)
437+
metric_pb2.MetricDescriptor.MetricKind.GAUGE)
437438
self.assertEqual(
438439
sd_md.value_type,
439-
monitoring_v3.enums.MetricDescriptor.ValueType.INT64)
440+
metric_pb2.MetricDescriptor.ValueType.INT64)
440441

441-
self.assertIsInstance(sd_md, monitoring_v3.types.MetricDescriptor)
442+
self.assertIsInstance(sd_md, metric_pb2.MetricDescriptor)
442443
exporter.client.create_metric_descriptor.assert_not_called()
443444

444445
def test_get_metric_descriptor_bad_type(self):
@@ -530,9 +531,13 @@ def test_export_metrics(self):
530531
exporter.export_metrics([mm])
531532

532533
self.assertEqual(exporter.client.create_time_series.call_count, 1)
533-
sd_args = exporter.client.create_time_series.call_args[0][1]
534+
sd_args = exporter.client.create_time_series.call_args.kwargs[
535+
'time_series'
536+
]
534537
self.assertEqual(len(sd_args), 1)
535-
[sd_arg] = exporter.client.create_time_series.call_args[0][1]
538+
[sd_arg] = exporter.client.create_time_series.call_args.kwargs[
539+
'time_series'
540+
]
536541
self.assertEqual(sd_arg.points[0].value.int64_value, 123)
537542

538543

@@ -654,21 +659,25 @@ def test_export_single_metric(self, mock_stats, mock_client):
654659
exporter.client.create_metric_descriptor.call_count,
655660
1)
656661
md_call_arg =\
657-
exporter.client.create_metric_descriptor.call_args[0][1]
662+
exporter.client.create_metric_descriptor.call_args.kwargs[
663+
'metric_descriptor'
664+
]
658665
self.assertEqual(
659666
md_call_arg.metric_kind,
660-
monitoring_v3.enums.MetricDescriptor.MetricKind.GAUGE
667+
metric_pb2.MetricDescriptor.MetricKind.GAUGE
661668
)
662669
self.assertEqual(
663670
md_call_arg.value_type,
664-
monitoring_v3.enums.MetricDescriptor.ValueType.INT64
671+
metric_pb2.MetricDescriptor.ValueType.INT64
665672
)
666673

667674
exporter.client.create_time_series.assert_called()
668675
self.assertEqual(
669676
exporter.client.create_time_series.call_count,
670677
1)
671-
ts_call_arg = exporter.client.create_time_series.call_args[0][1]
678+
ts_call_arg = exporter.client.create_time_series.call_args.kwargs[
679+
'time_series'
680+
]
672681
self.assertEqual(len(ts_call_arg), 1)
673682
self.assertEqual(len(ts_call_arg[0].points), 1)
674683
self.assertEqual(ts_call_arg[0].points[0].value.int64_value, 123)
@@ -812,6 +821,9 @@ def test_create_timeseries(self, monitor_resource_mock):
812821
v_data = measure_map.measure_to_view_map.get_view(
813822
VIDEO_SIZE_VIEW_NAME, None)
814823

824+
v_data._start_time = (
825+
TEST_TIME - timedelta(minutes=1)
826+
).strftime(stackdriver.EPOCH_PATTERN)
815827
v_data = metric_utils.view_data_to_metric(v_data, TEST_TIME)
816828

817829
time_series_list = exporter.create_time_series_list(v_data)
@@ -840,6 +852,15 @@ def test_create_timeseries(self, monitor_resource_mock):
840852
)
841853
self.assertEqual(value.distribution_value, expected_distb)
842854

855+
start_time_pb = (
856+
time_series.points[0].interval.start_time.timestamp_pb()
857+
)
858+
end_time_pb = time_series.points[0].interval.end_time.timestamp_pb()
859+
self.assertEqual(start_time_pb.seconds, 1545699663)
860+
self.assertEqual(start_time_pb.nanos, 4053)
861+
self.assertEqual(end_time_pb.seconds, 1545699723)
862+
self.assertEqual(end_time_pb.nanos, 4053)
863+
843864
@mock.patch('opencensus.ext.stackdriver.stats_exporter.'
844865
'monitored_resource.get_instance')
845866
def test_create_timeseries_with_resource(self, monitor_resource_mock):
@@ -1024,7 +1045,7 @@ def test_create_timeseries_str_tagvalue(self, monitor_resource_mock):
10241045
self.assertIsNotNone(time_series.resource)
10251046

10261047
self.assertEqual(len(time_series.points), 1)
1027-
expected_value = monitoring_v3.types.TypedValue()
1048+
expected_value = monitoring_v3.TypedValue()
10281049
# TODO: #565
10291050
expected_value.double_value = 25.0 * MiB
10301051
self.assertEqual(time_series.points[0].value, expected_value)
@@ -1066,7 +1087,7 @@ def test_create_timeseries_str_tagvalue_count_aggregtation(
10661087
self.assertIsNotNone(time_series.resource)
10671088

10681089
self.assertEqual(len(time_series.points), 1)
1069-
expected_value = monitoring_v3.types.TypedValue()
1090+
expected_value = monitoring_v3.TypedValue()
10701091
expected_value.int64_value = 3
10711092
self.assertEqual(time_series.points[0].value, expected_value)
10721093

@@ -1107,7 +1128,7 @@ def test_create_timeseries_last_value_float_tagvalue(
11071128
self.assertIsNotNone(time_series.resource)
11081129

11091130
self.assertEqual(len(time_series.points), 1)
1110-
expected_value = monitoring_v3.types.TypedValue()
1131+
expected_value = monitoring_v3.TypedValue()
11111132
expected_value.double_value = 25.7 * MiB
11121133
self.assertEqual(time_series.points[0].value, expected_value)
11131134

@@ -1163,7 +1184,7 @@ def test_create_timeseries_float_tagvalue(self, monitor_resource_mock):
11631184
self.assertIsNotNone(time_series.resource)
11641185

11651186
self.assertEqual(len(time_series.points), 1)
1166-
expected_value = monitoring_v3.types.TypedValue()
1187+
expected_value = monitoring_v3.TypedValue()
11671188
expected_value.double_value = 2.2 + 25 * MiB
11681189
self.assertEqual(time_series.points[0].value, expected_value)
11691190

@@ -1290,7 +1311,7 @@ def test_create_timeseries_disjoint_tags(self, monitoring_resoure_mock):
12901311
self.assertIsNotNone(time_series.resource)
12911312

12921313
self.assertEqual(len(time_series.points), 1)
1293-
expected_value = monitoring_v3.types.TypedValue()
1314+
expected_value = monitoring_v3.TypedValue()
12941315
# TODO: #565
12951316
expected_value.double_value = 25.0 * MiB
12961317
self.assertEqual(time_series.points[0].value, expected_value)

tests/system/stats/stackdriver/stackdriver_stats_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class TestBasicStats(unittest.TestCase):
4646

4747
def check_sd_md(self, exporter, view_description):
4848
"""Check that the metric descriptor was written to stackdriver."""
49-
name = exporter.client.project_path(PROJECT)
49+
name = exporter.client.common_project_path(PROJECT)
5050
list_metrics_descriptors = exporter.client.list_metric_descriptors(
5151
name)
5252

0 commit comments

Comments
 (0)