Coverage for anaconda_opentelemetry/_compat.py: 84%
43 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-01 20:06 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-01 20:06 +0000
1# -*- coding: utf-8 -*-
2# SPDX-FileCopyrightText: 2025 Anaconda, Inc
3# SPDX-License-Identifier: Apache-2.0
5# _compat.py
6"""
7Anaconda Telemetry - single point of contact with private OpenTelemetry APIs.
9Every OpenTelemetry symbol upstream does not guarantee (underscore-prefixed module
10or name) is imported here and nowhere else, so a ceiling bump is a one-file audit.
11``docs/source/otel-private-api.md`` holds the inventory and the supported range
12(opentelemetry-sdk >=1.40.0,<1.44).
14A private import that disappears degrades to a no-op with one warning, so it cannot
15raise out of a log handler and take down the host application.
17Re-exports are annotated ``Any``: each name is bound to unrelated types in the
18working and degraded branches.
19"""
21from __future__ import annotations
23import logging
24from typing import Any
26__all__ = [
27 "OTEL_PRIVATE_LOGS_AVAILABLE",
28 "BatchLogRecordProcessor",
29 "ConsoleLogRecordExporter",
30 "GaugeInstrument",
31 "LoggerProvider",
32 "LoggingHandler",
33 "LogRecordExporter",
34 "get_logger_provider",
35 "set_logger_provider",
36]
39class _UnavailablePrivateAPI:
40 """Inert stand-in: constructible and subclassable, every operation a no-op."""
42 def __init__(self, *args: Any, **kwargs: Any) -> None:
43 pass
45 def __getattr__(self, name: str) -> Any:
46 return _UnavailablePrivateAPI()
48 def __call__(self, *args: Any, **kwargs: Any) -> Any:
49 return None
51 def __bool__(self) -> bool:
52 return False
55def _unavailable(*args: Any, **kwargs: Any) -> None:
56 return None
59set_logger_provider: Any
60get_logger_provider: Any
61LoggerProvider: Any
62LoggingHandler: Any
63BatchLogRecordProcessor: Any
64ConsoleLogRecordExporter: Any
65LogRecordExporter: Any
67try:
68 import opentelemetry._logs as _api_logs
69 import opentelemetry.sdk._logs as _sdk_logs
70 import opentelemetry.sdk._logs.export as _sdk_logs_export
72 set_logger_provider = _api_logs.set_logger_provider
73 get_logger_provider = _api_logs.get_logger_provider
75 LoggerProvider = _sdk_logs.LoggerProvider
76 LoggingHandler = _sdk_logs.LoggingHandler
78 # `LogExporter` is a deprecated alias that warns on subclassing; both names
79 # exist across 1.40 - 1.43.
80 LogRecordExporter = _sdk_logs_export.LogRecordExporter
81 BatchLogRecordProcessor = _sdk_logs_export.BatchLogRecordProcessor
82 ConsoleLogRecordExporter = _sdk_logs_export.ConsoleLogRecordExporter
84 OTEL_PRIVATE_LOGS_AVAILABLE = True
85except Exception as _exc: # pragma: no cover - only on an unsupported SDK
86 logging.getLogger(__package__).warning(
87 "Anaconda OpenTelemetry: the installed opentelemetry-sdk does not expose the "
88 "private logs API this package requires (%s: %s). Log telemetry is disabled; "
89 "metrics and tracing are unaffected. Supported range: >=1.40.0,<1.44.",
90 type(_exc).__name__,
91 _exc,
92 )
93 set_logger_provider = _unavailable
94 get_logger_provider = _unavailable
95 LoggerProvider = _UnavailablePrivateAPI
96 LoggingHandler = _UnavailablePrivateAPI
97 LogRecordExporter = _UnavailablePrivateAPI
98 BatchLogRecordProcessor = _UnavailablePrivateAPI
99 ConsoleLogRecordExporter = _UnavailablePrivateAPI
100 OTEL_PRIVATE_LOGS_AVAILABLE = False
103def _resolve_gauge_instrument() -> Any:
104 """Return the synchronous gauge instrument class.
106 `opentelemetry.sdk.metrics` still exposes only `_Gauge` as of 1.43. The public
107 name is tried first so a promotion needs no code change. Used as a key in the
108 aggregation-temporality maps, where a miss silently falls back to the reader
109 default -- hence the warning.
110 """
111 import opentelemetry.sdk.metrics as _sdk_metrics
113 for name in ("Gauge", "_Gauge"):
114 instrument = getattr(_sdk_metrics, name, None)
115 if instrument is not None:
116 return instrument
117 logging.getLogger(__package__).warning(
118 "Anaconda OpenTelemetry: no Gauge instrument found in opentelemetry.sdk.metrics; "
119 "gauge aggregation temporality will fall back to the metric reader default."
120 )
121 return None
124GaugeInstrument: Any = _resolve_gauge_instrument()