Skip to content

Commit 2574707

Browse files
puskardeblzchenocelotl
authored
Adds support OTEL_SDK_DISABLED environment variable (#3648)
* Adds support OTEL_SDK_DISABLED environment variable * Pass schema_url and version to NoOpMeter and NoOpLogger, implement comments from review * Add CHANGELOG entry * Fix lint error * Suppress lint errors due to returning a NoOpTracer when SDK is disabled --------- Co-authored-by: Leighton Chen <lechen@microsoft.com> Co-authored-by: Diego Hurtado <ocelotl@users.noreply.github.com>
1 parent 6dd85fc commit 2574707

File tree

8 files changed

+54
-2
lines changed

8 files changed

+54
-2
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
([#3751](https://github.com/open-telemetry/opentelemetry-python/pull/3751))
1414
- bump mypy to 0.982
1515
([#3776](https://github.com/open-telemetry/opentelemetry-python/pull/3776))
16+
- Add support for OTEL_SDK_DISABLED environment variable
17+
([#3648](https://github.com/open-telemetry/opentelemetry-python/pull/3648))
1618
- Fix ValueError message for PeriodicExportingMetricsReader
1719
([#3769](https://github.com/open-telemetry/opentelemetry-python/pull/3769))
1820

opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
from opentelemetry.sdk.environment_variables import (
3838
OTEL_ATTRIBUTE_COUNT_LIMIT,
3939
OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT,
40+
OTEL_SDK_DISABLED,
4041
)
4142
from opentelemetry.sdk.resources import Resource
4243
from opentelemetry.sdk.util import ns_to_iso_str
@@ -607,6 +608,8 @@ def __init__(
607608
self._multi_log_record_processor = (
608609
multi_log_record_processor or SynchronousMultiLogRecordProcessor()
609610
)
611+
disabled = environ.get(OTEL_SDK_DISABLED, "")
612+
self._disabled = disabled.lower().strip() == "true"
610613
self._at_exit_handler = None
611614
if shutdown_on_exit:
612615
self._at_exit_handler = atexit.register(self.shutdown)
@@ -621,6 +624,9 @@ def get_logger(
621624
version: Optional[str] = None,
622625
schema_url: Optional[str] = None,
623626
) -> Logger:
627+
if self._disabled:
628+
_logger.warning("SDK is disabled.")
629+
return NoOpLogger(name, version=version, schema_url=schema_url)
624630
return Logger(
625631
self._resource,
626632
self._multi_log_record_processor,

opentelemetry-sdk/src/opentelemetry/sdk/environment_variables.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
OTEL_SDK_DISABLED = "OTEL_SDK_DISABLED"
16+
"""
17+
.. envvar:: OTEL_SDK_DISABLED
18+
19+
The :envvar:`OTEL_SDK_DISABLED` environment variable disables the SDK for all signals
20+
Default: "false"
21+
"""
22+
1523
OTEL_RESOURCE_ATTRIBUTES = "OTEL_RESOURCE_ATTRIBUTES"
1624
"""
1725
.. envvar:: OTEL_RESOURCE_ATTRIBUTES

opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
from atexit import register, unregister
1616
from logging import getLogger
17+
from os import environ
1718
from threading import Lock
1819
from time import time_ns
1920
from typing import Optional, Sequence
@@ -32,6 +33,7 @@
3233
)
3334
from opentelemetry.metrics import UpDownCounter as APIUpDownCounter
3435
from opentelemetry.metrics import _Gauge as APIGauge
36+
from opentelemetry.sdk.environment_variables import OTEL_SDK_DISABLED
3537
from opentelemetry.sdk.metrics._internal.exceptions import MetricsTimeoutError
3638
from opentelemetry.sdk.metrics._internal.instrument import (
3739
_Counter,
@@ -394,6 +396,8 @@ def __init__(
394396
self._measurement_consumer = SynchronousMeasurementConsumer(
395397
sdk_config=self._sdk_config
396398
)
399+
disabled = environ.get(OTEL_SDK_DISABLED, "")
400+
self._disabled = disabled.lower().strip() == "true"
397401

398402
if shutdown_on_exit:
399403
self._atexit_handler = register(self.shutdown)
@@ -512,6 +516,10 @@ def get_meter(
512516
schema_url: Optional[str] = None,
513517
) -> Meter:
514518

519+
if self._disabled:
520+
_logger.warning("SDK is disabled.")
521+
return NoOpMeter(name, version=version, schema_url=schema_url)
522+
515523
if self._shutdown:
516524
_logger.warning(
517525
"A shutdown `MeterProvider` can not provide a `Meter`"

opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT,
5050
OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT,
5151
OTEL_LINK_ATTRIBUTE_COUNT_LIMIT,
52+
OTEL_SDK_DISABLED,
5253
OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT,
5354
OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT,
5455
OTEL_SPAN_EVENT_COUNT_LIMIT,
@@ -62,7 +63,7 @@
6263
InstrumentationInfo,
6364
InstrumentationScope,
6465
)
65-
from opentelemetry.trace import SpanContext
66+
from opentelemetry.trace import NoOpTracer, SpanContext
6667
from opentelemetry.trace.status import Status, StatusCode
6768
from opentelemetry.util import types
6869
from opentelemetry.util._decorator import _agnosticcontextmanager
@@ -1176,6 +1177,8 @@ def __init__(
11761177
sampler = sampling._get_from_env_or_default()
11771178
self.sampler = sampler
11781179
self._span_limits = span_limits or SpanLimits()
1180+
disabled = environ.get(OTEL_SDK_DISABLED, "")
1181+
self._disabled = disabled.lower().strip() == "true"
11791182
self._atexit_handler = None
11801183

11811184
if shutdown_on_exit:
@@ -1191,6 +1194,9 @@ def get_tracer(
11911194
instrumenting_library_version: typing.Optional[str] = None,
11921195
schema_url: typing.Optional[str] = None,
11931196
) -> "trace_api.Tracer":
1197+
if self._disabled:
1198+
logger.warning("SDK is disabled.")
1199+
return NoOpTracer()
11941200
if not instrumenting_module_name: # Reject empty strings too.
11951201
instrumenting_module_name = ""
11961202
logger.error("get_tracer called with missing module name.")

opentelemetry-sdk/tests/logs/test_logs.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@
1515
# pylint: disable=protected-access
1616

1717
import unittest
18-
from unittest.mock import patch
18+
from unittest.mock import Mock, patch
1919

2020
from opentelemetry.sdk._logs import LoggerProvider
2121
from opentelemetry.sdk._logs._internal import (
22+
NoOpLogger,
2223
SynchronousMultiLogRecordProcessor,
2324
)
25+
from opentelemetry.sdk.environment_variables import OTEL_SDK_DISABLED
2426
from opentelemetry.sdk.resources import Resource
2527

2628

@@ -61,6 +63,11 @@ def test_get_logger(self):
6163
logger._instrumentation_scope.schema_url, "schema_url"
6264
)
6365

66+
@patch.dict("os.environ", {OTEL_SDK_DISABLED: "true"})
67+
def test_get_logger_with_sdk_disabled(self):
68+
logger = LoggerProvider().get_logger(Mock())
69+
self.assertIsInstance(logger, NoOpLogger)
70+
6471
@patch.object(Resource, "create")
6572
def test_logger_provider_init(self, resource_patch):
6673
logger_provider = LoggerProvider()

opentelemetry-sdk/tests/metrics/test_metrics.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from unittest.mock import MagicMock, Mock, patch
2020

2121
from opentelemetry.metrics import NoOpMeter
22+
from opentelemetry.sdk.environment_variables import OTEL_SDK_DISABLED
2223
from opentelemetry.sdk.metrics import (
2324
Counter,
2425
Histogram,
@@ -465,6 +466,11 @@ def test_create_observable_up_down_counter(self):
465466
)
466467
self.assertEqual(observable_up_down_counter.name, "name")
467468

469+
@patch.dict("os.environ", {OTEL_SDK_DISABLED: "true"})
470+
def test_get_meter_with_sdk_disabled(self):
471+
meter_provider = MeterProvider()
472+
self.assertIsInstance(meter_provider.get_meter(Mock()), NoOpMeter)
473+
468474

469475
class InMemoryMetricExporter(MetricExporter):
470476
def __init__(self):

opentelemetry-sdk/tests/trace/test_trace.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
# pylint: disable=too-many-lines
16+
# pylint: disable=no-member
1617

1718
import shutil
1819
import subprocess
@@ -33,6 +34,7 @@
3334
OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT,
3435
OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT,
3536
OTEL_LINK_ATTRIBUTE_COUNT_LIMIT,
37+
OTEL_SDK_DISABLED,
3638
OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT,
3739
OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT,
3840
OTEL_SPAN_EVENT_COUNT_LIMIT,
@@ -162,6 +164,13 @@ def test_tracer_provider_accepts_concurrent_multi_span_processor(self):
162164
span_processor, tracer_provider._active_span_processor
163165
)
164166

167+
@mock.patch.dict("os.environ", {OTEL_SDK_DISABLED: "true"})
168+
def test_get_tracer_with_sdk_disabled(self):
169+
tracer_provider = trace.TracerProvider()
170+
self.assertIsInstance(
171+
tracer_provider.get_tracer(Mock()), trace_api.NoOpTracer
172+
)
173+
165174

166175
class TestTracerSampling(unittest.TestCase):
167176
def tearDown(self):

0 commit comments

Comments
 (0)