From d9efda9179bcee3717e81044efe52f3e37acf7ae Mon Sep 17 00:00:00 2001 From: Lukas Hering Date: Sun, 26 Apr 2026 23:18:39 -0400 Subject: [PATCH 01/10] feat: Add ability to selectively enable exporting of SDK internal metrics with the OTEL_PYTHON_SDK_METRIC_ENABLE environment variable --- CHANGELOG.md | 2 + .../otlp/proto/common/_exporter_metrics.py | 7 ++ .../exporter/otlp/proto/grpc/exporter.py | 7 ++ .../tests/test_otlp_exporter_mixin.py | 18 ++++- .../otlp/proto/http/_log_exporter/__init__.py | 7 ++ .../proto/http/metric_exporter/__init__.py | 10 +++ .../proto/http/trace_exporter/__init__.py | 7 ++ .../metrics/test_otlp_metrics_exporter.py | 4 + .../tests/test_proto_log_exporter.py | 3 + .../tests/test_proto_span_exporter.py | 14 ++++ .../sdk/_logs/_internal/_logger_metrics.py | 11 +++ .../_shared_internal/_processor_metrics.py | 19 ++++- .../sdk/environment_variables/__init__.py | 9 +++ .../sdk/environment_variables/_internal.py | 39 ++++++++++ .../export/_metric_reader_metrics.py | 11 +++ .../sdk/trace/_tracer_metrics.py | 14 ++++ opentelemetry-sdk/tests/logs/test_export.py | 3 + .../tests/logs/test_sdk_metrics.py | 18 +++++ .../test_periodic_exporting_metric_reader.py | 6 +- .../test_environment_variables_internal.py | 73 +++++++++++++++++++ .../tests/trace/export/test_export.py | 3 + .../tests/trace/test_sdk_metrics.py | 22 ++++++ 22 files changed, 301 insertions(+), 6 deletions(-) create mode 100644 opentelemetry-sdk/src/opentelemetry/sdk/environment_variables/_internal.py create mode 100644 opentelemetry-sdk/tests/test_environment_variables_internal.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 941551d8a99..ec90254901f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#5088](https://github.com/open-telemetry/opentelemetry-python/pull/5088)) - ci: wait for tracecontext server readiness instead of a fixed sleep in `scripts/tracecontext-integration-test.sh` ([#5149](https://github.com/open-telemetry/opentelemetry-python/pull/5149)) +- Add ability to selectively enable exporting of SDK internal metrics with the `OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED` environment variable. + ([#5151](https://github.com/open-telemetry/opentelemetry-python/pull/5151)) ## Version 1.41.0/0.62b0 (2026-04-09) diff --git a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_exporter_metrics.py b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_exporter_metrics.py index 96d12a8857d..55686a66e61 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_exporter_metrics.py +++ b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_exporter_metrics.py @@ -63,6 +63,8 @@ def __init__( signal: Literal["traces", "metrics", "logs"], endpoint: UrlParseResult, meter_provider: MeterProvider | None, + *, + disabled: bool = False, ) -> None: if signal == "traces": create_exported = create_otel_sdk_exporter_span_exported @@ -104,9 +106,14 @@ def __init__( self._inflight = create_inflight(meter) self._exported = create_exported(meter) self._duration = create_otel_sdk_exporter_operation_duration(meter) + self._disabled = disabled @contextmanager def export_operation(self, num_items: int) -> Iterator[ExportResult]: + if self._disabled: + yield ExportResult() + return + start_time = perf_counter() self._inflight.add(num_items, self._standard_attrs) diff --git a/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py b/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py index 3627db70581..971967a16de 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py +++ b/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py @@ -103,6 +103,10 @@ OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_INSECURE, OTEL_EXPORTER_OTLP_TIMEOUT, + OTEL_PYTHON_SDK_METRICS_ENABLED, +) +from opentelemetry.sdk.environment_variables._internal import ( + parse_boolean_environment_variable, ) from opentelemetry.sdk.metrics.export import MetricExportResult, MetricsData from opentelemetry.sdk.resources import Resource as SDKResource @@ -392,6 +396,9 @@ def __init__( signal, parsed_url, meter_provider, + disabled=not parse_boolean_environment_variable( + OTEL_PYTHON_SDK_METRICS_ENABLED + ), ) self._initialize_channel_and_stub() diff --git a/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_exporter_mixin.py b/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_exporter_mixin.py index 87bd72c5550..ab609bff152 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_exporter_mixin.py +++ b/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_exporter_mixin.py @@ -54,6 +54,7 @@ from opentelemetry.sdk.environment_variables import ( _OTEL_PYTHON_EXPORTER_OTLP_GRPC_CREDENTIAL_PROVIDER, OTEL_EXPORTER_OTLP_COMPRESSION, + OTEL_PYTHON_SDK_METRICS_ENABLED, ) from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import InMemoryMetricReader @@ -387,13 +388,17 @@ def test_otlp_exporter_otlp_compression_envvar( ), ) + @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) def test_shutdown(self): add_TraceServiceServicer_to_server( TraceServiceServicerWithExportParams(StatusCode.OK), self.server, ) + exporter = OTLPSpanExporterForTesting( + insecure=True, meter_provider=self.meter_provider + ) self.assertEqual( - self.exporter.export([self.span]), SpanExportResult.SUCCESS + exporter.export([self.span]), SpanExportResult.SUCCESS ) metrics_data = self.metric_reader.get_metrics_data() scope_metrics = metrics_data.resource_metrics[0].scope_metrics[0] @@ -415,10 +420,10 @@ def test_shutdown(self): metrics[2].data.data_points[0].attributes ) - self.exporter.shutdown() + exporter.shutdown() with self.assertLogs(level=WARNING) as warning: self.assertEqual( - self.exporter.export([self.span]), SpanExportResult.FAILURE + exporter.export([self.span]), SpanExportResult.FAILURE ) self.assertEqual( warning.records[0].message, @@ -480,6 +485,7 @@ def test_export_over_closed_grpc_channel(self): system() == "Windows", "For gRPC + windows there's some added delay in the RPCs which breaks the assertion over amount of time passed.", ) + @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) def test_retry_info_is_respected(self): mock_trace_service = TraceServiceServicerWithExportParams( StatusCode.UNAVAILABLE, @@ -622,7 +628,11 @@ def test_otlp_headers_from_env(self): (), ) + @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) def test_permanent_failure(self): + exporter = OTLPSpanExporterForTesting( + insecure=True, meter_provider=self.meter_provider + ) with self.assertLogs(level=WARNING) as warning: add_TraceServiceServicer_to_server( TraceServiceServicerWithExportParams( @@ -631,7 +641,7 @@ def test_permanent_failure(self): self.server, ) self.assertEqual( - self.exporter.export([self.span]), SpanExportResult.FAILURE + exporter.export([self.span]), SpanExportResult.FAILURE ) self.assertEqual( warning.records[-1].message, 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 6032433dd12..fb46ce36a38 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 @@ -61,6 +61,10 @@ OTEL_EXPORTER_OTLP_LOGS_HEADERS, OTEL_EXPORTER_OTLP_LOGS_TIMEOUT, OTEL_EXPORTER_OTLP_TIMEOUT, + OTEL_PYTHON_SDK_METRICS_ENABLED, +) +from opentelemetry.sdk.environment_variables._internal import ( + parse_boolean_environment_variable, ) from opentelemetry.semconv._incubating.attributes.otel_attributes import ( OtelComponentTypeValues, @@ -157,6 +161,9 @@ def __init__( "logs", urlparse(self._endpoint), meter_provider, + disabled=not parse_boolean_environment_variable( + OTEL_PYTHON_SDK_METRICS_ENABLED + ), ) def _export( diff --git a/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py index efd63b45438..5b45c34e1be 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py @@ -86,6 +86,10 @@ OTEL_EXPORTER_OTLP_METRICS_HEADERS, OTEL_EXPORTER_OTLP_METRICS_TIMEOUT, OTEL_EXPORTER_OTLP_TIMEOUT, + OTEL_PYTHON_SDK_METRICS_ENABLED, +) +from opentelemetry.sdk.environment_variables._internal import ( + parse_boolean_environment_variable, ) from opentelemetry.sdk.metrics._internal.aggregation import Aggregation from opentelemetry.sdk.metrics.export import ( # noqa: F401 @@ -222,6 +226,9 @@ def __init__( "metrics", urlparse(self._endpoint), meter_provider, + disabled=not parse_boolean_environment_variable( + OTEL_PYTHON_SDK_METRICS_ENABLED + ), ) def _export( @@ -404,6 +411,9 @@ def set_meter_provider(self, meter_provider: MeterProvider) -> None: "metrics", urlparse(self._endpoint), meter_provider, + disabled=not parse_boolean_environment_variable( + OTEL_PYTHON_SDK_METRICS_ENABLED + ), ) 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 018d89df1ee..cc0285f30ca 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 @@ -57,6 +57,10 @@ OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_HEADERS, OTEL_EXPORTER_OTLP_TRACES_TIMEOUT, + OTEL_PYTHON_SDK_METRICS_ENABLED, +) +from opentelemetry.sdk.environment_variables._internal import ( + parse_boolean_environment_variable, ) from opentelemetry.sdk.trace import ReadableSpan from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult @@ -152,6 +156,9 @@ def __init__( "traces", urlparse(self._endpoint), meter_provider, + disabled=not parse_boolean_environment_variable( + OTEL_PYTHON_SDK_METRICS_ENABLED + ), ) def _export( diff --git a/exporter/opentelemetry-exporter-otlp-proto-http/tests/metrics/test_otlp_metrics_exporter.py b/exporter/opentelemetry-exporter-otlp-proto-http/tests/metrics/test_otlp_metrics_exporter.py index 5f7ae2afa9b..aeda4504d45 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-http/tests/metrics/test_otlp_metrics_exporter.py +++ b/exporter/opentelemetry-exporter-otlp-proto-http/tests/metrics/test_otlp_metrics_exporter.py @@ -69,6 +69,7 @@ OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE, OTEL_EXPORTER_OTLP_METRICS_TIMEOUT, OTEL_EXPORTER_OTLP_TIMEOUT, + OTEL_PYTHON_SDK_METRICS_ENABLED, ) from opentelemetry.sdk.metrics import ( Counter, @@ -334,6 +335,7 @@ def test_headers_parse_from_env(self): ), ) + @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) @patch.object(Session, "post") def test_success(self, mock_post): resp = Response() @@ -372,6 +374,7 @@ def test_success(self, mock_post): metrics[2].data.data_points[0].attributes ) + @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) @patch.object(Session, "post") def test_failure(self, mock_post): resp = Response() @@ -1291,6 +1294,7 @@ def test_preferred_aggregation_override(self): exporter._preferred_aggregation[Histogram], histogram_aggregation ) + @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) @patch.object(Session, "post") def test_retry_timeout(self, mock_post): exporter = OTLPMetricExporter( 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 7981b0bc821..3929e9df826 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 @@ -58,6 +58,7 @@ OTEL_EXPORTER_OTLP_LOGS_HEADERS, OTEL_EXPORTER_OTLP_LOGS_TIMEOUT, OTEL_EXPORTER_OTLP_TIMEOUT, + OTEL_PYTHON_SDK_METRICS_ENABLED, ) from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import InMemoryMetricReader @@ -467,6 +468,7 @@ def test_2xx_status_code(self, mock_otlp_metric_exporter): LogRecordExportResult.SUCCESS, ) + @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) @patch.object(Session, "post") def test_retry_timeout(self, mock_post): exporter = OTLPLogExporter( @@ -555,6 +557,7 @@ def test_export_no_collector_available_retryable(self, mock_post): warning.records[0].message, ) + @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) @patch.object(Session, "post") def test_export_no_collector_available(self, mock_post): exporter = OTLPLogExporter( 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 0df471aa693..66e291a8b43 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 @@ -48,6 +48,7 @@ OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_HEADERS, OTEL_EXPORTER_OTLP_TRACES_TIMEOUT, + OTEL_PYTHON_SDK_METRICS_ENABLED, ) from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import InMemoryMetricReader @@ -287,6 +288,18 @@ def test_2xx_status_code(self, mock_otlp_metric_exporter): OTLPSpanExporter().export(MagicMock()), SpanExportResult.SUCCESS ) + @patch.dict("os.environ", {}, clear=True) + @patch.object(OTLPSpanExporter, "_export", return_value=Mock(ok=True)) + def test_exporter_metrics_disabled_by_default(self, _mock_export): + exporter = OTLPSpanExporter(meter_provider=self.meter_provider) + + self.assertEqual( + exporter.export([BASIC_SPAN]), SpanExportResult.SUCCESS + ) + + self.assertIsNone(self.metric_reader.get_metrics_data()) + + @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) @patch.object(Session, "post") def test_retry_timeout(self, mock_post): exporter = OTLPSpanExporter( @@ -375,6 +388,7 @@ def test_export_no_collector_available_retryable(self, mock_post): warning.records[0].message, ) + @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) @patch.object(Session, "post") def test_export_no_collector_available(self, mock_post): exporter = OTLPSpanExporter( diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/_logger_metrics.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/_logger_metrics.py index 92a4c76a450..339d77121cb 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/_logger_metrics.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/_logger_metrics.py @@ -13,6 +13,12 @@ # limitations under the License. from opentelemetry import metrics as metrics_api +from opentelemetry.sdk.environment_variables import ( + OTEL_PYTHON_SDK_METRICS_ENABLED, +) +from opentelemetry.sdk.environment_variables._internal import ( + parse_boolean_environment_variable, +) from opentelemetry.semconv._incubating.metrics.otel_metrics import ( create_otel_sdk_log_created, ) @@ -22,6 +28,11 @@ class LoggerMetrics: def __init__(self, meter_provider: metrics_api.MeterProvider) -> None: meter = meter_provider.get_meter("opentelemetry-sdk") self._created_logs = create_otel_sdk_log_created(meter) + self._enabled = parse_boolean_environment_variable( + OTEL_PYTHON_SDK_METRICS_ENABLED + ) def emit_log(self) -> None: + if not self._enabled: + return self._created_logs.add(1) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/_processor_metrics.py b/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/_processor_metrics.py index 47f90c28522..82faedac8a5 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/_processor_metrics.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/_processor_metrics.py @@ -19,6 +19,12 @@ from typing import Literal from opentelemetry.metrics import CallbackOptions, MeterProvider, Observation +from opentelemetry.sdk.environment_variables import ( + OTEL_PYTHON_SDK_METRICS_ENABLED, +) +from opentelemetry.sdk.environment_variables._internal import ( + parse_boolean_environment_variable, +) from opentelemetry.semconv._incubating.attributes.otel_attributes import ( OTEL_COMPONENT_NAME, OTEL_COMPONENT_TYPE, @@ -75,12 +81,19 @@ def __init__( ) self._processed = create_processed(meter) + self._enabled = parse_boolean_environment_variable( + OTEL_PYTHON_SDK_METRICS_ENABLED + ) if capacity is not None: self._queue_capacity = create_queue_capacity(meter) - self._queue_capacity.add(capacity, self._standard_attrs) + if self._enabled: + self._queue_capacity.add(capacity, self._standard_attrs) def register_queue_size(self, get_queue_size: Callable[[], int]) -> None: + if not self._enabled: + return + def record_queue_size( _options: CallbackOptions, ) -> tuple[Observation]: @@ -103,9 +116,13 @@ def record_queue_size( ) def drop_items(self, count: int) -> None: + if not self._enabled: + return self._processed.add(count, self._dropped_attrs) def finish_items(self, count: int, error: Exception | None) -> None: + if not self._enabled: + return if not error: self._processed.add(count, self._standard_attrs) return diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables/__init__.py index 2e5f350512b..a56004b0f93 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables/__init__.py @@ -845,3 +845,12 @@ def channel_credential_provider() -> grpc.ChannelCredentials: This is an experimental environment variable and the name of this variable and its behavior can change in a non-backwards compatible way. """ + +OTEL_PYTHON_SDK_METRICS_ENABLED = "OTEL_PYTHON_SDK_METRICS_ENABLED" +""" +.. envvar:: OTEL_PYTHON_SDK_METRICS_ENABLED + +The :envvar:`OTEL_PYTHON_SDK_METRICS_ENABLED` environment variable enables +metrics emitted by the SDK about its own internal state. +Default: "false" +""" diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables/_internal.py b/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables/_internal.py new file mode 100644 index 00000000000..0e59c57aa4f --- /dev/null +++ b/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables/_internal.py @@ -0,0 +1,39 @@ +# 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 logging import getLogger +from os import environ + +_logger = getLogger(__name__) + + +def parse_boolean_environment_variable( + environment_variable: str, default: bool = False +) -> bool: + value = environ.get(environment_variable) + if value is None: + return default + + match value.strip().lower(): + case "true": + return True + case "false": + return False + case _: + _logger.warning( + "Invalid value for %s: %r. Expected 'true' or 'false'.", + environment_variable, + value, + ) + return default diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/_metric_reader_metrics.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/_metric_reader_metrics.py index 435d9c2da7b..5b5862fc98b 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/_metric_reader_metrics.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/_metric_reader_metrics.py @@ -1,6 +1,12 @@ from collections import Counter from opentelemetry.metrics import MeterProvider +from opentelemetry.sdk.environment_variables import ( + OTEL_PYTHON_SDK_METRICS_ENABLED, +) +from opentelemetry.sdk.environment_variables._internal import ( + parse_boolean_environment_variable, +) from opentelemetry.semconv._incubating.attributes.otel_attributes import ( OTEL_COMPONENT_NAME, OTEL_COMPONENT_TYPE, @@ -29,6 +35,11 @@ def __init__( self._collection_duration = ( create_otel_sdk_metric_reader_collection_duration(meter) ) + self._enabled = parse_boolean_environment_variable( + OTEL_PYTHON_SDK_METRICS_ENABLED + ) def record_collection(self, duration: float) -> None: + if not self._enabled: + return self._collection_duration.record(duration, self._standard_attrs) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/_tracer_metrics.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/_tracer_metrics.py index ad7de330c78..cd701f1b947 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/_tracer_metrics.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/_tracer_metrics.py @@ -17,6 +17,12 @@ from collections.abc import Callable from opentelemetry import metrics as metrics_api +from opentelemetry.sdk.environment_variables import ( + OTEL_PYTHON_SDK_METRICS_ENABLED, +) +from opentelemetry.sdk.environment_variables._internal import ( + parse_boolean_environment_variable, +) from opentelemetry.sdk.trace.sampling import Decision from opentelemetry.semconv._incubating.attributes.otel_attributes import ( OTEL_SPAN_PARENT_ORIGIN, @@ -36,12 +42,18 @@ def __init__(self, meter_provider: metrics_api.MeterProvider) -> None: self._started_spans = create_otel_sdk_span_started(meter) self._live_spans = create_otel_sdk_span_live(meter) + self._enabled = parse_boolean_environment_variable( + OTEL_PYTHON_SDK_METRICS_ENABLED + ) def start_span( self, parent_span_context: SpanContext | None, sampling_decision: Decision, ) -> Callable[[], None]: + if not self._enabled: + return noop + sampling_result_value = sampling_result(sampling_decision) self._started_spans.add( 1, @@ -60,6 +72,8 @@ def start_span( self._live_spans.add(1, live_span_attrs) def end_span() -> None: + if not self._enabled: + return self._live_spans.add(-1, live_span_attrs) return end_span diff --git a/opentelemetry-sdk/tests/logs/test_export.py b/opentelemetry-sdk/tests/logs/test_export.py index c36eeccfdc8..4fdcb90eb3f 100644 --- a/opentelemetry-sdk/tests/logs/test_export.py +++ b/opentelemetry-sdk/tests/logs/test_export.py @@ -51,6 +51,7 @@ OTEL_BLRP_MAX_EXPORT_BATCH_SIZE, OTEL_BLRP_MAX_QUEUE_SIZE, OTEL_BLRP_SCHEDULE_DELAY, + OTEL_PYTHON_SDK_METRICS_ENABLED, ) from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import InMemoryMetricReader @@ -406,6 +407,7 @@ def test_simple_log_record_processor_different_msg_types_with_formatter( ] self.assertEqual(expected, emitted) + @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) def test_metrics(self): # pylint: disable=too-many-locals metric_reader = InMemoryMetricReader() meter_provider = MeterProvider(metric_readers=[metric_reader]) @@ -695,6 +697,7 @@ def test_validation_negative_max_queue_size(self): max_export_batch_size=101, ) + @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) def test_metrics(self): # pylint: disable=too-many-locals,too-many-statements metric_reader = InMemoryMetricReader() meter_provider = MeterProvider(metric_readers=[metric_reader]) diff --git a/opentelemetry-sdk/tests/logs/test_sdk_metrics.py b/opentelemetry-sdk/tests/logs/test_sdk_metrics.py index 5a0e18c4fb9..b1e37099754 100644 --- a/opentelemetry-sdk/tests/logs/test_sdk_metrics.py +++ b/opentelemetry-sdk/tests/logs/test_sdk_metrics.py @@ -13,12 +13,17 @@ # limitations under the License. from unittest import TestCase +from unittest.mock import patch from opentelemetry.sdk._logs import LoggerProvider +from opentelemetry.sdk.environment_variables import ( + OTEL_PYTHON_SDK_METRICS_ENABLED, +) from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import InMemoryMetricReader +@patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) class TestLoggerProviderMetrics(TestCase): def setUp(self): self.metric_reader = InMemoryMetricReader() @@ -57,3 +62,16 @@ def test_create_logs(self): 2, {}, ) + + +class TestLoggerProviderMetricsDisabled(TestCase): + def test_disabled_by_default(self): + metric_reader = InMemoryMetricReader() + meter_provider = MeterProvider(metric_readers=[metric_reader]) + logger_provider = LoggerProvider(meter_provider=meter_provider) + logger = logger_provider.get_logger("test") + + logger.emit(body="log1") + + self.assertIsNone(metric_reader.get_metrics_data()) + meter_provider.shutdown() diff --git a/opentelemetry-sdk/tests/metrics/test_periodic_exporting_metric_reader.py b/opentelemetry-sdk/tests/metrics/test_periodic_exporting_metric_reader.py index 3e47e577689..6b294037294 100644 --- a/opentelemetry-sdk/tests/metrics/test_periodic_exporting_metric_reader.py +++ b/opentelemetry-sdk/tests/metrics/test_periodic_exporting_metric_reader.py @@ -20,10 +20,13 @@ from logging import WARNING from time import sleep, time_ns from typing import Optional, cast -from unittest.mock import Mock +from unittest.mock import Mock, patch import pytest +from opentelemetry.sdk.environment_variables import ( + OTEL_PYTHON_SDK_METRICS_ENABLED, +) from opentelemetry.sdk.metrics import ( Counter, MeterProvider, @@ -315,6 +318,7 @@ def test_metric_exporer_gc(self): "The PeriodicExportingMetricReader object created by this test wasn't garbage collected", ) + @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) def test_metric_reader_metrics(self): exporter = FakeMetricsExporter() pmr = PeriodicExportingMetricReader( diff --git a/opentelemetry-sdk/tests/test_environment_variables_internal.py b/opentelemetry-sdk/tests/test_environment_variables_internal.py new file mode 100644 index 00000000000..ab340585ed2 --- /dev/null +++ b/opentelemetry-sdk/tests/test_environment_variables_internal.py @@ -0,0 +1,73 @@ +# 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 unittest.mock import patch + +from opentelemetry.sdk.environment_variables._internal import ( + parse_boolean_environment_variable, +) + + +class TestParseBooleanEnvironmentVariable(TestCase): + def test_unset_returns_default(self): + for default, expected in ( + (False, False), + (True, True), + ): + with self.subTest(default=default): + with patch.dict("os.environ", {}, clear=True): + self.assertEqual( + parse_boolean_environment_variable( + "TEST_BOOL", default=default + ), + expected, + ) + + def test_valid_values(self): + for value, expected in ( + ("true", True), + (" TrUe ", True), + ("false", False), + (" FaLsE ", False), + ): + with self.subTest(value=value): + with patch.dict("os.environ", {"TEST_BOOL": value}): + self.assertEqual( + parse_boolean_environment_variable("TEST_BOOL"), + expected, + ) + + def test_invalid_value_warns_and_returns_default(self): + for default, expected in ( + (False, False), + (True, True), + ): + with self.subTest(default=default): + with patch.dict("os.environ", {"TEST_BOOL": "yes"}): + with self.assertLogs( + "opentelemetry.sdk.environment_variables._internal", + level="WARNING", + ) as logs: + self.assertEqual( + parse_boolean_environment_variable( + "TEST_BOOL", default=default + ), + expected, + ) + + self.assertIn( + "Invalid value for TEST_BOOL", + logs.records[0].message, + ) diff --git a/opentelemetry-sdk/tests/trace/export/test_export.py b/opentelemetry-sdk/tests/trace/export/test_export.py index 2d1321df81b..9cb3e83cdec 100644 --- a/opentelemetry-sdk/tests/trace/export/test_export.py +++ b/opentelemetry-sdk/tests/trace/export/test_export.py @@ -28,6 +28,7 @@ OTEL_BSP_MAX_EXPORT_BATCH_SIZE, OTEL_BSP_MAX_QUEUE_SIZE, OTEL_BSP_SCHEDULE_DELAY, + OTEL_PYTHON_SDK_METRICS_ENABLED, ) from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import InMemoryMetricReader @@ -146,6 +147,7 @@ def test_simple_span_processor_not_sampled(self): self.assertListEqual([], spans_names_list) + @mock.patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) def test_metrics(self): metric_reader = InMemoryMetricReader() meter_provider = MeterProvider(metric_readers=[metric_reader]) @@ -397,6 +399,7 @@ def test_batch_span_processor_parameters(self): max_export_batch_size=512, ) + @mock.patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) def test_metrics(self): # pylint: disable=too-many-locals,too-many-statements metric_reader = InMemoryMetricReader() meter_provider = MeterProvider(metric_readers=[metric_reader]) diff --git a/opentelemetry-sdk/tests/trace/test_sdk_metrics.py b/opentelemetry-sdk/tests/trace/test_sdk_metrics.py index 2baa967f8ad..b48845cb8de 100644 --- a/opentelemetry-sdk/tests/trace/test_sdk_metrics.py +++ b/opentelemetry-sdk/tests/trace/test_sdk_metrics.py @@ -13,8 +13,12 @@ # limitations under the License. from unittest import TestCase +from unittest.mock import patch from opentelemetry import trace as trace_api +from opentelemetry.sdk.environment_variables import ( + OTEL_PYTHON_SDK_METRICS_ENABLED, +) from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import InMemoryMetricReader from opentelemetry.sdk.trace import TracerProvider @@ -27,6 +31,7 @@ from opentelemetry.trace.span import SpanContext +@patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) class TestTracerProviderMetrics(TestCase): def setUp(self): self.metric_reader = InMemoryMetricReader() @@ -159,6 +164,7 @@ def test_dropped(self): }, ) self.assert_live_spans(metric_data, None, {}) + span.end() metric_data = self.metric_reader.get_metrics_data() self.assert_started_spans( @@ -242,3 +248,19 @@ def test_dropped_local_parent(self): }, ) self.assert_live_spans(metric_data, None, {}) + + +class TestTracerProviderMetricsDisabled(TestCase): + def test_disabled_by_default(self): + metric_reader = InMemoryMetricReader() + meter_provider = MeterProvider(metric_readers=[metric_reader]) + tracer_provider = TracerProvider( + sampler=ALWAYS_ON, meter_provider=meter_provider + ) + tracer = tracer_provider.get_tracer("test") + + with tracer.start_as_current_span("span"): + pass + + self.assertIsNone(metric_reader.get_metrics_data()) + meter_provider.shutdown() From 6a737e76cff00e5745d8cfa6d3234db29beef017 Mon Sep 17 00:00:00 2001 From: Lukas Hering Date: Sun, 26 Apr 2026 23:50:55 -0400 Subject: [PATCH 02/10] refactor ProcessorMetrics --- .../sdk/_logs/_internal/export/__init__.py | 10 ++++++++++ .../_shared_internal/_processor_metrics.py | 20 +++++++------------ .../sdk/trace/export/__init__.py | 10 ++++++++++ 3 files changed, 27 insertions(+), 13 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 1c0f82ac055..cf8b936dda4 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py @@ -46,6 +46,10 @@ OTEL_BLRP_MAX_EXPORT_BATCH_SIZE, OTEL_BLRP_MAX_QUEUE_SIZE, OTEL_BLRP_SCHEDULE_DELAY, + OTEL_PYTHON_SDK_METRICS_ENABLED, +) +from opentelemetry.sdk.environment_variables._internal import ( + parse_boolean_environment_variable, ) from opentelemetry.sdk.resources import Resource from opentelemetry.semconv._incubating.attributes.otel_attributes import ( @@ -190,6 +194,9 @@ def __init__( "logs", OtelComponentTypeValues.SIMPLE_LOG_PROCESSOR, meter_provider or get_meter_provider(), + disabled=not parse_boolean_environment_variable( + OTEL_PYTHON_SDK_METRICS_ENABLED + ), ) def on_emit(self, log_record: ReadWriteLogRecord): @@ -304,6 +311,9 @@ def __init__( OtelComponentTypeValues.BATCHING_LOG_PROCESSOR, meter_provider or get_meter_provider(), capacity=max_queue_size, + disabled=not parse_boolean_environment_variable( + OTEL_PYTHON_SDK_METRICS_ENABLED + ), ), ) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/_processor_metrics.py b/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/_processor_metrics.py index 82faedac8a5..13654143267 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/_processor_metrics.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/_processor_metrics.py @@ -19,12 +19,6 @@ from typing import Literal from opentelemetry.metrics import CallbackOptions, MeterProvider, Observation -from opentelemetry.sdk.environment_variables import ( - OTEL_PYTHON_SDK_METRICS_ENABLED, -) -from opentelemetry.sdk.environment_variables._internal import ( - parse_boolean_environment_variable, -) from opentelemetry.semconv._incubating.attributes.otel_attributes import ( OTEL_COMPONENT_NAME, OTEL_COMPONENT_TYPE, @@ -51,8 +45,10 @@ def __init__( meter_provider: MeterProvider, *, capacity: int | None = None, + disabled: bool = False, ) -> None: self._signal = signal + self._enabled = not disabled meter = meter_provider.get_meter("opentelemetry-sdk") self._meter = meter @@ -81,17 +77,15 @@ def __init__( ) self._processed = create_processed(meter) - self._enabled = parse_boolean_environment_variable( - OTEL_PYTHON_SDK_METRICS_ENABLED - ) + self._disabled = disabled if capacity is not None: self._queue_capacity = create_queue_capacity(meter) - if self._enabled: + if not self._disabled: self._queue_capacity.add(capacity, self._standard_attrs) def register_queue_size(self, get_queue_size: Callable[[], int]) -> None: - if not self._enabled: + if self._disabled: return def record_queue_size( @@ -116,12 +110,12 @@ def record_queue_size( ) def drop_items(self, count: int) -> None: - if not self._enabled: + if self._disabled: return self._processed.add(count, self._dropped_attrs) def finish_items(self, count: int, error: Exception | None) -> None: - if not self._enabled: + if self._disabled: return if not error: self._processed.add(count, self._standard_attrs) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py index 8cf9c5e922d..0a80696de45 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py @@ -33,6 +33,10 @@ OTEL_BSP_MAX_EXPORT_BATCH_SIZE, OTEL_BSP_MAX_QUEUE_SIZE, OTEL_BSP_SCHEDULE_DELAY, + OTEL_PYTHON_SDK_METRICS_ENABLED, +) +from opentelemetry.sdk.environment_variables._internal import ( + parse_boolean_environment_variable, ) from opentelemetry.sdk.trace import ReadableSpan, Span, SpanProcessor from opentelemetry.semconv._incubating.attributes.otel_attributes import ( @@ -106,6 +110,9 @@ def __init__( "traces", OtelComponentTypeValues.SIMPLE_SPAN_PROCESSOR, meter_provider or get_meter_provider(), + disabled=not parse_boolean_environment_variable( + OTEL_PYTHON_SDK_METRICS_ENABLED + ), ) def on_start( @@ -201,6 +208,9 @@ def __init__( OtelComponentTypeValues.BATCHING_SPAN_PROCESSOR, meter_provider or get_meter_provider(), capacity=max_queue_size, + disabled=not parse_boolean_environment_variable( + OTEL_PYTHON_SDK_METRICS_ENABLED + ), ), ) From 910a576ba6ae92eebbcfc93c7e4a759cf8c61fc5 Mon Sep 17 00:00:00 2001 From: Lukas Hering Date: Sun, 26 Apr 2026 23:52:46 -0400 Subject: [PATCH 03/10] remove unused instance variable --- .../src/opentelemetry/sdk/_shared_internal/_processor_metrics.py | 1 - 1 file changed, 1 deletion(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/_processor_metrics.py b/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/_processor_metrics.py index 13654143267..d5703733ae0 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/_processor_metrics.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/_processor_metrics.py @@ -48,7 +48,6 @@ def __init__( disabled: bool = False, ) -> None: self._signal = signal - self._enabled = not disabled meter = meter_provider.get_meter("opentelemetry-sdk") self._meter = meter From e0654021e8ae3b2b114a70acdfc9aa0367dcf1d1 Mon Sep 17 00:00:00 2001 From: Lukas Hering Date: Sun, 26 Apr 2026 23:58:23 -0400 Subject: [PATCH 04/10] minor refactor --- .../opentelemetry/sdk/_logs/_internal/_logger_metrics.py | 4 ++-- .../sdk/metrics/_internal/export/_metric_reader_metrics.py | 4 ++-- .../src/opentelemetry/sdk/trace/_tracer_metrics.py | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/_logger_metrics.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/_logger_metrics.py index 339d77121cb..f9b5201b726 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/_logger_metrics.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/_logger_metrics.py @@ -28,11 +28,11 @@ class LoggerMetrics: def __init__(self, meter_provider: metrics_api.MeterProvider) -> None: meter = meter_provider.get_meter("opentelemetry-sdk") self._created_logs = create_otel_sdk_log_created(meter) - self._enabled = parse_boolean_environment_variable( + self._disabled = not parse_boolean_environment_variable( OTEL_PYTHON_SDK_METRICS_ENABLED ) def emit_log(self) -> None: - if not self._enabled: + if self._disabled: return self._created_logs.add(1) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/_metric_reader_metrics.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/_metric_reader_metrics.py index 5b5862fc98b..b91b89820e8 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/_metric_reader_metrics.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/_metric_reader_metrics.py @@ -35,11 +35,11 @@ def __init__( self._collection_duration = ( create_otel_sdk_metric_reader_collection_duration(meter) ) - self._enabled = parse_boolean_environment_variable( + self._disabled = not parse_boolean_environment_variable( OTEL_PYTHON_SDK_METRICS_ENABLED ) def record_collection(self, duration: float) -> None: - if not self._enabled: + if self._disabled: return self._collection_duration.record(duration, self._standard_attrs) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/_tracer_metrics.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/_tracer_metrics.py index cd701f1b947..1e0ff46dc2c 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/_tracer_metrics.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/_tracer_metrics.py @@ -42,7 +42,7 @@ def __init__(self, meter_provider: metrics_api.MeterProvider) -> None: self._started_spans = create_otel_sdk_span_started(meter) self._live_spans = create_otel_sdk_span_live(meter) - self._enabled = parse_boolean_environment_variable( + self._disabled = not parse_boolean_environment_variable( OTEL_PYTHON_SDK_METRICS_ENABLED ) @@ -51,7 +51,7 @@ def start_span( parent_span_context: SpanContext | None, sampling_decision: Decision, ) -> Callable[[], None]: - if not self._enabled: + if self._disabled: return noop sampling_result_value = sampling_result(sampling_decision) @@ -72,7 +72,7 @@ def start_span( self._live_spans.add(1, live_span_attrs) def end_span() -> None: - if not self._enabled: + if self._disabled: return self._live_spans.add(-1, live_span_attrs) From e528cde8947d5b2ee763efe65d03138bb1d863f5 Mon Sep 17 00:00:00 2001 From: Lukas Hering Date: Mon, 27 Apr 2026 20:36:03 -0400 Subject: [PATCH 05/10] update naming of internal metric environment variable --- .../exporter/otlp/proto/grpc/exporter.py | 4 ++-- .../tests/test_otlp_exporter_mixin.py | 14 ++++++++++---- .../otlp/proto/http/_log_exporter/__init__.py | 4 ++-- .../otlp/proto/http/metric_exporter/__init__.py | 6 +++--- .../otlp/proto/http/trace_exporter/__init__.py | 4 ++-- .../tests/metrics/test_otlp_metrics_exporter.py | 14 ++++++++++---- .../tests/test_proto_log_exporter.py | 10 +++++++--- .../tests/test_proto_span_exporter.py | 10 +++++++--- .../sdk/_logs/_internal/_logger_metrics.py | 4 ++-- .../sdk/_logs/_internal/export/__init__.py | 6 +++--- .../sdk/environment_variables/__init__.py | 8 +++++--- .../_internal/export/_metric_reader_metrics.py | 4 ++-- .../src/opentelemetry/sdk/trace/_tracer_metrics.py | 4 ++-- .../src/opentelemetry/sdk/trace/export/__init__.py | 6 +++--- opentelemetry-sdk/tests/logs/test_export.py | 10 +++++++--- opentelemetry-sdk/tests/logs/test_sdk_metrics.py | 4 ++-- .../test_periodic_exporting_metric_reader.py | 6 ++++-- .../tests/trace/export/test_export.py | 10 +++++++--- opentelemetry-sdk/tests/trace/test_sdk_metrics.py | 4 ++-- 19 files changed, 82 insertions(+), 50 deletions(-) diff --git a/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py b/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py index 971967a16de..bd22bf75e51 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py +++ b/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py @@ -103,7 +103,7 @@ OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_INSECURE, OTEL_EXPORTER_OTLP_TIMEOUT, - OTEL_PYTHON_SDK_METRICS_ENABLED, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, ) from opentelemetry.sdk.environment_variables._internal import ( parse_boolean_environment_variable, @@ -397,7 +397,7 @@ def __init__( parsed_url, meter_provider, disabled=not parse_boolean_environment_variable( - OTEL_PYTHON_SDK_METRICS_ENABLED + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), ) diff --git a/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_exporter_mixin.py b/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_exporter_mixin.py index ab609bff152..de5c680381b 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_exporter_mixin.py +++ b/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_exporter_mixin.py @@ -54,7 +54,7 @@ from opentelemetry.sdk.environment_variables import ( _OTEL_PYTHON_EXPORTER_OTLP_GRPC_CREDENTIAL_PROVIDER, OTEL_EXPORTER_OTLP_COMPRESSION, - OTEL_PYTHON_SDK_METRICS_ENABLED, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, ) from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import InMemoryMetricReader @@ -388,7 +388,9 @@ def test_otlp_exporter_otlp_compression_envvar( ), ) - @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) + @patch.dict( + "os.environ", {OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED: "true"} + ) def test_shutdown(self): add_TraceServiceServicer_to_server( TraceServiceServicerWithExportParams(StatusCode.OK), @@ -485,7 +487,9 @@ def test_export_over_closed_grpc_channel(self): system() == "Windows", "For gRPC + windows there's some added delay in the RPCs which breaks the assertion over amount of time passed.", ) - @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) + @patch.dict( + "os.environ", {OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED: "true"} + ) def test_retry_info_is_respected(self): mock_trace_service = TraceServiceServicerWithExportParams( StatusCode.UNAVAILABLE, @@ -628,7 +632,9 @@ def test_otlp_headers_from_env(self): (), ) - @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) + @patch.dict( + "os.environ", {OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED: "true"} + ) def test_permanent_failure(self): exporter = OTLPSpanExporterForTesting( insecure=True, meter_provider=self.meter_provider 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 fb46ce36a38..115ef7c86ac 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 @@ -61,7 +61,7 @@ OTEL_EXPORTER_OTLP_LOGS_HEADERS, OTEL_EXPORTER_OTLP_LOGS_TIMEOUT, OTEL_EXPORTER_OTLP_TIMEOUT, - OTEL_PYTHON_SDK_METRICS_ENABLED, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, ) from opentelemetry.sdk.environment_variables._internal import ( parse_boolean_environment_variable, @@ -162,7 +162,7 @@ def __init__( urlparse(self._endpoint), meter_provider, disabled=not parse_boolean_environment_variable( - OTEL_PYTHON_SDK_METRICS_ENABLED + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), ) diff --git a/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py index 5b45c34e1be..af348fe2461 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py @@ -86,7 +86,7 @@ OTEL_EXPORTER_OTLP_METRICS_HEADERS, OTEL_EXPORTER_OTLP_METRICS_TIMEOUT, OTEL_EXPORTER_OTLP_TIMEOUT, - OTEL_PYTHON_SDK_METRICS_ENABLED, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, ) from opentelemetry.sdk.environment_variables._internal import ( parse_boolean_environment_variable, @@ -227,7 +227,7 @@ def __init__( urlparse(self._endpoint), meter_provider, disabled=not parse_boolean_environment_variable( - OTEL_PYTHON_SDK_METRICS_ENABLED + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), ) @@ -412,7 +412,7 @@ def set_meter_provider(self, meter_provider: MeterProvider) -> None: urlparse(self._endpoint), meter_provider, disabled=not parse_boolean_environment_variable( - OTEL_PYTHON_SDK_METRICS_ENABLED + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), ) 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 cc0285f30ca..8977833ff87 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 @@ -57,7 +57,7 @@ OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_HEADERS, OTEL_EXPORTER_OTLP_TRACES_TIMEOUT, - OTEL_PYTHON_SDK_METRICS_ENABLED, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, ) from opentelemetry.sdk.environment_variables._internal import ( parse_boolean_environment_variable, @@ -157,7 +157,7 @@ def __init__( urlparse(self._endpoint), meter_provider, disabled=not parse_boolean_environment_variable( - OTEL_PYTHON_SDK_METRICS_ENABLED + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), ) diff --git a/exporter/opentelemetry-exporter-otlp-proto-http/tests/metrics/test_otlp_metrics_exporter.py b/exporter/opentelemetry-exporter-otlp-proto-http/tests/metrics/test_otlp_metrics_exporter.py index aeda4504d45..39128e3187f 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-http/tests/metrics/test_otlp_metrics_exporter.py +++ b/exporter/opentelemetry-exporter-otlp-proto-http/tests/metrics/test_otlp_metrics_exporter.py @@ -69,7 +69,7 @@ OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE, OTEL_EXPORTER_OTLP_METRICS_TIMEOUT, OTEL_EXPORTER_OTLP_TIMEOUT, - OTEL_PYTHON_SDK_METRICS_ENABLED, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, ) from opentelemetry.sdk.metrics import ( Counter, @@ -335,7 +335,9 @@ def test_headers_parse_from_env(self): ), ) - @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) + @patch.dict( + "os.environ", {OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED: "true"} + ) @patch.object(Session, "post") def test_success(self, mock_post): resp = Response() @@ -374,7 +376,9 @@ def test_success(self, mock_post): metrics[2].data.data_points[0].attributes ) - @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) + @patch.dict( + "os.environ", {OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED: "true"} + ) @patch.object(Session, "post") def test_failure(self, mock_post): resp = Response() @@ -1294,7 +1298,9 @@ def test_preferred_aggregation_override(self): exporter._preferred_aggregation[Histogram], histogram_aggregation ) - @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) + @patch.dict( + "os.environ", {OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED: "true"} + ) @patch.object(Session, "post") def test_retry_timeout(self, mock_post): exporter = OTLPMetricExporter( 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 3929e9df826..bdcdfbe3c74 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 @@ -58,7 +58,7 @@ OTEL_EXPORTER_OTLP_LOGS_HEADERS, OTEL_EXPORTER_OTLP_LOGS_TIMEOUT, OTEL_EXPORTER_OTLP_TIMEOUT, - OTEL_PYTHON_SDK_METRICS_ENABLED, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, ) from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import InMemoryMetricReader @@ -468,7 +468,9 @@ def test_2xx_status_code(self, mock_otlp_metric_exporter): LogRecordExportResult.SUCCESS, ) - @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) + @patch.dict( + "os.environ", {OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED: "true"} + ) @patch.object(Session, "post") def test_retry_timeout(self, mock_post): exporter = OTLPLogExporter( @@ -557,7 +559,9 @@ def test_export_no_collector_available_retryable(self, mock_post): warning.records[0].message, ) - @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) + @patch.dict( + "os.environ", {OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED: "true"} + ) @patch.object(Session, "post") def test_export_no_collector_available(self, mock_post): exporter = OTLPLogExporter( 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 66e291a8b43..1f671be6107 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 @@ -48,7 +48,7 @@ OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_HEADERS, OTEL_EXPORTER_OTLP_TRACES_TIMEOUT, - OTEL_PYTHON_SDK_METRICS_ENABLED, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, ) from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import InMemoryMetricReader @@ -299,7 +299,9 @@ def test_exporter_metrics_disabled_by_default(self, _mock_export): self.assertIsNone(self.metric_reader.get_metrics_data()) - @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) + @patch.dict( + "os.environ", {OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED: "true"} + ) @patch.object(Session, "post") def test_retry_timeout(self, mock_post): exporter = OTLPSpanExporter( @@ -388,7 +390,9 @@ def test_export_no_collector_available_retryable(self, mock_post): warning.records[0].message, ) - @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) + @patch.dict( + "os.environ", {OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED: "true"} + ) @patch.object(Session, "post") def test_export_no_collector_available(self, mock_post): exporter = OTLPSpanExporter( diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/_logger_metrics.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/_logger_metrics.py index f9b5201b726..1f1ca83c3d5 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/_logger_metrics.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/_logger_metrics.py @@ -14,7 +14,7 @@ from opentelemetry import metrics as metrics_api from opentelemetry.sdk.environment_variables import ( - OTEL_PYTHON_SDK_METRICS_ENABLED, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, ) from opentelemetry.sdk.environment_variables._internal import ( parse_boolean_environment_variable, @@ -29,7 +29,7 @@ def __init__(self, meter_provider: metrics_api.MeterProvider) -> None: meter = meter_provider.get_meter("opentelemetry-sdk") self._created_logs = create_otel_sdk_log_created(meter) self._disabled = not parse_boolean_environment_variable( - OTEL_PYTHON_SDK_METRICS_ENABLED + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ) def emit_log(self) -> None: 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 cf8b936dda4..132dfcd2390 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py @@ -46,7 +46,7 @@ OTEL_BLRP_MAX_EXPORT_BATCH_SIZE, OTEL_BLRP_MAX_QUEUE_SIZE, OTEL_BLRP_SCHEDULE_DELAY, - OTEL_PYTHON_SDK_METRICS_ENABLED, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, ) from opentelemetry.sdk.environment_variables._internal import ( parse_boolean_environment_variable, @@ -195,7 +195,7 @@ def __init__( OtelComponentTypeValues.SIMPLE_LOG_PROCESSOR, meter_provider or get_meter_provider(), disabled=not parse_boolean_environment_variable( - OTEL_PYTHON_SDK_METRICS_ENABLED + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), ) @@ -312,7 +312,7 @@ def __init__( meter_provider or get_meter_provider(), capacity=max_queue_size, disabled=not parse_boolean_environment_variable( - OTEL_PYTHON_SDK_METRICS_ENABLED + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), ), ) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables/__init__.py index a56004b0f93..8e5bf7d3b09 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables/__init__.py @@ -846,11 +846,13 @@ def channel_credential_provider() -> grpc.ChannelCredentials: change in a non-backwards compatible way. """ -OTEL_PYTHON_SDK_METRICS_ENABLED = "OTEL_PYTHON_SDK_METRICS_ENABLED" +OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED = ( + "OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED" +) """ -.. envvar:: OTEL_PYTHON_SDK_METRICS_ENABLED +.. envvar:: OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED -The :envvar:`OTEL_PYTHON_SDK_METRICS_ENABLED` environment variable enables +The :envvar:`OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED` environment variable enables metrics emitted by the SDK about its own internal state. Default: "false" """ diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/_metric_reader_metrics.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/_metric_reader_metrics.py index b91b89820e8..b826091ac86 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/_metric_reader_metrics.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/_metric_reader_metrics.py @@ -2,7 +2,7 @@ from opentelemetry.metrics import MeterProvider from opentelemetry.sdk.environment_variables import ( - OTEL_PYTHON_SDK_METRICS_ENABLED, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, ) from opentelemetry.sdk.environment_variables._internal import ( parse_boolean_environment_variable, @@ -36,7 +36,7 @@ def __init__( create_otel_sdk_metric_reader_collection_duration(meter) ) self._disabled = not parse_boolean_environment_variable( - OTEL_PYTHON_SDK_METRICS_ENABLED + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ) def record_collection(self, duration: float) -> None: diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/_tracer_metrics.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/_tracer_metrics.py index 1e0ff46dc2c..8868a3cd4a0 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/_tracer_metrics.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/_tracer_metrics.py @@ -18,7 +18,7 @@ from opentelemetry import metrics as metrics_api from opentelemetry.sdk.environment_variables import ( - OTEL_PYTHON_SDK_METRICS_ENABLED, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, ) from opentelemetry.sdk.environment_variables._internal import ( parse_boolean_environment_variable, @@ -43,7 +43,7 @@ def __init__(self, meter_provider: metrics_api.MeterProvider) -> None: self._started_spans = create_otel_sdk_span_started(meter) self._live_spans = create_otel_sdk_span_live(meter) self._disabled = not parse_boolean_environment_variable( - OTEL_PYTHON_SDK_METRICS_ENABLED + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ) def start_span( diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py index 0a80696de45..666623a746f 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py @@ -33,7 +33,7 @@ OTEL_BSP_MAX_EXPORT_BATCH_SIZE, OTEL_BSP_MAX_QUEUE_SIZE, OTEL_BSP_SCHEDULE_DELAY, - OTEL_PYTHON_SDK_METRICS_ENABLED, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, ) from opentelemetry.sdk.environment_variables._internal import ( parse_boolean_environment_variable, @@ -111,7 +111,7 @@ def __init__( OtelComponentTypeValues.SIMPLE_SPAN_PROCESSOR, meter_provider or get_meter_provider(), disabled=not parse_boolean_environment_variable( - OTEL_PYTHON_SDK_METRICS_ENABLED + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), ) @@ -209,7 +209,7 @@ def __init__( meter_provider or get_meter_provider(), capacity=max_queue_size, disabled=not parse_boolean_environment_variable( - OTEL_PYTHON_SDK_METRICS_ENABLED + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), ), ) diff --git a/opentelemetry-sdk/tests/logs/test_export.py b/opentelemetry-sdk/tests/logs/test_export.py index 4fdcb90eb3f..bc8396b472e 100644 --- a/opentelemetry-sdk/tests/logs/test_export.py +++ b/opentelemetry-sdk/tests/logs/test_export.py @@ -51,7 +51,7 @@ OTEL_BLRP_MAX_EXPORT_BATCH_SIZE, OTEL_BLRP_MAX_QUEUE_SIZE, OTEL_BLRP_SCHEDULE_DELAY, - OTEL_PYTHON_SDK_METRICS_ENABLED, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, ) from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import InMemoryMetricReader @@ -407,7 +407,9 @@ def test_simple_log_record_processor_different_msg_types_with_formatter( ] self.assertEqual(expected, emitted) - @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) + @patch.dict( + "os.environ", {OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED: "true"} + ) def test_metrics(self): # pylint: disable=too-many-locals metric_reader = InMemoryMetricReader() meter_provider = MeterProvider(metric_readers=[metric_reader]) @@ -697,7 +699,9 @@ def test_validation_negative_max_queue_size(self): max_export_batch_size=101, ) - @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) + @patch.dict( + "os.environ", {OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED: "true"} + ) def test_metrics(self): # pylint: disable=too-many-locals,too-many-statements metric_reader = InMemoryMetricReader() meter_provider = MeterProvider(metric_readers=[metric_reader]) diff --git a/opentelemetry-sdk/tests/logs/test_sdk_metrics.py b/opentelemetry-sdk/tests/logs/test_sdk_metrics.py index b1e37099754..8095971b9cf 100644 --- a/opentelemetry-sdk/tests/logs/test_sdk_metrics.py +++ b/opentelemetry-sdk/tests/logs/test_sdk_metrics.py @@ -17,13 +17,13 @@ from opentelemetry.sdk._logs import LoggerProvider from opentelemetry.sdk.environment_variables import ( - OTEL_PYTHON_SDK_METRICS_ENABLED, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, ) from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import InMemoryMetricReader -@patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) +@patch.dict("os.environ", {OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED: "true"}) class TestLoggerProviderMetrics(TestCase): def setUp(self): self.metric_reader = InMemoryMetricReader() diff --git a/opentelemetry-sdk/tests/metrics/test_periodic_exporting_metric_reader.py b/opentelemetry-sdk/tests/metrics/test_periodic_exporting_metric_reader.py index 6b294037294..06bf447e301 100644 --- a/opentelemetry-sdk/tests/metrics/test_periodic_exporting_metric_reader.py +++ b/opentelemetry-sdk/tests/metrics/test_periodic_exporting_metric_reader.py @@ -25,7 +25,7 @@ import pytest from opentelemetry.sdk.environment_variables import ( - OTEL_PYTHON_SDK_METRICS_ENABLED, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, ) from opentelemetry.sdk.metrics import ( Counter, @@ -318,7 +318,9 @@ def test_metric_exporer_gc(self): "The PeriodicExportingMetricReader object created by this test wasn't garbage collected", ) - @patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) + @patch.dict( + "os.environ", {OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED: "true"} + ) def test_metric_reader_metrics(self): exporter = FakeMetricsExporter() pmr = PeriodicExportingMetricReader( diff --git a/opentelemetry-sdk/tests/trace/export/test_export.py b/opentelemetry-sdk/tests/trace/export/test_export.py index 9cb3e83cdec..abae8a29b86 100644 --- a/opentelemetry-sdk/tests/trace/export/test_export.py +++ b/opentelemetry-sdk/tests/trace/export/test_export.py @@ -28,7 +28,7 @@ OTEL_BSP_MAX_EXPORT_BATCH_SIZE, OTEL_BSP_MAX_QUEUE_SIZE, OTEL_BSP_SCHEDULE_DELAY, - OTEL_PYTHON_SDK_METRICS_ENABLED, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, ) from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import InMemoryMetricReader @@ -147,7 +147,9 @@ def test_simple_span_processor_not_sampled(self): self.assertListEqual([], spans_names_list) - @mock.patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) + @mock.patch.dict( + "os.environ", {OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED: "true"} + ) def test_metrics(self): metric_reader = InMemoryMetricReader() meter_provider = MeterProvider(metric_readers=[metric_reader]) @@ -399,7 +401,9 @@ def test_batch_span_processor_parameters(self): max_export_batch_size=512, ) - @mock.patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) + @mock.patch.dict( + "os.environ", {OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED: "true"} + ) def test_metrics(self): # pylint: disable=too-many-locals,too-many-statements metric_reader = InMemoryMetricReader() meter_provider = MeterProvider(metric_readers=[metric_reader]) diff --git a/opentelemetry-sdk/tests/trace/test_sdk_metrics.py b/opentelemetry-sdk/tests/trace/test_sdk_metrics.py index b48845cb8de..51fdd4c7155 100644 --- a/opentelemetry-sdk/tests/trace/test_sdk_metrics.py +++ b/opentelemetry-sdk/tests/trace/test_sdk_metrics.py @@ -17,7 +17,7 @@ from opentelemetry import trace as trace_api from opentelemetry.sdk.environment_variables import ( - OTEL_PYTHON_SDK_METRICS_ENABLED, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, ) from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import InMemoryMetricReader @@ -31,7 +31,7 @@ from opentelemetry.trace.span import SpanContext -@patch.dict("os.environ", {OTEL_PYTHON_SDK_METRICS_ENABLED: "true"}) +@patch.dict("os.environ", {OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED: "true"}) class TestTracerProviderMetrics(TestCase): def setUp(self): self.metric_reader = InMemoryMetricReader() From e0e25b79f2160d267192a5cfc7415b1448f97b57 Mon Sep 17 00:00:00 2001 From: Lukas Hering Date: Sun, 3 May 2026 00:27:39 -0400 Subject: [PATCH 06/10] update exporter metrics --- .../otlp/proto/common/_exporter_metrics.py | 58 +++++++++++---- .../tests/test_exporter_metrics.py | 74 +++++++++++++++++++ .../exporter/otlp/proto/grpc/exporter.py | 11 ++- .../otlp/proto/http/_log_exporter/__init__.py | 8 +- .../proto/http/metric_exporter/__init__.py | 14 ++-- .../proto/http/trace_exporter/__init__.py | 8 +- .../metrics/test_otlp_metrics_exporter.py | 15 ++++ 7 files changed, 153 insertions(+), 35 deletions(-) create mode 100644 exporter/opentelemetry-exporter-otlp-proto-common/tests/test_exporter_metrics.py diff --git a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_exporter_metrics.py b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_exporter_metrics.py index 55686a66e61..33ef7c11f8b 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_exporter_metrics.py +++ b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_exporter_metrics.py @@ -15,10 +15,10 @@ from __future__ import annotations from collections import Counter -from contextlib import contextmanager +from contextlib import AbstractContextManager, contextmanager from dataclasses import dataclass from time import perf_counter -from typing import TYPE_CHECKING, Iterator +from typing import TYPE_CHECKING, Iterator, Protocol from opentelemetry.metrics import MeterProvider, get_meter_provider from opentelemetry.semconv._incubating.attributes.otel_attributes import ( @@ -56,6 +56,19 @@ class ExportResult: error_attrs: Attributes = None +class ExporterMetricsT(Protocol): + def export_operation( + self, num_items: int + ) -> AbstractContextManager[ExportResult]: + ... + + +class NoOpExporterMetrics: + @contextmanager + def export_operation(self, num_items: int) -> Iterator[ExportResult]: + yield ExportResult() + + class ExporterMetrics: def __init__( self, @@ -63,8 +76,6 @@ def __init__( signal: Literal["traces", "metrics", "logs"], endpoint: UrlParseResult, meter_provider: MeterProvider | None, - *, - disabled: bool = False, ) -> None: if signal == "traces": create_exported = create_otel_sdk_exporter_span_exported @@ -87,14 +98,16 @@ def __init__( elif endpoint.scheme == "http": port = 80 - component_type = ( - component_type or OtelComponentTypeValues("unknown_otlp_exporter") - ).value - count = _component_counter[component_type] - _component_counter[component_type] = count + 1 + component_type_value = ( + component_type.value + if component_type + else "unknown_otlp_exporter" + ) + count = _component_counter[component_type_value] + _component_counter[component_type_value] = count + 1 self._standard_attrs: dict[str, AttributeValue] = { - OTEL_COMPONENT_TYPE: component_type, - OTEL_COMPONENT_NAME: f"{component_type}/{count}", + OTEL_COMPONENT_TYPE: component_type_value, + OTEL_COMPONENT_NAME: f"{component_type_value}/{count}", } if endpoint.hostname: self._standard_attrs[SERVER_ADDRESS] = endpoint.hostname @@ -106,14 +119,9 @@ def __init__( self._inflight = create_inflight(meter) self._exported = create_exported(meter) self._duration = create_otel_sdk_exporter_operation_duration(meter) - self._disabled = disabled @contextmanager def export_operation(self, num_items: int) -> Iterator[ExportResult]: - if self._disabled: - yield ExportResult() - return - start_time = perf_counter() self._inflight.add(num_items, self._standard_attrs) @@ -138,3 +146,21 @@ def export_operation(self, num_items: int) -> Iterator[ExportResult]: else exported_attrs ) self._duration.record(end_time - start_time, duration_attrs) + + +def create_exporter_metrics( + component_type: OtelComponentTypeValues | None, + signal: Literal["traces", "metrics", "logs"], + endpoint: UrlParseResult, + meter_provider: MeterProvider | None, + enabled: bool, +) -> ExporterMetricsT: + if not enabled: + return NoOpExporterMetrics() + + return ExporterMetrics( + component_type, + signal, + endpoint, + meter_provider, + ) diff --git a/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_exporter_metrics.py b/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_exporter_metrics.py new file mode 100644 index 00000000000..dfc0e18a0c2 --- /dev/null +++ b/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_exporter_metrics.py @@ -0,0 +1,74 @@ +# 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. + +import unittest +from unittest.mock import Mock, patch +from urllib.parse import urlparse + +from opentelemetry.exporter.otlp.proto.common._exporter_metrics import ( + ExporterMetrics, + NoOpExporterMetrics, + create_exporter_metrics, +) +from opentelemetry.semconv._incubating.attributes.otel_attributes import ( + OtelComponentTypeValues, +) + + +class TestExporterMetrics(unittest.TestCase): + def test_factory_returns_noop_when_disabled(self): + meter_provider = Mock() + + with patch( + "opentelemetry.exporter.otlp.proto.common." + "_exporter_metrics.get_meter_provider" + ) as get_meter_provider: + metrics = create_exporter_metrics( + "traces", + urlparse("http://localhost:4318/v1/traces"), + meter_provider, + False, + component_type=OtelComponentTypeValues.OTLP_HTTP_SPAN_EXPORTER, + ) + + self.assertIsInstance(metrics, NoOpExporterMetrics) + meter_provider.get_meter.assert_not_called() + get_meter_provider.assert_not_called() + + def test_factory_returns_exporter_metrics_when_enabled(self): + meter_provider = Mock() + meter_provider.get_meter.return_value = Mock() + + metrics = create_exporter_metrics( + "traces", + urlparse("http://localhost:4318/v1/traces"), + meter_provider, + True, + component_type=OtelComponentTypeValues.OTLP_HTTP_SPAN_EXPORTER, + ) + + self.assertIsInstance(metrics, ExporterMetrics) + meter_provider.get_meter.assert_called_once_with("opentelemetry-sdk") + + def test_noop_export_operation_yields_result(self): + metrics = NoOpExporterMetrics() + + with metrics.export_operation(1) as result: + result.error = RuntimeError("error") + + self.assertIsInstance(result.error, RuntimeError) + + +if __name__ == "__main__": + unittest.main() diff --git a/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py b/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py index bd22bf75e51..0eab60697d0 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py +++ b/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py @@ -57,7 +57,7 @@ ssl_channel_credentials, ) from opentelemetry.exporter.otlp.proto.common._exporter_metrics import ( - ExporterMetrics, + create_exporter_metrics, ) from opentelemetry.exporter.otlp.proto.common._internal import ( _get_resource_data, @@ -391,12 +391,12 @@ def __init__( self._component_type = component_type self._signal: Literal["traces", "metrics", "logs"] = signal self._parsed_url = parsed_url - self._metrics = ExporterMetrics( + self._metrics = create_exporter_metrics( self._component_type, signal, parsed_url, meter_provider, - disabled=not parse_boolean_environment_variable( + parse_boolean_environment_variable( OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), ) @@ -556,9 +556,12 @@ def _exporting(self) -> str: pass def _set_meter_provider(self, meter_provider: MeterProvider) -> None: - self._metrics = ExporterMetrics( + self._metrics = create_exporter_metrics( self._component_type, self._signal, self._parsed_url, meter_provider, + parse_boolean_environment_variable( + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED + ), ) 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 115ef7c86ac..e31c6a9ab6c 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 @@ -27,7 +27,7 @@ from requests.exceptions import ConnectionError from opentelemetry.exporter.otlp.proto.common._exporter_metrics import ( - ExporterMetrics, + create_exporter_metrics, ) from opentelemetry.exporter.otlp.proto.common._log_encoder import encode_logs from opentelemetry.exporter.otlp.proto.http import ( @@ -156,14 +156,14 @@ def __init__( ) self._shutdown = False - self._metrics = ExporterMetrics( - OtelComponentTypeValues.OTLP_HTTP_LOG_EXPORTER, + self._metrics = create_exporter_metrics( "logs", urlparse(self._endpoint), meter_provider, - disabled=not parse_boolean_environment_variable( + parse_boolean_environment_variable( OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), + component_type=OtelComponentTypeValues.OTLP_HTTP_LOG_EXPORTER, ) def _export( diff --git a/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py index af348fe2461..0a34404e3a2 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py @@ -35,7 +35,7 @@ from typing_extensions import deprecated from opentelemetry.exporter.otlp.proto.common._exporter_metrics import ( - ExporterMetrics, + create_exporter_metrics, ) from opentelemetry.exporter.otlp.proto.common._internal import ( _get_resource_data, @@ -221,14 +221,14 @@ def __init__( self._max_export_batch_size: int | None = max_export_batch_size self._shutdown = False - self._metrics = ExporterMetrics( - OtelComponentTypeValues.OTLP_HTTP_METRIC_EXPORTER, + self._metrics = create_exporter_metrics( "metrics", urlparse(self._endpoint), meter_provider, - disabled=not parse_boolean_environment_variable( + parse_boolean_environment_variable( OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), + component_type=OtelComponentTypeValues.OTLP_HTTP_METRIC_EXPORTER, ) def _export( @@ -406,14 +406,14 @@ def force_flush(self, timeout_millis: float = 10_000) -> bool: return True def set_meter_provider(self, meter_provider: MeterProvider) -> None: - self._metrics = ExporterMetrics( - OtelComponentTypeValues.OTLP_HTTP_METRIC_EXPORTER, + self._metrics = create_exporter_metrics( "metrics", urlparse(self._endpoint), meter_provider, - disabled=not parse_boolean_environment_variable( + parse_boolean_environment_variable( OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), + component_type=OtelComponentTypeValues.OTLP_HTTP_METRIC_EXPORTER, ) 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 8977833ff87..f6a8c8fca4d 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 @@ -27,7 +27,7 @@ from requests.exceptions import ConnectionError from opentelemetry.exporter.otlp.proto.common._exporter_metrics import ( - ExporterMetrics, + create_exporter_metrics, ) from opentelemetry.exporter.otlp.proto.common.trace_encoder import ( encode_spans, @@ -151,14 +151,14 @@ def __init__( ) self._shutdown = False - self._metrics = ExporterMetrics( - OtelComponentTypeValues.OTLP_HTTP_SPAN_EXPORTER, + self._metrics = create_exporter_metrics( "traces", urlparse(self._endpoint), meter_provider, - disabled=not parse_boolean_environment_variable( + parse_boolean_environment_variable( OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), + component_type=OtelComponentTypeValues.OTLP_HTTP_SPAN_EXPORTER, ) def _export( diff --git a/exporter/opentelemetry-exporter-otlp-proto-http/tests/metrics/test_otlp_metrics_exporter.py b/exporter/opentelemetry-exporter-otlp-proto-http/tests/metrics/test_otlp_metrics_exporter.py index 39128e3187f..83ecc8379de 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-http/tests/metrics/test_otlp_metrics_exporter.py +++ b/exporter/opentelemetry-exporter-otlp-proto-http/tests/metrics/test_otlp_metrics_exporter.py @@ -1283,6 +1283,21 @@ def test_2xx_status_code(self, mock_otlp_metric_exporter): MetricExportResult.SUCCESS, ) + @patch.dict("os.environ", {}, clear=True) + @patch.object(OTLPMetricExporter, "_export", return_value=Mock(ok=True)) + def test_exporter_metrics_disabled_after_set_meter_provider( + self, _mock_export + ): + exporter = OTLPMetricExporter() + exporter.set_meter_provider(self.meter_provider) + + self.assertEqual( + exporter.export(self.metrics["sum_int"]), + MetricExportResult.SUCCESS, + ) + + self.assertIsNone(self.metric_reader.get_metrics_data()) + def test_preferred_aggregation_override(self): histogram_aggregation = ExplicitBucketHistogramAggregation( boundaries=[0.05, 0.1, 0.5, 1, 5, 10], From 2f58d4c6b69ce636d28c1c9200990c8854cc7d86 Mon Sep 17 00:00:00 2001 From: Lukas Hering Date: Sun, 3 May 2026 00:50:42 -0400 Subject: [PATCH 07/10] implementation suggestions --- .../otlp/proto/common/_exporter_metrics.py | 7 +-- .../otlp/proto/http/_log_exporter/__init__.py | 2 +- .../proto/http/metric_exporter/__init__.py | 2 +- .../proto/http/trace_exporter/__init__.py | 2 +- .../sdk/_logs/_internal/__init__.py | 20 +++++-- .../sdk/_logs/_internal/_logger_metrics.py | 32 +++++++---- .../sdk/_logs/_internal/export/__init__.py | 12 +++-- .../sdk/_shared_internal/__init__.py | 4 +- .../_shared_internal/_processor_metrics.py | 54 ++++++++++++++----- .../sdk/metrics/_internal/export/__init__.py | 22 ++++++-- .../export/_metric_reader_metrics.py | 32 +++++++---- .../src/opentelemetry/sdk/trace/__init__.py | 13 ++++- .../sdk/trace/_tracer_metrics.py | 43 ++++++++++----- .../sdk/trace/export/__init__.py | 15 ++++-- opentelemetry-sdk/tests/logs/test_logs.py | 5 +- 15 files changed, 183 insertions(+), 82 deletions(-) diff --git a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_exporter_metrics.py b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_exporter_metrics.py index 33ef7c11f8b..30f4069e22e 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_exporter_metrics.py +++ b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_exporter_metrics.py @@ -59,8 +59,7 @@ class ExportResult: class ExporterMetricsT(Protocol): def export_operation( self, num_items: int - ) -> AbstractContextManager[ExportResult]: - ... + ) -> AbstractContextManager[ExportResult]: ... class NoOpExporterMetrics: @@ -99,9 +98,7 @@ def __init__( port = 80 component_type_value = ( - component_type.value - if component_type - else "unknown_otlp_exporter" + component_type.value if component_type else "unknown_otlp_exporter" ) count = _component_counter[component_type_value] _component_counter[component_type_value] = count + 1 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 e31c6a9ab6c..11bf9d683a8 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 @@ -157,13 +157,13 @@ def __init__( self._shutdown = False self._metrics = create_exporter_metrics( + OtelComponentTypeValues.OTLP_HTTP_LOG_EXPORTER, "logs", urlparse(self._endpoint), meter_provider, parse_boolean_environment_variable( OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), - component_type=OtelComponentTypeValues.OTLP_HTTP_LOG_EXPORTER, ) def _export( diff --git a/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py index 0a34404e3a2..8a53d9587a8 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py @@ -222,13 +222,13 @@ def __init__( self._shutdown = False self._metrics = create_exporter_metrics( + OtelComponentTypeValues.OTLP_HTTP_METRIC_EXPORTER, "metrics", urlparse(self._endpoint), meter_provider, parse_boolean_environment_variable( OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), - component_type=OtelComponentTypeValues.OTLP_HTTP_METRIC_EXPORTER, ) def _export( 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 f6a8c8fca4d..dc8eb71276c 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 @@ -152,13 +152,13 @@ def __init__( self._shutdown = False self._metrics = create_exporter_metrics( + OtelComponentTypeValues.OTLP_HTTP_SPAN_EXPORTER, "traces", urlparse(self._endpoint), meter_provider, parse_boolean_environment_variable( OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), - component_type=OtelComponentTypeValues.OTLP_HTTP_SPAN_EXPORTER, ) def _export( diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index 956d9f28bd7..09289e1310d 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -57,12 +57,19 @@ _create_log_record_with_exception, _set_log_record_exception_attributes, ) -from opentelemetry.sdk._logs._internal._logger_metrics import LoggerMetrics +from opentelemetry.sdk._logs._internal._logger_metrics import ( + LoggerMetricsT, + create_logger_metrics, +) from opentelemetry.sdk.environment_variables import ( OTEL_ATTRIBUTE_COUNT_LIMIT, OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, OTEL_SDK_DISABLED, ) +from opentelemetry.sdk.environment_variables._internal import ( + parse_boolean_environment_variable, +) from opentelemetry.sdk.resources import Resource from opentelemetry.sdk.util import ns_to_iso_str from opentelemetry.sdk.util._configurator import RuleBasedConfigurator @@ -77,6 +84,8 @@ ) from opentelemetry.util.types import AnyValue, _ExtendedAttributes +# pylint: disable=too-many-lines + _DEFAULT_OTEL_ATTRIBUTE_COUNT_LIMIT = 128 _ENV_VALUE_UNSET = "" @@ -675,7 +684,7 @@ def __init__( ], instrumentation_scope: InstrumentationScope, *, - logger_metrics: LoggerMetrics, + logger_metrics: LoggerMetricsT, _logger_config: _LoggerConfig, ): super().__init__( @@ -797,8 +806,11 @@ def __init__( self._multi_log_record_processor = ( multi_log_record_processor or SynchronousMultiLogRecordProcessor() ) - self._logger_metrics = LoggerMetrics( - meter_provider or get_meter_provider() + self._logger_metrics = create_logger_metrics( + meter_provider or get_meter_provider(), + parse_boolean_environment_variable( + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED + ), ) disabled = environ.get(OTEL_SDK_DISABLED, "") self._disabled = disabled.lower().strip() == "true" diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/_logger_metrics.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/_logger_metrics.py index 1f1ca83c3d5..76d5508bc47 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/_logger_metrics.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/_logger_metrics.py @@ -12,27 +12,37 @@ # See the License for the specific language governing permissions and # limitations under the License. +from typing import Protocol + from opentelemetry import metrics as metrics_api -from opentelemetry.sdk.environment_variables import ( - OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, -) -from opentelemetry.sdk.environment_variables._internal import ( - parse_boolean_environment_variable, -) from opentelemetry.semconv._incubating.metrics.otel_metrics import ( create_otel_sdk_log_created, ) +class LoggerMetricsT(Protocol): + def emit_log(self) -> None: ... + + +class NoOpLoggerMetrics: + def emit_log(self) -> None: + pass + + class LoggerMetrics: def __init__(self, meter_provider: metrics_api.MeterProvider) -> None: meter = meter_provider.get_meter("opentelemetry-sdk") self._created_logs = create_otel_sdk_log_created(meter) - self._disabled = not parse_boolean_environment_variable( - OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED - ) def emit_log(self) -> None: - if self._disabled: - return self._created_logs.add(1) + + +def create_logger_metrics( + meter_provider: metrics_api.MeterProvider, + enabled: bool, +) -> LoggerMetricsT: + if not enabled: + return NoOpLoggerMetrics() + + return LoggerMetrics(meter_provider) 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 132dfcd2390..95fd1bd71eb 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py @@ -39,7 +39,9 @@ from opentelemetry.sdk._shared_internal import ( BatchProcessor, DuplicateFilter, - ProcessorMetrics, +) +from opentelemetry.sdk._shared_internal._processor_metrics import ( + create_processor_metrics, ) from opentelemetry.sdk.environment_variables import ( OTEL_BLRP_EXPORT_TIMEOUT, @@ -190,11 +192,11 @@ def __init__( ): self._exporter = exporter self._shutdown = False - self._metrics = ProcessorMetrics( + self._metrics = create_processor_metrics( "logs", OtelComponentTypeValues.SIMPLE_LOG_PROCESSOR, meter_provider or get_meter_provider(), - disabled=not parse_boolean_environment_variable( + enabled=parse_boolean_environment_variable( OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), ) @@ -306,12 +308,12 @@ def __init__( export_timeout_millis, max_queue_size, "Log", - ProcessorMetrics( + create_processor_metrics( "logs", OtelComponentTypeValues.BATCHING_LOG_PROCESSOR, meter_provider or get_meter_provider(), capacity=max_queue_size, - disabled=not parse_boolean_environment_variable( + enabled=parse_boolean_environment_variable( OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), ), diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/__init__.py index cde19165d62..e58093be889 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/__init__.py @@ -37,7 +37,7 @@ set_value, ) from opentelemetry.sdk._shared_internal._processor_metrics import ( - ProcessorMetrics, + ProcessorMetricsT, ) from opentelemetry.util._once import Once @@ -101,7 +101,7 @@ def __init__( export_timeout_millis: float, max_queue_size: int, exporting: str, - metrics: ProcessorMetrics, + metrics: ProcessorMetricsT, ): self._bsp_reset_once = Once() self._exporter = exporter diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/_processor_metrics.py b/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/_processor_metrics.py index d5703733ae0..8afa00c66bd 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/_processor_metrics.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_shared_internal/_processor_metrics.py @@ -16,7 +16,7 @@ from collections import Counter from collections.abc import Callable -from typing import Literal +from typing import Literal, Protocol from opentelemetry.metrics import CallbackOptions, MeterProvider, Observation from opentelemetry.semconv._incubating.attributes.otel_attributes import ( @@ -37,6 +37,27 @@ _component_counter = Counter() +class ProcessorMetricsT(Protocol): + def register_queue_size( + self, get_queue_size: Callable[[], int] + ) -> None: ... + + def drop_items(self, count: int) -> None: ... + + def finish_items(self, count: int, error: Exception | None) -> None: ... + + +class NoOpProcessorMetrics: + def register_queue_size(self, get_queue_size: Callable[[], int]) -> None: + pass + + def drop_items(self, count: int) -> None: + pass + + def finish_items(self, count: int, error: Exception | None) -> None: + pass + + class ProcessorMetrics: def __init__( self, @@ -45,7 +66,6 @@ def __init__( meter_provider: MeterProvider, *, capacity: int | None = None, - disabled: bool = False, ) -> None: self._signal = signal meter = meter_provider.get_meter("opentelemetry-sdk") @@ -76,17 +96,12 @@ def __init__( ) self._processed = create_processed(meter) - self._disabled = disabled if capacity is not None: self._queue_capacity = create_queue_capacity(meter) - if not self._disabled: - self._queue_capacity.add(capacity, self._standard_attrs) + self._queue_capacity.add(capacity, self._standard_attrs) def register_queue_size(self, get_queue_size: Callable[[], int]) -> None: - if self._disabled: - return - def record_queue_size( _options: CallbackOptions, ) -> tuple[Observation]: @@ -109,13 +124,9 @@ def record_queue_size( ) def drop_items(self, count: int) -> None: - if self._disabled: - return self._processed.add(count, self._dropped_attrs) def finish_items(self, count: int, error: Exception | None) -> None: - if self._disabled: - return if not error: self._processed.add(count, self._standard_attrs) return @@ -124,3 +135,22 @@ def finish_items(self, count: int, error: Exception | None) -> None: ERROR_TYPE: type(error).__name__, } self._processed.add(count, attrs) + + +def create_processor_metrics( + signal: Literal["traces", "logs"], + component_type: OtelComponentTypeValues, + meter_provider: MeterProvider, + *, + capacity: int | None = None, + enabled: bool, +) -> ProcessorMetricsT: + if not enabled: + return NoOpProcessorMetrics() + + return ProcessorMetrics( + signal, + component_type, + meter_provider, + capacity=capacity, + ) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py index 66f327306a6..99f5132cc4f 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py @@ -39,6 +39,10 @@ from opentelemetry.sdk.environment_variables import ( OTEL_METRIC_EXPORT_INTERVAL, OTEL_METRIC_EXPORT_TIMEOUT, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, +) +from opentelemetry.sdk.environment_variables._internal import ( + parse_boolean_environment_variable, ) from opentelemetry.sdk.metrics._internal.aggregation import ( AggregationTemporality, @@ -67,7 +71,7 @@ ) from opentelemetry.util._once import Once -from ._metric_reader_metrics import MetricReaderMetrics +from ._metric_reader_metrics import create_metric_reader_metrics _logger = getLogger(__name__) @@ -331,8 +335,12 @@ def __init__( if otel_component_type else type(self).__qualname__ ) - self._metrics = MetricReaderMetrics( - self._otel_component_type, NoOpMeterProvider() + self._metrics = create_metric_reader_metrics( + self._otel_component_type, + NoOpMeterProvider(), + parse_boolean_environment_variable( + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED + ), ) @final @@ -390,8 +398,12 @@ def _receive_metrics( """Called by `MetricReader.collect` when it receives a batch of metrics""" def _set_meter_provider(self, meter_provider: MeterProvider) -> None: - self._metrics = MetricReaderMetrics( - self._otel_component_type, meter_provider + self._metrics = create_metric_reader_metrics( + self._otel_component_type, + meter_provider, + parse_boolean_environment_variable( + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED + ), ) def force_flush(self, timeout_millis: float = 10_000) -> bool: diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/_metric_reader_metrics.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/_metric_reader_metrics.py index b826091ac86..995207ea6c1 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/_metric_reader_metrics.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/_metric_reader_metrics.py @@ -1,12 +1,7 @@ from collections import Counter +from typing import Protocol from opentelemetry.metrics import MeterProvider -from opentelemetry.sdk.environment_variables import ( - OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, -) -from opentelemetry.sdk.environment_variables._internal import ( - parse_boolean_environment_variable, -) from opentelemetry.semconv._incubating.attributes.otel_attributes import ( OTEL_COMPONENT_NAME, OTEL_COMPONENT_TYPE, @@ -18,6 +13,15 @@ _component_counter = Counter() +class MetricReaderMetricsT(Protocol): + def record_collection(self, duration: float) -> None: ... + + +class NoOpMetricReaderMetrics: + def record_collection(self, duration: float) -> None: + pass + + class MetricReaderMetrics: def __init__( self, component_type: str, meter_provider: MeterProvider @@ -35,11 +39,17 @@ def __init__( self._collection_duration = ( create_otel_sdk_metric_reader_collection_duration(meter) ) - self._disabled = not parse_boolean_environment_variable( - OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED - ) def record_collection(self, duration: float) -> None: - if self._disabled: - return self._collection_duration.record(duration, self._standard_attrs) + + +def create_metric_reader_metrics( + component_type: str, + meter_provider: MeterProvider, + enabled: bool, +) -> MetricReaderMetricsT: + if not enabled: + return NoOpMetricReaderMetrics() + + return MetricReaderMetrics(component_type, meter_provider) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index 18fced70612..72830aab9f3 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -54,15 +54,19 @@ OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT, OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT, OTEL_LINK_ATTRIBUTE_COUNT_LIMIT, + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, OTEL_SDK_DISABLED, OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT, OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT, OTEL_SPAN_EVENT_COUNT_LIMIT, OTEL_SPAN_LINK_COUNT_LIMIT, ) +from opentelemetry.sdk.environment_variables._internal import ( + parse_boolean_environment_variable, +) from opentelemetry.sdk.resources import Resource from opentelemetry.sdk.trace import sampling -from opentelemetry.sdk.trace._tracer_metrics import TracerMetrics +from opentelemetry.sdk.trace._tracer_metrics import create_tracer_metrics from opentelemetry.sdk.trace.id_generator import IdGenerator, RandomIdGenerator from opentelemetry.sdk.util import BoundedList from opentelemetry.sdk.util._configurator import RuleBasedConfigurator @@ -1137,7 +1141,12 @@ def __init__( self._tracer_config = _tracer_config or _TracerConfig.default() meter_provider = meter_provider or metrics_api.get_meter_provider() - self._tracer_metrics = TracerMetrics(meter_provider) + self._tracer_metrics = create_tracer_metrics( + meter_provider, + parse_boolean_environment_variable( + OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED + ), + ) def _set_tracer_config(self, tracer_config: _TracerConfig): self._tracer_config = tracer_config diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/_tracer_metrics.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/_tracer_metrics.py index 8868a3cd4a0..9e59f789313 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/_tracer_metrics.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/_tracer_metrics.py @@ -15,14 +15,9 @@ from __future__ import annotations from collections.abc import Callable +from typing import Protocol from opentelemetry import metrics as metrics_api -from opentelemetry.sdk.environment_variables import ( - OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED, -) -from opentelemetry.sdk.environment_variables._internal import ( - parse_boolean_environment_variable, -) from opentelemetry.sdk.trace.sampling import Decision from opentelemetry.semconv._incubating.attributes.otel_attributes import ( OTEL_SPAN_PARENT_ORIGIN, @@ -36,24 +31,36 @@ from opentelemetry.trace.span import SpanContext +class TracerMetricsT(Protocol): + def start_span( + self, + parent_span_context: SpanContext | None, + sampling_decision: Decision, + ) -> Callable[[], None]: ... + + +# pylint: disable=no-self-use +class NoOpTracerMetrics: + def start_span( + self, + parent_span_context: SpanContext | None, + sampling_decision: Decision, + ) -> Callable[[], None]: + return noop + + class TracerMetrics: def __init__(self, meter_provider: metrics_api.MeterProvider) -> None: meter = meter_provider.get_meter("opentelemetry-sdk") self._started_spans = create_otel_sdk_span_started(meter) self._live_spans = create_otel_sdk_span_live(meter) - self._disabled = not parse_boolean_environment_variable( - OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED - ) def start_span( self, parent_span_context: SpanContext | None, sampling_decision: Decision, ) -> Callable[[], None]: - if self._disabled: - return noop - sampling_result_value = sampling_result(sampling_decision) self._started_spans.add( 1, @@ -72,13 +79,21 @@ def start_span( self._live_spans.add(1, live_span_attrs) def end_span() -> None: - if self._disabled: - return self._live_spans.add(-1, live_span_attrs) return end_span +def create_tracer_metrics( + meter_provider: metrics_api.MeterProvider, + enabled: bool, +) -> TracerMetricsT: + if not enabled: + return NoOpTracerMetrics() + + return TracerMetrics(meter_provider) + + def noop() -> None: pass diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py index 666623a746f..7fae9fdcdea 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py @@ -27,7 +27,12 @@ set_value, ) from opentelemetry.metrics import MeterProvider, get_meter_provider -from opentelemetry.sdk._shared_internal import BatchProcessor, ProcessorMetrics +from opentelemetry.sdk._shared_internal import ( + BatchProcessor, +) +from opentelemetry.sdk._shared_internal._processor_metrics import ( + create_processor_metrics, +) from opentelemetry.sdk.environment_variables import ( OTEL_BSP_EXPORT_TIMEOUT, OTEL_BSP_MAX_EXPORT_BATCH_SIZE, @@ -106,11 +111,11 @@ def __init__( meter_provider: MeterProvider | None = None, ): self.span_exporter = span_exporter - self._metrics = ProcessorMetrics( + self._metrics = create_processor_metrics( "traces", OtelComponentTypeValues.SIMPLE_SPAN_PROCESSOR, meter_provider or get_meter_provider(), - disabled=not parse_boolean_environment_variable( + enabled=parse_boolean_environment_variable( OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), ) @@ -203,12 +208,12 @@ def __init__( export_timeout_millis, max_queue_size, "Span", - ProcessorMetrics( + create_processor_metrics( "traces", OtelComponentTypeValues.BATCHING_SPAN_PROCESSOR, meter_provider or get_meter_provider(), capacity=max_queue_size, - disabled=not parse_boolean_environment_variable( + enabled=parse_boolean_environment_variable( OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), ), diff --git a/opentelemetry-sdk/tests/logs/test_logs.py b/opentelemetry-sdk/tests/logs/test_logs.py index deb242f4a11..54c9218ad91 100644 --- a/opentelemetry-sdk/tests/logs/test_logs.py +++ b/opentelemetry-sdk/tests/logs/test_logs.py @@ -20,7 +20,6 @@ from opentelemetry._logs import LogRecord, SeverityNumber from opentelemetry.attributes import BoundedAttributes from opentelemetry.context import get_current -from opentelemetry.metrics import NoOpMeterProvider from opentelemetry.sdk._logs import ( Logger, LoggerProvider, @@ -28,12 +27,12 @@ ReadWriteLogRecord, ) from opentelemetry.sdk._logs._internal import ( - LoggerMetrics, NoOpLogger, SynchronousMultiLogRecordProcessor, _disable_logger_configurator, _LoggerConfig, _RuleBasedLoggerConfigurator, + create_logger_metrics, ) from opentelemetry.sdk.environment_variables import OTEL_SDK_DISABLED from opentelemetry.sdk.resources import Resource @@ -289,7 +288,7 @@ def _get_logger(): "schema_url", {"an": "attribute"}, ), - logger_metrics=LoggerMetrics(NoOpMeterProvider()), + logger_metrics=create_logger_metrics(Mock(), False), _logger_config=_LoggerConfig.default(), ) return logger, log_record_processor_mock From bca66cd9bc664dd4bfdaf5ac98fd901676996603 Mon Sep 17 00:00:00 2001 From: Lukas Hering Date: Sun, 3 May 2026 00:53:29 -0400 Subject: [PATCH 08/10] fix test errors --- .../exporter/otlp/proto/http/metric_exporter/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py index 8a53d9587a8..edd3fa655f4 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp-proto-http/src/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py @@ -407,13 +407,13 @@ def force_flush(self, timeout_millis: float = 10_000) -> bool: def set_meter_provider(self, meter_provider: MeterProvider) -> None: self._metrics = create_exporter_metrics( + OtelComponentTypeValues.OTLP_HTTP_METRIC_EXPORTER, "metrics", urlparse(self._endpoint), meter_provider, parse_boolean_environment_variable( OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED ), - component_type=OtelComponentTypeValues.OTLP_HTTP_METRIC_EXPORTER, ) From e67e6b9c37cdca0c2df05d23492742e1c6f4102f Mon Sep 17 00:00:00 2001 From: Lukas Hering Date: Sun, 3 May 2026 00:58:18 -0400 Subject: [PATCH 09/10] fix proto common test errors --- .../tests/test_exporter_metrics.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_exporter_metrics.py b/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_exporter_metrics.py index dfc0e18a0c2..2144ab64774 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_exporter_metrics.py +++ b/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_exporter_metrics.py @@ -35,11 +35,11 @@ def test_factory_returns_noop_when_disabled(self): "_exporter_metrics.get_meter_provider" ) as get_meter_provider: metrics = create_exporter_metrics( + OtelComponentTypeValues.OTLP_HTTP_SPAN_EXPORTER, "traces", urlparse("http://localhost:4318/v1/traces"), meter_provider, False, - component_type=OtelComponentTypeValues.OTLP_HTTP_SPAN_EXPORTER, ) self.assertIsInstance(metrics, NoOpExporterMetrics) @@ -51,11 +51,11 @@ def test_factory_returns_exporter_metrics_when_enabled(self): meter_provider.get_meter.return_value = Mock() metrics = create_exporter_metrics( + OtelComponentTypeValues.OTLP_HTTP_SPAN_EXPORTER, "traces", urlparse("http://localhost:4318/v1/traces"), meter_provider, True, - component_type=OtelComponentTypeValues.OTLP_HTTP_SPAN_EXPORTER, ) self.assertIsInstance(metrics, ExporterMetrics) From 7bda95ef7069685dc2e501ae976337188257fa18 Mon Sep 17 00:00:00 2001 From: Lukas Hering Date: Sun, 3 May 2026 15:08:50 -0400 Subject: [PATCH 10/10] small tweak to exporter metrics test --- .../tests/test_exporter_metrics.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_exporter_metrics.py b/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_exporter_metrics.py index 2144ab64774..0e74b6d6512 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_exporter_metrics.py +++ b/exporter/opentelemetry-exporter-otlp-proto-common/tests/test_exporter_metrics.py @@ -68,7 +68,3 @@ def test_noop_export_operation_yields_result(self): result.error = RuntimeError("error") self.assertIsInstance(result.error, RuntimeError) - - -if __name__ == "__main__": - unittest.main()