From f8ac7c74ac9988b313d2a6405449542cfe8e6861 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Thu, 11 Jun 2020 11:33:23 -0600 Subject: [PATCH 01/22] Add OTLP metric exporter --- .../exporter/otlp/trace_exporter/__init__.py | 20 +- .../tests/test_otlp_trace_exporter.py | 2 +- .../src/opentelemetry/ext/otlp/exporter.py | 143 +++++++++++++ .../ext/otlp/metrics_exporter/__init__.py | 195 ++++++++++++++++++ .../tests/test_otlp_metric_exporter.py | 112 ++++++++++ 5 files changed, 459 insertions(+), 13 deletions(-) create mode 100644 ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py create mode 100644 ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/metrics_exporter/__init__.py create mode 100644 ext/opentelemetry-ext-otlp/tests/test_otlp_metric_exporter.py diff --git a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py index be1419fa39c..0332b5e0f9e 100644 --- a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py @@ -1,5 +1,4 @@ # Copyright The OpenTelemetry Authors -# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -19,16 +18,10 @@ from time import sleep from typing import Sequence as TypingSequence -from backoff import expo -from google.rpc.error_details_pb2 import RetryInfo -from grpc import ( - ChannelCredentials, - RpcError, - StatusCode, - insecure_channel, - secure_channel, +from opentelemetry.ext.otlp.exporter import ( + OTLPExporterMixin, + translate_key_values, ) - from opentelemetry.proto.collector.trace.v1.trace_service_pb2 import ( ExportTraceServiceRequest, ) @@ -78,7 +71,7 @@ def _translate_key_values(key, value): # pylint: disable=no-member -class OTLPSpanExporter(SpanExporter): +class OTLPSpanExporter(SpanExporter, OTLPExporterMixin): """OTLP span exporter Args: @@ -87,6 +80,9 @@ class OTLPSpanExporter(SpanExporter): metadata: Metadata to send when exporting """ + _result = SpanExportResult + _stub = TraceServiceStub + def __init__( self, endpoint="localhost:55680", @@ -218,7 +214,7 @@ def _translate_spans( sdk_resource_instrumentation_library_spans = {} - for sdk_span in sdk_spans: + for sdk_span in data: if sdk_span.resource not in ( sdk_resource_instrumentation_library_spans.keys() diff --git a/exporter/opentelemetry-exporter-otlp/tests/test_otlp_trace_exporter.py b/exporter/opentelemetry-exporter-otlp/tests/test_otlp_trace_exporter.py index 9058937f876..c73fd40898a 100644 --- a/exporter/opentelemetry-exporter-otlp/tests/test_otlp_trace_exporter.py +++ b/exporter/opentelemetry-exporter-otlp/tests/test_otlp_trace_exporter.py @@ -274,4 +274,4 @@ def test_translate_spans(self): ) # pylint: disable=protected-access - self.assertEqual(expected, self.exporter._translate_spans([self.span])) + self.assertEqual(expected, self.exporter._translate_data([self.span])) diff --git a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py new file mode 100644 index 00000000000..8eba4101a1b --- /dev/null +++ b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py @@ -0,0 +1,143 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""OTLP Span Exporter""" + +import logging +from abc import ABC, abstractmethod +from time import sleep + +from backoff import expo +from google.rpc.error_details_pb2 import RetryInfo +from grpc import ( + ChannelCredentials, + RpcError, + StatusCode, + insecure_channel, + secure_channel, +) + +logger = logging.getLogger(__name__) + + +def translate_key_values(key, value): + key_value = {"key": key} + + if isinstance(value, bool): + key_value["bool_value"] = value + + elif isinstance(value, str): + key_value["string_value"] = value + + elif isinstance(value, int): + key_value["int_value"] = value + + elif isinstance(value, float): + key_value["double_value"] = value + + else: + raise Exception( + "Invalid type {} of value {}".format(type(value), value) + ) + + return key_value + + +# pylint: disable=no-member +class OTLPExporterMixin(ABC): + """OTLP span exporter + + Args: + endpoint: OpenTelemetry Collector receiver endpoint + credentials: Credentials object for server authentication + metadata: Metadata to send when exporting + """ + + def __init__( + self, + endpoint="localhost:55678", + credentials: ChannelCredentials = None, + metadata=None, + ): + super().__init__() + + self._metadata = metadata + self._collector_span_kwargs = None + + if credentials is None: + self._client = self._stub(insecure_channel(endpoint)) + else: + self._client = self._stub(secure_channel(endpoint, credentials)) + + @abstractmethod + def _translate_data(self, data): + pass + + def _export(self, data): + # expo returns a generator that yields delay values which grow + # exponentially. Once delay is greater than max_value, the yielded + # value will remain constant. + # max_value is set to 900 (900 seconds is 15 minutes) to use the same + # value as used in the Go implementation. + + max_value = 900 + + for delay in expo(max_value=max_value): + + if delay == max_value: + return self._result.FAILURE + + try: + self._client.Export( + request=self._translate_data(data), + metadata=self._metadata, + ) + + return self._result.SUCCESS + + except RpcError as error: + + if error.code() in [ + StatusCode.CANCELLED, + StatusCode.DEADLINE_EXCEEDED, + StatusCode.PERMISSION_DENIED, + StatusCode.UNAUTHENTICATED, + StatusCode.RESOURCE_EXHAUSTED, + StatusCode.ABORTED, + StatusCode.OUT_OF_RANGE, + StatusCode.UNAVAILABLE, + StatusCode.DATA_LOSS, + ]: + + retry_info_bin = dict(error.trailing_metadata()).get( + "google.rpc.retryinfo-bin" + ) + if retry_info_bin is not None: + retry_info = RetryInfo() + retry_info.ParseFromString(retry_info_bin) + delay = ( + retry_info.retry_delay.seconds + + retry_info.retry_delay.nanos / 1.0e9 + ) + + logger.debug("Waiting %ss before retrying export of span") + sleep(delay) + continue + + if error.code() == StatusCode.OK: + return self._result.SUCCESS + + return self.result.FAILURE + + return self._result.FAILURE diff --git a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/metrics_exporter/__init__.py b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/metrics_exporter/__init__.py new file mode 100644 index 00000000000..f0d779bcf22 --- /dev/null +++ b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/metrics_exporter/__init__.py @@ -0,0 +1,195 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""OTLP Metrics Exporter""" + +import logging + +from opentelemetry.ext.otlp.exporter import ( + OTLPExporterMixin, + translate_key_values, +) +from opentelemetry.proto.collector.metrics.v1.metrics_service_pb2 import ( + ExportMetricsServiceRequest, +) +from opentelemetry.proto.collector.metrics.v1.metrics_service_pb2_grpc import ( + MetricsServiceStub, +) +from opentelemetry.proto.common.v1.common_pb2 import ( + AttributeKeyValue, + StringKeyValue, +) +from opentelemetry.proto.metrics.v1.metrics_pb2 import ( + DoubleDataPoint, + InstrumentationLibraryMetrics, + Int64DataPoint, +) +from opentelemetry.proto.metrics.v1.metrics_pb2 import ( + Metric as CollectorMetric, +) +from opentelemetry.proto.metrics.v1.metrics_pb2 import ( + MetricDescriptor, + ResourceMetrics, +) +from opentelemetry.proto.resource.v1.resource_pb2 import Resource +from opentelemetry.sdk.metrics import ( + Counter, + SumObserver, + UpDownCounter, + UpDownSumObserver, + ValueObserver, + ValueRecorder, +) +from opentelemetry.sdk.metrics.export import ( + MetricsExporter, + MetricsExportResult, +) + +logger = logging.getLogger(__name__) + + +class OTLPMetricsExporter(MetricsExporter, OTLPExporterMixin): + """OTLP metrics exporter + + Args: + endpoint: OpenTelemetry Collector receiver endpoint + credentials: Credentials object for server authentication + metadata: Metadata to send when exporting + """ + + _stub = MetricsServiceStub + _result = MetricsExportResult + + def _translate_data(self, data): + # pylint: disable=too-many-locals,no-member + # pylint: disable=attribute-defined-outside-init + + resource_metrics = [] + + sdk_resource_instrumentation_library_metrics = {} + + for sdk_metric in data: + + if sdk_metric.instrument.meter.resource not in ( + sdk_resource_instrumentation_library_metrics.keys() + ): + sdk_resource_instrumentation_library_metrics[ + sdk_metric.instrument.meter.resource + ] = InstrumentationLibraryMetrics() + + self._metric_descriptor_kwargs = {} + + if isinstance(sdk_metric.instrument, (Counter, UpDownCounter)): + temporality = MetricDescriptor.Temporality.DELTA + elif isinstance( + sdk_metric.instrument, (ValueRecorder, ValueObserver) + ): + temporality = MetricDescriptor.Temporality.INSTANTANEOUS + elif isinstance( + sdk_metric.instrument, (SumObserver, UpDownSumObserver) + ): + temporality = MetricDescriptor.Temporality.CUMULATIVE + + if sdk_metric.instrument.value_type is int: + type_ = MetricDescriptor.Type.INT64 + + elif sdk_metric.instrument.value_type is float: + type_ = MetricDescriptor.Type.DOUBLE + + # FIXME What are the types that correspond with + # MetricDescriptor.Type.HISTOGRAM and + # MetricDescriptor.Type.SUMMARY? + + metric_descriptor = MetricDescriptor( + name=sdk_metric.instrument.name, + description=sdk_metric.instrument.description, + unit=sdk_metric.instrument.unit, + type=type_, + temporality=temporality, + ) + + def get_data_points(sdk_metric, data_point_class): + + data_points = [] + + for ( + label, + bound_counter, + ) in sdk_metric.instrument.bound_instruments.items(): + + string_key_values = [] + + for label_key, label_value in label: + string_key_values.append( + StringKeyValue(key=label_key, value=label_value) + ) + data_points.append( + data_point_class( + labels=string_key_values, + value=bound_counter.aggregator.current, + ) + ) + + return data_points + + if metric_descriptor.type == MetricDescriptor.Type.INT64: + + collector_metric = CollectorMetric( + metric_descriptor=metric_descriptor, + int64_data_points=get_data_points( + sdk_metric, Int64DataPoint + ), + ) + + elif metric_descriptor.type == MetricDescriptor.Type.DOUBLE: + + collector_metric = CollectorMetric( + metric_descriptor=metric_descriptor, + double_data_points=get_data_points( + sdk_metric, DoubleDataPoint + ), + ) + + sdk_resource_instrumentation_library_metrics[ + sdk_metric.instrument.meter.resource + ].metrics.append(collector_metric) + + resource_metrics = [] + + for ( + sdk_resource, + instrumentation_library_metrics, + ) in sdk_resource_instrumentation_library_metrics.items(): + + collector_resource = Resource() + + for key, value in sdk_resource.labels.items(): + + try: + collector_resource.attributes.append( + AttributeKeyValue(**translate_key_values(key, value)) + ) + except Exception as error: # pylint: disable=broad-except + logger.exception(error) + + resource_metrics.append( + ResourceMetrics( + resource=collector_resource, + instrumentation_library_metrics=[ + instrumentation_library_metrics + ], + ) + ) + + return ExportMetricsServiceRequest(resource_metrics=resource_metrics) diff --git a/ext/opentelemetry-ext-otlp/tests/test_otlp_metric_exporter.py b/ext/opentelemetry-ext-otlp/tests/test_otlp_metric_exporter.py new file mode 100644 index 00000000000..3aeddb2a12b --- /dev/null +++ b/ext/opentelemetry-ext-otlp/tests/test_otlp_metric_exporter.py @@ -0,0 +1,112 @@ +# Copyright The OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from unittest import TestCase + +from opentelemetry.ext.otlp.metrics_exporter import OTLPMetricsExporter +from opentelemetry.proto.collector.metrics.v1.metrics_service_pb2 import ( + ExportMetricsServiceRequest, +) +from opentelemetry.proto.common.v1.common_pb2 import ( + AttributeKeyValue, + StringKeyValue, +) +from opentelemetry.proto.metrics.v1.metrics_pb2 import ( + InstrumentationLibraryMetrics, + Int64DataPoint, +) +from opentelemetry.proto.metrics.v1.metrics_pb2 import ( + Metric as CollectorMetric, +) +from opentelemetry.proto.metrics.v1.metrics_pb2 import ( + MetricDescriptor, + ResourceMetrics, +) +from opentelemetry.proto.resource.v1.resource_pb2 import ( + Resource as CollectorResource, +) +from opentelemetry.sdk.metrics import Counter, MeterProvider +from opentelemetry.sdk.metrics.export import MetricRecord +from opentelemetry.sdk.metrics.export.aggregate import CounterAggregator +from opentelemetry.sdk.resources import Resource + + +class TestOTLPMetricExporter(TestCase): + def setUp(self): + self.exporter = OTLPMetricsExporter() + + self.counter_metric_record = MetricRecord( + Counter( + "a", + "b", + "c", + int, + MeterProvider( + resource=Resource({"a": 1, "b": False}) + ).get_meter(__name__), + ("d",), + ), + {"e": "f"}, + CounterAggregator(), + ) + + def test_translate_spans(self): + # pylint: disable=no-member,protected-access + + self.counter_metric_record.instrument.add(1, {"a": "b"}) + + expected = ExportMetricsServiceRequest( + resource_metrics=[ + ResourceMetrics( + resource=CollectorResource( + attributes=[ + AttributeKeyValue(key="a", int_value=1), + AttributeKeyValue(key="b", bool_value=False), + ] + ), + instrumentation_library_metrics=[ + InstrumentationLibraryMetrics( + metrics=[ + CollectorMetric( + metric_descriptor=MetricDescriptor( + name="a", + description="b", + unit="c", + type=MetricDescriptor.Type.INT64, + temporality=( + MetricDescriptor.Temporality.DELTA + ), + ), + int64_data_points=[ + Int64DataPoint( + labels=[ + StringKeyValue( + key="a", value="b" + ) + ], + value=1, + ) + ], + ) + ] + ) + ], + ) + ] + ) + + actual = self.exporter._translate_data([self.counter_metric_record]) + + # pylint: disable=protected-access + self.assertEqual(expected, actual) From 7ea96a8548346b8a5b992385f88bb069bd5ed843 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 17 Jun 2020 15:28:31 -0600 Subject: [PATCH 02/22] Break in smaller methods --- .../ext/otlp/metrics_exporter/__init__.py | 125 ++++++++++-------- 1 file changed, 71 insertions(+), 54 deletions(-) diff --git a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/metrics_exporter/__init__.py b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/metrics_exporter/__init__.py index f0d779bcf22..aef13631096 100644 --- a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/metrics_exporter/__init__.py +++ b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/metrics_exporter/__init__.py @@ -34,13 +34,9 @@ DoubleDataPoint, InstrumentationLibraryMetrics, Int64DataPoint, -) -from opentelemetry.proto.metrics.v1.metrics_pb2 import ( - Metric as CollectorMetric, -) -from opentelemetry.proto.metrics.v1.metrics_pb2 import ( MetricDescriptor, ResourceMetrics, + Metric as CollectorMetric, ) from opentelemetry.proto.resource.v1.resource_pb2 import Resource from opentelemetry.sdk.metrics import ( @@ -59,6 +55,72 @@ logger = logging.getLogger(__name__) +def _get_data_points(sdk_metric, data_point_class): + + data_points = [] + + for ( + label, + bound_counter, + ) in sdk_metric.instrument.bound_instruments.items(): + + string_key_values = [] + + for label_key, label_value in label: + string_key_values.append( + StringKeyValue(key=label_key, value=label_value) + ) + data_points.append( + data_point_class( + labels=string_key_values, + value=bound_counter.aggregator.current, + ) + ) + + return data_points + + +def _get_temporality(instrument): + if isinstance(instrument, (Counter, UpDownCounter)): + temporality = MetricDescriptor.Temporality.DELTA + elif isinstance( + instrument, (ValueRecorder, ValueObserver) + ): + temporality = MetricDescriptor.Temporality.INSTANTANEOUS + elif isinstance( + instrument, (SumObserver, UpDownSumObserver) + ): + temporality = MetricDescriptor.Temporality.CUMULATIVE + else: + raise Exception( + "No temporality defined for instrument type {}".format( + type(instrument) + ) + ) + + return temporality + + +def _get_type(value_type): + if value_type is int: + type_ = MetricDescriptor.Type.INT64 + + elif value_type is float: + type_ = MetricDescriptor.Type.DOUBLE + + # FIXME What are the types that correspond with + # MetricDescriptor.Type.HISTOGRAM and + # MetricDescriptor.Type.SUMMARY? + else: + raise Exception( + "No type defined for valie type {}".format( + type(value_type) + ) + ) + + return type_ + + class OTLPMetricsExporter(MetricsExporter, OTLPExporterMixin): """OTLP metrics exporter @@ -90,64 +152,19 @@ def _translate_data(self, data): self._metric_descriptor_kwargs = {} - if isinstance(sdk_metric.instrument, (Counter, UpDownCounter)): - temporality = MetricDescriptor.Temporality.DELTA - elif isinstance( - sdk_metric.instrument, (ValueRecorder, ValueObserver) - ): - temporality = MetricDescriptor.Temporality.INSTANTANEOUS - elif isinstance( - sdk_metric.instrument, (SumObserver, UpDownSumObserver) - ): - temporality = MetricDescriptor.Temporality.CUMULATIVE - - if sdk_metric.instrument.value_type is int: - type_ = MetricDescriptor.Type.INT64 - - elif sdk_metric.instrument.value_type is float: - type_ = MetricDescriptor.Type.DOUBLE - - # FIXME What are the types that correspond with - # MetricDescriptor.Type.HISTOGRAM and - # MetricDescriptor.Type.SUMMARY? - metric_descriptor = MetricDescriptor( name=sdk_metric.instrument.name, description=sdk_metric.instrument.description, unit=sdk_metric.instrument.unit, - type=type_, - temporality=temporality, + type=_get_type(sdk_metric.instrument.value_type), + temporality=_get_temporality(sdk_metric.instrument), ) - def get_data_points(sdk_metric, data_point_class): - - data_points = [] - - for ( - label, - bound_counter, - ) in sdk_metric.instrument.bound_instruments.items(): - - string_key_values = [] - - for label_key, label_value in label: - string_key_values.append( - StringKeyValue(key=label_key, value=label_value) - ) - data_points.append( - data_point_class( - labels=string_key_values, - value=bound_counter.aggregator.current, - ) - ) - - return data_points - if metric_descriptor.type == MetricDescriptor.Type.INT64: collector_metric = CollectorMetric( metric_descriptor=metric_descriptor, - int64_data_points=get_data_points( + int64_data_points=_get_data_points( sdk_metric, Int64DataPoint ), ) @@ -156,7 +173,7 @@ def get_data_points(sdk_metric, data_point_class): collector_metric = CollectorMetric( metric_descriptor=metric_descriptor, - double_data_points=get_data_points( + double_data_points=_get_data_points( sdk_metric, DoubleDataPoint ), ) From 99288be4cbe4c3707ad38ea28324183b2892f2a8 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 17 Jun 2020 15:33:17 -0600 Subject: [PATCH 03/22] Updating --- .../src/opentelemetry/ext/otlp/exporter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py index 8eba4101a1b..c17c6ad335e 100644 --- a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py +++ b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py @@ -66,9 +66,9 @@ class OTLPExporterMixin(ABC): def __init__( self, - endpoint="localhost:55678", + endpoint: str = "localhost:55678", credentials: ChannelCredentials = None, - metadata=None, + metadata: tuple = None, ): super().__init__() From 2251818cb27c4f2827a2c8b3a68a084722ebcc9d Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 17 Jun 2020 15:35:26 -0600 Subject: [PATCH 04/22] More updatin --- .../src/opentelemetry/ext/otlp/exporter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py index c17c6ad335e..60747f1a6a1 100644 --- a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py +++ b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py @@ -56,11 +56,11 @@ def translate_key_values(key, value): # pylint: disable=no-member class OTLPExporterMixin(ABC): - """OTLP span exporter + """OTLP span/metric exporter Args: endpoint: OpenTelemetry Collector receiver endpoint - credentials: Credentials object for server authentication + credentials: ChannelCredentials object for server authentication metadata: Metadata to send when exporting """ From 641f2532c06696ec8b863dd94e99f8b8db13bec1 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 17 Jun 2020 15:52:06 -0600 Subject: [PATCH 05/22] Fix lint --- .../ext/otlp/metrics_exporter/__init__.py | 18 ++++++++---------- .../tests/test_otlp_metric_exporter.py | 1 - 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/metrics_exporter/__init__.py b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/metrics_exporter/__init__.py index aef13631096..f2e16404e56 100644 --- a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/metrics_exporter/__init__.py +++ b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/metrics_exporter/__init__.py @@ -34,9 +34,13 @@ DoubleDataPoint, InstrumentationLibraryMetrics, Int64DataPoint, +) +from opentelemetry.proto.metrics.v1.metrics_pb2 import ( + Metric as CollectorMetric, +) +from opentelemetry.proto.metrics.v1.metrics_pb2 import ( MetricDescriptor, ResourceMetrics, - Metric as CollectorMetric, ) from opentelemetry.proto.resource.v1.resource_pb2 import Resource from opentelemetry.sdk.metrics import ( @@ -83,13 +87,9 @@ def _get_data_points(sdk_metric, data_point_class): def _get_temporality(instrument): if isinstance(instrument, (Counter, UpDownCounter)): temporality = MetricDescriptor.Temporality.DELTA - elif isinstance( - instrument, (ValueRecorder, ValueObserver) - ): + elif isinstance(instrument, (ValueRecorder, ValueObserver)): temporality = MetricDescriptor.Temporality.INSTANTANEOUS - elif isinstance( - instrument, (SumObserver, UpDownSumObserver) - ): + elif isinstance(instrument, (SumObserver, UpDownSumObserver)): temporality = MetricDescriptor.Temporality.CUMULATIVE else: raise Exception( @@ -113,9 +113,7 @@ def _get_type(value_type): # MetricDescriptor.Type.SUMMARY? else: raise Exception( - "No type defined for valie type {}".format( - type(value_type) - ) + "No type defined for valie type {}".format(type(value_type)) ) return type_ diff --git a/ext/opentelemetry-ext-otlp/tests/test_otlp_metric_exporter.py b/ext/opentelemetry-ext-otlp/tests/test_otlp_metric_exporter.py index 3aeddb2a12b..62184cf9329 100644 --- a/ext/opentelemetry-ext-otlp/tests/test_otlp_metric_exporter.py +++ b/ext/opentelemetry-ext-otlp/tests/test_otlp_metric_exporter.py @@ -108,5 +108,4 @@ def test_translate_spans(self): actual = self.exporter._translate_data([self.counter_metric_record]) - # pylint: disable=protected-access self.assertEqual(expected, actual) From 38030b3b1d0e4a8ab6c7646eaed3c05ea4912e50 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 17 Jun 2020 16:37:32 -0600 Subject: [PATCH 06/22] Fix lint --- .../exporter/otlp/trace_exporter/__init__.py | 6 +-- .../src/opentelemetry/ext/otlp/exporter.py | 41 ++++++++++++++++- .../ext/otlp/metrics_exporter/__init__.py | 45 +++++-------------- .../tests/test_otlp_metric_exporter.py | 7 +-- 4 files changed, 57 insertions(+), 42 deletions(-) diff --git a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py index 0332b5e0f9e..3a067a95445 100644 --- a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py @@ -20,7 +20,8 @@ from opentelemetry.ext.otlp.exporter import ( OTLPExporterMixin, - translate_key_values, + _get_resource_data, + _translate_key_values, ) from opentelemetry.proto.collector.trace.v1.trace_service_pb2 import ( ExportTraceServiceRequest, @@ -271,8 +272,7 @@ def _translate_spans( ], ) ) - - return ExportTraceServiceRequest(resource_spans=resource_spans) + ) def export(self, spans: TypingSequence[SDKSpan]) -> SpanExportResult: # expo returns a generator that yields delay values which grow diff --git a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py index 60747f1a6a1..6ad7a890269 100644 --- a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py +++ b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py @@ -28,10 +28,13 @@ secure_channel, ) +from opentelemetry.proto.common.v1.common_pb2 import AttributeKeyValue +from opentelemetry.proto.resource.v1.resource_pb2 import Resource + logger = logging.getLogger(__name__) -def translate_key_values(key, value): +def _translate_key_values(key, value): key_value = {"key": key} if isinstance(value, bool): @@ -54,6 +57,42 @@ def translate_key_values(key, value): return key_value +def _get_resource_data( + sdk_resource_instrumentation_library_data, resource_class, name +): + + resource_data = [] + + for ( + sdk_resource, + instrumentation_library_data, + ) in sdk_resource_instrumentation_library_data.items(): + + collector_resource = Resource() + + for key, value in sdk_resource.labels.items(): + + try: + collector_resource.attributes.append( + AttributeKeyValue(**_translate_key_values(key, value)) + ) + except Exception as error: # pylint: disable=broad-except + logger.exception(error) + + resource_data.append( + resource_class( + **{ + "resource": collector_resource, + "instrumentation_library_{}".format(name): [ + instrumentation_library_data + ], + } + ) + ) + + return resource_data + + # pylint: disable=no-member class OTLPExporterMixin(ABC): """OTLP span/metric exporter diff --git a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/metrics_exporter/__init__.py b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/metrics_exporter/__init__.py index f2e16404e56..ccdbc306b25 100644 --- a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/metrics_exporter/__init__.py +++ b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/metrics_exporter/__init__.py @@ -18,7 +18,7 @@ from opentelemetry.ext.otlp.exporter import ( OTLPExporterMixin, - translate_key_values, + _get_resource_data, ) from opentelemetry.proto.collector.metrics.v1.metrics_service_pb2 import ( ExportMetricsServiceRequest, @@ -26,10 +26,7 @@ from opentelemetry.proto.collector.metrics.v1.metrics_service_pb2_grpc import ( MetricsServiceStub, ) -from opentelemetry.proto.common.v1.common_pb2 import ( - AttributeKeyValue, - StringKeyValue, -) +from opentelemetry.proto.common.v1.common_pb2 import StringKeyValue from opentelemetry.proto.metrics.v1.metrics_pb2 import ( DoubleDataPoint, InstrumentationLibraryMetrics, @@ -42,7 +39,6 @@ MetricDescriptor, ResourceMetrics, ) -from opentelemetry.proto.resource.v1.resource_pb2 import Resource from opentelemetry.sdk.metrics import ( Counter, SumObserver, @@ -85,6 +81,7 @@ def _get_data_points(sdk_metric, data_point_class): def _get_temporality(instrument): + # pylint: disable=no-member if isinstance(instrument, (Counter, UpDownCounter)): temporality = MetricDescriptor.Temporality.DELTA elif isinstance(instrument, (ValueRecorder, ValueObserver)): @@ -102,6 +99,7 @@ def _get_temporality(instrument): def _get_type(value_type): + # pylint: disable=no-member if value_type is int: type_ = MetricDescriptor.Type.INT64 @@ -135,8 +133,6 @@ def _translate_data(self, data): # pylint: disable=too-many-locals,no-member # pylint: disable=attribute-defined-outside-init - resource_metrics = [] - sdk_resource_instrumentation_library_metrics = {} for sdk_metric in data: @@ -180,31 +176,10 @@ def _translate_data(self, data): sdk_metric.instrument.meter.resource ].metrics.append(collector_metric) - resource_metrics = [] - - for ( - sdk_resource, - instrumentation_library_metrics, - ) in sdk_resource_instrumentation_library_metrics.items(): - - collector_resource = Resource() - - for key, value in sdk_resource.labels.items(): - - try: - collector_resource.attributes.append( - AttributeKeyValue(**translate_key_values(key, value)) - ) - except Exception as error: # pylint: disable=broad-except - logger.exception(error) - - resource_metrics.append( - ResourceMetrics( - resource=collector_resource, - instrumentation_library_metrics=[ - instrumentation_library_metrics - ], - ) + return ExportMetricsServiceRequest( + resource_metrics=_get_resource_data( + sdk_resource_instrumentation_library_metrics, + ResourceMetrics, + "metrics", ) - - return ExportMetricsServiceRequest(resource_metrics=resource_metrics) + ) diff --git a/ext/opentelemetry-ext-otlp/tests/test_otlp_metric_exporter.py b/ext/opentelemetry-ext-otlp/tests/test_otlp_metric_exporter.py index 62184cf9329..a940944f7e8 100644 --- a/ext/opentelemetry-ext-otlp/tests/test_otlp_metric_exporter.py +++ b/ext/opentelemetry-ext-otlp/tests/test_otlp_metric_exporter.py @@ -38,7 +38,7 @@ ) from opentelemetry.sdk.metrics import Counter, MeterProvider from opentelemetry.sdk.metrics.export import MetricRecord -from opentelemetry.sdk.metrics.export.aggregate import CounterAggregator +from opentelemetry.sdk.metrics.export.aggregate import SumAggregator from opentelemetry.sdk.resources import Resource @@ -58,11 +58,11 @@ def setUp(self): ("d",), ), {"e": "f"}, - CounterAggregator(), + SumAggregator(), ) def test_translate_spans(self): - # pylint: disable=no-member,protected-access + # pylint: disable=no-member self.counter_metric_record.instrument.add(1, {"a": "b"}) @@ -106,6 +106,7 @@ def test_translate_spans(self): ] ) + # pylint: disable=protected-access actual = self.exporter._translate_data([self.counter_metric_record]) self.assertEqual(expected, actual) From c8c62ac6a7181d10aa904c1105759f2427b1e5f4 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 17 Jun 2020 16:43:26 -0600 Subject: [PATCH 07/22] Add changelog entry --- ext/opentelemetry-ext-otlp/CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 ext/opentelemetry-ext-otlp/CHANGELOG.md diff --git a/ext/opentelemetry-ext-otlp/CHANGELOG.md b/ext/opentelemetry-ext-otlp/CHANGELOG.md new file mode 100644 index 00000000000..c4a5c9d1d0f --- /dev/null +++ b/ext/opentelemetry-ext-otlp/CHANGELOG.md @@ -0,0 +1,12 @@ +# Changelog + +## Unreleased + +- Add metric OTLP exporter + ([#835](https://github.com/open-telemetry/opentelemetry-python/pull/835)) + +## 0.9b0 + +Released 2020-06-10 + +- Initial release From 632b1f597193f850e433b249bda73c449aac14bc Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Thu, 18 Jun 2020 12:04:34 -0600 Subject: [PATCH 08/22] Fix ordering for 35 --- .../tests/test_otlp_metric_exporter.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ext/opentelemetry-ext-otlp/tests/test_otlp_metric_exporter.py b/ext/opentelemetry-ext-otlp/tests/test_otlp_metric_exporter.py index a940944f7e8..5d25d85ab89 100644 --- a/ext/opentelemetry-ext-otlp/tests/test_otlp_metric_exporter.py +++ b/ext/opentelemetry-ext-otlp/tests/test_otlp_metric_exporter.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +from collections import OrderedDict from unittest import TestCase from opentelemetry.ext.otlp.metrics_exporter import OTLPMetricsExporter @@ -39,7 +40,7 @@ from opentelemetry.sdk.metrics import Counter, MeterProvider from opentelemetry.sdk.metrics.export import MetricRecord from opentelemetry.sdk.metrics.export.aggregate import SumAggregator -from opentelemetry.sdk.resources import Resource +from opentelemetry.sdk.resources import Resource as SDKResource class TestOTLPMetricExporter(TestCase): @@ -53,18 +54,18 @@ def setUp(self): "c", int, MeterProvider( - resource=Resource({"a": 1, "b": False}) + resource=SDKResource(OrderedDict([("a", 1), ("b", False)])) ).get_meter(__name__), ("d",), ), - {"e": "f"}, + OrderedDict([("e", "f")]), SumAggregator(), ) def test_translate_spans(self): # pylint: disable=no-member - self.counter_metric_record.instrument.add(1, {"a": "b"}) + self.counter_metric_record.instrument.add(1, OrderedDict([("a", "b")])) expected = ExportMetricsServiceRequest( resource_metrics=[ From 48e8916d040e85b8c2b8b842e545e4f5108dc89d Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Thu, 18 Jun 2020 12:10:47 -0600 Subject: [PATCH 09/22] Fix lint --- .../src/opentelemetry/ext/otlp/exporter.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py index 6ad7a890269..7ae934649ff 100644 --- a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py +++ b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py @@ -73,6 +73,7 @@ def _get_resource_data( for key, value in sdk_resource.labels.items(): try: + # pylint: disable=no-member collector_resource.attributes.append( AttributeKeyValue(**_translate_key_values(key, value)) ) From 3f34857f354750760ca8d37df1e113a8dc3b47f2 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 24 Jun 2020 11:52:03 -0600 Subject: [PATCH 10/22] Fix docstring --- .../src/opentelemetry/ext/otlp/exporter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py index 7ae934649ff..9fe9cbbf57d 100644 --- a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py +++ b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""OTLP Span Exporter""" +"""OTLP Exporter""" import logging from abc import ABC, abstractmethod From 1ac507eaa74b20729ff73a48cec626902ffd05d0 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 24 Jun 2020 12:22:06 -0600 Subject: [PATCH 11/22] Updating example --- ...or_example.py => otlpcollector_example.py} | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) rename docs/getting_started/{otcollector_example.py => otlpcollector_example.py} (78%) diff --git a/docs/getting_started/otcollector_example.py b/docs/getting_started/otlpcollector_example.py similarity index 78% rename from docs/getting_started/otcollector_example.py rename to docs/getting_started/otlpcollector_example.py index b1887c3d0c9..ae7bec58757 100644 --- a/docs/getting_started/otcollector_example.py +++ b/docs/getting_started/otlpcollector_example.py @@ -16,33 +16,29 @@ import time from opentelemetry import metrics, trace -from opentelemetry.ext.otcollector.metrics_exporter import ( - CollectorMetricsExporter, -) -from opentelemetry.ext.otcollector.trace_exporter import CollectorSpanExporter +from opentelemetry.ext.otcollector.trace_exporter import OTLPSpanExporter +from opentelemetry.ext.otcollector.metrics_exporter import OTLPMetricsExporter from opentelemetry.sdk.metrics import Counter, MeterProvider from opentelemetry.sdk.metrics.export.controller import PushController from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchExportSpanProcessor -# create a CollectorSpanExporter -span_exporter = CollectorSpanExporter( - # optional: - # endpoint="myCollectorUrl:55678", - # service_name="test_service", - # host_name="machine/container name", +span_exporter = OTLPSpanExporter( + # optional + # endpoint:="myCollectorURL:55678", + # credentials=ChannelCredentials(credentials), + # metadata=(("metadata", "metadata")), ) tracer_provider = TracerProvider() trace.set_tracer_provider(tracer_provider) span_processor = BatchExportSpanProcessor(span_exporter) tracer_provider.add_span_processor(span_processor) -# create a CollectorMetricsExporter -metric_exporter = CollectorMetricsExporter( - # optional: - # endpoint="myCollectorUrl:55678", - # service_name="test_service", - # host_name="machine/container name", +metric_exporter = OTLPMetricsExporter( + # optional + # endpoint:="myCollectorURL:55678", + # credentials=ChannelCredentials(credentials), + # metadata=(("metadata", "metadata")), ) # Meter is responsible for creating and recording metrics From 93bf1fffcebbb81838202d2011d50c6215771a47 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Thu, 25 Jun 2020 09:57:04 -0600 Subject: [PATCH 12/22] Fix docs --- docs/getting-started.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started.rst b/docs/getting-started.rst index 198bd0f1e31..f60c473ba23 100644 --- a/docs/getting-started.rst +++ b/docs/getting-started.rst @@ -316,6 +316,6 @@ Install the OpenTelemetry Collector exporter: And execute the following script: -.. literalinclude:: getting_started/otcollector_example.py +.. literalinclude:: getting_started/otlpcollector_example.py :language: python :lines: 15- From 7ab7984152ea8556fb0373999bfc989ba65f1525 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Thu, 25 Jun 2020 10:30:58 -0600 Subject: [PATCH 13/22] Fix lint --- docs/getting_started/otlpcollector_example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting_started/otlpcollector_example.py b/docs/getting_started/otlpcollector_example.py index ae7bec58757..1ee900e5d16 100644 --- a/docs/getting_started/otlpcollector_example.py +++ b/docs/getting_started/otlpcollector_example.py @@ -16,8 +16,8 @@ import time from opentelemetry import metrics, trace -from opentelemetry.ext.otcollector.trace_exporter import OTLPSpanExporter from opentelemetry.ext.otcollector.metrics_exporter import OTLPMetricsExporter +from opentelemetry.ext.otcollector.trace_exporter import OTLPSpanExporter from opentelemetry.sdk.metrics import Counter, MeterProvider from opentelemetry.sdk.metrics.export.controller import PushController from opentelemetry.sdk.trace import TracerProvider From 02a788e39096ad8b8b43c9492875978de06baa3a Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Tue, 7 Jul 2020 15:26:54 -0600 Subject: [PATCH 14/22] Fix logging message --- .../src/opentelemetry/ext/otlp/exporter.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py index 9fe9cbbf57d..5a475e9327b 100644 --- a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py +++ b/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py @@ -171,7 +171,10 @@ def _export(self, data): + retry_info.retry_delay.nanos / 1.0e9 ) - logger.debug("Waiting %ss before retrying export of span") + logger.debug( + "Waiting %ss before retrying export of span", + delay + ) sleep(delay) continue From 522cf09f5d3d4e09811bbc642a24891cd5b7ea6d Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Tue, 4 Aug 2020 09:54:44 -0600 Subject: [PATCH 15/22] Move exporter to new location --- .../opentelemetry-exporter-otlp/CHANGELOG.md | 5 +- .../opentelemetry/exporter}/otlp/exporter.py | 0 .../otlp/metrics_exporter/__init__.py | 0 .../exporter/otlp/trace_exporter/__init__.py | 127 ++---------------- .../tests/test_otlp_metric_exporter.py | 0 .../tests/test_otlp_trace_exporter.py | 8 +- ext/opentelemetry-ext-otlp/CHANGELOG.md | 12 -- 7 files changed, 16 insertions(+), 136 deletions(-) rename {ext/opentelemetry-ext-otlp/src/opentelemetry/ext => exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter}/otlp/exporter.py (100%) rename {ext/opentelemetry-ext-otlp/src/opentelemetry/ext => exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter}/otlp/metrics_exporter/__init__.py (100%) rename {ext/opentelemetry-ext-otlp => exporter/opentelemetry-exporter-otlp}/tests/test_otlp_metric_exporter.py (100%) delete mode 100644 ext/opentelemetry-ext-otlp/CHANGELOG.md diff --git a/exporter/opentelemetry-exporter-otlp/CHANGELOG.md b/exporter/opentelemetry-exporter-otlp/CHANGELOG.md index 24eb8bcf580..ed6aee3b4c6 100644 --- a/exporter/opentelemetry-exporter-otlp/CHANGELOG.md +++ b/exporter/opentelemetry-exporter-otlp/CHANGELOG.md @@ -2,9 +2,10 @@ ## Unreleased -## Version 0.12b0 +- Add metric OTLP exporter + ([#835](https://github.com/open-telemetry/opentelemetry-python/pull/835)) -Released 2020-08-14 +## Version 0.12b0 - Change package name to opentelemetry-exporter-otlp ([#953](https://github.com/open-telemetry/opentelemetry-python/pull/953)) diff --git a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py similarity index 100% rename from ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/exporter.py rename to exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py diff --git a/ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/metrics_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/metrics_exporter/__init__.py similarity index 100% rename from ext/opentelemetry-ext-otlp/src/opentelemetry/ext/otlp/metrics_exporter/__init__.py rename to exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/metrics_exporter/__init__.py diff --git a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py index 3a067a95445..8703bc7f587 100644 --- a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py @@ -14,9 +14,7 @@ """OTLP Span Exporter""" import logging -from collections.abc import Mapping, Sequence -from time import sleep -from typing import Sequence as TypingSequence +from typing import Sequence from opentelemetry.ext.otlp.exporter import ( OTLPExporterMixin, @@ -29,8 +27,6 @@ from opentelemetry.proto.collector.trace.v1.trace_service_pb2_grpc import ( TraceServiceStub, ) -from opentelemetry.proto.common.v1.common_pb2 import AnyValue, KeyValue -from opentelemetry.proto.resource.v1.resource_pb2 import Resource from opentelemetry.proto.trace.v1.trace_pb2 import ( InstrumentationLibrarySpans, ResourceSpans, @@ -43,34 +39,6 @@ logger = logging.getLogger(__name__) -def _translate_key_values(key, value): - - if isinstance(value, bool): - any_value = AnyValue(bool_value=value) - - elif isinstance(value, str): - any_value = AnyValue(string_value=value) - - elif isinstance(value, int): - any_value = AnyValue(int_value=value) - - elif isinstance(value, float): - any_value = AnyValue(double_value=value) - - elif isinstance(value, Sequence): - any_value = AnyValue(array_value=value) - - elif isinstance(value, Mapping): - any_value = AnyValue(kvlist_value=value) - - else: - raise Exception( - "Invalid type {} of value {}".format(type(value), value) - ) - - return KeyValue(key=key, value=any_value) - - # pylint: disable=no-member class OTLPSpanExporter(SpanExporter, OTLPExporterMixin): """OTLP span exporter @@ -209,9 +177,7 @@ def _translate_status(self, sdk_span): message=sdk_span.status.description, ) - def _translate_spans( - self, sdk_spans: TypingSequence[SDKSpan], - ) -> ExportTraceServiceRequest: + def _translate_data(self, data) -> ExportTraceServiceRequest: sdk_resource_instrumentation_library_spans = {} @@ -246,91 +212,16 @@ def _translate_spans( sdk_span.resource ].spans.append(CollectorSpan(**self._collector_span_kwargs)) - resource_spans = [] - - for ( - sdk_resource, - instrumentation_library_spans, - ) in sdk_resource_instrumentation_library_spans.items(): - - collector_resource = Resource() - - for key, value in sdk_resource.labels.items(): - - try: - collector_resource.attributes.append( - _translate_key_values(key, value) - ) - except Exception as error: # pylint: disable=broad-except - logger.exception(error) - - resource_spans.append( - ResourceSpans( - resource=collector_resource, - instrumentation_library_spans=[ - instrumentation_library_spans - ], - ) + return ExportTraceServiceRequest( + resource_spans=_get_resource_data( + sdk_resource_instrumentation_library_spans, + ResourceSpans, + "spans", ) ) - def export(self, spans: TypingSequence[SDKSpan]) -> SpanExportResult: - # expo returns a generator that yields delay values which grow - # exponentially. Once delay is greater than max_value, the yielded - # value will remain constant. - # max_value is set to 900 (900 seconds is 15 minutes) to use the same - # value as used in the Go implementation. - - max_value = 900 - - for delay in expo(max_value=max_value): - - if delay == max_value: - return SpanExportResult.FAILURE - - try: - self._client.Export( - request=self._translate_spans(spans), - metadata=self._metadata, - ) - - return SpanExportResult.SUCCESS - - except RpcError as error: - - if error.code() in [ - StatusCode.CANCELLED, - StatusCode.DEADLINE_EXCEEDED, - StatusCode.PERMISSION_DENIED, - StatusCode.UNAUTHENTICATED, - StatusCode.RESOURCE_EXHAUSTED, - StatusCode.ABORTED, - StatusCode.OUT_OF_RANGE, - StatusCode.UNAVAILABLE, - StatusCode.DATA_LOSS, - ]: - - retry_info_bin = dict(error.trailing_metadata()).get( - "google.rpc.retryinfo-bin" - ) - if retry_info_bin is not None: - retry_info = RetryInfo() - retry_info.ParseFromString(retry_info_bin) - delay = ( - retry_info.retry_delay.seconds - + retry_info.retry_delay.nanos / 1.0e9 - ) - - logger.debug("Waiting %ss before retrying export of span") - sleep(delay) - continue - - if error.code() == StatusCode.OK: - return SpanExportResult.SUCCESS - - return SpanExportResult.FAILURE - - return SpanExportResult.FAILURE + def export(self, spans: Sequence[SDKSpan]) -> SpanExportResult: + return self._export(spans) def shutdown(self): pass diff --git a/ext/opentelemetry-ext-otlp/tests/test_otlp_metric_exporter.py b/exporter/opentelemetry-exporter-otlp/tests/test_otlp_metric_exporter.py similarity index 100% rename from ext/opentelemetry-ext-otlp/tests/test_otlp_metric_exporter.py rename to exporter/opentelemetry-exporter-otlp/tests/test_otlp_metric_exporter.py diff --git a/exporter/opentelemetry-exporter-otlp/tests/test_otlp_trace_exporter.py b/exporter/opentelemetry-exporter-otlp/tests/test_otlp_trace_exporter.py index c73fd40898a..b0ec8e4517e 100644 --- a/exporter/opentelemetry-exporter-otlp/tests/test_otlp_trace_exporter.py +++ b/exporter/opentelemetry-exporter-otlp/tests/test_otlp_trace_exporter.py @@ -142,8 +142,8 @@ def setUp(self): def tearDown(self): self.server.stop(None) - @patch("opentelemetry.exporter.otlp.trace_exporter.expo") - @patch("opentelemetry.exporter.otlp.trace_exporter.sleep") + @patch("opentelemetry.exporter.otlp.exporter.expo") + @patch("opentelemetry.exporter.otlp.exporter.sleep") def test_unavailable(self, mock_sleep, mock_expo): mock_expo.configure_mock(**{"return_value": [1]}) @@ -156,8 +156,8 @@ def test_unavailable(self, mock_sleep, mock_expo): ) mock_sleep.assert_called_with(1) - @patch("opentelemetry.exporter.otlp.trace_exporter.expo") - @patch("opentelemetry.exporter.otlp.trace_exporter.sleep") + @patch("opentelemetry.exporter.otlp.exporter.expo") + @patch("opentelemetry.exporter.otlp.exporter.sleep") def test_unavailable_delay(self, mock_sleep, mock_expo): mock_expo.configure_mock(**{"return_value": [1]}) diff --git a/ext/opentelemetry-ext-otlp/CHANGELOG.md b/ext/opentelemetry-ext-otlp/CHANGELOG.md deleted file mode 100644 index c4a5c9d1d0f..00000000000 --- a/ext/opentelemetry-ext-otlp/CHANGELOG.md +++ /dev/null @@ -1,12 +0,0 @@ -# Changelog - -## Unreleased - -- Add metric OTLP exporter - ([#835](https://github.com/open-telemetry/opentelemetry-python/pull/835)) - -## 0.9b0 - -Released 2020-06-10 - -- Initial release From 2cb0abb787ae898704c7fdc1a948bbd860bbf665 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Tue, 4 Aug 2020 15:20:42 -0600 Subject: [PATCH 16/22] WIP --- .../opentelemetry/exporter/otlp/exporter.py | 22 ++++++++++++------- .../otlp/metrics_exporter/__init__.py | 2 +- .../exporter/otlp/trace_exporter/__init__.py | 2 +- .../tests/test_otlp_metric_exporter.py | 10 +++++---- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py index 5a475e9327b..80af69b505e 100644 --- a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py +++ b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py @@ -16,6 +16,7 @@ import logging from abc import ABC, abstractmethod +from collections.abc import Mapping, Sequence from time import sleep from backoff import expo @@ -28,33 +29,38 @@ secure_channel, ) -from opentelemetry.proto.common.v1.common_pb2 import AttributeKeyValue from opentelemetry.proto.resource.v1.resource_pb2 import Resource +from opentelemetry.proto.common.v1.common_pb2 import AnyValue, KeyValue logger = logging.getLogger(__name__) def _translate_key_values(key, value): - key_value = {"key": key} if isinstance(value, bool): - key_value["bool_value"] = value + any_value = AnyValue(bool_value=value) elif isinstance(value, str): - key_value["string_value"] = value + any_value = AnyValue(string_value=value) elif isinstance(value, int): - key_value["int_value"] = value + any_value = AnyValue(int_value=value) elif isinstance(value, float): - key_value["double_value"] = value + any_value = AnyValue(double_value=value) + + elif isinstance(value, Sequence): + any_value = AnyValue(array_value=value) + + elif isinstance(value, Mapping): + any_value = AnyValue(kvlist_value=value) else: raise Exception( "Invalid type {} of value {}".format(type(value), value) ) - return key_value + return KeyValue(key=key, value=any_value) def _get_resource_data( @@ -75,7 +81,7 @@ def _get_resource_data( try: # pylint: disable=no-member collector_resource.attributes.append( - AttributeKeyValue(**_translate_key_values(key, value)) + _translate_key_values(key, value) ) except Exception as error: # pylint: disable=broad-except logger.exception(error) diff --git a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/metrics_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/metrics_exporter/__init__.py index ccdbc306b25..777638d951c 100644 --- a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/metrics_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/metrics_exporter/__init__.py @@ -16,7 +16,7 @@ import logging -from opentelemetry.ext.otlp.exporter import ( +from opentelemetry.exporter.otlp.exporter import ( OTLPExporterMixin, _get_resource_data, ) diff --git a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py index 8703bc7f587..3eade54be2a 100644 --- a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py @@ -16,7 +16,7 @@ import logging from typing import Sequence -from opentelemetry.ext.otlp.exporter import ( +from opentelemetry.exporter.otlp.exporter import ( OTLPExporterMixin, _get_resource_data, _translate_key_values, diff --git a/exporter/opentelemetry-exporter-otlp/tests/test_otlp_metric_exporter.py b/exporter/opentelemetry-exporter-otlp/tests/test_otlp_metric_exporter.py index 5d25d85ab89..57a02d03937 100644 --- a/exporter/opentelemetry-exporter-otlp/tests/test_otlp_metric_exporter.py +++ b/exporter/opentelemetry-exporter-otlp/tests/test_otlp_metric_exporter.py @@ -15,12 +15,11 @@ from collections import OrderedDict from unittest import TestCase -from opentelemetry.ext.otlp.metrics_exporter import OTLPMetricsExporter +from opentelemetry.exporter.otlp.metrics_exporter import OTLPMetricsExporter from opentelemetry.proto.collector.metrics.v1.metrics_service_pb2 import ( ExportMetricsServiceRequest, ) from opentelemetry.proto.common.v1.common_pb2 import ( - AttributeKeyValue, StringKeyValue, ) from opentelemetry.proto.metrics.v1.metrics_pb2 import ( @@ -34,6 +33,7 @@ MetricDescriptor, ResourceMetrics, ) +from opentelemetry.proto.common.v1.common_pb2 import AnyValue, KeyValue from opentelemetry.proto.resource.v1.resource_pb2 import ( Resource as CollectorResource, ) @@ -72,8 +72,10 @@ def test_translate_spans(self): ResourceMetrics( resource=CollectorResource( attributes=[ - AttributeKeyValue(key="a", int_value=1), - AttributeKeyValue(key="b", bool_value=False), + KeyValue(key="a", value=AnyValue(int_value=1)), + KeyValue( + key="b", value=AnyValue(bool_value=False) + ), ] ), instrumentation_library_metrics=[ From b3711ba54ea8da35e15e46e4719a91411b7bd09c Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Tue, 4 Aug 2020 16:45:39 -0600 Subject: [PATCH 17/22] All tests passing --- .../exporter/otlp/metrics_exporter/__init__.py | 18 ++++++++++++------ .../tests/test_otlp_metric_exporter.py | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/metrics_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/metrics_exporter/__init__.py index 777638d951c..a881ed705c6 100644 --- a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/metrics_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/metrics_exporter/__init__.py @@ -70,12 +70,18 @@ def _get_data_points(sdk_metric, data_point_class): string_key_values.append( StringKeyValue(key=label_key, value=label_value) ) - data_points.append( - data_point_class( - labels=string_key_values, - value=bound_counter.aggregator.current, - ) - ) + + for view_data in bound_counter.view_datas: + + if view_data.labels == label: + + data_points.append( + data_point_class( + labels=string_key_values, + value=view_data.aggregator.current + ) + ) + break return data_points diff --git a/exporter/opentelemetry-exporter-otlp/tests/test_otlp_metric_exporter.py b/exporter/opentelemetry-exporter-otlp/tests/test_otlp_metric_exporter.py index 57a02d03937..b7bc78680e8 100644 --- a/exporter/opentelemetry-exporter-otlp/tests/test_otlp_metric_exporter.py +++ b/exporter/opentelemetry-exporter-otlp/tests/test_otlp_metric_exporter.py @@ -62,7 +62,7 @@ def setUp(self): SumAggregator(), ) - def test_translate_spans(self): + def test_translate_metrics(self): # pylint: disable=no-member self.counter_metric_record.instrument.add(1, OrderedDict([("a", "b")])) From 44b94329990d2d8a5212606ed9dcd965ef9ee6f7 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Tue, 4 Aug 2020 16:51:54 -0600 Subject: [PATCH 18/22] Fix lint --- .../src/opentelemetry/exporter/otlp/exporter.py | 5 ++--- .../opentelemetry/exporter/otlp/metrics_exporter/__init__.py | 2 +- .../tests/test_otlp_metric_exporter.py | 3 ++- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py index 80af69b505e..4e31432606e 100644 --- a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py +++ b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py @@ -29,8 +29,8 @@ secure_channel, ) -from opentelemetry.proto.resource.v1.resource_pb2 import Resource from opentelemetry.proto.common.v1.common_pb2 import AnyValue, KeyValue +from opentelemetry.proto.resource.v1.resource_pb2 import Resource logger = logging.getLogger(__name__) @@ -178,8 +178,7 @@ def _export(self, data): ) logger.debug( - "Waiting %ss before retrying export of span", - delay + "Waiting %ss before retrying export of span", delay ) sleep(delay) continue diff --git a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/metrics_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/metrics_exporter/__init__.py index a881ed705c6..bd1ff4bf60c 100644 --- a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/metrics_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/metrics_exporter/__init__.py @@ -78,7 +78,7 @@ def _get_data_points(sdk_metric, data_point_class): data_points.append( data_point_class( labels=string_key_values, - value=view_data.aggregator.current + value=view_data.aggregator.current, ) ) break diff --git a/exporter/opentelemetry-exporter-otlp/tests/test_otlp_metric_exporter.py b/exporter/opentelemetry-exporter-otlp/tests/test_otlp_metric_exporter.py index b7bc78680e8..20fecd44a22 100644 --- a/exporter/opentelemetry-exporter-otlp/tests/test_otlp_metric_exporter.py +++ b/exporter/opentelemetry-exporter-otlp/tests/test_otlp_metric_exporter.py @@ -20,6 +20,8 @@ ExportMetricsServiceRequest, ) from opentelemetry.proto.common.v1.common_pb2 import ( + AnyValue, + KeyValue, StringKeyValue, ) from opentelemetry.proto.metrics.v1.metrics_pb2 import ( @@ -33,7 +35,6 @@ MetricDescriptor, ResourceMetrics, ) -from opentelemetry.proto.common.v1.common_pb2 import AnyValue, KeyValue from opentelemetry.proto.resource.v1.resource_pb2 import ( Resource as CollectorResource, ) From c693326d42166aa1572acb98a44c0c83b7629ba4 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Thu, 6 Aug 2020 15:39:03 -0600 Subject: [PATCH 19/22] Fix docs --- docs/getting-started.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started.rst b/docs/getting-started.rst index f60c473ba23..8c27ddfa4d3 100644 --- a/docs/getting-started.rst +++ b/docs/getting-started.rst @@ -312,7 +312,7 @@ Install the OpenTelemetry Collector exporter: .. code-block:: sh - pip install opentelemetry-instrumentation-otcollector + pip install opentelemetry-exporter-otlp And execute the following script: From d06d65467bde24c74cc09852ea5431a64968285e Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Mon, 10 Aug 2020 14:58:49 -0600 Subject: [PATCH 20/22] Update port --- .../opentelemetry/exporter/otlp/exporter.py | 2 +- .../exporter/otlp/trace_exporter/__init__.py | 18 ------------------ 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py index 4e31432606e..6df9752922f 100644 --- a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py +++ b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py @@ -112,7 +112,7 @@ class OTLPExporterMixin(ABC): def __init__( self, - endpoint: str = "localhost:55678", + endpoint: str = "localhost:55680", credentials: ChannelCredentials = None, metadata: tuple = None, ): diff --git a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py index 3eade54be2a..b61b0a55fd4 100644 --- a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py @@ -52,24 +52,6 @@ class OTLPSpanExporter(SpanExporter, OTLPExporterMixin): _result = SpanExportResult _stub = TraceServiceStub - def __init__( - self, - endpoint="localhost:55680", - credentials: ChannelCredentials = None, - metadata=None, - ): - super().__init__() - - self._metadata = metadata - self._collector_span_kwargs = None - - if credentials is None: - self._client = TraceServiceStub(insecure_channel(endpoint)) - else: - self._client = TraceServiceStub( - secure_channel(endpoint, credentials) - ) - def _translate_name(self, sdk_span): self._collector_span_kwargs["name"] = sdk_span.name From 338cc53af583e161d1a54392b18b34a0ab090606 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Mon, 10 Aug 2020 15:02:35 -0600 Subject: [PATCH 21/22] Update docs --- docs/getting_started/otlpcollector_example.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/getting_started/otlpcollector_example.py b/docs/getting_started/otlpcollector_example.py index 1ee900e5d16..15254c7cc50 100644 --- a/docs/getting_started/otlpcollector_example.py +++ b/docs/getting_started/otlpcollector_example.py @@ -16,8 +16,8 @@ import time from opentelemetry import metrics, trace -from opentelemetry.ext.otcollector.metrics_exporter import OTLPMetricsExporter -from opentelemetry.ext.otcollector.trace_exporter import OTLPSpanExporter +from opentelemetry.exporter.otlp.metrics_exporter import OTLPMetricsExporter +from opentelemetry.exporter.otlp.trace_exporter import OTLPSpanExporter from opentelemetry.sdk.metrics import Counter, MeterProvider from opentelemetry.sdk.metrics.export.controller import PushController from opentelemetry.sdk.trace import TracerProvider From f9df1e40907bec1cdcd40262998fb7f29b82e2df Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Mon, 10 Aug 2020 16:48:02 -0600 Subject: [PATCH 22/22] Add fixes --- .pylintrc | 1 + .../src/opentelemetry/exporter/otlp/exporter.py | 3 +++ .../exporter/otlp/metrics_exporter/__init__.py | 9 ++++++++- .../exporter/otlp/trace_exporter/__init__.py | 3 --- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.pylintrc b/.pylintrc index 5f9463df7d5..8f29b634f1b 100644 --- a/.pylintrc +++ b/.pylintrc @@ -65,6 +65,7 @@ disable=missing-docstring, too-few-public-methods, # Might be good to re-enable this later. too-many-instance-attributes, too-many-arguments, + duplicate-code, ungrouped-imports, # Leave this up to isort wrong-import-order, # Leave this up to isort bad-continuation, # Leave this up to black diff --git a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py index 6df9752922f..0ce7ef66177 100644 --- a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py +++ b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py @@ -189,3 +189,6 @@ def _export(self, data): return self.result.FAILURE return self._result.FAILURE + + def shutdown(self): + pass diff --git a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/metrics_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/metrics_exporter/__init__.py index bd1ff4bf60c..944428e37d0 100644 --- a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/metrics_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/metrics_exporter/__init__.py @@ -15,7 +15,9 @@ """OTLP Metrics Exporter""" import logging +from typing import Sequence +# pylint: disable=duplicate-code from opentelemetry.exporter.otlp.exporter import ( OTLPExporterMixin, _get_resource_data, @@ -39,8 +41,9 @@ MetricDescriptor, ResourceMetrics, ) +from opentelemetry.sdk.metrics import Counter +from opentelemetry.sdk.metrics import Metric as SDKMetric from opentelemetry.sdk.metrics import ( - Counter, SumObserver, UpDownCounter, UpDownSumObserver, @@ -189,3 +192,7 @@ def _translate_data(self, data): "metrics", ) ) + + def export(self, metrics: Sequence[SDKMetric]) -> MetricsExportResult: + # pylint: disable=arguments-differ + return self._export(metrics) diff --git a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py index b61b0a55fd4..5a9a74a304f 100644 --- a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py @@ -204,6 +204,3 @@ def _translate_data(self, data) -> ExportTraceServiceRequest: def export(self, spans: Sequence[SDKSpan]) -> SpanExportResult: return self._export(spans) - - def shutdown(self): - pass