Skip to content

Commit f91df37

Browse files
committed
cleaned up attribute parsing
1 parent 92156ac commit f91df37

2 files changed

Lines changed: 58 additions & 22 deletions

File tree

packages/google-cloud-bigtable/google/cloud/bigtable/data/_metrics/handlers/gcp_exporter.py

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from collections import defaultdict
1818
import logging
1919
import time
20+
from typing import Any, Mapping
2021

2122
from google.api.distribution_pb2 import Distribution
2223
from google.api.metric_pb2 import Metric as GMetric
@@ -42,6 +43,7 @@
4243
NumberDataPoint,
4344
PeriodicExportingMetricReader,
4445
)
46+
from opentelemetry.util.types import Attributes
4547

4648
from google.cloud.bigtable.data._metrics.handlers.opentelemetry import (
4749
OpenTelemetryMetricsHandler,
@@ -89,6 +91,29 @@
8991
for n in INSTRUMENT_NAMES
9092
]
9193

94+
# Maps OpenTelemetry data point resource attribute names to Cloud Monitoring MonitoredResource label names
95+
_RESOURCE_KEY_MAP = {
96+
"resource_project": "project_id",
97+
"resource_instance": "instance",
98+
"resource_cluster": "cluster",
99+
"resource_table": "table",
100+
"resource_zone": "zone",
101+
}
102+
103+
104+
def _partition_attributes(
105+
attributes: Attributes
106+
) -> tuple[dict[str, str], dict[str, str]]:
107+
"""Split data point attributes into monitored resource labels and metric labels."""
108+
resource_labels = {label_name: "" for label_name in _RESOURCE_KEY_MAP.values()}
109+
metric_labels = {}
110+
for attr_key, attr_value in attributes.items():
111+
if attr_key in _RESOURCE_KEY_MAP:
112+
resource_labels[_RESOURCE_KEY_MAP[attr_key]] = str(attr_value)
113+
elif not attr_key.startswith("resource_"):
114+
metric_labels[attr_key] = str(attr_value)
115+
return resource_labels, metric_labels
116+
92117

93118
class GoogleCloudMetricsHandler(OpenTelemetryMetricsHandler):
94119
"""
@@ -161,9 +186,10 @@ def export(
161186
for metric in scope_metric.metrics:
162187
for data_point in metric.data.data_points:
163188
if data_point.attributes:
164-
project_id = data_point.attributes.get(
165-
"resource_project", ""
189+
resource_labels, metric_labels = _partition_attributes(
190+
data_point.attributes
166191
)
192+
project_id = resource_labels.get("project_id", "")
167193
if not project_id:
168194
_LOGGER.warning(
169195
"Missing resource_project attribute for metric %s",
@@ -172,21 +198,7 @@ def export(
172198
continue
173199
monitored_resource = MonitoredResource(
174200
type="bigtable_client_raw",
175-
labels={
176-
"project_id": project_id,
177-
"instance": data_point.attributes.get(
178-
"resource_instance", ""
179-
),
180-
"cluster": data_point.attributes.get(
181-
"resource_cluster", ""
182-
),
183-
"table": data_point.attributes.get(
184-
"resource_table", ""
185-
),
186-
"zone": data_point.attributes.get(
187-
"resource_zone", ""
188-
),
189-
},
201+
labels=resource_labels,
190202
)
191203
try:
192204
point = self._to_point(data_point)
@@ -204,11 +216,7 @@ def export(
204216
points=[point],
205217
metric=GMetric(
206218
type=f"{self.prefix}/{metric.name}",
207-
labels={
208-
k: str(v)
209-
for k, v in data_point.attributes.items()
210-
if not k.startswith("resource_")
211-
},
219+
labels=metric_labels,
212220
),
213221
unit=metric.unit,
214222
)

packages/google-cloud-bigtable/tests/unit/data/_metrics/test_gcp_exporter_handler.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,34 @@ def _make_one(self, *args, **kwargs):
130130
with mock.patch("google.auth.default", return_value=(mock.Mock(), "project")):
131131
return BigtableMetricsExporter(*args, **kwargs)
132132

133+
def test__partition_attributes(self):
134+
from google.cloud.bigtable.data._metrics.handlers.gcp_exporter import (
135+
_partition_attributes,
136+
)
137+
138+
attributes = {
139+
"resource_project": "proj-1",
140+
"resource_instance": "inst-1",
141+
"resource_cluster": "cls-1",
142+
"resource_table": "tbl-1",
143+
"resource_zone": "zone-1",
144+
"method": "ReadRows",
145+
"status_code": "OK",
146+
"resource_custom_unsupported": "should_be_stripped",
147+
}
148+
res_labels, metric_labels = _partition_attributes(attributes)
149+
assert res_labels == {
150+
"project_id": "proj-1",
151+
"instance": "inst-1",
152+
"cluster": "cls-1",
153+
"table": "tbl-1",
154+
"zone": "zone-1",
155+
}
156+
assert metric_labels == {
157+
"method": "ReadRows",
158+
"status_code": "OK",
159+
}
160+
133161
def test_ctor_defaults(self):
134162
from google.cloud.monitoring_v3 import MetricServiceClient
135163

0 commit comments

Comments
 (0)