From ffd7daade395d320260c8efc21bfc1a5d6106546 Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Mon, 4 Jan 2021 09:12:29 -0800 Subject: [PATCH 1/2] pass OTLP metadata as tuple instead of string --- .../opentelemetry/exporter/otlp/exporter.py | 6 +++- .../otlp/metrics_exporter/__init__.py | 2 +- .../exporter/otlp/trace_exporter/__init__.py | 2 +- .../tests/test_otlp_metric_exporter.py | 33 +++++++++++++++++-- .../tests/test_otlp_trace_exporter.py | 33 +++++++++++++++++-- 5 files changed, 69 insertions(+), 7 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 915e5f4d3ee..e00f119b000 100644 --- a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py +++ b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/exporter.py @@ -151,7 +151,7 @@ def __init__( endpoint: Optional[str] = None, insecure: Optional[bool] = None, credentials: Optional[ChannelCredentials] = None, - headers: Optional[str] = None, + headers: Optional[Sequence] = None, timeout: Optional[int] = None, compression: str = None, ): @@ -169,6 +169,10 @@ def __init__( insecure = False self._headers = headers or Configuration().EXPORTER_OTLP_HEADERS + if isinstance(self._headers, str): + self._headers = tuple( + tuple(item.split("=")) for item in self._headers.split(",") + ) self._timeout = ( timeout or Configuration().EXPORTER_OTLP_TIMEOUT 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 559e313477d..c371c177e9c 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 @@ -139,7 +139,7 @@ def __init__( endpoint: Optional[str] = None, insecure: Optional[bool] = None, credentials: Optional[ChannelCredentials] = None, - headers: Optional[str] = None, + headers: Optional[Sequence] = None, timeout: Optional[int] = None, ): if insecure is 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 1af8d26aa91..029f93841af 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 @@ -69,7 +69,7 @@ def __init__( endpoint: Optional[str] = None, insecure: Optional[bool] = None, credentials: Optional[ChannelCredentials] = None, - headers: Optional[str] = None, + headers: Optional[Sequence] = None, timeout: Optional[int] = None, ): if insecure is None: 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 c8664f94fa7..6ecce722a32 100644 --- a/exporter/opentelemetry-exporter-otlp/tests/test_otlp_metric_exporter.py +++ b/exporter/opentelemetry-exporter-otlp/tests/test_otlp_metric_exporter.py @@ -73,7 +73,7 @@ def tearDown(self): "OTEL_EXPORTER_OTLP_METRIC_ENDPOINT": "collector:55680", "OTEL_EXPORTER_OTLP_METRIC_CERTIFICATE": THIS_DIR + "/fixtures/test.cert", - "OTEL_EXPORTER_OTLP_METRIC_HEADERS": "key1:value1;key2:value2", + "OTEL_EXPORTER_OTLP_METRIC_HEADERS": "key1=value1,key2=value2", "OTEL_EXPORTER_OTLP_METRIC_TIMEOUT": "10", }, ) @@ -85,7 +85,7 @@ def test_env_variables(self, mock_exporter_mixin): _, kwargs = mock_exporter_mixin.call_args_list[0] self.assertEqual(kwargs["endpoint"], "collector:55680") - self.assertEqual(kwargs["headers"], "key1:value1;key2:value2") + self.assertEqual(kwargs["headers"], "key1=value1,key2=value2") self.assertEqual(kwargs["timeout"], 10) self.assertIsNotNone(kwargs["credentials"]) self.assertIsInstance(kwargs["credentials"], ChannelCredentials) @@ -102,6 +102,35 @@ def test_no_credentials_error( OTLPMetricsExporter(insecure=False) self.assertTrue(mock_ssl_channel.called) + @patch.dict( + "os.environ", + {"OTEL_EXPORTER_OTLP_METRIC_HEADERS": "key1=value1,key2=value2"}, + ) + @patch("opentelemetry.exporter.otlp.exporter.ssl_channel_credentials") + @patch("opentelemetry.exporter.otlp.exporter.secure_channel") + # pylint: disable=unused-argument + def test_otlp_headers_from_env(self, mock_ssl_channel, mock_secure): + exporter = OTLPMetricsExporter() + # pylint: disable=protected-access + self.assertEqual( + exporter._headers, (("key1", "value1"), ("key2", "value2")), + ) + exporter = OTLPMetricsExporter( + headers=(("key3", "value3"), ("key4", "value4")) + ) + # pylint: disable=protected-access + self.assertEqual( + exporter._headers, (("key3", "value3"), ("key4", "value4")), + ) + + @patch("opentelemetry.exporter.otlp.exporter.ssl_channel_credentials") + @patch("opentelemetry.exporter.otlp.exporter.secure_channel") + # pylint: disable=unused-argument + def test_otlp_headers(self, mock_ssl_channel, mock_secure): + exporter = OTLPMetricsExporter() + # pylint: disable=protected-access + self.assertIsNone(exporter._headers, None) + @patch("opentelemetry.sdk.metrics.export.aggregate.time_ns") def test_translate_counter_export_record(self, mock_time_ns): mock_time_ns.configure_mock(**{"return_value": 1}) 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 b691e85849c..76fd0948887 100644 --- a/exporter/opentelemetry-exporter-otlp/tests/test_otlp_trace_exporter.py +++ b/exporter/opentelemetry-exporter-otlp/tests/test_otlp_trace_exporter.py @@ -170,7 +170,7 @@ def tearDown(self): "OTEL_EXPORTER_OTLP_SPAN_ENDPOINT": "collector:55680", "OTEL_EXPORTER_OTLP_SPAN_CERTIFICATE": THIS_DIR + "/fixtures/test.cert", - "OTEL_EXPORTER_OTLP_SPAN_HEADERS": "key1:value1;key2:value2", + "OTEL_EXPORTER_OTLP_SPAN_HEADERS": "key1=value1,key2=value2", "OTEL_EXPORTER_OTLP_SPAN_TIMEOUT": "10", }, ) @@ -182,7 +182,7 @@ def test_env_variables(self, mock_exporter_mixin): _, kwargs = mock_exporter_mixin.call_args_list[0] self.assertEqual(kwargs["endpoint"], "collector:55680") - self.assertEqual(kwargs["headers"], "key1:value1;key2:value2") + self.assertEqual(kwargs["headers"], "key1=value1,key2=value2") self.assertEqual(kwargs["timeout"], 10) self.assertIsNotNone(kwargs["credentials"]) self.assertIsInstance(kwargs["credentials"], ChannelCredentials) @@ -197,6 +197,35 @@ def test_no_credentials_error( OTLPSpanExporter(insecure=False) self.assertTrue(mock_ssl_channel.called) + @patch.dict( + "os.environ", + {"OTEL_EXPORTER_OTLP_SPAN_HEADERS": "key1=value1,key2=value2"}, + ) + @patch("opentelemetry.exporter.otlp.exporter.ssl_channel_credentials") + @patch("opentelemetry.exporter.otlp.exporter.secure_channel") + # pylint: disable=unused-argument + def test_otlp_headers_from_env(self, mock_ssl_channel, mock_secure): + exporter = OTLPSpanExporter() + # pylint: disable=protected-access + self.assertEqual( + exporter._headers, (("key1", "value1"), ("key2", "value2")) + ) + exporter = OTLPSpanExporter( + headers=(("key3", "value3"), ("key4", "value4")) + ) + # pylint: disable=protected-access + self.assertEqual( + exporter._headers, (("key3", "value3"), ("key4", "value4")) + ) + + @patch("opentelemetry.exporter.otlp.exporter.ssl_channel_credentials") + @patch("opentelemetry.exporter.otlp.exporter.secure_channel") + # pylint: disable=unused-argument + def test_otlp_headers(self, mock_ssl_channel, mock_secure): + exporter = OTLPSpanExporter() + # pylint: disable=protected-access + self.assertIsNone(exporter._headers, None) + @patch("opentelemetry.exporter.otlp.exporter.expo") @patch("opentelemetry.exporter.otlp.exporter.sleep") def test_unavailable(self, mock_sleep, mock_expo): From c065ff9d62783e7ff753adf448b7d5a8c101a44b Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Mon, 4 Jan 2021 09:16:57 -0800 Subject: [PATCH 2/2] update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ccf9f81c10c..04654658d25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - `opentelemetry-exporter-zipkin` Updated zipkin exporter status code and error tag ([#1486](https://github.com/open-telemetry/opentelemetry-python/pull/1486)) +- `opentelemetry-exporter-otlp` Headers are now passed in as tuple as metadata, instead of a + string, which was incorrect. + ([#1507](https://github.com/open-telemetry/opentelemetry-python/pull/1507)) + ## [0.16b1](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v0.16b1) - 2020-11-26 ### Added