From 48d1c4e60677f8f1ef390598bb6bd67d154e0876 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Tue, 7 Nov 2023 16:16:44 -0800 Subject: [PATCH 1/4] support passing in explicit resource types --- .../resourcedetector/gcp_resource_detector/_constants.py | 2 ++ .../resourcedetector/gcp_resource_detector/_mapping.py | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_constants.py b/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_constants.py index 27f74707..e7850d07 100644 --- a/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_constants.py +++ b/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_constants.py @@ -32,6 +32,8 @@ class ResourceAttributes: K8S_NAMESPACE_NAME = "k8s.namespace.name" K8S_NODE_NAME = "k8s.node.name" K8S_POD_NAME = "k8s.pod.name" + MONITORED_RESOURCE_TYPE = "monitored_resource.type" + MONITORED_RESOURCE_LABEL_PREFIX = "monitored_resource.labels." SERVICE_INSTANCE_ID = "service.instance.id" SERVICE_NAME = "service.name" SERVICE_NAMESPACE = "service.namespace" diff --git a/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_mapping.py b/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_mapping.py index 1e054b92..effd8335 100644 --- a/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_mapping.py +++ b/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_mapping.py @@ -156,6 +156,14 @@ def get_monitored_resource( attrs = resource.attributes + # check for explicit resource type + resource_type = attrs.get(ResourceAttributes.MONITORED_RESOURCE_TYPE) + if resource_type is not None: + prefix = ResourceAttributes.MONITORED_RESOURCE_LABEL_PREFIX + # filter out only monitored resource attributes + resource_labels = {k[len(prefix):]:v for k,v in attrs.items() if k.startswith(prefix)} + return MonitoredResourceData(type=resource_type, labels=resource_labels) + platform = attrs.get(ResourceAttributes.CLOUD_PLATFORM_KEY) if platform == ResourceAttributes.GCP_COMPUTE_ENGINE: mr = _create_monitored_resource(_constants.GCE_INSTANCE, attrs) From bab26c508343ccbb8b72baf4ad6b1efda45e722e Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Tue, 7 Nov 2023 16:21:57 -0800 Subject: [PATCH 2/4] pass in monitored resource at init --- .../exporter/cloud_monitoring/__init__.py | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/opentelemetry-exporter-gcp-monitoring/src/opentelemetry/exporter/cloud_monitoring/__init__.py b/opentelemetry-exporter-gcp-monitoring/src/opentelemetry/exporter/cloud_monitoring/__init__.py index 1ecc65df..e1e17016 100644 --- a/opentelemetry-exporter-gcp-monitoring/src/opentelemetry/exporter/cloud_monitoring/__init__.py +++ b/opentelemetry-exporter-gcp-monitoring/src/opentelemetry/exporter/cloud_monitoring/__init__.py @@ -95,6 +95,9 @@ class CloudMonitoringMetricsExporter(MetricExporter): each other. prefix: the prefix of the metric. It is "workload.googleapis.com" by default if not specified. + monitored_resource: the GCP monitored resource to use for all metrics. + If not specified, the exporter will attempt to detect the + monitored_resource automatically from the OpenTelemetry resource. """ def __init__( @@ -103,6 +106,7 @@ def __init__( client: Optional[MetricServiceClient] = None, add_unique_identifier: bool = False, prefix: Optional[str] = "workload.googleapis.com", + monitored_resource: Optional[MonitoredResource] = None, ): # Default preferred_temporality is all CUMULATIVE so need to customize super().__init__() @@ -133,6 +137,7 @@ def __init__( self._exporter_start_time_nanos, ) = divmod(time_ns(), NANOS_PER_SECOND) self._prefix = prefix + self.monitored_resource = monitored_resource def _batch_write(self, series: List[TimeSeries]) -> None: """Cloud Monitoring allows writing up to 200 time series at once @@ -301,18 +306,20 @@ def export( all_series = [] for resource_metric in metrics_data.resource_metrics: - monitored_resource_data = get_monitored_resource( - resource_metric.resource - ) - # convert it to proto - monitored_resource = ( - MonitoredResource( - type=monitored_resource_data.type, - labels=monitored_resource_data.labels, + if self.monitored_resource is None: + # auto-detect the monitored resource + monitored_resource_data = get_monitored_resource( + resource_metric.resource + ) + # convert it to proto + monitored_resource = ( + MonitoredResource( + type=monitored_resource_data.type, + labels=monitored_resource_data.labels, + ) + if monitored_resource_data + else None ) - if monitored_resource_data - else None - ) for scope_metric in resource_metric.scope_metrics: for metric in scope_metric.metrics: From 46e27d98f900755d798bb636ec06beb6cfc26b12 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Tue, 7 Nov 2023 16:44:22 -0800 Subject: [PATCH 3/4] removed changes to Otel resource parsing --- .../resourcedetector/gcp_resource_detector/_constants.py | 2 -- .../resourcedetector/gcp_resource_detector/_mapping.py | 8 -------- 2 files changed, 10 deletions(-) diff --git a/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_constants.py b/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_constants.py index e7850d07..27f74707 100644 --- a/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_constants.py +++ b/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_constants.py @@ -32,8 +32,6 @@ class ResourceAttributes: K8S_NAMESPACE_NAME = "k8s.namespace.name" K8S_NODE_NAME = "k8s.node.name" K8S_POD_NAME = "k8s.pod.name" - MONITORED_RESOURCE_TYPE = "monitored_resource.type" - MONITORED_RESOURCE_LABEL_PREFIX = "monitored_resource.labels." SERVICE_INSTANCE_ID = "service.instance.id" SERVICE_NAME = "service.name" SERVICE_NAMESPACE = "service.namespace" diff --git a/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_mapping.py b/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_mapping.py index effd8335..1e054b92 100644 --- a/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_mapping.py +++ b/opentelemetry-resourcedetector-gcp/src/opentelemetry/resourcedetector/gcp_resource_detector/_mapping.py @@ -156,14 +156,6 @@ def get_monitored_resource( attrs = resource.attributes - # check for explicit resource type - resource_type = attrs.get(ResourceAttributes.MONITORED_RESOURCE_TYPE) - if resource_type is not None: - prefix = ResourceAttributes.MONITORED_RESOURCE_LABEL_PREFIX - # filter out only monitored resource attributes - resource_labels = {k[len(prefix):]:v for k,v in attrs.items() if k.startswith(prefix)} - return MonitoredResourceData(type=resource_type, labels=resource_labels) - platform = attrs.get(ResourceAttributes.CLOUD_PLATFORM_KEY) if platform == ResourceAttributes.GCP_COMPUTE_ENGINE: mr = _create_monitored_resource(_constants.GCE_INSTANCE, attrs) From 4770f3b1f4aa5ffa3f313536278170a7032af992 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Tue, 7 Nov 2023 16:52:08 -0800 Subject: [PATCH 4/4] set monitored_resource to instance property on each loop --- .../src/opentelemetry/exporter/cloud_monitoring/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opentelemetry-exporter-gcp-monitoring/src/opentelemetry/exporter/cloud_monitoring/__init__.py b/opentelemetry-exporter-gcp-monitoring/src/opentelemetry/exporter/cloud_monitoring/__init__.py index e1e17016..d74744d8 100644 --- a/opentelemetry-exporter-gcp-monitoring/src/opentelemetry/exporter/cloud_monitoring/__init__.py +++ b/opentelemetry-exporter-gcp-monitoring/src/opentelemetry/exporter/cloud_monitoring/__init__.py @@ -306,7 +306,8 @@ def export( all_series = [] for resource_metric in metrics_data.resource_metrics: - if self.monitored_resource is None: + monitored_resource = self.monitored_resource + if monitored_resource is None: # auto-detect the monitored resource monitored_resource_data = get_monitored_resource( resource_metric.resource