|
3 | 3 | # Copyright (c) Microsoft Corporation.
|
4 | 4 | # Licensed under the MIT License.
|
5 | 5 | # ------------------------------------
|
6 |
| -from typing import Any, Optional, TextIO, Union, cast |
7 |
| - |
8 |
| -import io |
| 6 | +from typing import Optional |
9 | 7 | import logging
|
10 |
| -import sys |
11 |
| - |
12 | 8 | from enum import Enum
|
13 | 9 |
|
14 | 10 | from azure.core.tracing import AbstractSpan, SpanKind # type: ignore
|
@@ -157,150 +153,3 @@ def start_span(
|
157 | 153 | span.add_attribute(GEN_AI_REQUEST_RESPONSE_FORMAT, response_format)
|
158 | 154 |
|
159 | 155 | return span
|
160 |
| - |
161 |
| - |
162 |
| -# Internal helper functions to enable OpenTelemetry, used by both sync and async clients |
163 |
| -def _get_trace_exporter(destination: Union[TextIO, str, None]) -> Any: |
164 |
| - if isinstance(destination, str): |
165 |
| - # `destination` is the OTLP endpoint |
166 |
| - # See: https://opentelemetry-python.readthedocs.io/en/latest/exporter/otlp/otlp.html#usage |
167 |
| - try: |
168 |
| - from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter # type: ignore |
169 |
| - except ModuleNotFoundError as e: |
170 |
| - raise ModuleNotFoundError( |
171 |
| - "OpenTelemetry OTLP exporter is not installed. " |
172 |
| - + "Please install it using 'pip install opentelemetry-exporter-otlp-proto-grpc'" |
173 |
| - ) from e |
174 |
| - return OTLPSpanExporter(endpoint=destination) |
175 |
| - |
176 |
| - if isinstance(destination, io.TextIOWrapper): |
177 |
| - if destination is sys.stdout: |
178 |
| - # See: https://opentelemetry-python.readthedocs.io/en/latest/sdk/trace.export.html#opentelemetry.sdk.trace.export.ConsoleSpanExporter # pylint: disable=line-too-long |
179 |
| - try: |
180 |
| - from opentelemetry.sdk.trace.export import ConsoleSpanExporter |
181 |
| - except ModuleNotFoundError as e: |
182 |
| - raise ModuleNotFoundError( |
183 |
| - "OpenTelemetry SDK is not installed. Please install it using 'pip install opentelemetry-sdk'" |
184 |
| - ) from e |
185 |
| - |
186 |
| - return ConsoleSpanExporter() |
187 |
| - raise ValueError("Only `sys.stdout` is supported at the moment for type `TextIO`") |
188 |
| - |
189 |
| - return None |
190 |
| - |
191 |
| - |
192 |
| -def _get_log_exporter(destination: Union[TextIO, str, None]) -> Any: |
193 |
| - if isinstance(destination, str): |
194 |
| - # `destination` is the OTLP endpoint |
195 |
| - # See: https://opentelemetry-python.readthedocs.io/en/latest/exporter/otlp/otlp.html#usage |
196 |
| - try: |
197 |
| - # _logs are considered beta (not internal) in OpenTelemetry Python API/SDK. |
198 |
| - # So it's ok to use it for local development, but we'll swallow |
199 |
| - # any errors in case of any breaking changes on OTel side. |
200 |
| - from opentelemetry.exporter.otlp.proto.grpc._log_exporter import OTLPLogExporter # type: ignore # pylint: disable=import-error,no-name-in-module |
201 |
| - except Exception as ex: # pylint: disable=broad-exception-caught |
202 |
| - # since OTel logging is still in beta in Python, we're going to swallow any errors |
203 |
| - # and just warn about them. |
204 |
| - logger.warning("Failed to configure OpenTelemetry logging.", exc_info=ex) |
205 |
| - return None |
206 |
| - |
207 |
| - return OTLPLogExporter(endpoint=destination) |
208 |
| - |
209 |
| - if isinstance(destination, io.TextIOWrapper): |
210 |
| - if destination is sys.stdout: |
211 |
| - # See: https://opentelemetry-python.readthedocs.io/en/latest/sdk/trace.export.html#opentelemetry.sdk.trace.export.ConsoleSpanExporter # pylint: disable=line-too-long |
212 |
| - try: |
213 |
| - from opentelemetry.sdk._logs.export import ConsoleLogExporter |
214 |
| - |
215 |
| - return ConsoleLogExporter() |
216 |
| - except ModuleNotFoundError as ex: |
217 |
| - # since OTel logging is still in beta in Python, we're going to swallow any errors |
218 |
| - # and just warn about them. |
219 |
| - logger.warning("Failed to configure OpenTelemetry logging.", exc_info=ex) |
220 |
| - return None |
221 |
| - raise ValueError("Only `sys.stdout` is supported at the moment for type `TextIO`") |
222 |
| - |
223 |
| - return None |
224 |
| - |
225 |
| - |
226 |
| -def _configure_tracing(span_exporter: Any) -> None: |
227 |
| - if span_exporter is None: |
228 |
| - return |
229 |
| - |
230 |
| - try: |
231 |
| - from opentelemetry import trace |
232 |
| - from opentelemetry.sdk.trace import TracerProvider |
233 |
| - from opentelemetry.sdk.trace.export import SimpleSpanProcessor |
234 |
| - except ModuleNotFoundError as e: |
235 |
| - raise ModuleNotFoundError( |
236 |
| - "OpenTelemetry SDK is not installed. Please install it using 'pip install opentelemetry-sdk'" |
237 |
| - ) from e |
238 |
| - |
239 |
| - # if tracing was not setup before, we need to create a new TracerProvider |
240 |
| - if not isinstance(trace.get_tracer_provider(), TracerProvider): |
241 |
| - # If the provider is NoOpTracerProvider, we need to create a new TracerProvider |
242 |
| - provider = TracerProvider() |
243 |
| - trace.set_tracer_provider(provider) |
244 |
| - |
245 |
| - # get_tracer_provider returns opentelemetry.trace.TracerProvider |
246 |
| - # however, we have opentelemetry.sdk.trace.TracerProvider, which implements |
247 |
| - # add_span_processor method, though we need to cast it to fix type checking. |
248 |
| - provider = cast(TracerProvider, trace.get_tracer_provider()) |
249 |
| - provider.add_span_processor(SimpleSpanProcessor(span_exporter)) |
250 |
| - |
251 |
| - |
252 |
| -def _configure_logging(log_exporter: Any) -> None: |
253 |
| - if log_exporter is None: |
254 |
| - return |
255 |
| - |
256 |
| - try: |
257 |
| - # _events and _logs are considered beta (not internal) in |
258 |
| - # OpenTelemetry Python API/SDK. |
259 |
| - # So it's ok to use them for local development, but we'll swallow |
260 |
| - # any errors in case of any breaking changes on OTel side. |
261 |
| - from opentelemetry import _logs, _events |
262 |
| - from opentelemetry.sdk._logs import LoggerProvider # pylint: disable=import-error,no-name-in-module |
263 |
| - from opentelemetry.sdk._events import EventLoggerProvider # pylint: disable=import-error,no-name-in-module |
264 |
| - from opentelemetry.sdk._logs.export import ( |
265 |
| - SimpleLogRecordProcessor, |
266 |
| - ) # pylint: disable=import-error,no-name-in-module |
267 |
| - |
268 |
| - if not isinstance(_logs.get_logger_provider(), LoggerProvider): |
269 |
| - logger_provider = LoggerProvider() |
270 |
| - _logs.set_logger_provider(logger_provider) |
271 |
| - |
272 |
| - # get_logger_provider returns opentelemetry._logs.LoggerProvider |
273 |
| - # however, we have opentelemetry.sdk._logs.LoggerProvider, which implements |
274 |
| - # add_log_record_processor method, though we need to cast it to fix type checking. |
275 |
| - logger_provider = cast(LoggerProvider, _logs.get_logger_provider()) |
276 |
| - logger_provider.add_log_record_processor(SimpleLogRecordProcessor(log_exporter)) |
277 |
| - _events.set_event_logger_provider(EventLoggerProvider(logger_provider)) |
278 |
| - except Exception as ex: # pylint: disable=broad-exception-caught |
279 |
| - # since OTel logging is still in beta in Python, we're going to swallow any errors |
280 |
| - # and just warn about them. |
281 |
| - logger.warning("Failed to configure OpenTelemetry logging.", exc_info=ex) |
282 |
| - |
283 |
| - |
284 |
| -def enable_telemetry(destination: Union[TextIO, str, None] = None, **kwargs) -> None: # pylint: disable=unused-argument |
285 |
| - """Enable tracing and logging to console (sys.stdout), or to an OpenTelemetry Protocol (OTLP) endpoint. |
286 |
| -
|
287 |
| - :param destination: `sys.stdout` to print telemetry to console or a string holding the |
288 |
| - OpenTelemetry protocol (OTLP) endpoint. |
289 |
| - If not provided, this method enables instrumentation, but does not configure OpenTelemetry |
290 |
| - SDK to export traces and logs. |
291 |
| - :type destination: Union[TextIO, str, None] |
292 |
| - """ |
293 |
| - span_exporter = _get_trace_exporter(destination) |
294 |
| - _configure_tracing(span_exporter) |
295 |
| - |
296 |
| - log_exporter = _get_log_exporter(destination) |
297 |
| - _configure_logging(log_exporter) |
298 |
| - |
299 |
| - try: |
300 |
| - from azure.ai.agents.telemetry import AIAgentsInstrumentor |
301 |
| - |
302 |
| - agents_instrumentor = AIAgentsInstrumentor() |
303 |
| - if not agents_instrumentor.is_instrumented(): |
304 |
| - agents_instrumentor.instrument() |
305 |
| - except Exception as exc: # pylint: disable=broad-exception-caught |
306 |
| - logger.warning("Could not call `AIAgentsInstrumentor().instrument()`", exc_info=exc) |
0 commit comments