about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/azure/monitor/opentelemetry/_configure.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/azure/monitor/opentelemetry/_configure.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-4a52a71956a8d46fcb7294ac71734504bb09bcc2.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/azure/monitor/opentelemetry/_configure.py')
-rw-r--r--.venv/lib/python3.12/site-packages/azure/monitor/opentelemetry/_configure.py288
1 files changed, 288 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/azure/monitor/opentelemetry/_configure.py b/.venv/lib/python3.12/site-packages/azure/monitor/opentelemetry/_configure.py
new file mode 100644
index 00000000..c9910392
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/azure/monitor/opentelemetry/_configure.py
@@ -0,0 +1,288 @@
+# -------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License in the project root for
+# license information.
+# --------------------------------------------------------------------------
+from functools import cached_property
+from logging import getLogger
+from typing import Dict, List, cast
+
+from opentelemetry._events import _set_event_logger_provider
+from opentelemetry._logs import set_logger_provider
+from opentelemetry.instrumentation.dependencies import (
+    get_dist_dependency_conflicts,
+)
+from opentelemetry.instrumentation.instrumentor import (  # type: ignore
+    BaseInstrumentor,
+)
+from opentelemetry.metrics import set_meter_provider
+from opentelemetry.sdk._events import EventLoggerProvider
+from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
+from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
+from opentelemetry.sdk.metrics import MeterProvider
+from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
+from opentelemetry.sdk.metrics.view import View
+from opentelemetry.sdk.resources import Resource
+from opentelemetry.sdk.trace import TracerProvider
+from opentelemetry.sdk.trace.export import BatchSpanProcessor
+from opentelemetry.trace import set_tracer_provider
+from opentelemetry.util._importlib_metadata import (
+    EntryPoint,
+    distributions,
+    entry_points,
+)
+
+from azure.core.settings import settings
+from azure.core.tracing.ext.opentelemetry_span import OpenTelemetrySpan
+from azure.monitor.opentelemetry._constants import (
+    _ALL_SUPPORTED_INSTRUMENTED_LIBRARIES,
+    _AZURE_SDK_INSTRUMENTATION_NAME,
+    DISABLE_LOGGING_ARG,
+    DISABLE_METRICS_ARG,
+    DISABLE_TRACING_ARG,
+    ENABLE_LIVE_METRICS_ARG,
+    LOGGER_NAME_ARG,
+    RESOURCE_ARG,
+    SAMPLING_RATIO_ARG,
+    SPAN_PROCESSORS_ARG,
+    VIEWS_ARG,
+)
+from azure.monitor.opentelemetry._types import ConfigurationValue
+from azure.monitor.opentelemetry.exporter._quickpulse import (  # pylint: disable=import-error,no-name-in-module
+    enable_live_metrics,
+)
+from azure.monitor.opentelemetry.exporter._quickpulse._processor import (  # pylint: disable=import-error,no-name-in-module
+    _QuickpulseLogRecordProcessor,
+    _QuickpulseSpanProcessor,
+)
+from azure.monitor.opentelemetry.exporter import (  # pylint: disable=import-error,no-name-in-module
+    ApplicationInsightsSampler,
+    AzureMonitorLogExporter,
+    AzureMonitorMetricExporter,
+    AzureMonitorTraceExporter,
+)
+from azure.monitor.opentelemetry.exporter._utils import (  # pylint: disable=import-error,no-name-in-module
+    _is_attach_enabled,
+    _is_on_functions,
+)
+from azure.monitor.opentelemetry._diagnostics.diagnostic_logging import (
+    _DISTRO_DETECTS_ATTACH,
+    AzureDiagnosticLogging,
+)
+from azure.monitor.opentelemetry._utils.configurations import (
+    _get_configurations,
+    _is_instrumentation_enabled,
+)
+
+_logger = getLogger(__name__)
+
+
+def configure_azure_monitor(**kwargs) -> None:  # pylint: disable=C4758
+    """This function works as a configuration layer that allows the
+    end user to configure OpenTelemetry and Azure monitor components. The
+    configuration can be done via arguments passed to this function.
+
+    :keyword str connection_string: Connection string for your Application Insights resource.
+    :keyword credential: Token credential, such as `ManagedIdentityCredential` or `ClientSecretCredential`,
+     used for Azure Active Directory (AAD) authentication. Defaults to `None`.
+    :paramtype credential: ~azure.core.credentials.TokenCredential or None
+    :keyword bool disable_offline_storage: Boolean value to determine whether to disable storing failed
+     telemetry records for retry. Defaults to `False`.
+    :keyword str logger_name: The name of the Python logger that telemetry will be collected.
+    :keyword dict instrumentation_options: A nested dictionary that determines which instrumentations
+     to enable or disable.  Instrumentations are referred to by their Library Names. For example,
+     `{"azure_sdk": {"enabled": False}, "flask": {"enabled": False}, "django": {"enabled": True}}`
+     will disable Azure Core Tracing and the Flask instrumentation but leave Django and the other default
+     instrumentations enabled.
+    :keyword ~opentelemetry.sdk.resources.Resource resource: OpenTelemetry Resource object. Passed in Resource
+     Attributes take priority over default attributes and those from Resource Detectors.
+    :keyword list[~opentelemetry.sdk.trace.SpanProcessor] span_processors: List of `SpanProcessor` objects
+     to process every span prior to exporting. Will be run sequentially.
+    :keyword bool enable_live_metrics: Boolean value to determine whether to enable live metrics feature.
+     Defaults to `False`.
+    :keyword str storage_directory: Storage directory in which to store retry files. Defaults to
+     `<tempfile.gettempdir()>/Microsoft/AzureMonitor/opentelemetry-python-<your-instrumentation-key>`.
+    :keyword list[~opentelemetry.sdk.metrics.view.View] views: List of `View` objects to configure and filter
+     metric output.
+    :rtype: None
+    """
+
+    _send_attach_warning()
+
+    configurations = _get_configurations(**kwargs)
+
+    disable_tracing = configurations[DISABLE_TRACING_ARG]
+    disable_logging = configurations[DISABLE_LOGGING_ARG]
+    disable_metrics = configurations[DISABLE_METRICS_ARG]
+    enable_live_metrics_config = configurations[ENABLE_LIVE_METRICS_ARG]
+
+    # Setup live metrics
+    if enable_live_metrics_config:
+        _setup_live_metrics(configurations)
+
+    # Setup tracing pipeline
+    if not disable_tracing:
+        _setup_tracing(configurations)
+
+    # Setup logging pipeline
+    if not disable_logging:
+        _setup_logging(configurations)
+
+    # Setup metrics pipeline
+    if not disable_metrics:
+        _setup_metrics(configurations)
+
+    # Setup instrumentations
+    # Instrumentations need to be setup last so to use the global providers
+    # instanstiated in the other setup steps
+    _setup_instrumentations(configurations)
+
+
+def _setup_tracing(configurations: Dict[str, ConfigurationValue]):
+    resource: Resource = configurations[RESOURCE_ARG]  # type: ignore
+    sampling_ratio = configurations[SAMPLING_RATIO_ARG]
+    tracer_provider = TracerProvider(
+        sampler=ApplicationInsightsSampler(sampling_ratio=cast(float, sampling_ratio)), resource=resource
+    )
+    for span_processor in configurations[SPAN_PROCESSORS_ARG]:  # type: ignore
+        tracer_provider.add_span_processor(span_processor)  # type: ignore
+    if configurations.get(ENABLE_LIVE_METRICS_ARG):
+        qsp = _QuickpulseSpanProcessor()
+        tracer_provider.add_span_processor(qsp)
+    trace_exporter = AzureMonitorTraceExporter(**configurations)
+    bsp = BatchSpanProcessor(
+        trace_exporter,
+    )
+    tracer_provider.add_span_processor(bsp)
+    set_tracer_provider(tracer_provider)
+    if _is_instrumentation_enabled(configurations, _AZURE_SDK_INSTRUMENTATION_NAME):
+        settings.tracing_implementation = OpenTelemetrySpan
+
+
+def _setup_logging(configurations: Dict[str, ConfigurationValue]):
+    resource: Resource = configurations[RESOURCE_ARG]  # type: ignore
+    logger_provider = LoggerProvider(resource=resource)
+    if configurations.get(ENABLE_LIVE_METRICS_ARG):
+        qlp = _QuickpulseLogRecordProcessor()
+        logger_provider.add_log_record_processor(qlp)
+    log_exporter = AzureMonitorLogExporter(**configurations)
+    log_record_processor = BatchLogRecordProcessor(
+        log_exporter,
+    )
+    logger_provider.add_log_record_processor(log_record_processor)
+    set_logger_provider(logger_provider)
+    logger_name: str = configurations[LOGGER_NAME_ARG]  # type: ignore
+    logger = getLogger(logger_name)
+    # Only add OpenTelemetry LoggingHandler if logger does not already have the handler
+    # This is to prevent most duplicate logging telemetry
+    if not any(isinstance(handler, LoggingHandler) for handler in logger.handlers):
+        handler = LoggingHandler(logger_provider=logger_provider)
+        logger.addHandler(handler)
+
+    # Setup EventLoggerProvider
+    event_provider = EventLoggerProvider(logger_provider)
+    _set_event_logger_provider(event_provider, False)
+
+
+def _setup_metrics(configurations: Dict[str, ConfigurationValue]):
+    resource: Resource = configurations[RESOURCE_ARG]  # type: ignore
+    views: List[View] = configurations[VIEWS_ARG]  # type: ignore
+    metric_exporter = AzureMonitorMetricExporter(**configurations)
+    reader = PeriodicExportingMetricReader(metric_exporter)
+    meter_provider = MeterProvider(
+        metric_readers=[reader],
+        resource=resource,
+        views=views,
+    )
+    set_meter_provider(meter_provider)
+
+
+def _setup_live_metrics(configurations):
+    enable_live_metrics(**configurations)
+
+
+class _EntryPointDistFinder:
+    @cached_property
+    def _mapping(self):
+        return {self._key_for(ep): dist for dist in distributions() for ep in dist.entry_points}
+
+    def dist_for(self, entry_point: EntryPoint):
+        dist = getattr(entry_point, "dist", None)
+        if dist:
+            return dist
+
+        return self._mapping.get(self._key_for(entry_point))
+
+    @staticmethod
+    def _key_for(entry_point: EntryPoint):
+        return f"{entry_point.group}:{entry_point.name}:{entry_point.value}"
+
+
+def _setup_instrumentations(configurations: Dict[str, ConfigurationValue]):
+    entry_point_finder = _EntryPointDistFinder()
+    # use pkg_resources for now until https://github.com/open-telemetry/opentelemetry-python/pull/3168 is merged
+    for entry_point in entry_points(group="opentelemetry_instrumentor"):
+        lib_name = entry_point.name
+        if lib_name not in _ALL_SUPPORTED_INSTRUMENTED_LIBRARIES:
+            continue
+        if not _is_instrumentation_enabled(configurations, lib_name):
+            _logger.debug("Instrumentation skipped for library %s", entry_point.name)
+            continue
+        try:
+            # Check if dependent libraries/version are installed
+            entry_point_dist = entry_point_finder.dist_for(entry_point)  # type: ignore
+            conflict = get_dist_dependency_conflicts(entry_point_dist)  # type: ignore
+            if conflict:
+                _logger.debug(
+                    "Skipping instrumentation %s: %s",
+                    entry_point.name,
+                    conflict,
+                )
+                continue
+            # Load the instrumentor via entrypoint
+            instrumentor: BaseInstrumentor = entry_point.load()
+            # tell instrumentation to not run dep checks again as we already did it above
+            instrumentor().instrument(skip_dep_check=True)
+        except Exception as ex:  # pylint: disable=broad-except
+            _logger.warning(
+                "Exception occurred when instrumenting: %s.",
+                lib_name,
+                exc_info=ex,
+            )
+    _setup_additional_azure_sdk_instrumentations(configurations)
+
+
+def _send_attach_warning():
+    if _is_attach_enabled() and not _is_on_functions():
+        AzureDiagnosticLogging.warning(
+            "Distro detected that automatic attach may have occurred. Check your data to ensure "
+            "that telemetry is not being duplicated. This may impact your cost.",
+            _DISTRO_DETECTS_ATTACH,
+        )
+
+
+def _setup_additional_azure_sdk_instrumentations(configurations: Dict[str, ConfigurationValue]):
+    if _AZURE_SDK_INSTRUMENTATION_NAME not in _ALL_SUPPORTED_INSTRUMENTED_LIBRARIES:
+        return
+
+    if not _is_instrumentation_enabled(configurations, _AZURE_SDK_INSTRUMENTATION_NAME):
+        _logger.debug("Instrumentation skipped for library azure_sdk")
+        return
+
+    try:
+        from azure.ai.inference.tracing import AIInferenceInstrumentor  # pylint: disable=import-error,no-name-in-module
+    except Exception as ex:  # pylint: disable=broad-except
+        _logger.debug(
+            "Failed to import AIInferenceInstrumentor from azure-ai-inference",
+            exc_info=ex,
+        )
+        return
+
+    try:
+        AIInferenceInstrumentor().instrument()
+    except Exception as ex:  # pylint: disable=broad-except
+        _logger.warning(
+            "Exception occurred when instrumenting: %s.",
+            "azure-ai-inference",
+            exc_info=ex,
+        )