diff --git a/CHANGELOG.md b/CHANGELOG.md index 2aa395855a5..51135293b7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased](https://github.com/open-telemetry/opentelemetry-python/compare/v1.12.0rc1-0.31b0...HEAD) +- Add optional sessions parameter to all Exporters leveraging requests.Session +([#2783](https://github.com/open-telemetry/opentelemetry-python/pull/2783)) - Add min/max fields to Histogram ([#2759](https://github.com/open-telemetry/opentelemetry-python/pull/2759)) - `opentelemetry-exporter-otlp-proto-http` Add support for OTLP/HTTP log exporter diff --git a/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/_log_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/_log_exporter/__init__.py index 0cca6995675..041f1ab3c07 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/_log_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/_log_exporter/__init__.py @@ -62,6 +62,7 @@ def __init__( headers: Optional[Dict[str, str]] = None, timeout: Optional[int] = None, compression: Optional[Compression] = None, + session: Optional[requests.Session] = None, ): self._endpoint = endpoint or _append_logs_path( environ.get(OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_ENDPOINT) @@ -75,7 +76,7 @@ def __init__( environ.get(OTEL_EXPORTER_OTLP_TIMEOUT, DEFAULT_TIMEOUT) ) self._compression = compression or _compression_from_env() - self._session = requests.Session() + self._session = session or requests.Session() self._session.headers.update(self._headers) self._session.headers.update( {"Content-Type": _ProtobufEncoder._CONTENT_TYPE} diff --git a/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/trace_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/trace_exporter/__init__.py index 156afc247d9..6f0d6ee58df 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/trace_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/trace_exporter/__init__.py @@ -63,6 +63,7 @@ def __init__( headers: Optional[Dict[str, str]] = None, timeout: Optional[int] = None, compression: Optional[Compression] = None, + session: Optional[requests.Session] = None, ): self._endpoint = endpoint or environ.get( OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, @@ -86,7 +87,7 @@ def __init__( ) ) self._compression = compression or _compression_from_env() - self._session = requests.Session() + self._session = session or requests.Session() self._session.headers.update(self._headers) self._session.headers.update( {"Content-Type": _ProtobufEncoder._CONTENT_TYPE} diff --git a/exporter/opentelemetry-exporter-otlp-proto-http/tests/test_proto_log_exporter.py b/exporter/opentelemetry-exporter-otlp-proto-http/tests/test_proto_log_exporter.py index 13b20190da5..d5e34b7463d 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-http/tests/test_proto_log_exporter.py +++ b/exporter/opentelemetry-exporter-otlp-proto-http/tests/test_proto_log_exporter.py @@ -16,7 +16,9 @@ import unittest from typing import List, Tuple -from unittest.mock import patch +from unittest.mock import MagicMock, patch + +import requests from opentelemetry.exporter.otlp.proto.http import Compression from opentelemetry.exporter.otlp.proto.http._log_exporter import ( @@ -81,6 +83,7 @@ def test_constructor_default(self): self.assertEqual(exporter._timeout, DEFAULT_TIMEOUT) self.assertIs(exporter._compression, DEFAULT_COMPRESSION) self.assertEqual(exporter._headers, {}) + self.assertIsInstance(exporter._session, requests.Session) @patch.dict( "os.environ", @@ -93,12 +96,14 @@ def test_constructor_default(self): }, ) def test_exporter_constructor_take_priority(self): + sess = MagicMock() exporter = OTLPLogExporter( endpoint="endpoint.local:69/logs", certificate_file="/hello.crt", headers={"testHeader1": "value1", "testHeader2": "value2"}, timeout=70, compression=Compression.NoCompression, + session=sess(), ) self.assertEqual(exporter._endpoint, "endpoint.local:69/logs") @@ -109,6 +114,7 @@ def test_exporter_constructor_take_priority(self): exporter._headers, {"testHeader1": "value1", "testHeader2": "value2"}, ) + self.assertTrue(sess.called) @patch.dict( "os.environ", @@ -133,6 +139,7 @@ def test_exporter_env(self): self.assertEqual( exporter._headers, {"envheader1": "val1", "envheader2": "val2"} ) + self.assertIsInstance(exporter._session, requests.Session) def test_encode(self): sdk_logs, expected_encoding = self.get_test_logs() diff --git a/exporter/opentelemetry-exporter-otlp-proto-http/tests/test_proto_span_exporter.py b/exporter/opentelemetry-exporter-otlp-proto-http/tests/test_proto_span_exporter.py index e3cd2046267..4eb0db6160c 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-http/tests/test_proto_span_exporter.py +++ b/exporter/opentelemetry-exporter-otlp-proto-http/tests/test_proto_span_exporter.py @@ -15,6 +15,8 @@ import unittest from unittest.mock import patch +import requests + from opentelemetry.exporter.otlp.proto.http import Compression from opentelemetry.exporter.otlp.proto.http.trace_exporter import ( DEFAULT_COMPRESSION, @@ -55,6 +57,7 @@ def test_constructor_default(self): self.assertEqual(exporter._timeout, DEFAULT_TIMEOUT) self.assertIs(exporter._compression, DEFAULT_COMPRESSION) self.assertEqual(exporter._headers, {}) + self.assertIsInstance(exporter._session, requests.Session) @patch.dict( "os.environ", @@ -86,6 +89,7 @@ def test_exporter_traces_env_take_priority(self): "traceenv3": "==val3==", }, ) + self.assertIsInstance(exporter._session, requests.Session) @patch.dict( "os.environ", @@ -105,6 +109,7 @@ def test_exporter_constructor_take_priority(self): headers={"testHeader1": "value1", "testHeader2": "value2"}, timeout=20, compression=Compression.NoCompression, + session=requests.Session(), ) self.assertEqual(exporter._endpoint, "example.com/1234") @@ -115,6 +120,7 @@ def test_exporter_constructor_take_priority(self): exporter._headers, {"testHeader1": "value1", "testHeader2": "value2"}, ) + self.assertIsInstance(exporter._session, requests.Session) @patch.dict( "os.environ", diff --git a/exporter/opentelemetry-exporter-zipkin-json/src/opentelemetry/exporter/zipkin/json/__init__.py b/exporter/opentelemetry-exporter-zipkin-json/src/opentelemetry/exporter/zipkin/json/__init__.py index 0e0642d0bea..7728090f546 100644 --- a/exporter/opentelemetry-exporter-zipkin-json/src/opentelemetry/exporter/zipkin/json/__init__.py +++ b/exporter/opentelemetry-exporter-zipkin-json/src/opentelemetry/exporter/zipkin/json/__init__.py @@ -31,6 +31,8 @@ .. code:: python + import requests + from opentelemetry import trace from opentelemetry.exporter.zipkin.json import ZipkinExporter from opentelemetry.sdk.trace import TracerProvider @@ -47,8 +49,9 @@ # local_node_ipv4="192.168.0.1", # local_node_ipv6="2001:db8::c001", # local_node_port=31313, - # max_tag_value_length=256 - # timeout=5 (in seconds) + # max_tag_value_length=256, + # timeout=5 (in seconds), + # session=requests.Session(), ) # Create a BatchSpanProcessor and add the exporter to it @@ -103,6 +106,7 @@ def __init__( local_node_port: Optional[int] = None, max_tag_value_length: Optional[int] = None, timeout: Optional[int] = None, + session: Optional[requests.Session] = None, ): """Zipkin exporter. @@ -116,6 +120,7 @@ def __init__( max_tag_value_length: Max length string attribute values can have. timeout: Maximum time the Zipkin exporter will wait for each batch export. The default value is 10s. + session: Connection session to the Zipkin collector endpoint. The tuple (local_node_ipv4, local_node_ipv6, local_node_port) is used to represent the network context of a node in the service graph. @@ -135,7 +140,7 @@ def __init__( elif version == Protocol.V2: self.encoder = JsonV2Encoder(max_tag_value_length) - self.session = requests.Session() + self.session = session or requests.Session() self.session.headers.update( {"Content-Type": self.encoder.content_type()} ) diff --git a/exporter/opentelemetry-exporter-zipkin-json/tests/test_zipkin_exporter.py b/exporter/opentelemetry-exporter-zipkin-json/tests/test_zipkin_exporter.py index 5c2aa0cbe69..77e3ef53755 100644 --- a/exporter/opentelemetry-exporter-zipkin-json/tests/test_zipkin_exporter.py +++ b/exporter/opentelemetry-exporter-zipkin-json/tests/test_zipkin_exporter.py @@ -17,6 +17,8 @@ import unittest from unittest.mock import patch +import requests + from opentelemetry import trace from opentelemetry.exporter.zipkin.encoder import Protocol from opentelemetry.exporter.zipkin.json import DEFAULT_ENDPOINT, ZipkinExporter @@ -55,6 +57,7 @@ def tearDown(self): def test_constructor_default(self): exporter = ZipkinExporter() self.assertIsInstance(exporter.encoder, JsonV2Encoder) + self.assertIsInstance(exporter.session, requests.Session) self.assertEqual(exporter.endpoint, DEFAULT_ENDPOINT) self.assertEqual(exporter.local_node.service_name, TEST_SERVICE_NAME) self.assertEqual(exporter.local_node.ipv4, None) @@ -83,6 +86,7 @@ def test_constructor_protocol_endpoint(self): exporter = ZipkinExporter(endpoint=endpoint) self.assertIsInstance(exporter.encoder, JsonV2Encoder) + self.assertIsInstance(exporter.session, requests.Session) self.assertEqual(exporter.endpoint, endpoint) self.assertEqual(exporter.local_node.service_name, TEST_SERVICE_NAME) self.assertEqual(exporter.local_node.ipv4, None) @@ -104,6 +108,7 @@ def test_constructor_all_params_and_env_vars(self): local_node_port = 30301 max_tag_value_length = 56 timeout_param = 20 + session_param = requests.Session() exporter = ZipkinExporter( constructor_param_version, @@ -113,9 +118,11 @@ def test_constructor_all_params_and_env_vars(self): local_node_port, max_tag_value_length, timeout_param, + session_param, ) self.assertIsInstance(exporter.encoder, JsonV2Encoder) + self.assertIsInstance(exporter.session, requests.Session) self.assertEqual(exporter.endpoint, constructor_param_endpoint) self.assertEqual(exporter.local_node.service_name, TEST_SERVICE_NAME) self.assertEqual( diff --git a/exporter/opentelemetry-exporter-zipkin-proto-http/src/opentelemetry/exporter/zipkin/proto/http/__init__.py b/exporter/opentelemetry-exporter-zipkin-proto-http/src/opentelemetry/exporter/zipkin/proto/http/__init__.py index bd98a1ff06c..5856cd7e4ea 100644 --- a/exporter/opentelemetry-exporter-zipkin-proto-http/src/opentelemetry/exporter/zipkin/proto/http/__init__.py +++ b/exporter/opentelemetry-exporter-zipkin-proto-http/src/opentelemetry/exporter/zipkin/proto/http/__init__.py @@ -31,6 +31,8 @@ .. code:: python + import requests + from opentelemetry import trace from opentelemetry.exporter.zipkin.proto.http import ZipkinExporter from opentelemetry.sdk.trace import TracerProvider @@ -46,8 +48,9 @@ # local_node_ipv4="192.168.0.1", # local_node_ipv6="2001:db8::c001", # local_node_port=31313, - # max_tag_value_length=256 - # timeout=5 (in seconds) + # max_tag_value_length=256, + # timeout=5 (in seconds), + # session=requests.Session() ) # Create a BatchSpanProcessor and add the exporter to it @@ -99,6 +102,7 @@ def __init__( local_node_port: Optional[int] = None, max_tag_value_length: Optional[int] = None, timeout: Optional[int] = None, + session: Optional[requests.Session] = None, ): """Zipkin exporter. @@ -112,6 +116,7 @@ def __init__( max_tag_value_length: Max length string attribute values can have. timeout: Maximum time the Zipkin exporter will wait for each batch export. The default value is 10s. + session: Connection session to the Zipkin collector endpoint. The tuple (local_node_ipv4, local_node_ipv6, local_node_port) is used to represent the network context of a node in the service graph. @@ -128,7 +133,7 @@ def __init__( self.encoder = ProtobufEncoder(max_tag_value_length) - self.session = requests.Session() + self.session = session or requests.Session() self.session.headers.update( {"Content-Type": self.encoder.content_type()} ) diff --git a/exporter/opentelemetry-exporter-zipkin-proto-http/tests/test_zipkin_exporter.py b/exporter/opentelemetry-exporter-zipkin-proto-http/tests/test_zipkin_exporter.py index 8b8b01438e2..8a3c055437a 100644 --- a/exporter/opentelemetry-exporter-zipkin-proto-http/tests/test_zipkin_exporter.py +++ b/exporter/opentelemetry-exporter-zipkin-proto-http/tests/test_zipkin_exporter.py @@ -17,6 +17,8 @@ import unittest from unittest.mock import patch +import requests + from opentelemetry import trace from opentelemetry.exporter.zipkin.node_endpoint import NodeEndpoint from opentelemetry.exporter.zipkin.proto.http import ( @@ -57,6 +59,7 @@ def tearDown(self): def test_constructor_default(self): exporter = ZipkinExporter() self.assertIsInstance(exporter.encoder, ProtobufEncoder) + self.assertIsInstance(exporter.session, requests.Session) self.assertEqual(exporter.endpoint, DEFAULT_ENDPOINT) self.assertEqual(exporter.local_node.service_name, TEST_SERVICE_NAME) self.assertEqual(exporter.local_node.ipv4, None) @@ -85,6 +88,7 @@ def test_constructor_protocol_endpoint(self): exporter = ZipkinExporter(endpoint) self.assertIsInstance(exporter.encoder, ProtobufEncoder) + self.assertIsInstance(exporter.session, requests.Session) self.assertEqual(exporter.endpoint, endpoint) self.assertEqual(exporter.local_node.service_name, TEST_SERVICE_NAME) self.assertEqual(exporter.local_node.ipv4, None) @@ -105,6 +109,7 @@ def test_constructor_all_params_and_env_vars(self): local_node_port = 30301 max_tag_value_length = 56 timeout_param = 20 + session_param = requests.Session() exporter = ZipkinExporter( constructor_param_endpoint, @@ -113,9 +118,11 @@ def test_constructor_all_params_and_env_vars(self): local_node_port, max_tag_value_length, timeout_param, + session_param, ) self.assertIsInstance(exporter.encoder, ProtobufEncoder) + self.assertIsInstance(exporter.session, requests.Session) self.assertEqual(exporter.endpoint, constructor_param_endpoint) self.assertEqual(exporter.local_node.service_name, TEST_SERVICE_NAME) self.assertEqual(