From 884e3b4be1a063d12a5e158ab58e251b56b348f4 Mon Sep 17 00:00:00 2001 From: jerevoss Date: Fri, 24 Mar 2023 11:00:33 -0700 Subject: [PATCH 1/4] Adding speced out env vars and args to BLRP --- CHANGELOG.md | 2 + .../sdk/_logs/_internal/export/__init__.py | 62 +++++++++- .../sdk/environment_variables.py | 40 ++++++- opentelemetry-sdk/tests/logs/test_export.py | 109 ++++++++++++++++++ 4 files changed, 204 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1474ce01ba..2834af9cfe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#2964](https://github.com/open-telemetry/opentelemetry-python/pull/2964)) - Add OpenCensus trace bridge/shim ([#3210](https://github.com/open-telemetry/opentelemetry-python/pull/3210)) +- Add speced out environment variables and arguments for BatchLogRecordProcessor + ([#3237](https://github.com/open-telemetry/opentelemetry-python/pull/3237)) ## Version 1.16.0/0.37b0 (2023-02-17) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py index 6f2f1c2c26..ab016d8779 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py @@ -19,7 +19,7 @@ import os import sys import threading -from os import linesep +from os import environ, linesep from time import time_ns from typing import IO, Callable, Deque, List, Optional, Sequence @@ -30,6 +30,12 @@ set_value, ) from opentelemetry.sdk._logs import LogData, LogRecord, LogRecordProcessor +from opentelemetry.sdk.environment_variables import ( + OTEL_BLRP_EXPORT_TIMEOUT, + OTEL_BLRP_MAX_EXPORT_BATCH_SIZE, + OTEL_BLRP_MAX_QUEUE_SIZE, + OTEL_BLRP_SCHEDULE_DELAY, +) from opentelemetry.util._once import Once _logger = logging.getLogger(__name__) @@ -142,20 +148,66 @@ class BatchLogRecordProcessor(LogRecordProcessor): """This is an implementation of LogRecordProcessor which creates batches of received logs in the export-friendly LogData representation and send to the configured LogExporter, as soon as they are emitted. + + `BatchLogRecordProcessor` is configurable with the following environment + variables which correspond to constructor parameters: + + - :envvar:`OTEL_BLRP_SCHEDULE_DELAY` + - :envvar:`OTEL_BLRP_MAX_QUEUE_SIZE` + - :envvar:`OTEL_BLRP_MAX_EXPORT_BATCH_SIZE` + - :envvar:`OTEL_BLRP_EXPORT_TIMEOUT` """ def __init__( self, exporter: LogExporter, - schedule_delay_millis: int = 5000, - max_export_batch_size: int = 512, - export_timeout_millis: int = 30000, + max_queue_size: int = None, + schedule_delay_millis: int = None, + max_export_batch_size: int = None, + export_timeout_millis: int = None, ): + if max_queue_size is None: + max_queue_size = int(environ.get(OTEL_BLRP_MAX_QUEUE_SIZE, 2048)) + + if schedule_delay_millis is None: + schedule_delay_millis = int( + environ.get(OTEL_BLRP_SCHEDULE_DELAY, 5000) + ) + + if max_export_batch_size is None: + max_export_batch_size = int( + environ.get(OTEL_BLRP_MAX_EXPORT_BATCH_SIZE, 512) + ) + + if export_timeout_millis is None: + export_timeout_millis = int( + environ.get(OTEL_BLRP_EXPORT_TIMEOUT, 30000) + ) + + if max_queue_size <= 0: + raise ValueError("max_queue_size must be a positive integer.") + + if schedule_delay_millis <= 0: + raise ValueError("schedule_delay_millis must be positive.") + + if max_export_batch_size <= 0: + raise ValueError( + "max_export_batch_size must be a positive integer." + ) + + if max_export_batch_size > max_queue_size: + raise ValueError( + "max_export_batch_size must be less than or equal to max_queue_size." + ) + self._exporter = exporter + self._max_queue_size = max_queue_size self._schedule_delay_millis = schedule_delay_millis self._max_export_batch_size = max_export_batch_size self._export_timeout_millis = export_timeout_millis - self._queue = collections.deque() # type: Deque[LogData] + self._queue = collections.deque( + [], max_queue_size + ) # type: Deque[LogData] self._worker_thread = threading.Thread( name="OtelBatchLogRecordProcessor", target=self.worker, diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables.py b/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables.py index 3881994326..0d90270a53 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables.py @@ -66,11 +66,43 @@ i.e. the SDK behaves as if OTEL_TRACES_SAMPLER_ARG is not set. """ +OTEL_BLRP_SCHEDULE_DELAY = "OTEL_BLRP_SCHEDULE_DELAY" +""" +.. envvar:: OTEL_BLRP_SCHEDULE_DELAY + +The :envvar:`OTEL_BLRP_SCHEDULE_DELAY` represents the delay interval between two consecutive exports of the BatchLogRecordProcessor. +Default: 5000 +""" + +OTEL_BLRP_EXPORT_TIMEOUT = "OTEL_BLRP_EXPORT_TIMEOUT" +""" +.. envvar:: OTEL_BLRP_EXPORT_TIMEOUT + +The :envvar:`OTEL_BLRP_EXPORT_TIMEOUT` represents the maximum allowed time to export data from the BatchLogRecordProcessor. +Default: 30000 +""" + +OTEL_BLRP_MAX_QUEUE_SIZE = "OTEL_BLRP_MAX_QUEUE_SIZE" +""" +.. envvar:: OTEL_BLRP_MAX_QUEUE_SIZE + +The :envvar:`OTEL_BLRP_MAX_QUEUE_SIZE` represents the maximum queue size for the data export of the BatchLogRecordProcessor. +Default: 2048 +""" + +OTEL_BLRP_MAX_EXPORT_BATCH_SIZE = "OTEL_BLRP_MAX_EXPORT_BATCH_SIZE" +""" +.. envvar:: OTEL_BLRP_MAX_EXPORT_BATCH_SIZE + +The :envvar:`OTEL_BLRP_MAX_EXPORT_BATCH_SIZE` represents the maximum batch size for the data export of the BatchLogRecordProcessor. +Default: 512 +""" + OTEL_BSP_SCHEDULE_DELAY = "OTEL_BSP_SCHEDULE_DELAY" """ .. envvar:: OTEL_BSP_SCHEDULE_DELAY -The :envvar:`OTEL_BSP_SCHEDULE_DELAY` represents the delay interval between two consecutive exports. +The :envvar:`OTEL_BSP_SCHEDULE_DELAY` represents the delay interval between two consecutive exports of the BatchSpanProcessor. Default: 5000 """ @@ -78,7 +110,7 @@ """ .. envvar:: OTEL_BSP_EXPORT_TIMEOUT -The :envvar:`OTEL_BSP_EXPORT_TIMEOUT` represents the maximum allowed time to export data. +The :envvar:`OTEL_BSP_EXPORT_TIMEOUT` represents the maximum allowed time to export data from the BatchSpanProcessor. Default: 30000 """ @@ -86,7 +118,7 @@ """ .. envvar:: OTEL_BSP_MAX_QUEUE_SIZE -The :envvar:`OTEL_BSP_MAX_QUEUE_SIZE` represents the maximum queue size for the data export. +The :envvar:`OTEL_BSP_MAX_QUEUE_SIZE` represents the maximum queue size for the data export of the BatchSpanProcessor. Default: 2048 """ @@ -94,7 +126,7 @@ """ .. envvar:: OTEL_BSP_MAX_EXPORT_BATCH_SIZE -The :envvar:`OTEL_BSP_MAX_EXPORT_BATCH_SIZE` represents the maximum batch size for the data export. +The :envvar:`OTEL_BSP_MAX_EXPORT_BATCH_SIZE` represents the maximum batch size for the data export of the BatchSpanProcessor. Default: 512 """ diff --git a/opentelemetry-sdk/tests/logs/test_export.py b/opentelemetry-sdk/tests/logs/test_export.py index 6a6b1d5bf8..09a328b5f2 100644 --- a/opentelemetry-sdk/tests/logs/test_export.py +++ b/opentelemetry-sdk/tests/logs/test_export.py @@ -35,6 +35,12 @@ InMemoryLogExporter, SimpleLogRecordProcessor, ) +from opentelemetry.sdk.environment_variables import ( + OTEL_BLRP_EXPORT_TIMEOUT, + OTEL_BLRP_MAX_EXPORT_BATCH_SIZE, + OTEL_BLRP_MAX_QUEUE_SIZE, + OTEL_BLRP_SCHEDULE_DELAY, +) from opentelemetry.sdk.resources import Resource as SDKResource from opentelemetry.sdk.util.instrumentation import InstrumentationScope from opentelemetry.test.concurrency_test import ConcurrencyTestBase @@ -175,6 +181,109 @@ def test_emit_call_log_record(self): logger.error("error") self.assertEqual(log_record_processor.emit.call_count, 1) + def test_args(self): + exporter = InMemoryLogExporter() + log_record_processor = BatchLogRecordProcessor( + exporter, + max_queue_size=1024, + schedule_delay_millis=2500, + max_export_batch_size=256, + export_timeout_millis=15000, + ) + self.assertEqual(log_record_processor._exporter, exporter) + self.assertEqual(log_record_processor._max_queue_size, 1024) + self.assertEqual(log_record_processor._schedule_delay_millis, 2500) + self.assertEqual(log_record_processor._max_export_batch_size, 256) + self.assertEqual(log_record_processor._export_timeout_millis, 15000) + + @patch.dict( + "os.environ", + { + OTEL_BLRP_MAX_QUEUE_SIZE: "1024", + OTEL_BLRP_SCHEDULE_DELAY: "2500", + OTEL_BLRP_MAX_EXPORT_BATCH_SIZE: "256", + OTEL_BLRP_EXPORT_TIMEOUT: "15000", + }, + ) + def test_env_vars(self): + exporter = InMemoryLogExporter() + log_record_processor = BatchLogRecordProcessor(exporter) + self.assertEqual(log_record_processor._exporter, exporter) + self.assertEqual(log_record_processor._max_queue_size, 1024) + self.assertEqual(log_record_processor._schedule_delay_millis, 2500) + self.assertEqual(log_record_processor._max_export_batch_size, 256) + self.assertEqual(log_record_processor._export_timeout_millis, 15000) + + def test_args_defaults(self): + exporter = InMemoryLogExporter() + log_record_processor = BatchLogRecordProcessor(exporter) + self.assertEqual(log_record_processor._exporter, exporter) + self.assertEqual(log_record_processor._max_queue_size, 2048) + self.assertEqual(log_record_processor._schedule_delay_millis, 5000) + self.assertEqual(log_record_processor._max_export_batch_size, 512) + self.assertEqual(log_record_processor._export_timeout_millis, 30000) + + def test_args_none_defaults(self): + exporter = InMemoryLogExporter() + log_record_processor = BatchLogRecordProcessor( + exporter, + max_queue_size=None, + schedule_delay_millis=None, + max_export_batch_size=None, + export_timeout_millis=None, + ) + self.assertEqual(log_record_processor._exporter, exporter) + self.assertEqual(log_record_processor._max_queue_size, 2048) + self.assertEqual(log_record_processor._schedule_delay_millis, 5000) + self.assertEqual(log_record_processor._max_export_batch_size, 512) + self.assertEqual(log_record_processor._export_timeout_millis, 30000) + + def test_validation_negative_max_queue_size(self): + exporter = InMemoryLogExporter() + self.assertRaises( + ValueError, + BatchLogRecordProcessor, + exporter, + max_queue_size=0, + ) + self.assertRaises( + ValueError, + BatchLogRecordProcessor, + exporter, + max_queue_size=-1, + ) + self.assertRaises( + ValueError, + BatchLogRecordProcessor, + exporter, + schedule_delay_millis=0, + ) + self.assertRaises( + ValueError, + BatchLogRecordProcessor, + exporter, + schedule_delay_millis=-1, + ) + self.assertRaises( + ValueError, + BatchLogRecordProcessor, + exporter, + max_export_batch_size=0, + ) + self.assertRaises( + ValueError, + BatchLogRecordProcessor, + exporter, + max_export_batch_size=-1, + ) + self.assertRaises( + ValueError, + BatchLogRecordProcessor, + exporter, + max_queue_size=100, + max_export_batch_size=101, + ) + def test_shutdown(self): exporter = InMemoryLogExporter() log_record_processor = BatchLogRecordProcessor(exporter) From 0591db03019d437af425ff350671e7e011a4c8b4 Mon Sep 17 00:00:00 2001 From: jerevoss Date: Tue, 28 Mar 2023 17:44:30 -0700 Subject: [PATCH 2/4] feedback: changelog, value error handling --- CHANGELOG.md | 5 +- .../sdk/_logs/_internal/export/__init__.py | 91 ++++++++++++++++--- .../sdk/trace/export/__init__.py | 79 ++++++++++++++-- opentelemetry-sdk/tests/logs/test_export.py | 18 ++++ .../tests/trace/export/test_export.py | 33 ++++++- 5 files changed, 198 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2834af9cfe..279185dafa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix suppress instrumentation for log batch processor ([#3223](https://github.com/open-telemetry/opentelemetry-python/pull/3223)) +- Add speced out environment variables and arguments for BatchLogRecordProcessor + ([#3237](https://github.com/open-telemetry/opentelemetry-python/pull/3237)) + ## Version 1.17.0/0.38b0 (2023-03-22) - Implement LowMemory temporality @@ -30,8 +33,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#2964](https://github.com/open-telemetry/opentelemetry-python/pull/2964)) - Add OpenCensus trace bridge/shim ([#3210](https://github.com/open-telemetry/opentelemetry-python/pull/3210)) -- Add speced out environment variables and arguments for BatchLogRecordProcessor - ([#3237](https://github.com/open-telemetry/opentelemetry-python/pull/3237)) ## Version 1.16.0/0.37b0 (2023-02-17) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py index ab016d8779..02cf1b50d2 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py @@ -38,6 +38,14 @@ ) from opentelemetry.util._once import Once +_DEFAULT_SCHEDULE_DELAY_MILLIS = 5000 +_DEFAULT_MAX_EXPORT_BATCH_SIZE = 512 +_DEFAULT_EXPORT_TIMEOUT_MILLIS = 30000 +_DEFAULT_MAX_QUEUE_SIZE = 2048 +_ENV_VAR_INT_VALUE_ERROR_MESSAGE = ( + "Unable to parse value for %s as integer. Defaulting to %s: %s" +) + _logger = logging.getLogger(__name__) @@ -161,28 +169,81 @@ class BatchLogRecordProcessor(LogRecordProcessor): def __init__( self, exporter: LogExporter, - max_queue_size: int = None, - schedule_delay_millis: int = None, + schedule_delay_millis: float = None, max_export_batch_size: int = None, - export_timeout_millis: int = None, + export_timeout_millis: float = None, + max_queue_size: int = None, ): - if max_queue_size is None: - max_queue_size = int(environ.get(OTEL_BLRP_MAX_QUEUE_SIZE, 2048)) - if schedule_delay_millis is None: - schedule_delay_millis = int( - environ.get(OTEL_BLRP_SCHEDULE_DELAY, 5000) - ) + try: + schedule_delay_millis = int( + environ.get( + OTEL_BLRP_SCHEDULE_DELAY, + _DEFAULT_SCHEDULE_DELAY_MILLIS, + ) + ) + except ValueError as e: + schedule_delay_millis = _DEFAULT_SCHEDULE_DELAY_MILLIS + _logger.warning( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE + % ( + OTEL_BLRP_SCHEDULE_DELAY, + _DEFAULT_SCHEDULE_DELAY_MILLIS, + e, + ) + ) if max_export_batch_size is None: - max_export_batch_size = int( - environ.get(OTEL_BLRP_MAX_EXPORT_BATCH_SIZE, 512) - ) + try: + max_export_batch_size = int( + environ.get( + OTEL_BLRP_MAX_EXPORT_BATCH_SIZE, + _DEFAULT_MAX_EXPORT_BATCH_SIZE, + ) + ) + except ValueError as e: + max_export_batch_size = _DEFAULT_MAX_EXPORT_BATCH_SIZE + _logger.warning( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE + % ( + OTEL_BLRP_SCHEDULE_DELAY, + _DEFAULT_MAX_EXPORT_BATCH_SIZE, + e, + ) + ) if export_timeout_millis is None: - export_timeout_millis = int( - environ.get(OTEL_BLRP_EXPORT_TIMEOUT, 30000) - ) + try: + export_timeout_millis = int( + environ.get( + OTEL_BLRP_EXPORT_TIMEOUT, + _DEFAULT_EXPORT_TIMEOUT_MILLIS, + ) + ) + except ValueError as e: + export_timeout_millis = _DEFAULT_EXPORT_TIMEOUT_MILLIS + _logger.warning( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE + % ( + OTEL_BLRP_SCHEDULE_DELAY, + _DEFAULT_EXPORT_TIMEOUT_MILLIS, + e, + ) + ) + + if max_queue_size is None: + try: + max_queue_size = int( + environ.get( + OTEL_BLRP_MAX_QUEUE_SIZE, _DEFAULT_MAX_QUEUE_SIZE + ) + ) + except ValueError as e: + max_queue_size = _DEFAULT_MAX_QUEUE_SIZE + _logger.warning( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE + % (OTEL_BLRP_SCHEDULE_DELAY, _DEFAULT_MAX_QUEUE_SIZE, e) + ) if max_queue_size <= 0: raise ValueError("max_queue_size must be a positive integer.") diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py index ef04895819..67999237a8 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py @@ -39,6 +39,14 @@ from opentelemetry.sdk.trace import ReadableSpan, Span, SpanProcessor from opentelemetry.util._once import Once +_DEFAULT_SCHEDULE_DELAY_MILLIS = 5000 +_DEFAULT_MAX_EXPORT_BATCH_SIZE = 512 +_DEFAULT_EXPORT_TIMEOUT_MILLIS = 30000 +_DEFAULT_MAX_QUEUE_SIZE = 2048 +_ENV_VAR_INT_VALUE_ERROR_MESSAGE = ( + "Unable to parse value for %s as integer. Defaulting to %s: %s" +) + logger = logging.getLogger(__name__) @@ -154,22 +162,73 @@ def __init__( ): if max_queue_size is None: - max_queue_size = int(environ.get(OTEL_BSP_MAX_QUEUE_SIZE, 2048)) + try: + max_queue_size = int( + environ.get( + OTEL_BSP_MAX_QUEUE_SIZE, _DEFAULT_MAX_QUEUE_SIZE + ) + ) + except ValueError as e: + max_queue_size = _DEFAULT_MAX_QUEUE_SIZE + logger.warning( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE + % (OTEL_BSP_MAX_QUEUE_SIZE, _DEFAULT_MAX_QUEUE_SIZE, e) + ) if schedule_delay_millis is None: - schedule_delay_millis = int( - environ.get(OTEL_BSP_SCHEDULE_DELAY, 5000) - ) + try: + schedule_delay_millis = int( + environ.get( + OTEL_BSP_SCHEDULE_DELAY, _DEFAULT_SCHEDULE_DELAY_MILLIS + ) + ) + except ValueError as e: + schedule_delay_millis = _DEFAULT_SCHEDULE_DELAY_MILLIS + logger.warning( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE + % ( + OTEL_BSP_SCHEDULE_DELAY, + _DEFAULT_SCHEDULE_DELAY_MILLIS, + e, + ) + ) if max_export_batch_size is None: - max_export_batch_size = int( - environ.get(OTEL_BSP_MAX_EXPORT_BATCH_SIZE, 512) - ) + try: + max_export_batch_size = int( + environ.get( + OTEL_BSP_MAX_EXPORT_BATCH_SIZE, + _DEFAULT_MAX_EXPORT_BATCH_SIZE, + ) + ) + except ValueError as e: + max_export_batch_size = _DEFAULT_MAX_EXPORT_BATCH_SIZE + logger.warning( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE + % ( + OTEL_BSP_MAX_EXPORT_BATCH_SIZE, + _DEFAULT_MAX_EXPORT_BATCH_SIZE, + e, + ) + ) if export_timeout_millis is None: - export_timeout_millis = int( - environ.get(OTEL_BSP_EXPORT_TIMEOUT, 30000) - ) + try: + export_timeout_millis = int( + environ.get( + OTEL_BSP_EXPORT_TIMEOUT, _DEFAULT_EXPORT_TIMEOUT_MILLIS + ) + ) + except ValueError as e: + export_timeout_millis = _DEFAULT_EXPORT_TIMEOUT_MILLIS + logger.warning( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE + % ( + OTEL_BSP_EXPORT_TIMEOUT, + _DEFAULT_EXPORT_TIMEOUT_MILLIS, + e, + ) + ) if max_queue_size <= 0: raise ValueError("max_queue_size must be a positive integer.") diff --git a/opentelemetry-sdk/tests/logs/test_export.py b/opentelemetry-sdk/tests/logs/test_export.py index 09a328b5f2..aa68b09624 100644 --- a/opentelemetry-sdk/tests/logs/test_export.py +++ b/opentelemetry-sdk/tests/logs/test_export.py @@ -223,6 +223,24 @@ def test_args_defaults(self): self.assertEqual(log_record_processor._max_export_batch_size, 512) self.assertEqual(log_record_processor._export_timeout_millis, 30000) + @patch.dict( + "os.environ", + { + OTEL_BLRP_MAX_QUEUE_SIZE: "a", + OTEL_BLRP_SCHEDULE_DELAY: " ", + OTEL_BLRP_MAX_EXPORT_BATCH_SIZE: "One", + OTEL_BLRP_EXPORT_TIMEOUT: "@", + }, + ) + def test_args_env_var_value_error(self): + exporter = InMemoryLogExporter() + log_record_processor = BatchLogRecordProcessor(exporter) + self.assertEqual(log_record_processor._exporter, exporter) + self.assertEqual(log_record_processor._max_queue_size, 2048) + self.assertEqual(log_record_processor._schedule_delay_millis, 5000) + self.assertEqual(log_record_processor._max_export_batch_size, 512) + self.assertEqual(log_record_processor._export_timeout_millis, 30000) + def test_args_none_defaults(self): exporter = InMemoryLogExporter() log_record_processor = BatchLogRecordProcessor( diff --git a/opentelemetry-sdk/tests/trace/export/test_export.py b/opentelemetry-sdk/tests/trace/export/test_export.py index 422945798f..cb7739f328 100644 --- a/opentelemetry-sdk/tests/trace/export/test_export.py +++ b/opentelemetry-sdk/tests/trace/export/test_export.py @@ -175,7 +175,7 @@ class TestBatchSpanProcessor(ConcurrencyTestBase): OTEL_BSP_EXPORT_TIMEOUT: "4", }, ) - def test_batch_span_processor_environment_variables(self): + def test_args_env_var(self): batch_span_processor = export.BatchSpanProcessor( MySpanExporter(destination=[]) @@ -186,6 +186,37 @@ def test_batch_span_processor_environment_variables(self): self.assertEqual(batch_span_processor.max_export_batch_size, 3) self.assertEqual(batch_span_processor.export_timeout_millis, 4) + def test_args_env_var_defaults(self): + + batch_span_processor = export.BatchSpanProcessor( + MySpanExporter(destination=[]) + ) + + self.assertEqual(batch_span_processor.max_queue_size, 2048) + self.assertEqual(batch_span_processor.schedule_delay_millis, 5000) + self.assertEqual(batch_span_processor.max_export_batch_size, 512) + self.assertEqual(batch_span_processor.export_timeout_millis, 30000) + + @mock.patch.dict( + "os.environ", + { + OTEL_BSP_MAX_QUEUE_SIZE: "a", + OTEL_BSP_SCHEDULE_DELAY: " ", + OTEL_BSP_MAX_EXPORT_BATCH_SIZE: "One", + OTEL_BSP_EXPORT_TIMEOUT: "@", + }, + ) + def test_args_env_var_value_error(self): + + batch_span_processor = export.BatchSpanProcessor( + MySpanExporter(destination=[]) + ) + + self.assertEqual(batch_span_processor.max_queue_size, 2048) + self.assertEqual(batch_span_processor.schedule_delay_millis, 5000) + self.assertEqual(batch_span_processor.max_export_batch_size, 512) + self.assertEqual(batch_span_processor.export_timeout_millis, 30000) + def test_on_start_accepts_parent_context(self): # pylint: disable=no-self-use my_exporter = MySpanExporter(destination=[]) From c2c06b370a11fc9ee0cce006e6f82e22f40dc4d6 Mon Sep 17 00:00:00 2001 From: jerevoss Date: Thu, 30 Mar 2023 14:04:58 -0700 Subject: [PATCH 3/4] Replaced warnings with exception and replaced "lazy logging" --- CHANGELOG.md | 2 - .../sdk/_logs/_internal/export/__init__.py | 50 ++++++++----------- .../sdk/trace/export/__init__.py | 50 ++++++++----------- 3 files changed, 42 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 279185dafa..18b06465df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,12 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - Fix exporting of ExponentialBucketHistogramAggregation from opentelemetry.sdk.metrics.view ([#3240](https://github.com/open-telemetry/opentelemetry-python/pull/3240)) - - Fix headers types mismatch for OTLP Exporters ([#3226](https://github.com/open-telemetry/opentelemetry-python/pull/3226)) - Fix suppress instrumentation for log batch processor ([#3223](https://github.com/open-telemetry/opentelemetry-python/pull/3223)) - - Add speced out environment variables and arguments for BatchLogRecordProcessor ([#3237](https://github.com/open-telemetry/opentelemetry-python/pull/3237)) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py index 02cf1b50d2..4abf32f7b5 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py @@ -43,7 +43,7 @@ _DEFAULT_EXPORT_TIMEOUT_MILLIS = 30000 _DEFAULT_MAX_QUEUE_SIZE = 2048 _ENV_VAR_INT_VALUE_ERROR_MESSAGE = ( - "Unable to parse value for %s as integer. Defaulting to %s: %s" + "Unable to parse value for %s as integer. Defaulting to %s." ) _logger = logging.getLogger(__name__) @@ -182,15 +182,12 @@ def __init__( _DEFAULT_SCHEDULE_DELAY_MILLIS, ) ) - except ValueError as e: + except ValueError: schedule_delay_millis = _DEFAULT_SCHEDULE_DELAY_MILLIS - _logger.warning( - _ENV_VAR_INT_VALUE_ERROR_MESSAGE - % ( - OTEL_BLRP_SCHEDULE_DELAY, - _DEFAULT_SCHEDULE_DELAY_MILLIS, - e, - ) + _logger.exception( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE, + OTEL_BLRP_SCHEDULE_DELAY, + _DEFAULT_SCHEDULE_DELAY_MILLIS, ) if max_export_batch_size is None: @@ -201,15 +198,12 @@ def __init__( _DEFAULT_MAX_EXPORT_BATCH_SIZE, ) ) - except ValueError as e: + except ValueError: max_export_batch_size = _DEFAULT_MAX_EXPORT_BATCH_SIZE - _logger.warning( - _ENV_VAR_INT_VALUE_ERROR_MESSAGE - % ( - OTEL_BLRP_SCHEDULE_DELAY, - _DEFAULT_MAX_EXPORT_BATCH_SIZE, - e, - ) + _logger.exception( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE, + OTEL_BLRP_SCHEDULE_DELAY, + _DEFAULT_MAX_EXPORT_BATCH_SIZE, ) if export_timeout_millis is None: @@ -220,15 +214,12 @@ def __init__( _DEFAULT_EXPORT_TIMEOUT_MILLIS, ) ) - except ValueError as e: + except ValueError: export_timeout_millis = _DEFAULT_EXPORT_TIMEOUT_MILLIS - _logger.warning( - _ENV_VAR_INT_VALUE_ERROR_MESSAGE - % ( - OTEL_BLRP_SCHEDULE_DELAY, - _DEFAULT_EXPORT_TIMEOUT_MILLIS, - e, - ) + _logger.exception( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE, + OTEL_BLRP_SCHEDULE_DELAY, + _DEFAULT_EXPORT_TIMEOUT_MILLIS, ) if max_queue_size is None: @@ -238,11 +229,12 @@ def __init__( OTEL_BLRP_MAX_QUEUE_SIZE, _DEFAULT_MAX_QUEUE_SIZE ) ) - except ValueError as e: + except ValueError: max_queue_size = _DEFAULT_MAX_QUEUE_SIZE - _logger.warning( - _ENV_VAR_INT_VALUE_ERROR_MESSAGE - % (OTEL_BLRP_SCHEDULE_DELAY, _DEFAULT_MAX_QUEUE_SIZE, e) + _logger.exception( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE, + OTEL_BLRP_SCHEDULE_DELAY, + _DEFAULT_MAX_QUEUE_SIZE, ) if max_queue_size <= 0: diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py index 67999237a8..28252a7d0e 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py @@ -44,7 +44,7 @@ _DEFAULT_EXPORT_TIMEOUT_MILLIS = 30000 _DEFAULT_MAX_QUEUE_SIZE = 2048 _ENV_VAR_INT_VALUE_ERROR_MESSAGE = ( - "Unable to parse value for %s as integer. Defaulting to %s: %s" + "Unable to parse value for %s as integer. Defaulting to %s." ) logger = logging.getLogger(__name__) @@ -168,11 +168,12 @@ def __init__( OTEL_BSP_MAX_QUEUE_SIZE, _DEFAULT_MAX_QUEUE_SIZE ) ) - except ValueError as e: + except ValueError: max_queue_size = _DEFAULT_MAX_QUEUE_SIZE - logger.warning( - _ENV_VAR_INT_VALUE_ERROR_MESSAGE - % (OTEL_BSP_MAX_QUEUE_SIZE, _DEFAULT_MAX_QUEUE_SIZE, e) + logger.exception( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE, + OTEL_BSP_MAX_QUEUE_SIZE, + _DEFAULT_MAX_QUEUE_SIZE, ) if schedule_delay_millis is None: @@ -182,15 +183,12 @@ def __init__( OTEL_BSP_SCHEDULE_DELAY, _DEFAULT_SCHEDULE_DELAY_MILLIS ) ) - except ValueError as e: + except ValueError: schedule_delay_millis = _DEFAULT_SCHEDULE_DELAY_MILLIS - logger.warning( - _ENV_VAR_INT_VALUE_ERROR_MESSAGE - % ( - OTEL_BSP_SCHEDULE_DELAY, - _DEFAULT_SCHEDULE_DELAY_MILLIS, - e, - ) + logger.exception( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE, + OTEL_BSP_SCHEDULE_DELAY, + _DEFAULT_SCHEDULE_DELAY_MILLIS, ) if max_export_batch_size is None: @@ -201,15 +199,12 @@ def __init__( _DEFAULT_MAX_EXPORT_BATCH_SIZE, ) ) - except ValueError as e: + except ValueError: max_export_batch_size = _DEFAULT_MAX_EXPORT_BATCH_SIZE - logger.warning( - _ENV_VAR_INT_VALUE_ERROR_MESSAGE - % ( - OTEL_BSP_MAX_EXPORT_BATCH_SIZE, - _DEFAULT_MAX_EXPORT_BATCH_SIZE, - e, - ) + logger.exception( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE, + OTEL_BSP_MAX_EXPORT_BATCH_SIZE, + _DEFAULT_MAX_EXPORT_BATCH_SIZE, ) if export_timeout_millis is None: @@ -219,15 +214,12 @@ def __init__( OTEL_BSP_EXPORT_TIMEOUT, _DEFAULT_EXPORT_TIMEOUT_MILLIS ) ) - except ValueError as e: + except ValueError: export_timeout_millis = _DEFAULT_EXPORT_TIMEOUT_MILLIS - logger.warning( - _ENV_VAR_INT_VALUE_ERROR_MESSAGE - % ( - OTEL_BSP_EXPORT_TIMEOUT, - _DEFAULT_EXPORT_TIMEOUT_MILLIS, - e, - ) + logger.exception( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE, + OTEL_BSP_EXPORT_TIMEOUT, + _DEFAULT_EXPORT_TIMEOUT_MILLIS, ) if max_queue_size <= 0: From bd2e0981715723c3191dd5c9dd9bf0c68b24accd Mon Sep 17 00:00:00 2001 From: jerevoss Date: Thu, 30 Mar 2023 16:30:25 -0700 Subject: [PATCH 4/4] Factored out defaulting and validation --- .../sdk/_logs/_internal/export/__init__.py | 168 ++++++++++-------- .../sdk/trace/export/__init__.py | 163 ++++++++++------- 2 files changed, 192 insertions(+), 139 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py index 4abf32f7b5..4903873432 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py @@ -174,84 +174,27 @@ def __init__( export_timeout_millis: float = None, max_queue_size: int = None, ): + if max_queue_size is None: + max_queue_size = BatchLogRecordProcessor._default_max_queue_size() + if schedule_delay_millis is None: - try: - schedule_delay_millis = int( - environ.get( - OTEL_BLRP_SCHEDULE_DELAY, - _DEFAULT_SCHEDULE_DELAY_MILLIS, - ) - ) - except ValueError: - schedule_delay_millis = _DEFAULT_SCHEDULE_DELAY_MILLIS - _logger.exception( - _ENV_VAR_INT_VALUE_ERROR_MESSAGE, - OTEL_BLRP_SCHEDULE_DELAY, - _DEFAULT_SCHEDULE_DELAY_MILLIS, - ) + schedule_delay_millis = ( + BatchLogRecordProcessor._default_schedule_delay_millis() + ) if max_export_batch_size is None: - try: - max_export_batch_size = int( - environ.get( - OTEL_BLRP_MAX_EXPORT_BATCH_SIZE, - _DEFAULT_MAX_EXPORT_BATCH_SIZE, - ) - ) - except ValueError: - max_export_batch_size = _DEFAULT_MAX_EXPORT_BATCH_SIZE - _logger.exception( - _ENV_VAR_INT_VALUE_ERROR_MESSAGE, - OTEL_BLRP_SCHEDULE_DELAY, - _DEFAULT_MAX_EXPORT_BATCH_SIZE, - ) + max_export_batch_size = ( + BatchLogRecordProcessor._default_max_export_batch_size() + ) if export_timeout_millis is None: - try: - export_timeout_millis = int( - environ.get( - OTEL_BLRP_EXPORT_TIMEOUT, - _DEFAULT_EXPORT_TIMEOUT_MILLIS, - ) - ) - except ValueError: - export_timeout_millis = _DEFAULT_EXPORT_TIMEOUT_MILLIS - _logger.exception( - _ENV_VAR_INT_VALUE_ERROR_MESSAGE, - OTEL_BLRP_SCHEDULE_DELAY, - _DEFAULT_EXPORT_TIMEOUT_MILLIS, - ) - - if max_queue_size is None: - try: - max_queue_size = int( - environ.get( - OTEL_BLRP_MAX_QUEUE_SIZE, _DEFAULT_MAX_QUEUE_SIZE - ) - ) - except ValueError: - max_queue_size = _DEFAULT_MAX_QUEUE_SIZE - _logger.exception( - _ENV_VAR_INT_VALUE_ERROR_MESSAGE, - OTEL_BLRP_SCHEDULE_DELAY, - _DEFAULT_MAX_QUEUE_SIZE, - ) - - if max_queue_size <= 0: - raise ValueError("max_queue_size must be a positive integer.") - - if schedule_delay_millis <= 0: - raise ValueError("schedule_delay_millis must be positive.") - - if max_export_batch_size <= 0: - raise ValueError( - "max_export_batch_size must be a positive integer." + export_timeout_millis = ( + BatchLogRecordProcessor._default_export_timeout_millis() ) - if max_export_batch_size > max_queue_size: - raise ValueError( - "max_export_batch_size must be less than or equal to max_queue_size." - ) + BatchLogRecordProcessor._validate_arguments( + max_queue_size, schedule_delay_millis, max_export_batch_size + ) self._exporter = exporter self._max_queue_size = max_queue_size @@ -438,3 +381,86 @@ def force_flush(self, timeout_millis: Optional[int] = None) -> bool: if not ret: _logger.warning("Timeout was exceeded in force_flush().") return ret + + @staticmethod + def _default_max_queue_size(): + try: + return int( + environ.get(OTEL_BLRP_MAX_QUEUE_SIZE, _DEFAULT_MAX_QUEUE_SIZE) + ) + except ValueError: + _logger.exception( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE, + OTEL_BLRP_MAX_QUEUE_SIZE, + _DEFAULT_MAX_QUEUE_SIZE, + ) + return _DEFAULT_MAX_QUEUE_SIZE + + @staticmethod + def _default_schedule_delay_millis(): + try: + return int( + environ.get( + OTEL_BLRP_SCHEDULE_DELAY, _DEFAULT_SCHEDULE_DELAY_MILLIS + ) + ) + except ValueError: + _logger.exception( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE, + OTEL_BLRP_SCHEDULE_DELAY, + _DEFAULT_SCHEDULE_DELAY_MILLIS, + ) + return _DEFAULT_SCHEDULE_DELAY_MILLIS + + @staticmethod + def _default_max_export_batch_size(): + try: + return int( + environ.get( + OTEL_BLRP_MAX_EXPORT_BATCH_SIZE, + _DEFAULT_MAX_EXPORT_BATCH_SIZE, + ) + ) + except ValueError: + _logger.exception( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE, + OTEL_BLRP_MAX_EXPORT_BATCH_SIZE, + _DEFAULT_MAX_EXPORT_BATCH_SIZE, + ) + return _DEFAULT_MAX_EXPORT_BATCH_SIZE + + @staticmethod + def _default_export_timeout_millis(): + try: + return int( + environ.get( + OTEL_BLRP_EXPORT_TIMEOUT, _DEFAULT_EXPORT_TIMEOUT_MILLIS + ) + ) + except ValueError: + _logger.exception( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE, + OTEL_BLRP_EXPORT_TIMEOUT, + _DEFAULT_EXPORT_TIMEOUT_MILLIS, + ) + return _DEFAULT_EXPORT_TIMEOUT_MILLIS + + @staticmethod + def _validate_arguments( + max_queue_size, schedule_delay_millis, max_export_batch_size + ): + if max_queue_size <= 0: + raise ValueError("max_queue_size must be a positive integer.") + + if schedule_delay_millis <= 0: + raise ValueError("schedule_delay_millis must be positive.") + + if max_export_batch_size <= 0: + raise ValueError( + "max_export_batch_size must be a positive integer." + ) + + if max_export_batch_size > max_queue_size: + raise ValueError( + "max_export_batch_size must be less than or equal to max_queue_size." + ) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py index 28252a7d0e..7f56a30172 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py @@ -160,83 +160,27 @@ def __init__( max_export_batch_size: int = None, export_timeout_millis: float = None, ): - if max_queue_size is None: - try: - max_queue_size = int( - environ.get( - OTEL_BSP_MAX_QUEUE_SIZE, _DEFAULT_MAX_QUEUE_SIZE - ) - ) - except ValueError: - max_queue_size = _DEFAULT_MAX_QUEUE_SIZE - logger.exception( - _ENV_VAR_INT_VALUE_ERROR_MESSAGE, - OTEL_BSP_MAX_QUEUE_SIZE, - _DEFAULT_MAX_QUEUE_SIZE, - ) + max_queue_size = BatchSpanProcessor._default_max_queue_size() if schedule_delay_millis is None: - try: - schedule_delay_millis = int( - environ.get( - OTEL_BSP_SCHEDULE_DELAY, _DEFAULT_SCHEDULE_DELAY_MILLIS - ) - ) - except ValueError: - schedule_delay_millis = _DEFAULT_SCHEDULE_DELAY_MILLIS - logger.exception( - _ENV_VAR_INT_VALUE_ERROR_MESSAGE, - OTEL_BSP_SCHEDULE_DELAY, - _DEFAULT_SCHEDULE_DELAY_MILLIS, - ) + schedule_delay_millis = ( + BatchSpanProcessor._default_schedule_delay_millis() + ) if max_export_batch_size is None: - try: - max_export_batch_size = int( - environ.get( - OTEL_BSP_MAX_EXPORT_BATCH_SIZE, - _DEFAULT_MAX_EXPORT_BATCH_SIZE, - ) - ) - except ValueError: - max_export_batch_size = _DEFAULT_MAX_EXPORT_BATCH_SIZE - logger.exception( - _ENV_VAR_INT_VALUE_ERROR_MESSAGE, - OTEL_BSP_MAX_EXPORT_BATCH_SIZE, - _DEFAULT_MAX_EXPORT_BATCH_SIZE, - ) + max_export_batch_size = ( + BatchSpanProcessor._default_max_export_batch_size() + ) if export_timeout_millis is None: - try: - export_timeout_millis = int( - environ.get( - OTEL_BSP_EXPORT_TIMEOUT, _DEFAULT_EXPORT_TIMEOUT_MILLIS - ) - ) - except ValueError: - export_timeout_millis = _DEFAULT_EXPORT_TIMEOUT_MILLIS - logger.exception( - _ENV_VAR_INT_VALUE_ERROR_MESSAGE, - OTEL_BSP_EXPORT_TIMEOUT, - _DEFAULT_EXPORT_TIMEOUT_MILLIS, - ) - - if max_queue_size <= 0: - raise ValueError("max_queue_size must be a positive integer.") - - if schedule_delay_millis <= 0: - raise ValueError("schedule_delay_millis must be positive.") - - if max_export_batch_size <= 0: - raise ValueError( - "max_export_batch_size must be a positive integer." + export_timeout_millis = ( + BatchSpanProcessor._default_export_timeout_millis() ) - if max_export_batch_size > max_queue_size: - raise ValueError( - "max_export_batch_size must be less than or equal to max_queue_size." - ) + BatchSpanProcessor._validate_arguments( + max_queue_size, schedule_delay_millis, max_export_batch_size + ) self.span_exporter = span_exporter self.queue = collections.deque( @@ -468,6 +412,89 @@ def shutdown(self) -> None: self.worker_thread.join() self.span_exporter.shutdown() + @staticmethod + def _default_max_queue_size(): + try: + return int( + environ.get(OTEL_BSP_MAX_QUEUE_SIZE, _DEFAULT_MAX_QUEUE_SIZE) + ) + except ValueError: + logger.exception( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE, + OTEL_BSP_MAX_QUEUE_SIZE, + _DEFAULT_MAX_QUEUE_SIZE, + ) + return _DEFAULT_MAX_QUEUE_SIZE + + @staticmethod + def _default_schedule_delay_millis(): + try: + return int( + environ.get( + OTEL_BSP_SCHEDULE_DELAY, _DEFAULT_SCHEDULE_DELAY_MILLIS + ) + ) + except ValueError: + logger.exception( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE, + OTEL_BSP_SCHEDULE_DELAY, + _DEFAULT_SCHEDULE_DELAY_MILLIS, + ) + return _DEFAULT_SCHEDULE_DELAY_MILLIS + + @staticmethod + def _default_max_export_batch_size(): + try: + return int( + environ.get( + OTEL_BSP_MAX_EXPORT_BATCH_SIZE, + _DEFAULT_MAX_EXPORT_BATCH_SIZE, + ) + ) + except ValueError: + logger.exception( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE, + OTEL_BSP_MAX_EXPORT_BATCH_SIZE, + _DEFAULT_MAX_EXPORT_BATCH_SIZE, + ) + return _DEFAULT_MAX_EXPORT_BATCH_SIZE + + @staticmethod + def _default_export_timeout_millis(): + try: + return int( + environ.get( + OTEL_BSP_EXPORT_TIMEOUT, _DEFAULT_EXPORT_TIMEOUT_MILLIS + ) + ) + except ValueError: + logger.exception( + _ENV_VAR_INT_VALUE_ERROR_MESSAGE, + OTEL_BSP_EXPORT_TIMEOUT, + _DEFAULT_EXPORT_TIMEOUT_MILLIS, + ) + return _DEFAULT_EXPORT_TIMEOUT_MILLIS + + @staticmethod + def _validate_arguments( + max_queue_size, schedule_delay_millis, max_export_batch_size + ): + if max_queue_size <= 0: + raise ValueError("max_queue_size must be a positive integer.") + + if schedule_delay_millis <= 0: + raise ValueError("schedule_delay_millis must be positive.") + + if max_export_batch_size <= 0: + raise ValueError( + "max_export_batch_size must be a positive integer." + ) + + if max_export_batch_size > max_queue_size: + raise ValueError( + "max_export_batch_size must be less than or equal to max_queue_size." + ) + class ConsoleSpanExporter(SpanExporter): """Implementation of :class:`SpanExporter` that prints spans to the