diff --git a/sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md b/sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md index 9918bfe87542..8e98f6de937f 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md +++ b/sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md @@ -8,6 +8,8 @@ ([#310](https://github.com/microsoft/ApplicationInsights-Python/pull/310)) - Replace explicit log processor exporter interval env var with OT SDK env var ([#31740](https://github.com/Azure/azure-sdk-for-python/pull/31740)) +- Un-vendoring instrumentations + ([#31744](https://github.com/Azure/azure-sdk-for-python/pull/31740)) ### Breaking Changes diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_configure.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_configure.py index f41013f5ea07..e5a833e3c685 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_configure.py +++ b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_configure.py @@ -7,6 +7,12 @@ from typing import Dict, cast from opentelemetry._logs import get_logger_provider, set_logger_provider +from opentelemetry.instrumentation.dependencies import ( + get_dist_dependency_conflicts, +) +from opentelemetry.instrumentation.instrumentor import ( + BaseInstrumentor, +) from opentelemetry.metrics import set_meter_provider from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler from opentelemetry.sdk._logs.export import BatchLogRecordProcessor @@ -28,12 +34,6 @@ SAMPLING_RATIO_ARG, ) from azure.monitor.opentelemetry._types import ConfigurationValue -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.dependencies import ( - get_dependency_conflicts, -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.instrumentor import ( - BaseInstrumentor, -) from azure.monitor.opentelemetry.exporter import ( # pylint: disable=import-error ApplicationInsightsSampler, AzureMonitorLogExporter, @@ -44,16 +44,15 @@ _logger = getLogger(__name__) - -_SUPPORTED_INSTRUMENTED_LIBRARIES_DEPENDENCIES_MAP = { - "django": ("django >= 1.10",), - "fastapi": ("fastapi ~= 0.58",), - "flask": ("flask >= 1.0, < 3.0",), - "psycopg2": ("psycopg2 >= 2.7.3.1",), - "requests": ("requests ~= 2.0",), - "urllib": tuple(), - "urllib3": ("urllib3 >= 1.0.0, < 2.0.0",), -} +_SUPPORTED_INSTRUMENTED_LIBRARIES = ( + "django", + "fastapi", + "flask", + "psycopg2", + "requests", + "urllib", + "urllib3", +) def configure_azure_monitor(**kwargs) -> None: @@ -138,10 +137,10 @@ def _setup_instrumentations(configurations: Dict[str, ConfigurationValue]): # use pkg_resources for now until https://github.com/open-telemetry/opentelemetry-python/pull/3168 is merged for entry_point in iter_entry_points( - "azure_monitor_opentelemetry_instrumentor" + "opentelemetry_instrumentor" ): lib_name = entry_point.name - if lib_name not in _SUPPORTED_INSTRUMENTED_LIBRARIES_DEPENDENCIES_MAP: + if lib_name not in _SUPPORTED_INSTRUMENTED_LIBRARIES: continue if entry_point.name in disabled_instrumentations: _logger.debug( @@ -150,10 +149,7 @@ def _setup_instrumentations(configurations: Dict[str, ConfigurationValue]): continue try: # Check if dependent libraries/version are installed - instruments = _SUPPORTED_INSTRUMENTED_LIBRARIES_DEPENDENCIES_MAP[ - lib_name - ] - conflict = get_dependency_conflicts(instruments) + conflict = get_dist_dependency_conflicts(entry_point.dist) if conflict: _logger.debug( "Skipping instrumentation %s: %s", diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/__init__.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/__init__.py deleted file mode 100644 index 0bdee620366b..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# ------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License in the project root for -# license information. -# -------------------------------------------------------------------------- diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/__init__.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/__init__.py deleted file mode 100644 index 0bdee620366b..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# ------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License in the project root for -# license information. -# -------------------------------------------------------------------------- diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/__init__.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/__init__.py deleted file mode 100644 index 0bdee620366b..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# ------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License in the project root for -# license information. -# -------------------------------------------------------------------------- diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/__init__.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/__init__.py deleted file mode 100644 index 0bdee620366b..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# ------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License in the project root for -# license information. -# -------------------------------------------------------------------------- diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/asgi/__init__.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/asgi/__init__.py deleted file mode 100644 index 574ed9849611..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/asgi/__init__.py +++ /dev/null @@ -1,487 +0,0 @@ -# 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. -# pylint: disable=too-many-locals - - -import typing -import urllib -from functools import wraps -from timeit import default_timer -from typing import Tuple - -from asgiref.compatibility import guarantee_single_callable - -from opentelemetry import context, trace -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.asgi.version import ( - __version__ -) # noqa -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.propagators import ( - get_global_response_propagator, -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.utils import ( - _start_internal_or_server_span, - http_status_to_status_code, -) -from opentelemetry.metrics import get_meter -from opentelemetry.propagators.textmap import Getter, Setter -from opentelemetry.semconv.metrics import MetricInstruments -from opentelemetry.semconv.trace import SpanAttributes -from opentelemetry.trace import Span, set_span_in_context -from opentelemetry.trace.status import Status, StatusCode -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.util.http import ( - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS, - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST, - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE, - SanitizeValue, - _parse_active_request_count_attrs, - _parse_duration_attrs, - get_custom_headers, - normalise_request_header_name, - normalise_response_header_name, - remove_url_credentials, -) - -_ServerRequestHookT = typing.Optional[typing.Callable[[Span, dict], None]] -_ClientRequestHookT = typing.Optional[typing.Callable[[Span, dict], None]] -_ClientResponseHookT = typing.Optional[typing.Callable[[Span, dict], None]] - - -class ASGIGetter(Getter[dict]): - def get( - self, carrier: dict, key: str - ) -> typing.Optional[typing.List[str]]: - """Getter implementation to retrieve a HTTP header value from the ASGI - scope. - - Args: - carrier: ASGI scope object - key: header name in scope - Returns: - A list with a single string with the header value if it exists, - else None. - """ - headers = carrier.get("headers") - if not headers: - return None - - # ASGI header keys are in lower case - key = key.lower() - decoded = [ - _value.decode("utf8") - for (_key, _value) in headers - if _key.decode("utf8").lower() == key - ] - if not decoded: - return None - return decoded - - def keys(self, carrier: dict) -> typing.List[str]: - headers = carrier.get("headers") or [] - return [_key.decode("utf8") for (_key, _value) in headers] - - -asgi_getter = ASGIGetter() - - -class ASGISetter(Setter[dict]): - def set( - self, carrier: dict, key: str, value: str - ) -> None: # pylint: disable=no-self-use - """Sets response header values on an ASGI scope according to `the spec `_. - - Args: - carrier: ASGI scope object - key: response header name to set - value: response header value - Returns: - None - """ - headers = carrier.get("headers") - if not headers: - headers = [] - carrier["headers"] = headers - - headers.append([key.lower().encode(), value.encode()]) - - -asgi_setter = ASGISetter() - - -def collect_request_attributes(scope): - """Collects HTTP request attributes from the ASGI scope and returns a - dictionary to be used as span creation attributes.""" - server_host, port, http_url = get_host_port_url_tuple(scope) - query_string = scope.get("query_string") - if query_string and http_url: - if isinstance(query_string, bytes): - query_string = query_string.decode("utf8") - http_url += "?" + urllib.parse.unquote(query_string) - - result = { - SpanAttributes.HTTP_SCHEME: scope.get("scheme"), - SpanAttributes.HTTP_HOST: server_host, - SpanAttributes.NET_HOST_PORT: port, - SpanAttributes.HTTP_FLAVOR: scope.get("http_version"), - SpanAttributes.HTTP_TARGET: scope.get("path"), - SpanAttributes.HTTP_URL: remove_url_credentials(http_url), - } - http_method = scope.get("method") - if http_method: - result[SpanAttributes.HTTP_METHOD] = http_method - - http_host_value_list = asgi_getter.get(scope, "host") - if http_host_value_list: - result[SpanAttributes.HTTP_SERVER_NAME] = ",".join( - http_host_value_list - ) - http_user_agent = asgi_getter.get(scope, "user-agent") - if http_user_agent: - result[SpanAttributes.HTTP_USER_AGENT] = http_user_agent[0] - - if "client" in scope and scope["client"] is not None: - result[SpanAttributes.NET_PEER_IP] = scope.get("client")[0] - result[SpanAttributes.NET_PEER_PORT] = scope.get("client")[1] - - # remove None values - result = {k: v for k, v in result.items() if v is not None} - - return result - - -def collect_custom_request_headers_attributes(scope): - """returns custom HTTP request headers to be added into SERVER span as span attributes - Refer specification https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-request-and-response-headers - """ - - sanitize = SanitizeValue( - get_custom_headers( - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS - ) - ) - - # Decode headers before processing. - headers = { - _key.decode("utf8"): _value.decode("utf8") - for (_key, _value) in scope.get("headers") - } - - return sanitize.sanitize_header_values( - headers, - get_custom_headers( - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST - ), - normalise_request_header_name, - ) - - -def collect_custom_response_headers_attributes(message): - """returns custom HTTP response headers to be added into SERVER span as span attributes - Refer specification https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-request-and-response-headers - """ - - sanitize = SanitizeValue( - get_custom_headers( - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS - ) - ) - - # Decode headers before processing. - headers = { - _key.decode("utf8"): _value.decode("utf8") - for (_key, _value) in message.get("headers") - } - - return sanitize.sanitize_header_values( - headers, - get_custom_headers( - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE - ), - normalise_response_header_name, - ) - - -def get_host_port_url_tuple(scope): - """Returns (host, port, full_url) tuple.""" - server = scope.get("server") or ["0.0.0.0", 80] # nosec - port = server[1] - server_host = server[0] + (":" + str(port) if str(port) != "80" else "") - full_path = scope.get("root_path", "") + scope.get("path", "") - http_url = scope.get("scheme", "http") + "://" + server_host + full_path - return server_host, port, http_url - - -def set_status_code(span, status_code): - """Adds HTTP response attributes to span using the status_code argument.""" - if not span.is_recording(): - return - try: - status_code = int(status_code) - except ValueError: - span.set_status( - Status( - StatusCode.ERROR, - "Non-integer HTTP status: " + repr(status_code), - ) - ) - else: - span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, status_code) - span.set_status( - Status(http_status_to_status_code(status_code, server_span=True)) - ) - - -def get_default_span_details(scope: dict) -> Tuple[str, dict]: - """Default implementation for get_default_span_details - Args: - scope: the ASGI scope dictionary - Returns: - a tuple of the span name, and any attributes to attach to the span. - """ - span_name = ( - scope.get("path", "").strip() - or f"HTTP {scope.get('method', '').strip()}" - ) - - return span_name, {} - - -def _collect_target_attribute( - scope: typing.Dict[str, typing.Any] -) -> typing.Optional[str]: - """ - Returns the target path as defined by the Semantic Conventions. - - This value is suitable to use in metrics as it should replace concrete - values with a parameterized name. Example: /api/users/{user_id} - - Refer to the specification - https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/http-metrics.md#parameterized-attributes - - Note: this function requires specific code for each framework, as there's no - standard attribute to use. - """ - # FastAPI - root_path = scope.get("root_path", "") - - route = scope.get("route") - path_format = getattr(route, "path_format", None) - if path_format: - return f"{root_path}{path_format}" - - return None - - -class OpenTelemetryMiddleware: - """The ASGI application middleware. - - This class is an ASGI middleware that starts and annotates spans for any - requests it is invoked with. - - Args: - app: The ASGI application callable to forward requests to. - default_span_details: Callback which should return a string and a tuple, representing the desired default span name and a - dictionary with any additional span attributes to set. - Optional: Defaults to get_default_span_details. - server_request_hook: Optional callback which is called with the server span and ASGI - scope object for every incoming request. - client_request_hook: Optional callback which is called with the internal span and an ASGI - scope which is sent as a dictionary for when the method receive is called. - client_response_hook: Optional callback which is called with the internal span and an ASGI - event which is sent as a dictionary for when the method send is called. - tracer_provider: The optional tracer provider to use. If omitted - the current globally configured one is used. - """ - - # pylint: disable=too-many-branches - def __init__( - self, - app, - excluded_urls=None, - default_span_details=None, - server_request_hook: _ServerRequestHookT = None, - client_request_hook: _ClientRequestHookT = None, - client_response_hook: _ClientResponseHookT = None, - tracer_provider=None, - meter_provider=None, - meter=None, - ): - self.app = guarantee_single_callable(app) - self.tracer = trace.get_tracer(__name__, __version__, tracer_provider) - self.meter = ( - get_meter(__name__, __version__, meter_provider) - if meter is None - else meter - ) - self.duration_histogram = self.meter.create_histogram( - name=MetricInstruments.HTTP_SERVER_DURATION, - unit="ms", - description="measures the duration of the inbound HTTP request", - ) - self.active_requests_counter = self.meter.create_up_down_counter( - name=MetricInstruments.HTTP_SERVER_ACTIVE_REQUESTS, - unit="requests", - description="measures the number of concurrent HTTP requests that are currently in-flight", - ) - self.excluded_urls = excluded_urls - self.default_span_details = ( - default_span_details or get_default_span_details - ) - self.server_request_hook = server_request_hook - self.client_request_hook = client_request_hook - self.client_response_hook = client_response_hook - - async def __call__(self, scope, receive, send): - """The ASGI application - - Args: - scope: An ASGI environment. - receive: An awaitable callable yielding dictionaries - send: An awaitable callable taking a single dictionary as argument. - """ - if scope["type"] not in ("http", "websocket"): - return await self.app(scope, receive, send) - - _, _, url = get_host_port_url_tuple(scope) - if self.excluded_urls and self.excluded_urls.url_disabled(url): - return await self.app(scope, receive, send) - - span_name, additional_attributes = self.default_span_details(scope) - - attributes = collect_request_attributes(scope) - attributes.update(additional_attributes) - span, token = _start_internal_or_server_span( - tracer=self.tracer, - span_name=span_name, - start_time=None, - context_carrier=scope, - context_getter=asgi_getter, - attributes=attributes, - ) - active_requests_count_attrs = _parse_active_request_count_attrs( - attributes - ) - duration_attrs = _parse_duration_attrs(attributes) - - if scope["type"] == "http": - self.active_requests_counter.add(1, active_requests_count_attrs) - try: - with trace.use_span(span, end_on_exit=True) as current_span: - if current_span.is_recording(): - for key, value in attributes.items(): - current_span.set_attribute(key, value) - - if current_span.kind == trace.SpanKind.SERVER: - custom_attributes = ( - collect_custom_request_headers_attributes(scope) - ) - if len(custom_attributes) > 0: - current_span.set_attributes(custom_attributes) - - if callable(self.server_request_hook): - self.server_request_hook(current_span, scope) - - otel_receive = self._get_otel_receive( - span_name, scope, receive - ) - - otel_send = self._get_otel_send( - current_span, - span_name, - scope, - send, - duration_attrs, - ) - start = default_timer() - - await self.app(scope, otel_receive, otel_send) - finally: - if scope["type"] == "http": - target = _collect_target_attribute(scope) - if target: - duration_attrs[SpanAttributes.HTTP_TARGET] = target - duration = max(round((default_timer() - start) * 1000), 0) - self.duration_histogram.record(duration, duration_attrs) - self.active_requests_counter.add( - -1, active_requests_count_attrs - ) - if token: - context.detach(token) - - # pylint: enable=too-many-branches - - def _get_otel_receive(self, server_span_name, scope, receive): - @wraps(receive) - async def otel_receive(): - with self.tracer.start_as_current_span( - " ".join((server_span_name, scope["type"], "receive")) - ) as receive_span: - if callable(self.client_request_hook): - self.client_request_hook(receive_span, scope) - message = await receive() - if receive_span.is_recording(): - if message["type"] == "websocket.receive": - set_status_code(receive_span, 200) - receive_span.set_attribute("type", message["type"]) - return message - - return otel_receive - - def _get_otel_send( - self, server_span, server_span_name, scope, send, duration_attrs - ): - @wraps(send) - async def otel_send(message): - with self.tracer.start_as_current_span( - " ".join((server_span_name, scope["type"], "send")) - ) as send_span: - if callable(self.client_response_hook): - self.client_response_hook(send_span, message) - if send_span.is_recording(): - if message["type"] == "http.response.start": - status_code = message["status"] - duration_attrs[ - SpanAttributes.HTTP_STATUS_CODE - ] = status_code - set_status_code(server_span, status_code) - set_status_code(send_span, status_code) - elif message["type"] == "websocket.send": - set_status_code(server_span, 200) - set_status_code(send_span, 200) - send_span.set_attribute("type", message["type"]) - if ( - server_span.is_recording() - and server_span.kind == trace.SpanKind.SERVER - and "headers" in message - ): - custom_response_attributes = ( - collect_custom_response_headers_attributes(message) - ) - if len(custom_response_attributes) > 0: - server_span.set_attributes( - custom_response_attributes - ) - - propagator = get_global_response_propagator() - if propagator: - propagator.inject( - message, - context=set_span_in_context( - server_span, trace.context_api.Context() - ), - setter=asgi_setter, - ) - - await send(message) - - return otel_send diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/asgi/package.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/asgi/package.py deleted file mode 100644 index c219ec549968..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/asgi/package.py +++ /dev/null @@ -1,16 +0,0 @@ -# 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. - - -_instruments = ("asgiref ~= 3.0",) diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/asgi/version.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/asgi/version.py deleted file mode 100644 index a84e45c8896e..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/asgi/version.py +++ /dev/null @@ -1,15 +0,0 @@ -# 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. - -__version__ = "0.39b0" diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/auto_instrumentation/__init__.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/auto_instrumentation/__init__.py deleted file mode 100644 index 1339113a7c3a..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/auto_instrumentation/__init__.py +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env python3 - -# 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 argparse import REMAINDER, ArgumentParser -from logging import getLogger -from os import environ, execl, getcwd -from os.path import abspath, dirname, pathsep -from re import sub -from shutil import which - -from pkg_resources import iter_entry_points - -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.version import ( - __version__ -) - -_logger = getLogger(__name__) - - -def run() -> None: - parser = ArgumentParser( - description=""" - opentelemetry-instrument automatically instruments a Python - program and its dependencies and then runs the program. - """, - epilog=""" - Optional arguments (except for --help and --version) for opentelemetry-instrument - directly correspond with OpenTelemetry environment variables. The - corresponding optional argument is formed by removing the OTEL_ or - OTEL_PYTHON_ prefix from the environment variable and lower casing the - rest. For example, the optional argument --attribute_value_length_limit - corresponds with the environment variable - OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT. - - These optional arguments will override the current value of the - corresponding environment variable during the execution of the command. - """, - ) - - argument_otel_environment_variable = {} - - for entry_point in iter_entry_points( - "opentelemetry_environment_variables" - ): - environment_variable_module = entry_point.load() - - for attribute in dir(environment_variable_module): - if attribute.startswith("OTEL_"): - argument = sub(r"OTEL_(PYTHON_)?", "", attribute).lower() - - parser.add_argument( - f"--{argument}", - required=False, - ) - argument_otel_environment_variable[argument] = attribute - - parser.add_argument( - "--version", - help="print version information", - action="version", - version="%(prog)s " + __version__, - ) - parser.add_argument("command", help="Your Python application.") - parser.add_argument( - "command_args", - help="Arguments for your application.", - nargs=REMAINDER, - ) - - args = parser.parse_args() - - for argument, otel_environment_variable in ( - argument_otel_environment_variable - ).items(): - value = getattr(args, argument) - if value is not None: - environ[otel_environment_variable] = value - - python_path = environ.get("PYTHONPATH") - - if not python_path: - python_path = [] - - else: - python_path = python_path.split(pathsep) - - cwd_path = getcwd() - - # This is being added to support applications that are being run from their - # own executable, like Django. - # FIXME investigate if there is another way to achieve this - if cwd_path not in python_path: - python_path.insert(0, cwd_path) - - filedir_path = dirname(abspath(__file__)) - - python_path = [path for path in python_path if path != filedir_path] - - python_path.insert(0, filedir_path) - - environ["PYTHONPATH"] = pathsep.join(python_path) - - executable = which(args.command) - execl(executable, executable, *args.command_args) diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/auto_instrumentation/sitecustomize.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/auto_instrumentation/sitecustomize.py deleted file mode 100644 index 6b142f75737d..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/auto_instrumentation/sitecustomize.py +++ /dev/null @@ -1,134 +0,0 @@ -# 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 -from os.path import abspath, dirname, pathsep - -from pkg_resources import iter_entry_points - -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.dependencies import ( - get_dist_dependency_conflicts, -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.distro import ( - BaseDistro, - DefaultDistro -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.environment_variables import ( - OTEL_PYTHON_DISABLED_INSTRUMENTATIONS, -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.utils import ( - _python_path_without_directory -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.version import ( - __version__ -) - -logger = getLogger(__name__) - - -def _load_distros() -> BaseDistro: - for entry_point in iter_entry_points("opentelemetry_distro"): - try: - distro = entry_point.load()() - if not isinstance(distro, BaseDistro): - logger.debug( - "%s is not an OpenTelemetry Distro. Skipping", - entry_point.name, - ) - continue - logger.debug( - "Distribution %s will be configured", entry_point.name - ) - return distro - except Exception as exc: # pylint: disable=broad-except - logger.exception( - "Distribution %s configuration failed", entry_point.name - ) - raise exc - return DefaultDistro() - - -def _load_instrumentors(distro): - package_to_exclude = environ.get(OTEL_PYTHON_DISABLED_INSTRUMENTATIONS, []) - if isinstance(package_to_exclude, str): - package_to_exclude = package_to_exclude.split(",") - # to handle users entering "requests , flask" or "requests, flask" with spaces - package_to_exclude = [x.strip() for x in package_to_exclude] - - for entry_point in iter_entry_points("opentelemetry_pre_instrument"): - entry_point.load()() - - for entry_point in iter_entry_points("opentelemetry_instrumentor"): - if entry_point.name in package_to_exclude: - logger.debug( - "Instrumentation skipped for library %s", entry_point.name - ) - continue - - try: - conflict = get_dist_dependency_conflicts(entry_point.dist) - if conflict: - logger.debug( - "Skipping instrumentation %s: %s", - entry_point.name, - conflict, - ) - continue - - # tell instrumentation to not run dep checks again as we already did it above - distro.load_instrumentor(entry_point, skip_dep_check=True) - logger.debug("Instrumented %s", entry_point.name) - except Exception as exc: # pylint: disable=broad-except - logger.exception("Instrumenting of %s failed", entry_point.name) - raise exc - - for entry_point in iter_entry_points("opentelemetry_post_instrument"): - entry_point.load()() - - -def _load_configurators(): - configured = None - for entry_point in iter_entry_points("opentelemetry_configurator"): - if configured is not None: - logger.warning( - "Configuration of %s not loaded, %s already loaded", - entry_point.name, - configured, - ) - continue - try: - entry_point.load()().configure(auto_instrumentation_version=__version__) # type: ignore - configured = entry_point.name - except Exception as exc: # pylint: disable=broad-except - logger.exception("Configuration of %s failed", entry_point.name) - raise exc - - -def initialize(): - # prevents auto-instrumentation of subprocesses if code execs another python process - environ["PYTHONPATH"] = _python_path_without_directory( - environ["PYTHONPATH"], dirname(abspath(__file__)), pathsep - ) - - try: - distro = _load_distros() - distro.configure() - _load_configurators() - _load_instrumentors(distro) - except Exception: # pylint: disable=broad-except - logger.exception("Failed to auto initialize opentelemetry") - - -initialize() diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/bootstrap.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/bootstrap.py deleted file mode 100644 index ab1577b55323..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/bootstrap.py +++ /dev/null @@ -1,163 +0,0 @@ -#!/usr/bin/env python3 - -# 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 argparse -import logging -import subprocess -import sys - -import pkg_resources - -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.bootstrap_gen import ( - default_instrumentations, - libraries, -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.version import ( - __version__ -) - -logger = logging.getLogger(__name__) - - -def _syscall(func): - def wrapper(package=None): - try: - if package: - return func(package) - return func() - except subprocess.SubprocessError as exp: - cmd = getattr(exp, "cmd", None) - if cmd: - msg = f'Error calling system command "{" ".join(cmd)}"' - if package: - msg = f'{msg} for package "{package}"' - raise RuntimeError(msg) - - return wrapper - - -@_syscall -def _sys_pip_install(package): - # explicit upgrade strategy to override potential pip config - subprocess.check_call( - [ - sys.executable, - "-m", - "pip", - "install", - "-U", - "--upgrade-strategy", - "only-if-needed", - package, - ] - ) - - -def _pip_check(): - """Ensures none of the instrumentations have dependency conflicts. - Clean check reported as: - 'No broken requirements found.' - Dependency conflicts are reported as: - 'opentelemetry-instrumentation-flask 1.0.1 has requirement opentelemetry-sdk<2.0,>=1.0, but you have opentelemetry-sdk 0.5.' - To not be too restrictive, we'll only check for relevant packages. - """ - with subprocess.Popen( - [sys.executable, "-m", "pip", "check"], stdout=subprocess.PIPE - ) as check_pipe: - pip_check = check_pipe.communicate()[0].decode() - pip_check_lower = pip_check.lower() - for package_tup in libraries.values(): - for package in package_tup: - if package.lower() in pip_check_lower: - raise RuntimeError(f"Dependency conflict found: {pip_check}") - - -def _is_installed(req): - if req in sys.modules: - return True - - try: - pkg_resources.get_distribution(req) - except pkg_resources.DistributionNotFound: - return False - except pkg_resources.VersionConflict as exc: - logger.warning( - "instrumentation for package %s is available but version %s is installed. Skipping.", - exc.req, - exc.dist.as_requirement(), # pylint: disable=no-member - ) - return False - return True - - -def _find_installed_libraries(): - libs = default_instrumentations[:] - libs.extend( - [ - v["instrumentation"] - for _, v in libraries.items() - if _is_installed(v["library"]) - ] - ) - return libs - - -def _run_requirements(): - logger.setLevel(logging.ERROR) - print("\n".join(_find_installed_libraries()), end="") - - -def _run_install(): - for lib in _find_installed_libraries(): - _sys_pip_install(lib) - _pip_check() - - -def run() -> None: - action_install = "install" - action_requirements = "requirements" - - parser = argparse.ArgumentParser( - description=""" - opentelemetry-bootstrap detects installed libraries and automatically - installs the relevant instrumentation packages for them. - """ - ) - parser.add_argument( - "--version", - help="print version information", - action="version", - version="%(prog)s " + __version__, - ) - parser.add_argument( - "-a", - "--action", - choices=[action_install, action_requirements], - default=action_requirements, - help=""" - install - uses pip to install the new requirements using to the - currently active site-package. - requirements - prints out the new requirements to stdout. Action can - be piped and appended to a requirements.txt file. - """, - ) - args = parser.parse_args() - - cmd = { - action_install: _run_install, - action_requirements: _run_requirements, - }[args.action] - cmd() diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/bootstrap_gen.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/bootstrap_gen.py deleted file mode 100644 index f78c60cf98b5..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/bootstrap_gen.py +++ /dev/null @@ -1,175 +0,0 @@ -# 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. - -# DO NOT EDIT. THIS FILE WAS AUTOGENERATED FROM INSTRUMENTATION PACKAGES. -# RUN `python scripts/generate_instrumentation_bootstrap.py` TO REGENERATE. - -libraries = { - "aio_pika": { - "library": "aio_pika >= 7.2.0, < 10.0.0", - "instrumentation": "opentelemetry-instrumentation-aio-pika==0.39b0", - }, - "aiohttp": { - "library": "aiohttp ~= 3.0", - "instrumentation": "opentelemetry-instrumentation-aiohttp-client==0.39b0", - }, - "aiopg": { - "library": "aiopg >= 0.13.0, < 2.0.0", - "instrumentation": "opentelemetry-instrumentation-aiopg==0.39b0", - }, - "asgiref": { - "library": "asgiref ~= 3.0", - "instrumentation": "opentelemetry-instrumentation-asgi==0.39b0", - }, - "asyncpg": { - "library": "asyncpg >= 0.12.0", - "instrumentation": "opentelemetry-instrumentation-asyncpg==0.39b0", - }, - "boto": { - "library": "boto~=2.0", - "instrumentation": "opentelemetry-instrumentation-boto==0.39b0", - }, - "boto3": { - "library": "boto3 ~= 1.0", - "instrumentation": "opentelemetry-instrumentation-boto3sqs==0.39b0", - }, - "botocore": { - "library": "botocore ~= 1.0", - "instrumentation": "opentelemetry-instrumentation-botocore==0.39b0", - }, - "celery": { - "library": "celery >= 4.0, < 6.0", - "instrumentation": "opentelemetry-instrumentation-celery==0.39b0", - }, - "confluent-kafka": { - "library": "confluent-kafka >= 1.8.2, < 2.0.0", - "instrumentation": "opentelemetry-instrumentation-confluent-kafka==0.39b0", - }, - "django": { - "library": "django >= 1.10", - "instrumentation": "opentelemetry-instrumentation-django==0.39b0", - }, - "elasticsearch": { - "library": "elasticsearch >= 2.0", - "instrumentation": "opentelemetry-instrumentation-elasticsearch==0.39b0", - }, - "falcon": { - "library": "falcon >= 1.4.1, < 4.0.0", - "instrumentation": "opentelemetry-instrumentation-falcon==0.39b0", - }, - "fastapi": { - "library": "fastapi ~= 0.58", - "instrumentation": "opentelemetry-instrumentation-fastapi==0.39b0", - }, - "flask": { - "library": "flask >= 1.0, < 3.0", - "instrumentation": "opentelemetry-instrumentation-flask==0.39b0", - }, - "grpcio": { - "library": "grpcio ~= 1.27", - "instrumentation": "opentelemetry-instrumentation-grpc==0.39b0", - }, - "httpx": { - "library": "httpx >= 0.18.0, <= 0.23.0", - "instrumentation": "opentelemetry-instrumentation-httpx==0.39b0", - }, - "jinja2": { - "library": "jinja2 >= 2.7, < 4.0", - "instrumentation": "opentelemetry-instrumentation-jinja2==0.39b0", - }, - "kafka-python": { - "library": "kafka-python >= 2.0", - "instrumentation": "opentelemetry-instrumentation-kafka-python==0.39b0", - }, - "mysql-connector-python": { - "library": "mysql-connector-python ~= 8.0", - "instrumentation": "opentelemetry-instrumentation-mysql==0.39b0", - }, - "pika": { - "library": "pika >= 0.12.0", - "instrumentation": "opentelemetry-instrumentation-pika==0.39b0", - }, - "psycopg2": { - "library": "psycopg2 >= 2.7.3.1", - "instrumentation": "opentelemetry-instrumentation-psycopg2==0.39b0", - }, - "pymemcache": { - "library": "pymemcache >= 1.3.5, < 5", - "instrumentation": "opentelemetry-instrumentation-pymemcache==0.39b0", - }, - "pymongo": { - "library": "pymongo >= 3.1, < 5.0", - "instrumentation": "opentelemetry-instrumentation-pymongo==0.39b0", - }, - "PyMySQL": { - "library": "PyMySQL < 2", - "instrumentation": "opentelemetry-instrumentation-pymysql==0.39b0", - }, - "pyramid": { - "library": "pyramid >= 1.7", - "instrumentation": "opentelemetry-instrumentation-pyramid==0.39b0", - }, - "redis": { - "library": "redis >= 2.6", - "instrumentation": "opentelemetry-instrumentation-redis==0.39b0", - }, - "remoulade": { - "library": "remoulade >= 0.50", - "instrumentation": "opentelemetry-instrumentation-remoulade==0.39b0", - }, - "requests": { - "library": "requests ~= 2.0", - "instrumentation": "opentelemetry-instrumentation-requests==0.39b0", - }, - "scikit-learn": { - "library": "scikit-learn ~= 0.24.0", - "instrumentation": "opentelemetry-instrumentation-sklearn==0.39b0", - }, - "sqlalchemy": { - "library": "sqlalchemy", - "instrumentation": "opentelemetry-instrumentation-sqlalchemy==0.39b0", - }, - "starlette": { - "library": "starlette ~= 0.13.0", - "instrumentation": "opentelemetry-instrumentation-starlette==0.39b0", - }, - "psutil": { - "library": "psutil >= 5", - "instrumentation": "opentelemetry-instrumentation-system-metrics==0.39b0", - }, - "tornado": { - "library": "tornado >= 5.1.1", - "instrumentation": "opentelemetry-instrumentation-tornado==0.39b0", - }, - "tortoise-orm": { - "library": "tortoise-orm >= 0.17.0", - "instrumentation": "opentelemetry-instrumentation-tortoiseorm==0.39b0", - }, - "pydantic": { - "library": "pydantic >= 1.10.2", - "instrumentation": "opentelemetry-instrumentation-tortoiseorm==0.39b0", - }, - "urllib3": { - "library": "urllib3 >= 1.0.0, < 2.0.0", - "instrumentation": "opentelemetry-instrumentation-urllib3==0.39b0", - }, -} -default_instrumentations = [ - "opentelemetry-instrumentation-aws-lambda==0.39b0", - "opentelemetry-instrumentation-dbapi==0.39b0", - "opentelemetry-instrumentation-logging==0.39b0", - "opentelemetry-instrumentation-sqlite3==0.39b0", - "opentelemetry-instrumentation-urllib==0.39b0", - "opentelemetry-instrumentation-wsgi==0.39b0", -] diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/dbapi/__init__.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/dbapi/__init__.py deleted file mode 100644 index 16aad5263764..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/dbapi/__init__.py +++ /dev/null @@ -1,473 +0,0 @@ -# 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 functools -import logging -import re -import typing - -import wrapt - -from opentelemetry import trace as trace_api -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.dbapi.version import ( - __version__ -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.sqlcommenter_utils import ( - _add_sql_comment -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.utils import ( - _get_opentelemetry_values, - unwrap, -) -from opentelemetry.semconv.trace import SpanAttributes -from opentelemetry.trace import SpanKind, TracerProvider, get_tracer - -_logger = logging.getLogger(__name__) - - -def trace_integration( - connect_module: typing.Callable[..., typing.Any], - connect_method_name: str, - database_system: str, - connection_attributes: typing.Dict = None, - tracer_provider: typing.Optional[TracerProvider] = None, - capture_parameters: bool = False, - enable_commenter: bool = False, - db_api_integration_factory=None, -): - """Integrate with DB API library. - https://www.python.org/dev/peps/pep-0249/ - - Args: - connect_module: Module name where connect method is available. - connect_method_name: The connect method name. - database_system: An identifier for the database management system (DBMS) - product being used. - connection_attributes: Attribute names for database, port, host and - user in Connection object. - tracer_provider: The :class:`opentelemetry.trace.TracerProvider` to - use. If omitted the current configured one is used. - capture_parameters: Configure if db.statement.parameters should be captured. - enable_commenter: Flag to enable/disable sqlcommenter. - db_api_integration_factory: The `DatabaseApiIntegration` to use. If none is passed the - default one is used. - """ - wrap_connect( - __name__, - connect_module, - connect_method_name, - database_system, - connection_attributes, - version=__version__, - tracer_provider=tracer_provider, - capture_parameters=capture_parameters, - enable_commenter=enable_commenter, - db_api_integration_factory=db_api_integration_factory, - ) - - -def wrap_connect( - name: str, - connect_module: typing.Callable[..., typing.Any], - connect_method_name: str, - database_system: str, - connection_attributes: typing.Dict = None, - version: str = "", - tracer_provider: typing.Optional[TracerProvider] = None, - capture_parameters: bool = False, - enable_commenter: bool = False, - db_api_integration_factory=None, - commenter_options: dict = None, -): - """Integrate with DB API library. - https://www.python.org/dev/peps/pep-0249/ - - Args: - connect_module: Module name where connect method is available. - connect_method_name: The connect method name. - database_system: An identifier for the database management system (DBMS) - product being used. - connection_attributes: Attribute names for database, port, host and - user in Connection object. - tracer_provider: The :class:`opentelemetry.trace.TracerProvider` to - use. If omitted the current configured one is used. - capture_parameters: Configure if db.statement.parameters should be captured. - enable_commenter: Flag to enable/disable sqlcommenter. - db_api_integration_factory: The `DatabaseApiIntegration` to use. If none is passed the - default one is used. - commenter_options: Configurations for tags to be appended at the sql query. - - """ - db_api_integration_factory = ( - db_api_integration_factory or DatabaseApiIntegration - ) - - # pylint: disable=unused-argument - def wrap_connect_( - wrapped: typing.Callable[..., typing.Any], - instance: typing.Any, - args: typing.Tuple[typing.Any, typing.Any], - kwargs: typing.Dict[typing.Any, typing.Any], - ): - db_integration = db_api_integration_factory( - name, - database_system, - connection_attributes=connection_attributes, - version=version, - tracer_provider=tracer_provider, - capture_parameters=capture_parameters, - enable_commenter=enable_commenter, - commenter_options=commenter_options, - connect_module=connect_module, - ) - return db_integration.wrapped_connection(wrapped, args, kwargs) - - try: - wrapt.wrap_function_wrapper( - connect_module, connect_method_name, wrap_connect_ - ) - except Exception as ex: # pylint: disable=broad-except - _logger.warning("Failed to integrate with DB API. %s", str(ex)) - - -def unwrap_connect( - connect_module: typing.Callable[..., typing.Any], connect_method_name: str -): - """Disable integration with DB API library. - https://www.python.org/dev/peps/pep-0249/ - - Args: - connect_module: Module name where the connect method is available. - connect_method_name: The connect method name. - """ - unwrap(connect_module, connect_method_name) - - -def instrument_connection( - name: str, - connection, - database_system: str, - connection_attributes: typing.Dict = None, - version: str = "", - tracer_provider: typing.Optional[TracerProvider] = None, - capture_parameters: bool = False, - enable_commenter: bool = False, - commenter_options: dict = None, -): - """Enable instrumentation in a database connection. - - Args: - connection: The connection to instrument. - database_system: An identifier for the database management system (DBMS) - product being used. - connection_attributes: Attribute names for database, port, host and - user in a connection object. - tracer_provider: The :class:`opentelemetry.trace.TracerProvider` to - use. If omitted the current configured one is used. - capture_parameters: Configure if db.statement.parameters should be captured. - enable_commenter: Flag to enable/disable sqlcommenter. - commenter_options: Configurations for tags to be appended at the sql query. - - Returns: - An instrumented connection. - """ - if isinstance(connection, wrapt.ObjectProxy): - _logger.warning("Connection already instrumented") - return connection - - db_integration = DatabaseApiIntegration( - name, - database_system, - connection_attributes=connection_attributes, - version=version, - tracer_provider=tracer_provider, - capture_parameters=capture_parameters, - enable_commenter=enable_commenter, - commenter_options=commenter_options, - ) - db_integration.get_connection_attributes(connection) - return get_traced_connection_proxy(connection, db_integration) - - -def uninstrument_connection(connection): - """Disable instrumentation in a database connection. - - Args: - connection: The connection to uninstrument. - - Returns: - An uninstrumented connection. - """ - if isinstance(connection, wrapt.ObjectProxy): - return connection.__wrapped__ - - _logger.warning("Connection is not instrumented") - return connection - - -class DatabaseApiIntegration: - def __init__( - self, - name: str, - database_system: str, - connection_attributes=None, - version: str = "", - tracer_provider: typing.Optional[TracerProvider] = None, - capture_parameters: bool = False, - enable_commenter: bool = False, - commenter_options: dict = None, - connect_module: typing.Callable[..., typing.Any] = None, - ): - self.connection_attributes = connection_attributes - if self.connection_attributes is None: - self.connection_attributes = { - "database": "database", - "port": "port", - "host": "host", - "user": "user", - } - self._name = name - self._version = version - self._tracer = get_tracer( - self._name, - instrumenting_library_version=self._version, - tracer_provider=tracer_provider, - ) - self.capture_parameters = capture_parameters - self.enable_commenter = enable_commenter - self.commenter_options = commenter_options - self.database_system = database_system - self.connection_props = {} - self.span_attributes = {} - self.name = "" - self.database = "" - self.connect_module = connect_module - - def wrapped_connection( - self, - connect_method: typing.Callable[..., typing.Any], - args: typing.Tuple[typing.Any, typing.Any], - kwargs: typing.Dict[typing.Any, typing.Any], - ): - """Add object proxy to connection object.""" - connection = connect_method(*args, **kwargs) - self.get_connection_attributes(connection) - return get_traced_connection_proxy(connection, self) - - def get_connection_attributes(self, connection): - # Populate span fields using connection - for key, value in self.connection_attributes.items(): - # Allow attributes nested in connection object - attribute = functools.reduce( - lambda attribute, attribute_value: getattr( - attribute, attribute_value, None - ), - value.split("."), - connection, - ) - if attribute: - self.connection_props[key] = attribute - self.name = self.database_system - self.database = self.connection_props.get("database", "") - if self.database: - # PyMySQL encodes names with utf-8 - if hasattr(self.database, "decode"): - self.database = self.database.decode(errors="ignore") - self.name += "." + self.database - user = self.connection_props.get("user") - # PyMySQL encodes this data - if user and isinstance(user, bytes): - user = user.decode() - if user is not None: - self.span_attributes[SpanAttributes.DB_USER] = str(user) - host = self.connection_props.get("host") - if host is not None: - self.span_attributes[SpanAttributes.NET_PEER_NAME] = host - port = self.connection_props.get("port") - if port is not None: - self.span_attributes[SpanAttributes.NET_PEER_PORT] = port - - -def get_traced_connection_proxy( - connection, db_api_integration, *args, **kwargs -): - # pylint: disable=abstract-method - class TracedConnectionProxy(wrapt.ObjectProxy): - # pylint: disable=unused-argument - def __init__(self, connection, *args, **kwargs): - wrapt.ObjectProxy.__init__(self, connection) - - def __getattribute__(self, name): - if object.__getattribute__(self, name): - return object.__getattribute__(self, name) - - return object.__getattribute__( - object.__getattribute__(self, "_connection"), name - ) - - def cursor(self, *args, **kwargs): - return get_traced_cursor_proxy( - self.__wrapped__.cursor(*args, **kwargs), db_api_integration - ) - - def __enter__(self): - self.__wrapped__.__enter__() - return self - - def __exit__(self, *args, **kwargs): - self.__wrapped__.__exit__(*args, **kwargs) - - return TracedConnectionProxy(connection, *args, **kwargs) - - -class CursorTracer: - def __init__(self, db_api_integration: DatabaseApiIntegration) -> None: - self._db_api_integration = db_api_integration - self._commenter_enabled = self._db_api_integration.enable_commenter - self._commenter_options = ( - self._db_api_integration.commenter_options - if self._db_api_integration.commenter_options - else {} - ) - self._connect_module = self._db_api_integration.connect_module - self._leading_comment_remover = re.compile(r"^/\*.*?\*/") - - def _populate_span( - self, - span: trace_api.Span, - cursor, - *args: typing.Tuple[typing.Any, typing.Any], - ): - if not span.is_recording(): - return - statement = self.get_statement(cursor, args) - span.set_attribute( - SpanAttributes.DB_SYSTEM, self._db_api_integration.database_system - ) - span.set_attribute( - SpanAttributes.DB_NAME, self._db_api_integration.database - ) - span.set_attribute(SpanAttributes.DB_STATEMENT, statement) - - for ( - attribute_key, - attribute_value, - ) in self._db_api_integration.span_attributes.items(): - span.set_attribute(attribute_key, attribute_value) - - if self._db_api_integration.capture_parameters and len(args) > 1: - span.set_attribute("db.statement.parameters", str(args[1])) - - def get_operation_name(self, cursor, args): # pylint: disable=no-self-use - if args and isinstance(args[0], str): - # Strip leading comments so we get the operation name. - return self._leading_comment_remover.sub("", args[0]).split()[0] - return "" - - def get_statement(self, cursor, args): # pylint: disable=no-self-use - if not args: - return "" - statement = args[0] - if isinstance(statement, bytes): - return statement.decode("utf8", "replace") - return statement - - def traced_execution( - self, - cursor, - query_method: typing.Callable[..., typing.Any], - *args: typing.Tuple[typing.Any, typing.Any], - **kwargs: typing.Dict[typing.Any, typing.Any], - ): - name = self.get_operation_name(cursor, args) - if not name: - name = ( - self._db_api_integration.database - if self._db_api_integration.database - else self._db_api_integration.name - ) - - with self._db_api_integration._tracer.start_as_current_span( - name, kind=SpanKind.CLIENT - ) as span: - self._populate_span(span, cursor, *args) - if args and self._commenter_enabled: - try: - args_list = list(args) - commenter_data = dict( - # Psycopg2/framework information - db_driver=f"psycopg2:{self._connect_module.__version__.split(' ')[0]}", - dbapi_threadsafety=self._connect_module.threadsafety, - dbapi_level=self._connect_module.apilevel, - libpq_version=self._connect_module.__libpq_version__, - driver_paramstyle=self._connect_module.paramstyle, - ) - if self._commenter_options.get( - "opentelemetry_values", True - ): - commenter_data.update(**_get_opentelemetry_values()) - - # Filter down to just the requested attributes. - commenter_data = { - k: v - for k, v in commenter_data.items() - if self._commenter_options.get(k, True) - } - statement = _add_sql_comment( - args_list[0], **commenter_data - ) - - args_list[0] = statement - args = tuple(args_list) - - except Exception as exc: # pylint: disable=broad-except - _logger.exception( - "Exception while generating sql comment: %s", exc - ) - return query_method(*args, **kwargs) - - -def get_traced_cursor_proxy(cursor, db_api_integration, *args, **kwargs): - _cursor_tracer = CursorTracer(db_api_integration) - - # pylint: disable=abstract-method - class TracedCursorProxy(wrapt.ObjectProxy): - # pylint: disable=unused-argument - def __init__(self, cursor, *args, **kwargs): - wrapt.ObjectProxy.__init__(self, cursor) - - def execute(self, *args, **kwargs): - return _cursor_tracer.traced_execution( - self.__wrapped__, self.__wrapped__.execute, *args, **kwargs - ) - - def executemany(self, *args, **kwargs): - return _cursor_tracer.traced_execution( - self.__wrapped__, self.__wrapped__.executemany, *args, **kwargs - ) - - def callproc(self, *args, **kwargs): - return _cursor_tracer.traced_execution( - self.__wrapped__, self.__wrapped__.callproc, *args, **kwargs - ) - - def __enter__(self): - self.__wrapped__.__enter__() - return self - - def __exit__(self, *args, **kwargs): - self.__wrapped__.__exit__(*args, **kwargs) - - return TracedCursorProxy(cursor, *args, **kwargs) diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/dbapi/package.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/dbapi/package.py deleted file mode 100644 index 7a66a17a93f9..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/dbapi/package.py +++ /dev/null @@ -1,16 +0,0 @@ -# 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. - - -_instruments = tuple() diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/dbapi/version.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/dbapi/version.py deleted file mode 100644 index 6cca9608e388..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/dbapi/version.py +++ /dev/null @@ -1,17 +0,0 @@ -# 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. - -__version__ = "0.39b0" - -_instruments = tuple() diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/dependencies.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/dependencies.py deleted file mode 100644 index 2da0a3d18bf1..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/dependencies.py +++ /dev/null @@ -1,62 +0,0 @@ -from logging import getLogger -from typing import Collection, Optional - -from pkg_resources import ( - Distribution, - DistributionNotFound, - RequirementParseError, - VersionConflict, - get_distribution, -) - -logger = getLogger(__name__) - - -class DependencyConflict: - required: str = None - found: Optional[str] = None - - def __init__(self, required, found=None): - self.required = required - self.found = found - - def __str__(self): - return f'DependencyConflict: requested: "{self.required}" but found: "{self.found}"' - - -def get_dist_dependency_conflicts( - dist: Distribution, -) -> Optional[DependencyConflict]: - main_deps = dist.requires() - instrumentation_deps = [] - for dep in dist.requires(("instruments",)): - if dep not in main_deps: - # we set marker to none so string representation of the dependency looks like - # requests ~= 1.0 - # instead of - # requests ~= 1.0; extra = "instruments" - # which does not work with `get_distribution()` - dep.marker = None - instrumentation_deps.append(str(dep)) - - return get_dependency_conflicts(instrumentation_deps) - - -def get_dependency_conflicts( - deps: Collection[str], -) -> Optional[DependencyConflict]: - for dep in deps: - try: - get_distribution(dep) - except VersionConflict as exc: - return DependencyConflict(dep, exc.dist) - except DistributionNotFound: - return DependencyConflict(dep) - except RequirementParseError as exc: - logger.warning( - 'error parsing dependency, reporting as a conflict: "%s" - %s', - dep, - exc, - ) - return DependencyConflict(dep) - return None diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/distro.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/distro.py deleted file mode 100644 index 298c119586ef..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/distro.py +++ /dev/null @@ -1,73 +0,0 @@ -# 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. -# type: ignore - -""" -OpenTelemetry Base Distribution (Distro) -""" - -from abc import ABC, abstractmethod -from logging import getLogger - -from pkg_resources import EntryPoint - -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.instrumentor import ( - BaseInstrumentor -) - -_LOG = getLogger(__name__) - - -class BaseDistro(ABC): - """An ABC for distro""" - - _instance = None - - def __new__(cls, *args, **kwargs): - - if cls._instance is None: - cls._instance = object.__new__(cls, *args, **kwargs) - - return cls._instance - - @abstractmethod - def _configure(self, **kwargs): - """Configure the distribution""" - - def configure(self, **kwargs): - """Configure the distribution""" - self._configure(**kwargs) - - def load_instrumentor( # pylint: disable=no-self-use - self, entry_point: EntryPoint, **kwargs - ): - """Takes a collection of instrumentation entry points - and activates them by instantiating and calling instrument() - on each one. - - Distros can override this method to customize the behavior by - inspecting each entry point and configuring them in special ways, - passing additional arguments, load a replacement/fork instead, - skip loading entirely, etc. - """ - instrumentor: BaseInstrumentor = entry_point.load() - instrumentor().instrument(**kwargs) - - -class DefaultDistro(BaseDistro): - def _configure(self, **kwargs): - pass - - -__all__ = ["BaseDistro", "DefaultDistro"] diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/__init__.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/__init__.py deleted file mode 100644 index f0d86fc9ac1e..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/__init__.py +++ /dev/null @@ -1,164 +0,0 @@ -# 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 -from typing import Collection - -from django import VERSION as django_version -from django.conf import settings -from django.core.exceptions import ImproperlyConfigured - -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.django.environment_variables import ( - OTEL_PYTHON_DJANGO_INSTRUMENT, -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.django.middleware.otel_middleware import ( - _DjangoMiddleware, -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.django.package import ( - _instruments -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.django.version import ( - __version__ -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.instrumentor import ( - BaseInstrumentor -) -from opentelemetry.metrics import get_meter -from opentelemetry.semconv.metrics import MetricInstruments -from opentelemetry.trace import get_tracer -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.util.http import get_excluded_urls, parse_excluded_urls - -DJANGO_2_0 = django_version >= (2, 0) - -_excluded_urls_from_env = get_excluded_urls("DJANGO") -_logger = getLogger(__name__) - - -def _get_django_middleware_setting() -> str: - # In Django versions 1.x, setting MIDDLEWARE_CLASSES can be used as a legacy - # alternative to MIDDLEWARE. This is the case when `settings.MIDDLEWARE` has - # its default value (`None`). - if not DJANGO_2_0 and getattr(settings, "MIDDLEWARE", None) is None: - return "MIDDLEWARE_CLASSES" - return "MIDDLEWARE" - - -class DjangoInstrumentor(BaseInstrumentor): - """An instrumentor for Django - - See `BaseInstrumentor` - """ - - _opentelemetry_middleware = ".".join( - [_DjangoMiddleware.__module__, _DjangoMiddleware.__qualname__] - ) - - _sql_commenter_middleware = "azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.django.middleware.sqlcommenter_middleware.SqlCommenter" - - def instrumentation_dependencies(self) -> Collection[str]: - return _instruments - - def _instrument(self, **kwargs): - # FIXME this is probably a pattern that will show up in the rest of the - # ext. Find a better way of implementing this. - if environ.get(OTEL_PYTHON_DJANGO_INSTRUMENT) == "False": - return - - tracer_provider = kwargs.get("tracer_provider") - meter_provider = kwargs.get("meter_provider") - _excluded_urls = kwargs.get("excluded_urls") - tracer = get_tracer( - __name__, - __version__, - tracer_provider=tracer_provider, - ) - meter = get_meter(__name__, __version__, meter_provider=meter_provider) - _DjangoMiddleware._tracer = tracer - _DjangoMiddleware._meter = meter - _DjangoMiddleware._excluded_urls = ( - _excluded_urls_from_env - if _excluded_urls is None - else parse_excluded_urls(_excluded_urls) - ) - _DjangoMiddleware._otel_request_hook = kwargs.pop("request_hook", None) - _DjangoMiddleware._otel_response_hook = kwargs.pop( - "response_hook", None - ) - _DjangoMiddleware._duration_histogram = meter.create_histogram( - name=MetricInstruments.HTTP_SERVER_DURATION, - unit="ms", - description="measures the duration of the inbound http request", - ) - _DjangoMiddleware._active_request_counter = meter.create_up_down_counter( - name=MetricInstruments.HTTP_SERVER_ACTIVE_REQUESTS, - unit="requests", - description="measures the number of concurrent HTTP requests those are currently in flight", - ) - # This can not be solved, but is an inherent problem of this approach: - # the order of middleware entries matters, and here you have no control - # on that: - # https://docs.djangoproject.com/en/3.0/topics/http/middleware/#activating-middleware - # https://docs.djangoproject.com/en/3.0/ref/middleware/#middleware-ordering - - _middleware_setting = _get_django_middleware_setting() - settings_middleware = [] - try: - settings_middleware = getattr(settings, _middleware_setting, []) - except ImproperlyConfigured as exception: - _logger.debug( - "DJANGO_SETTINGS_MODULE environment variable not configured. Defaulting to empty settings: %s", - exception, - ) - settings.configure() - settings_middleware = getattr(settings, _middleware_setting, []) - except ModuleNotFoundError as exception: - _logger.debug( - "DJANGO_SETTINGS_MODULE points to a non-existent module. Defaulting to empty settings: %s", - exception, - ) - settings.configure() - settings_middleware = getattr(settings, _middleware_setting, []) - - # Django allows to specify middlewares as a tuple, so we convert this tuple to a - # list, otherwise we wouldn't be able to call append/remove - if isinstance(settings_middleware, tuple): - settings_middleware = list(settings_middleware) - - is_sql_commentor_enabled = kwargs.pop("is_sql_commentor_enabled", None) - - if is_sql_commentor_enabled: - settings_middleware.insert(0, self._sql_commenter_middleware) - - settings_middleware.insert(0, self._opentelemetry_middleware) - - setattr(settings, _middleware_setting, settings_middleware) - - def _uninstrument(self, **kwargs): - _middleware_setting = _get_django_middleware_setting() - settings_middleware = getattr(settings, _middleware_setting, None) - - # FIXME This is starting to smell like trouble. We have 2 mechanisms - # that may make this condition be True, one implemented in - # BaseInstrumentor and another one implemented in _instrument. Both - # stop _instrument from running and thus, settings_middleware not being - # set. - if settings_middleware is None or ( - self._opentelemetry_middleware not in settings_middleware - ): - return - - settings_middleware.remove(self._opentelemetry_middleware) - setattr(settings, _middleware_setting, settings_middleware) diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/environment_variables.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/environment_variables.py deleted file mode 100644 index 4972a62e9336..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/environment_variables.py +++ /dev/null @@ -1,15 +0,0 @@ -# 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. - -OTEL_PYTHON_DJANGO_INSTRUMENT = "OTEL_PYTHON_DJANGO_INSTRUMENT" diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/middleware/__init__.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/middleware/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/middleware/otel_middleware.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/middleware/otel_middleware.py deleted file mode 100644 index 0518b9af5baf..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/middleware/otel_middleware.py +++ /dev/null @@ -1,401 +0,0 @@ -# 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 types -from logging import getLogger -from time import time -from timeit import default_timer -from typing import Callable - -from django import VERSION as django_version -from django.http import HttpRequest, HttpResponse - -from opentelemetry.context import detach -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.propagators import ( - get_global_response_propagator, -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.utils import ( - _start_internal_or_server_span, - extract_attributes_from_object, -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.wsgi import ( - add_response_attributes -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.wsgi import ( - collect_custom_request_headers_attributes as wsgi_collect_custom_request_headers_attributes, -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.wsgi import ( - collect_custom_response_headers_attributes as wsgi_collect_custom_response_headers_attributes, -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.wsgi import ( - collect_request_attributes as wsgi_collect_request_attributes, -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.wsgi import ( - wsgi_getter -) -from opentelemetry.semconv.trace import SpanAttributes -from opentelemetry.trace import Span, SpanKind, use_span -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.util.http import ( - _parse_active_request_count_attrs, - _parse_duration_attrs, - get_excluded_urls, - get_traced_request_attrs, -) - -try: - from django.core.urlresolvers import ( # pylint: disable=no-name-in-module - Resolver404, - resolve, - ) -except ImportError: - from django.urls import Resolver404, resolve - -DJANGO_2_0 = django_version >= (2, 0) -DJANGO_3_0 = django_version >= (3, 0) - -if DJANGO_2_0: - # Since Django 2.0, only `settings.MIDDLEWARE` is supported, so new-style - # middlewares can be used. - class MiddlewareMixin: - def __init__(self, get_response): - self.get_response = get_response - - def __call__(self, request): - self.process_request(request) - response = self.get_response(request) - return self.process_response(request, response) - -else: - # Django versions 1.x can use `settings.MIDDLEWARE_CLASSES` and expect - # old-style middlewares, which are created by inheriting from - # `deprecation.MiddlewareMixin` since its creation in Django 1.10 and 1.11, - # or from `object` for older versions. - try: - from django.utils.deprecation import MiddlewareMixin - except ImportError: - MiddlewareMixin = object - -if DJANGO_3_0: - from django.core.handlers.asgi import ASGIRequest -else: - ASGIRequest = None - -# try/except block exclusive for optional ASGI imports. -try: - from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.asgi import ( - asgi_getter, - asgi_setter - ) - from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.asgi import ( - collect_custom_request_headers_attributes as asgi_collect_custom_request_attributes, - ) - from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.asgi import ( - collect_custom_response_headers_attributes as asgi_collect_custom_response_attributes, - ) - from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.asgi import ( - collect_request_attributes as asgi_collect_request_attributes, - ) - from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.asgi import ( - set_status_code - ) - - _is_asgi_supported = True -except ImportError: - asgi_getter = None - asgi_collect_request_attributes = None - set_status_code = None - _is_asgi_supported = False - - -_logger = getLogger(__name__) -_attributes_by_preference = [ - [ - SpanAttributes.HTTP_SCHEME, - SpanAttributes.HTTP_HOST, - SpanAttributes.HTTP_TARGET, - ], - [ - SpanAttributes.HTTP_SCHEME, - SpanAttributes.HTTP_SERVER_NAME, - SpanAttributes.NET_HOST_PORT, - SpanAttributes.HTTP_TARGET, - ], - [ - SpanAttributes.HTTP_SCHEME, - SpanAttributes.NET_HOST_NAME, - SpanAttributes.NET_HOST_PORT, - SpanAttributes.HTTP_TARGET, - ], - [SpanAttributes.HTTP_URL], -] - - -def _is_asgi_request(request: HttpRequest) -> bool: - return ASGIRequest is not None and isinstance(request, ASGIRequest) - - -class _DjangoMiddleware(MiddlewareMixin): - """Django Middleware for OpenTelemetry""" - - _environ_activation_key = ( - "opentelemetry-instrumentor-django.activation_key" - ) - _environ_token = "opentelemetry-instrumentor-django.token" - _environ_span_key = "opentelemetry-instrumentor-django.span_key" - _environ_exception_key = "opentelemetry-instrumentor-django.exception_key" - _environ_active_request_attr_key = ( - "opentelemetry-instrumentor-django.active_request_attr_key" - ) - _environ_duration_attr_key = ( - "opentelemetry-instrumentor-django.duration_attr_key" - ) - _environ_timer_key = "opentelemetry-instrumentor-django.timer_key" - _traced_request_attrs = get_traced_request_attrs("DJANGO") - _excluded_urls = get_excluded_urls("DJANGO") - _tracer = None - _meter = None - _duration_histogram = None - _active_request_counter = None - - _otel_request_hook: Callable[[Span, HttpRequest], None] = None - _otel_response_hook: Callable[ - [Span, HttpRequest, HttpResponse], None - ] = None - - @staticmethod - def _get_span_name(request): - try: - if getattr(request, "resolver_match"): - match = request.resolver_match - else: - match = resolve(request.path) - - if hasattr(match, "route"): - return match.route - - # Instead of using `view_name`, better to use `_func_name` as some applications can use similar - # view names in different modules - if hasattr(match, "_func_name"): - return match._func_name # pylint: disable=protected-access - - # Fallback for safety as `_func_name` private field - return match.view_name - - except Resolver404: - return f"HTTP {request.method}" - - # pylint: disable=too-many-locals - def process_request(self, request): - # request.META is a dictionary containing all available HTTP headers - # Read more about request.META here: - # https://docs.djangoproject.com/en/3.0/ref/request-response/#django.http.HttpRequest.META - - if self._excluded_urls.url_disabled(request.build_absolute_uri("?")): - return - - is_asgi_request = _is_asgi_request(request) - if not _is_asgi_supported and is_asgi_request: - return - - # pylint:disable=W0212 - request._otel_start_time = time() - request_meta = request.META - - if is_asgi_request: - carrier = request.scope - carrier_getter = asgi_getter - collect_request_attributes = asgi_collect_request_attributes - else: - carrier = request_meta - carrier_getter = wsgi_getter - collect_request_attributes = wsgi_collect_request_attributes - - attributes = collect_request_attributes(carrier) - span, token = _start_internal_or_server_span( - tracer=self._tracer, - span_name=self._get_span_name(request), - start_time=request_meta.get( - "opentelemetry-instrumentor-django.starttime_key" - ), - context_carrier=carrier, - context_getter=carrier_getter, - attributes=attributes, - ) - - active_requests_count_attrs = _parse_active_request_count_attrs( - attributes - ) - duration_attrs = _parse_duration_attrs(attributes) - - request.META[ - self._environ_active_request_attr_key - ] = active_requests_count_attrs - request.META[self._environ_duration_attr_key] = duration_attrs - self._active_request_counter.add(1, active_requests_count_attrs) - if span.is_recording(): - attributes = extract_attributes_from_object( - request, self._traced_request_attrs, attributes - ) - if is_asgi_request: - # ASGI requests include extra attributes in request.scope.headers. - attributes = extract_attributes_from_object( - types.SimpleNamespace( - **{ - name.decode("latin1"): value.decode("latin1") - for name, value in request.scope.get("headers", []) - } - ), - self._traced_request_attrs, - attributes, - ) - if span.is_recording() and span.kind == SpanKind.SERVER: - attributes.update( - asgi_collect_custom_request_attributes(carrier) - ) - else: - if span.is_recording() and span.kind == SpanKind.SERVER: - custom_attributes = ( - wsgi_collect_custom_request_headers_attributes(carrier) - ) - if len(custom_attributes) > 0: - span.set_attributes(custom_attributes) - - for key, value in attributes.items(): - span.set_attribute(key, value) - - activation = use_span(span, end_on_exit=True) - activation.__enter__() # pylint: disable=E1101 - request_start_time = default_timer() - request.META[self._environ_timer_key] = request_start_time - request.META[self._environ_activation_key] = activation - request.META[self._environ_span_key] = span - if token: - request.META[self._environ_token] = token - - if _DjangoMiddleware._otel_request_hook: - _DjangoMiddleware._otel_request_hook( # pylint: disable=not-callable - span, request - ) - - # pylint: disable=unused-argument - def process_view(self, request, view_func, *args, **kwargs): - # Process view is executed before the view function, here we get the - # route template from request.resolver_match. It is not set yet in process_request - if self._excluded_urls.url_disabled(request.build_absolute_uri("?")): - return - - if ( - self._environ_activation_key in request.META.keys() - and self._environ_span_key in request.META.keys() - ): - span = request.META[self._environ_span_key] - - if span.is_recording(): - match = getattr(request, "resolver_match", None) - if match: - route = getattr(match, "route", None) - if route: - span.set_attribute(SpanAttributes.HTTP_ROUTE, route) - - def process_exception(self, request, exception): - if self._excluded_urls.url_disabled(request.build_absolute_uri("?")): - return - - if self._environ_activation_key in request.META.keys(): - request.META[self._environ_exception_key] = exception - - # pylint: disable=too-many-branches - # pylint: disable=too-many-locals - def process_response(self, request, response): - if self._excluded_urls.url_disabled(request.build_absolute_uri("?")): - return response - - is_asgi_request = _is_asgi_request(request) - if not _is_asgi_supported and is_asgi_request: - return response - - activation = request.META.pop(self._environ_activation_key, None) - span = request.META.pop(self._environ_span_key, None) - active_requests_count_attrs = request.META.pop( - self._environ_active_request_attr_key, None - ) - duration_attrs = request.META.pop( - self._environ_duration_attr_key, None - ) - if duration_attrs: - duration_attrs[ - SpanAttributes.HTTP_STATUS_CODE - ] = response.status_code - request_start_time = request.META.pop(self._environ_timer_key, None) - - if activation and span: - if is_asgi_request: - set_status_code(span, response.status_code) - - if span.is_recording() and span.kind == SpanKind.SERVER: - custom_headers = {} - for key, value in response.items(): - asgi_setter.set(custom_headers, key, value) - - custom_res_attributes = ( - asgi_collect_custom_response_attributes(custom_headers) - ) - for key, value in custom_res_attributes.items(): - span.set_attribute(key, value) - else: - add_response_attributes( - span, - f"{response.status_code} {response.reason_phrase}", - response.items(), - ) - if span.is_recording() and span.kind == SpanKind.SERVER: - custom_attributes = ( - wsgi_collect_custom_response_headers_attributes( - response.items() - ) - ) - if len(custom_attributes) > 0: - span.set_attributes(custom_attributes) - - propagator = get_global_response_propagator() - if propagator: - propagator.inject(response) - - # record any exceptions raised while processing the request - exception = request.META.pop(self._environ_exception_key, None) - if _DjangoMiddleware._otel_response_hook: - _DjangoMiddleware._otel_response_hook( # pylint: disable=not-callable - span, request, response - ) - - if exception: - activation.__exit__( - type(exception), - exception, - getattr(exception, "__traceback__", None), - ) - else: - activation.__exit__(None, None, None) - - if request_start_time is not None: - duration = max( - round((default_timer() - request_start_time) * 1000), 0 - ) - self._duration_histogram.record(duration, duration_attrs) - self._active_request_counter.add(-1, active_requests_count_attrs) - if request.META.get(self._environ_token, None) is not None: - detach(request.META.get(self._environ_token)) - request.META.pop(self._environ_token) - - return response diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/middleware/sqlcommenter_middleware.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/middleware/sqlcommenter_middleware.py deleted file mode 100644 index 24fcab5d0b6c..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/middleware/sqlcommenter_middleware.py +++ /dev/null @@ -1,123 +0,0 @@ -#!/usr/bin/python -# -# 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 contextlib import ExitStack -from logging import getLogger -from typing import Any, Type, TypeVar - -# pylint: disable=no-name-in-module -from django import conf, get_version -from django.db import connections -from django.db.backends.utils import CursorDebugWrapper - -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.sqlcommenter_utils import ( - _add_sql_comment -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.utils import ( - _get_opentelemetry_values -) -from opentelemetry.trace.propagation.tracecontext import ( - TraceContextTextMapPropagator, -) - -_propagator = TraceContextTextMapPropagator() - -_django_version = get_version() -_logger = getLogger(__name__) - -T = TypeVar("T") # pylint: disable-msg=invalid-name - - -class SqlCommenter: - """ - Middleware to append a comment to each database query with details about - the framework and the execution context. - """ - - def __init__(self, get_response) -> None: - self.get_response = get_response - - def __call__(self, request) -> Any: - with ExitStack() as stack: - for db_alias in connections: - stack.enter_context( - connections[db_alias].execute_wrapper( - _QueryWrapper(request) - ) - ) - return self.get_response(request) - - -class _QueryWrapper: - def __init__(self, request) -> None: - self.request = request - - def __call__(self, execute: Type[T], sql, params, many, context) -> T: - # pylint: disable-msg=too-many-locals - with_framework = getattr( - conf.settings, "SQLCOMMENTER_WITH_FRAMEWORK", True - ) - with_controller = getattr( - conf.settings, "SQLCOMMENTER_WITH_CONTROLLER", True - ) - with_route = getattr(conf.settings, "SQLCOMMENTER_WITH_ROUTE", True) - with_app_name = getattr( - conf.settings, "SQLCOMMENTER_WITH_APP_NAME", True - ) - with_opentelemetry = getattr( - conf.settings, "SQLCOMMENTER_WITH_OPENTELEMETRY", True - ) - with_db_driver = getattr( - conf.settings, "SQLCOMMENTER_WITH_DB_DRIVER", True - ) - - db_driver = context["connection"].settings_dict.get("ENGINE", "") - resolver_match = self.request.resolver_match - - sql = _add_sql_comment( - sql, - # Information about the controller. - controller=resolver_match.view_name - if resolver_match and with_controller - else None, - # route is the pattern that matched a request with a controller i.e. the regex - # See https://docs.djangoproject.com/en/stable/ref/urlresolvers/#django.urls.ResolverMatch.route - # getattr() because the attribute doesn't exist in Django < 2.2. - route=getattr(resolver_match, "route", None) - if resolver_match and with_route - else None, - # app_name is the application namespace for the URL pattern that matches the URL. - # See https://docs.djangoproject.com/en/stable/ref/urlresolvers/#django.urls.ResolverMatch.app_name - app_name=(resolver_match.app_name or None) - if resolver_match and with_app_name - else None, - # Framework centric information. - framework=f"django:{_django_version}" if with_framework else None, - # Information about the database and driver. - db_driver=db_driver if with_db_driver else None, - **_get_opentelemetry_values() if with_opentelemetry else {}, - ) - - # TODO: MySQL truncates logs > 1024B so prepend comments - # instead of statements, if the engine is MySQL. - # See: - # * https://github.com/basecamp/marginalia/issues/61 - # * https://github.com/basecamp/marginalia/pull/80 - - # Add the query to the query log if debugging. - if isinstance(context["cursor"], CursorDebugWrapper): - context["connection"].queries_log.append(sql) - - return execute(sql, params, many, context) diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/package.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/package.py deleted file mode 100644 index 290061a36fb2..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/package.py +++ /dev/null @@ -1,17 +0,0 @@ -# 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. - - -_instruments = ("django >= 1.10",) -_supports_metrics = True diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/version.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/version.py deleted file mode 100644 index a84e45c8896e..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/django/version.py +++ /dev/null @@ -1,15 +0,0 @@ -# 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. - -__version__ = "0.39b0" diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/environment_variables.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/environment_variables.py deleted file mode 100644 index ad28f0685908..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/environment_variables.py +++ /dev/null @@ -1,18 +0,0 @@ -# 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. - -OTEL_PYTHON_DISABLED_INSTRUMENTATIONS = "OTEL_PYTHON_DISABLED_INSTRUMENTATIONS" -""" -.. envvar:: OTEL_PYTHON_DISABLED_INSTRUMENTATIONS -""" diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/fastapi/__init__.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/fastapi/__init__.py deleted file mode 100644 index da0917d5b0d7..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/fastapi/__init__.py +++ /dev/null @@ -1,183 +0,0 @@ -# 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 logging -import typing -from typing import Collection - -import fastapi -from starlette.routing import Match - -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.fastapi.package import _instruments -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.fastapi.version import __version__ -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.instrumentor import BaseInstrumentor -from opentelemetry.metrics import get_meter -from opentelemetry.semconv.trace import SpanAttributes -from opentelemetry.trace import Span -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.util.http import get_excluded_urls, parse_excluded_urls - -_excluded_urls_from_env = get_excluded_urls("FASTAPI") -_logger = logging.getLogger(__name__) - -_ServerRequestHookT = typing.Optional[typing.Callable[[Span, dict], None]] -_ClientRequestHookT = typing.Optional[typing.Callable[[Span, dict], None]] -_ClientResponseHookT = typing.Optional[typing.Callable[[Span, dict], None]] - - -class FastAPIInstrumentor(BaseInstrumentor): - """An instrumentor for FastAPI - - See `BaseInstrumentor` - """ - - _original_fastapi = None - - @staticmethod - def instrument_app( - app: fastapi.FastAPI, - server_request_hook: _ServerRequestHookT = None, - client_request_hook: _ClientRequestHookT = None, - client_response_hook: _ClientResponseHookT = None, - tracer_provider=None, - meter_provider=None, - excluded_urls=None, - ): - """Instrument an uninstrumented FastAPI application.""" - if not hasattr(app, "_is_instrumented_by_opentelemetry"): - app._is_instrumented_by_opentelemetry = False - - if not getattr(app, "_is_instrumented_by_opentelemetry", False): - if excluded_urls is None: - excluded_urls = _excluded_urls_from_env - else: - excluded_urls = parse_excluded_urls(excluded_urls) - meter = get_meter(__name__, __version__, meter_provider) - - app.add_middleware( - OpenTelemetryMiddleware, - excluded_urls=excluded_urls, - default_span_details=_get_route_details, - server_request_hook=server_request_hook, - client_request_hook=client_request_hook, - client_response_hook=client_response_hook, - tracer_provider=tracer_provider, - meter=meter, - ) - app._is_instrumented_by_opentelemetry = True - if app not in _InstrumentedFastAPI._instrumented_fastapi_apps: - _InstrumentedFastAPI._instrumented_fastapi_apps.add(app) - else: - _logger.warning( - "Attempting to instrument FastAPI app while already instrumented" - ) - - @staticmethod - def uninstrument_app(app: fastapi.FastAPI): - app.user_middleware = [ - x - for x in app.user_middleware - if x.cls is not OpenTelemetryMiddleware - ] - app.middleware_stack = app.build_middleware_stack() - app._is_instrumented_by_opentelemetry = False - - def instrumentation_dependencies(self) -> Collection[str]: - return _instruments - - def _instrument(self, **kwargs): - self._original_fastapi = fastapi.FastAPI - _InstrumentedFastAPI._tracer_provider = kwargs.get("tracer_provider") - _InstrumentedFastAPI._server_request_hook = kwargs.get( - "server_request_hook" - ) - _InstrumentedFastAPI._client_request_hook = kwargs.get( - "client_request_hook" - ) - _InstrumentedFastAPI._client_response_hook = kwargs.get( - "client_response_hook" - ) - _excluded_urls = kwargs.get("excluded_urls") - _InstrumentedFastAPI._excluded_urls = ( - _excluded_urls_from_env - if _excluded_urls is None - else parse_excluded_urls(_excluded_urls) - ) - _InstrumentedFastAPI._meter_provider = kwargs.get("meter_provider") - fastapi.FastAPI = _InstrumentedFastAPI - - def _uninstrument(self, **kwargs): - for instance in _InstrumentedFastAPI._instrumented_fastapi_apps: - self.uninstrument_app(instance) - _InstrumentedFastAPI._instrumented_fastapi_apps.clear() - fastapi.FastAPI = self._original_fastapi - - -class _InstrumentedFastAPI(fastapi.FastAPI): - _tracer_provider = None - _meter_provider = None - _excluded_urls = None - _server_request_hook: _ServerRequestHookT = None - _client_request_hook: _ClientRequestHookT = None - _client_response_hook: _ClientResponseHookT = None - _instrumented_fastapi_apps = set() - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - meter = get_meter( - __name__, __version__, _InstrumentedFastAPI._meter_provider - ) - self.add_middleware( - OpenTelemetryMiddleware, - excluded_urls=_InstrumentedFastAPI._excluded_urls, - default_span_details=_get_route_details, - server_request_hook=_InstrumentedFastAPI._server_request_hook, - client_request_hook=_InstrumentedFastAPI._client_request_hook, - client_response_hook=_InstrumentedFastAPI._client_response_hook, - tracer_provider=_InstrumentedFastAPI._tracer_provider, - meter=meter, - ) - self._is_instrumented_by_opentelemetry = True - _InstrumentedFastAPI._instrumented_fastapi_apps.add(self) - - def __del__(self): - if self in _InstrumentedFastAPI._instrumented_fastapi_apps: - _InstrumentedFastAPI._instrumented_fastapi_apps.remove(self) - - -def _get_route_details(scope): - """Callback to retrieve the fastapi route being served. - - TODO: there is currently no way to retrieve http.route from - a starlette application from scope. - - See: https://github.com/encode/starlette/pull/804 - """ - app = scope["app"] - route = None - for starlette_route in app.routes: - match, _ = starlette_route.matches(scope) - if match == Match.FULL: - route = starlette_route.path - break - if match == Match.PARTIAL: - route = starlette_route.path - # method only exists for http, if websocket - # leave it blank. - span_name = route or scope.get("method", "") - attributes = {} - if route: - attributes[SpanAttributes.HTTP_ROUTE] = route - return span_name, attributes diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/fastapi/package.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/fastapi/package.py deleted file mode 100644 index 8df84fc93181..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/fastapi/package.py +++ /dev/null @@ -1,18 +0,0 @@ -# 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. - - -_instruments = ("fastapi ~= 0.58",) - -_supports_metrics = True diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/fastapi/version.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/fastapi/version.py deleted file mode 100644 index a84e45c8896e..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/fastapi/version.py +++ /dev/null @@ -1,15 +0,0 @@ -# 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. - -__version__ = "0.39b0" diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/flask/__init__.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/flask/__init__.py deleted file mode 100644 index 722b457a7b5e..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/flask/__init__.py +++ /dev/null @@ -1,420 +0,0 @@ -# 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. - -# Note: This package is not named "flask" because of -# https://github.com/PyCQA/pylint/issues/2648 - - -from logging import getLogger -from threading import get_ident -from time import time_ns -from timeit import default_timer -from typing import Collection - -import flask - -import azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.wsgi as otel_wsgi -from opentelemetry import context, trace -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.flask.package import _instruments -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.flask.version import __version__ -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.instrumentor import BaseInstrumentor -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.propagators import ( - get_global_response_propagator, -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.utils import _start_internal_or_server_span -from opentelemetry.metrics import get_meter -from opentelemetry.semconv.metrics import MetricInstruments -from opentelemetry.semconv.trace import SpanAttributes -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.util.http import get_excluded_urls, parse_excluded_urls - -_logger = getLogger(__name__) - -_ENVIRON_STARTTIME_KEY = "opentelemetry-flask.starttime_key" -_ENVIRON_SPAN_KEY = "opentelemetry-flask.span_key" -_ENVIRON_ACTIVATION_KEY = "opentelemetry-flask.activation_key" -_ENVIRON_THREAD_ID_KEY = "opentelemetry-flask.thread_id_key" -_ENVIRON_TOKEN = "opentelemetry-flask.token" - -_excluded_urls_from_env = get_excluded_urls("FLASK") - - -def get_default_span_name(): - try: - span_name = flask.request.url_rule.rule - except AttributeError: - span_name = otel_wsgi.get_default_span_name(flask.request.environ) - return span_name - - -def _rewrapped_app( - wsgi_app, - active_requests_counter, - duration_histogram, - response_hook=None, - excluded_urls=None, -): - def _wrapped_app(wrapped_app_environ, start_response): - # We want to measure the time for route matching, etc. - # In theory, we could start the span here and use - # update_name later but that API is "highly discouraged" so - # we better avoid it. - wrapped_app_environ[_ENVIRON_STARTTIME_KEY] = time_ns() - start = default_timer() - attributes = otel_wsgi.collect_request_attributes(wrapped_app_environ) - active_requests_count_attrs = ( - otel_wsgi._parse_active_request_count_attrs(attributes) - ) - duration_attrs = otel_wsgi._parse_duration_attrs(attributes) - active_requests_counter.add(1, active_requests_count_attrs) - - def _start_response(status, response_headers, *args, **kwargs): - if flask.request and ( - excluded_urls is None - or not excluded_urls.url_disabled(flask.request.url) - ): - span = flask.request.environ.get(_ENVIRON_SPAN_KEY) - - propagator = get_global_response_propagator() - if propagator: - propagator.inject( - response_headers, - setter=otel_wsgi.default_response_propagation_setter, - ) - - if span: - otel_wsgi.add_response_attributes( - span, status, response_headers - ) - status_code = otel_wsgi._parse_status_code(status) - if status_code is not None: - duration_attrs[ - SpanAttributes.HTTP_STATUS_CODE - ] = status_code - if ( - span.is_recording() - and span.kind == trace.SpanKind.SERVER - ): - custom_attributes = otel_wsgi.collect_custom_response_headers_attributes( - response_headers - ) - if len(custom_attributes) > 0: - span.set_attributes(custom_attributes) - else: - _logger.warning( - "Flask environ's OpenTelemetry span " - "missing at _start_response(%s)", - status, - ) - if response_hook is not None: - response_hook(span, status, response_headers) - return start_response(status, response_headers, *args, **kwargs) - - result = wsgi_app(wrapped_app_environ, _start_response) - duration = max(round((default_timer() - start) * 1000), 0) - duration_histogram.record(duration, duration_attrs) - active_requests_counter.add(-1, active_requests_count_attrs) - return result - - return _wrapped_app - - -def _wrapped_before_request( - request_hook=None, - tracer=None, - excluded_urls=None, - enable_commenter=True, - commenter_options=None, -): - def _before_request(): - if excluded_urls and excluded_urls.url_disabled(flask.request.url): - return - flask_request_environ = flask.request.environ - span_name = get_default_span_name() - - span, token = _start_internal_or_server_span( - tracer=tracer, - span_name=span_name, - start_time=flask_request_environ.get(_ENVIRON_STARTTIME_KEY), - context_carrier=flask_request_environ, - context_getter=otel_wsgi.wsgi_getter, - ) - - if request_hook: - request_hook(span, flask_request_environ) - - if span.is_recording(): - attributes = otel_wsgi.collect_request_attributes( - flask_request_environ - ) - if flask.request.url_rule: - # For 404 that result from no route found, etc, we - # don't have a url_rule. - attributes[ - SpanAttributes.HTTP_ROUTE - ] = flask.request.url_rule.rule - for key, value in attributes.items(): - span.set_attribute(key, value) - if span.is_recording() and span.kind == trace.SpanKind.SERVER: - custom_attributes = ( - otel_wsgi.collect_custom_request_headers_attributes( - flask_request_environ - ) - ) - if len(custom_attributes) > 0: - span.set_attributes(custom_attributes) - - activation = trace.use_span(span, end_on_exit=True) - activation.__enter__() # pylint: disable=E1101 - flask_request_environ[_ENVIRON_ACTIVATION_KEY] = activation - flask_request_environ[_ENVIRON_THREAD_ID_KEY] = get_ident() - flask_request_environ[_ENVIRON_SPAN_KEY] = span - flask_request_environ[_ENVIRON_TOKEN] = token - - if enable_commenter: - current_context = context.get_current() - flask_info = {} - - # https://flask.palletsprojects.com/en/1.1.x/api/#flask.has_request_context - if flask and flask.request: - if commenter_options.get("framework", True): - flask_info["framework"] = f"flask:{flask.__version__}" - if ( - commenter_options.get("controller", True) - and flask.request.endpoint - ): - flask_info["controller"] = flask.request.endpoint - if ( - commenter_options.get("route", True) - and flask.request.url_rule - and flask.request.url_rule.rule - ): - flask_info["route"] = flask.request.url_rule.rule - sqlcommenter_context = context.set_value( - "SQLCOMMENTER_ORM_TAGS_AND_VALUES", flask_info, current_context - ) - context.attach(sqlcommenter_context) - - return _before_request - - -def _wrapped_teardown_request( - excluded_urls=None, -): - def _teardown_request(exc): - # pylint: disable=E1101 - if excluded_urls and excluded_urls.url_disabled(flask.request.url): - return - - activation = flask.request.environ.get(_ENVIRON_ACTIVATION_KEY) - thread_id = flask.request.environ.get(_ENVIRON_THREAD_ID_KEY) - if not activation or thread_id != get_ident(): - # This request didn't start a span, maybe because it was created in - # a way that doesn't run `before_request`, like when it is created - # with `app.test_request_context`. - # - # Similarly, check the thread_id against the current thread to ensure - # tear down only happens on the original thread. This situation can - # arise if the original thread handling the request spawn children - # threads and then uses something like copy_current_request_context - # to copy the request context. - return - if exc is None: - activation.__exit__(None, None, None) - else: - activation.__exit__( - type(exc), exc, getattr(exc, "__traceback__", None) - ) - - if flask.request.environ.get(_ENVIRON_TOKEN, None): - context.detach(flask.request.environ.get(_ENVIRON_TOKEN)) - - return _teardown_request - - -class _InstrumentedFlask(flask.Flask): - _excluded_urls = None - _tracer_provider = None - _request_hook = None - _response_hook = None - _enable_commenter = True - _commenter_options = None - _meter_provider = None - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - self._original_wsgi_app = self.wsgi_app - self._is_instrumented_by_opentelemetry = True - - meter = get_meter( - __name__, __version__, _InstrumentedFlask._meter_provider - ) - duration_histogram = meter.create_histogram( - name=MetricInstruments.HTTP_SERVER_DURATION, - unit="ms", - description="measures the duration of the inbound HTTP request", - ) - active_requests_counter = meter.create_up_down_counter( - name=MetricInstruments.HTTP_SERVER_ACTIVE_REQUESTS, - unit="requests", - description="measures the number of concurrent HTTP requests that are currently in-flight", - ) - - self.wsgi_app = _rewrapped_app( - self.wsgi_app, - active_requests_counter, - duration_histogram, - _InstrumentedFlask._response_hook, - excluded_urls=_InstrumentedFlask._excluded_urls, - ) - - tracer = trace.get_tracer( - __name__, __version__, _InstrumentedFlask._tracer_provider - ) - - _before_request = _wrapped_before_request( - _InstrumentedFlask._request_hook, - tracer, - excluded_urls=_InstrumentedFlask._excluded_urls, - enable_commenter=_InstrumentedFlask._enable_commenter, - commenter_options=_InstrumentedFlask._commenter_options, - ) - self._before_request = _before_request - self.before_request(_before_request) - - _teardown_request = _wrapped_teardown_request( - excluded_urls=_InstrumentedFlask._excluded_urls, - ) - self.teardown_request(_teardown_request) - - -class FlaskInstrumentor(BaseInstrumentor): - # pylint: disable=protected-access,attribute-defined-outside-init - """An instrumentor for flask.Flask - - See `BaseInstrumentor` - """ - - def instrumentation_dependencies(self) -> Collection[str]: - return _instruments - - def _instrument(self, **kwargs): - self._original_flask = flask.Flask - request_hook = kwargs.get("request_hook") - response_hook = kwargs.get("response_hook") - if callable(request_hook): - _InstrumentedFlask._request_hook = request_hook - if callable(response_hook): - _InstrumentedFlask._response_hook = response_hook - tracer_provider = kwargs.get("tracer_provider") - _InstrumentedFlask._tracer_provider = tracer_provider - excluded_urls = kwargs.get("excluded_urls") - _InstrumentedFlask._excluded_urls = ( - _excluded_urls_from_env - if excluded_urls is None - else parse_excluded_urls(excluded_urls) - ) - enable_commenter = kwargs.get("enable_commenter", True) - _InstrumentedFlask._enable_commenter = enable_commenter - - commenter_options = kwargs.get("commenter_options", {}) - _InstrumentedFlask._commenter_options = commenter_options - meter_provider = kwargs.get("meter_provider") - _InstrumentedFlask._meter_provider = meter_provider - flask.Flask = _InstrumentedFlask - - def _uninstrument(self, **kwargs): - flask.Flask = self._original_flask - - @staticmethod - def instrument_app( - app, - request_hook=None, - response_hook=None, - tracer_provider=None, - excluded_urls=None, - enable_commenter=True, - commenter_options=None, - meter_provider=None, - ): - if not hasattr(app, "_is_instrumented_by_opentelemetry"): - app._is_instrumented_by_opentelemetry = False - - if not app._is_instrumented_by_opentelemetry: - excluded_urls = ( - parse_excluded_urls(excluded_urls) - if excluded_urls is not None - else _excluded_urls_from_env - ) - meter = get_meter(__name__, __version__, meter_provider) - duration_histogram = meter.create_histogram( - name=MetricInstruments.HTTP_SERVER_DURATION, - unit="ms", - description="measures the duration of the inbound HTTP request", - ) - active_requests_counter = meter.create_up_down_counter( - name=MetricInstruments.HTTP_SERVER_ACTIVE_REQUESTS, - unit="requests", - description="measures the number of concurrent HTTP requests that are currently in-flight", - ) - - app._original_wsgi_app = app.wsgi_app - app.wsgi_app = _rewrapped_app( - app.wsgi_app, - active_requests_counter, - duration_histogram, - response_hook, - excluded_urls=excluded_urls, - ) - - tracer = trace.get_tracer(__name__, __version__, tracer_provider) - - _before_request = _wrapped_before_request( - request_hook, - tracer, - excluded_urls=excluded_urls, - enable_commenter=enable_commenter, - commenter_options=commenter_options - if commenter_options - else {}, - ) - app._before_request = _before_request - app.before_request(_before_request) - - _teardown_request = _wrapped_teardown_request( - excluded_urls=excluded_urls, - ) - app._teardown_request = _teardown_request - app.teardown_request(_teardown_request) - app._is_instrumented_by_opentelemetry = True - else: - _logger.warning( - "Attempting to instrument Flask app while already instrumented" - ) - - @staticmethod - def uninstrument_app(app): - if hasattr(app, "_original_wsgi_app"): - app.wsgi_app = app._original_wsgi_app - - # FIXME add support for other Flask blueprints that are not None - app.before_request_funcs[None].remove(app._before_request) - app.teardown_request_funcs[None].remove(app._teardown_request) - del app._original_wsgi_app - app._is_instrumented_by_opentelemetry = False - else: - _logger.warning( - "Attempting to uninstrument Flask " - "app while already uninstrumented" - ) diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/flask/package.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/flask/package.py deleted file mode 100644 index 33bfe4ccba7e..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/flask/package.py +++ /dev/null @@ -1,18 +0,0 @@ -# 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. - - -_instruments = ("flask >= 1.0, < 3.0",) - -_supports_metrics = True diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/flask/version.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/flask/version.py deleted file mode 100644 index a84e45c8896e..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/flask/version.py +++ /dev/null @@ -1,15 +0,0 @@ -# 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. - -__version__ = "0.39b0" diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/instrumentor.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/instrumentor.py deleted file mode 100644 index 3cc46a4e6bfd..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/instrumentor.py +++ /dev/null @@ -1,131 +0,0 @@ -# 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. -# type: ignore - -""" -OpenTelemetry Base Instrumentor -""" - -from abc import ABC, abstractmethod -from logging import getLogger -from typing import Collection, Optional - -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.dependencies import ( - DependencyConflict, - get_dependency_conflicts, -) - -_LOG = getLogger(__name__) - - -class BaseInstrumentor(ABC): - """An ABC for instrumentors - - Child classes of this ABC should instrument specific third - party libraries or frameworks either by using the - ``opentelemetry-instrument`` command or by calling their methods - directly. - - Since every third party library or framework is different and has different - instrumentation needs, more methods can be added to the child classes as - needed to provide practical instrumentation to the end user. - """ - - _instance = None - _is_instrumented_by_opentelemetry = False - - def __new__(cls, *args, **kwargs): - if cls._instance is None: - cls._instance = object.__new__(cls) - - return cls._instance - - @property - def is_instrumented_by_opentelemetry(self): - return self._is_instrumented_by_opentelemetry - - @abstractmethod - def instrumentation_dependencies(self) -> Collection[str]: - """Return a list of python packages with versions that the will be instrumented. - - The format should be the same as used in requirements.txt or pyproject.toml. - - For example, if an instrumentation instruments requests 1.x, this method should look - like: - - def instrumentation_dependencies(self) -> Collection[str]: - return ['requests ~= 1.0'] - - This will ensure that the instrumentation will only be used when the specified library - is present in the environment. - """ - - def _instrument(self, **kwargs): - """Instrument the library""" - - @abstractmethod - def _uninstrument(self, **kwargs): - """Uninstrument the library""" - - def _check_dependency_conflicts(self) -> Optional[DependencyConflict]: - dependencies = self.instrumentation_dependencies() - return get_dependency_conflicts(dependencies) - - def instrument(self, **kwargs): - """Instrument the library - - This method will be called without any optional arguments by the - ``opentelemetry-instrument`` command. - - This means that calling this method directly without passing any - optional values should do the very same thing that the - ``opentelemetry-instrument`` command does. - """ - - if self._is_instrumented_by_opentelemetry: - _LOG.warning("Attempting to instrument while already instrumented") - return None - - # check if instrumentor has any missing or conflicting dependencies - skip_dep_check = kwargs.pop("skip_dep_check", False) - if not skip_dep_check: - conflict = self._check_dependency_conflicts() - if conflict: - _LOG.error(conflict) - return None - - result = self._instrument( # pylint: disable=assignment-from-no-return - **kwargs - ) - self._is_instrumented_by_opentelemetry = True - return result - - def uninstrument(self, **kwargs): - """Uninstrument the library - - See ``BaseInstrumentor.instrument`` for more information regarding the - usage of ``kwargs``. - """ - - if self._is_instrumented_by_opentelemetry: - result = self._uninstrument(**kwargs) - self._is_instrumented_by_opentelemetry = False - return result - - _LOG.warning("Attempting to uninstrument while already uninstrumented") - - return None - - -__all__ = ["BaseInstrumentor"] diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/propagators.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/propagators.py deleted file mode 100644 index bc40f7742c7c..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/propagators.py +++ /dev/null @@ -1,124 +0,0 @@ -# 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. - -""" -This module implements experimental propagators to inject trace context -into response carriers. This is useful for server side frameworks that start traces -when server requests and want to share the trace context with the client so the -client can add its spans to the same trace. - -This is part of an upcoming W3C spec and will eventually make it to the Otel spec. - -https://w3c.github.io/trace-context/#trace-context-http-response-headers-format -""" - -import typing -from abc import ABC, abstractmethod - -from opentelemetry import trace -from opentelemetry.context.context import Context -from opentelemetry.propagators import textmap -from opentelemetry.trace import format_span_id, format_trace_id - -_HTTP_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers" -_RESPONSE_PROPAGATOR = None - - -def get_global_response_propagator(): - return _RESPONSE_PROPAGATOR - - -def set_global_response_propagator(propagator): - global _RESPONSE_PROPAGATOR # pylint:disable=global-statement - _RESPONSE_PROPAGATOR = propagator - - -class Setter(ABC): - @abstractmethod - def set(self, carrier, key, value): - """Inject the provided key value pair in carrier.""" - - -class DictHeaderSetter(Setter): - def set(self, carrier, key, value): # pylint: disable=no-self-use - old_value = carrier.get(key, "") - if old_value: - value = f"{old_value}, {value}" - carrier[key] = value - - -class FuncSetter(Setter): - """FuncSetter coverts a function into a valid Setter. Any function that can - set values in a carrier can be converted into a Setter by using FuncSetter. - This is useful when injecting trace context into non-dict objects such - HTTP Response objects for different framework. - - For example, it can be used to create a setter for Falcon response object as: - - setter = FuncSetter(falcon.api.Response.append_header) - - and then used with the propagator as: - - propagator.inject(falcon_response, setter=setter) - - This would essentially make the propagator call `falcon_response.append_header(key, value)` - """ - - def __init__(self, func): - self._func = func - - def set(self, carrier, key, value): - self._func(carrier, key, value) - - -default_setter = DictHeaderSetter() - - -class ResponsePropagator(ABC): - @abstractmethod - def inject( - self, - carrier: textmap.CarrierT, - context: typing.Optional[Context] = None, - setter: textmap.Setter = default_setter, - ) -> None: - """Injects SpanContext into the HTTP response carrier.""" - - -class TraceResponsePropagator(ResponsePropagator): - """Experimental propagator that injects tracecontext into HTTP responses.""" - - def inject( - self, - carrier: textmap.CarrierT, - context: typing.Optional[Context] = None, - setter: textmap.Setter = default_setter, - ) -> None: - """Injects SpanContext into the HTTP response carrier.""" - span = trace.get_current_span(context) - span_context = span.get_span_context() - if span_context == trace.INVALID_SPAN_CONTEXT: - return - - header_name = "traceresponse" - setter.set( - carrier, - header_name, - f"00-{format_trace_id(span_context.trace_id)}-{format_span_id(span_context.span_id)}-{span_context.trace_flags:02x}", - ) - setter.set( - carrier, - _HTTP_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS, - header_name, - ) diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/psycopg2/__init__.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/psycopg2/__init__.py deleted file mode 100644 index 2da379cdcb21..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/psycopg2/__init__.py +++ /dev/null @@ -1,175 +0,0 @@ -# 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 logging -import typing -from typing import Collection - -import psycopg2 -from psycopg2.extensions import ( - cursor as pg_cursor, # pylint: disable=no-name-in-module -) -from psycopg2.sql import Composed # pylint: disable=no-name-in-module - -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation import dbapi -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.instrumentor import BaseInstrumentor -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.psycopg2.package import _instruments -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.psycopg2.version import __version__ - -_logger = logging.getLogger(__name__) -_OTEL_CURSOR_FACTORY_KEY = "_otel_orig_cursor_factory" - - -class Psycopg2Instrumentor(BaseInstrumentor): - _CONNECTION_ATTRIBUTES = { - "database": "info.dbname", - "port": "info.port", - "host": "info.host", - "user": "info.user", - } - - _DATABASE_SYSTEM = "postgresql" - - def instrumentation_dependencies(self) -> Collection[str]: - return _instruments - - def _instrument(self, **kwargs): - """Integrate with PostgreSQL Psycopg library. - Psycopg: http://initd.org/psycopg/ - """ - tracer_provider = kwargs.get("tracer_provider") - enable_sqlcommenter = kwargs.get("enable_commenter", False) - commenter_options = kwargs.get("commenter_options", {}) - dbapi.wrap_connect( - __name__, - psycopg2, - "connect", - self._DATABASE_SYSTEM, - self._CONNECTION_ATTRIBUTES, - version=__version__, - tracer_provider=tracer_provider, - db_api_integration_factory=DatabaseApiIntegration, - enable_commenter=enable_sqlcommenter, - commenter_options=commenter_options, - ) - - def _uninstrument(self, **kwargs): - """ "Disable Psycopg2 instrumentation""" - dbapi.unwrap_connect(psycopg2, "connect") - - # TODO(owais): check if core dbapi can do this for all dbapi implementations e.g, pymysql and mysql - @staticmethod - def instrument_connection(connection, tracer_provider=None): - if not hasattr(connection, "_is_instrumented_by_opentelemetry"): - connection._is_instrumented_by_opentelemetry = False - - if not connection._is_instrumented_by_opentelemetry: - setattr( - connection, _OTEL_CURSOR_FACTORY_KEY, connection.cursor_factory - ) - connection.cursor_factory = _new_cursor_factory( - tracer_provider=tracer_provider - ) - connection._is_instrumented_by_opentelemetry = True - else: - _logger.warning( - "Attempting to instrument Psycopg connection while already instrumented" - ) - return connection - - # TODO(owais): check if core dbapi can do this for all dbapi implementations e.g, pymysql and mysql - @staticmethod - def uninstrument_connection(connection): - connection.cursor_factory = getattr( - connection, _OTEL_CURSOR_FACTORY_KEY, None - ) - - return connection - - -# TODO(owais): check if core dbapi can do this for all dbapi implementations e.g, pymysql and mysql -class DatabaseApiIntegration(dbapi.DatabaseApiIntegration): - def wrapped_connection( - self, - connect_method: typing.Callable[..., typing.Any], - args: typing.Tuple[typing.Any, typing.Any], - kwargs: typing.Dict[typing.Any, typing.Any], - ): - """Add object proxy to connection object.""" - base_cursor_factory = kwargs.pop("cursor_factory", None) - new_factory_kwargs = {"db_api": self} - if base_cursor_factory: - new_factory_kwargs["base_factory"] = base_cursor_factory - kwargs["cursor_factory"] = _new_cursor_factory(**new_factory_kwargs) - connection = connect_method(*args, **kwargs) - self.get_connection_attributes(connection) - return connection - - -class CursorTracer(dbapi.CursorTracer): - def get_operation_name(self, cursor, args): - if not args: - return "" - - statement = args[0] - if isinstance(statement, Composed): - statement = statement.as_string(cursor) - - if isinstance(statement, str): - # Strip leading comments so we get the operation name. - return self._leading_comment_remover.sub("", statement).split()[0] - - return "" - - def get_statement(self, cursor, args): - if not args: - return "" - - statement = args[0] - if isinstance(statement, Composed): - statement = statement.as_string(cursor) - return statement - - -def _new_cursor_factory(db_api=None, base_factory=None, tracer_provider=None): - if not db_api: - db_api = DatabaseApiIntegration( - __name__, - Psycopg2Instrumentor._DATABASE_SYSTEM, - connection_attributes=Psycopg2Instrumentor._CONNECTION_ATTRIBUTES, - version=__version__, - tracer_provider=tracer_provider, - ) - - base_factory = base_factory or pg_cursor - _cursor_tracer = CursorTracer(db_api) - - class TracedCursorFactory(base_factory): - def execute(self, *args, **kwargs): - return _cursor_tracer.traced_execution( - self, super().execute, *args, **kwargs - ) - - def executemany(self, *args, **kwargs): - return _cursor_tracer.traced_execution( - self, super().executemany, *args, **kwargs - ) - - def callproc(self, *args, **kwargs): - return _cursor_tracer.traced_execution( - self, super().callproc, *args, **kwargs - ) - - return TracedCursorFactory diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/psycopg2/package.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/psycopg2/package.py deleted file mode 100644 index 9757a8df7941..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/psycopg2/package.py +++ /dev/null @@ -1,16 +0,0 @@ -# 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. - - -_instruments = ("psycopg2 >= 2.7.3.1",) diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/psycopg2/version.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/psycopg2/version.py deleted file mode 100644 index a84e45c8896e..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/psycopg2/version.py +++ /dev/null @@ -1,15 +0,0 @@ -# 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. - -__version__ = "0.39b0" diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/py.typed b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/py.typed deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/requests/__init__.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/requests/__init__.py deleted file mode 100644 index f7e65e2ecde5..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/requests/__init__.py +++ /dev/null @@ -1,266 +0,0 @@ -# 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 functools -import types -from timeit import default_timer -from typing import Callable, Collection, Optional -from urllib.parse import urlparse - -from requests.models import PreparedRequest, Response -from requests.sessions import Session -from requests.structures import CaseInsensitiveDict - -from opentelemetry import context - -# FIXME: fix the importing of this private attribute when the location of the _SUPPRESS_HTTP_INSTRUMENTATION_KEY is defined. -from opentelemetry.context import _SUPPRESS_HTTP_INSTRUMENTATION_KEY -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.instrumentor import BaseInstrumentor -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.requests.package import _instruments -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.requests.version import __version__ -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.utils import ( - _SUPPRESS_INSTRUMENTATION_KEY, - http_status_to_status_code, -) -from opentelemetry.metrics import Histogram, get_meter -from opentelemetry.propagate import inject -from opentelemetry.semconv.metrics import MetricInstruments -from opentelemetry.semconv.trace import SpanAttributes -from opentelemetry.trace import SpanKind, Tracer, get_tracer -from opentelemetry.trace.span import Span -from opentelemetry.trace.status import Status -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.util.http import ( - ExcludeList, - get_excluded_urls, - parse_excluded_urls, - remove_url_credentials, -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.util.http.httplib import set_ip_on_next_http_connection - -_excluded_urls_from_env = get_excluded_urls("REQUESTS") - -_RequestHookT = Optional[Callable[[Span, PreparedRequest], None]] -_ResponseHookT = Optional[Callable[[Span, PreparedRequest], None]] - - -# pylint: disable=unused-argument -# pylint: disable=R0915 -def _instrument( - tracer: Tracer, - duration_histogram: Histogram, - request_hook: _RequestHookT = None, - response_hook: _ResponseHookT = None, - excluded_urls: ExcludeList = None, -): - """Enables tracing of all requests calls that go through - :code:`requests.session.Session.request` (this includes - :code:`requests.get`, etc.).""" - - # Since - # https://github.com/psf/requests/commit/d72d1162142d1bf8b1b5711c664fbbd674f349d1 - # (v0.7.0, Oct 23, 2011), get, post, etc are implemented via request which - # again, is implemented via Session.request (`Session` was named `session` - # before v1.0.0, Dec 17, 2012, see - # https://github.com/psf/requests/commit/4e5c4a6ab7bb0195dececdd19bb8505b872fe120) - - wrapped_send = Session.send - - # pylint: disable-msg=too-many-locals,too-many-branches - @functools.wraps(wrapped_send) - def instrumented_send(self, request, **kwargs): - if excluded_urls and excluded_urls.url_disabled(request.url): - return wrapped_send(self, request, **kwargs) - - def get_or_create_headers(): - request.headers = ( - request.headers - if request.headers is not None - else CaseInsensitiveDict() - ) - return request.headers - - if context.get_value( - _SUPPRESS_INSTRUMENTATION_KEY - ) or context.get_value(_SUPPRESS_HTTP_INSTRUMENTATION_KEY): - return wrapped_send(self, request, **kwargs) - - # See - # https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-client - method = request.method.upper() - span_name = get_default_span_name(method) - - url = remove_url_credentials(request.url) - - span_attributes = { - SpanAttributes.HTTP_METHOD: method, - SpanAttributes.HTTP_URL: url, - } - - metric_labels = { - SpanAttributes.HTTP_METHOD: method, - } - - try: - parsed_url = urlparse(url) - metric_labels[SpanAttributes.HTTP_SCHEME] = parsed_url.scheme - if parsed_url.hostname: - metric_labels[SpanAttributes.HTTP_HOST] = parsed_url.hostname - metric_labels[ - SpanAttributes.NET_PEER_NAME - ] = parsed_url.hostname - if parsed_url.port: - metric_labels[SpanAttributes.NET_PEER_PORT] = parsed_url.port - except ValueError: - pass - - with tracer.start_as_current_span( - span_name, kind=SpanKind.CLIENT, attributes=span_attributes - ) as span, set_ip_on_next_http_connection(span): - exception = None - if callable(request_hook): - request_hook(span, request) - - headers = get_or_create_headers() - inject(headers) - - token = context.attach( - context.set_value(_SUPPRESS_HTTP_INSTRUMENTATION_KEY, True) - ) - - start_time = default_timer() - - try: - result = wrapped_send(self, request, **kwargs) # *** PROCEED - except Exception as exc: # pylint: disable=W0703 - exception = exc - result = getattr(exc, "response", None) - finally: - elapsed_time = max( - round((default_timer() - start_time) * 1000), 0 - ) - context.detach(token) - - if isinstance(result, Response): - if span.is_recording(): - span.set_attribute( - SpanAttributes.HTTP_STATUS_CODE, result.status_code - ) - span.set_status( - Status(http_status_to_status_code(result.status_code)) - ) - - metric_labels[ - SpanAttributes.HTTP_STATUS_CODE - ] = result.status_code - - if result.raw is not None: - version = getattr(result.raw, "version", None) - if version: - metric_labels[SpanAttributes.HTTP_FLAVOR] = ( - "1.1" if version == 11 else "1.0" - ) - - if callable(response_hook): - response_hook(span, request, result) - - duration_histogram.record(elapsed_time, attributes=metric_labels) - - if exception is not None: - raise exception.with_traceback(exception.__traceback__) - - return result - - instrumented_send.opentelemetry_instrumentation_requests_applied = True - Session.send = instrumented_send - - -def _uninstrument(): - """Disables instrumentation of :code:`requests` through this module. - - Note that this only works if no other module also patches requests.""" - _uninstrument_from(Session) - - -def _uninstrument_from(instr_root, restore_as_bound_func=False): - for instr_func_name in ("request", "send"): - instr_func = getattr(instr_root, instr_func_name) - if not getattr( - instr_func, - "opentelemetry_instrumentation_requests_applied", - False, - ): - continue - - original = instr_func.__wrapped__ # pylint:disable=no-member - if restore_as_bound_func: - original = types.MethodType(original, instr_root) - setattr(instr_root, instr_func_name, original) - - -def get_default_span_name(method): - """Default implementation for name_callback, returns HTTP {method_name}.""" - return f"HTTP {method.strip()}" - - -class RequestsInstrumentor(BaseInstrumentor): - """An instrumentor for requests - See `BaseInstrumentor` - """ - - def instrumentation_dependencies(self) -> Collection[str]: - return _instruments - - def _instrument(self, **kwargs): - """Instruments requests module - - Args: - **kwargs: Optional arguments - ``tracer_provider``: a TracerProvider, defaults to global - ``request_hook``: An optional callback that is invoked right after a span is created. - ``response_hook``: An optional callback which is invoked right before the span is finished processing a response. - ``excluded_urls``: A string containing a comma-delimited - list of regexes used to exclude URLs from tracking - """ - tracer_provider = kwargs.get("tracer_provider") - tracer = get_tracer(__name__, __version__, tracer_provider) - excluded_urls = kwargs.get("excluded_urls") - meter_provider = kwargs.get("meter_provider") - meter = get_meter( - __name__, - __version__, - meter_provider, - ) - duration_histogram = meter.create_histogram( - name=MetricInstruments.HTTP_CLIENT_DURATION, - unit="ms", - description="measures the duration of the outbound HTTP request", - ) - _instrument( - tracer, - duration_histogram, - request_hook=kwargs.get("request_hook"), - response_hook=kwargs.get("response_hook"), - excluded_urls=_excluded_urls_from_env - if excluded_urls is None - else parse_excluded_urls(excluded_urls), - ) - - def _uninstrument(self, **kwargs): - _uninstrument() - - @staticmethod - def uninstrument_session(session): - """Disables instrumentation on the session object.""" - _uninstrument_from(session, restore_as_bound_func=True) diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/requests/package.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/requests/package.py deleted file mode 100644 index 8424bfeb2aa1..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/requests/package.py +++ /dev/null @@ -1,18 +0,0 @@ -# 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. - - -_instruments = ("requests ~= 2.0",) - -_supports_metrics = True diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/requests/version.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/requests/version.py deleted file mode 100644 index a84e45c8896e..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/requests/version.py +++ /dev/null @@ -1,15 +0,0 @@ -# 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. - -__version__ = "0.39b0" diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/sqlcommenter_utils.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/sqlcommenter_utils.py deleted file mode 100644 index f201269ea2ad..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/sqlcommenter_utils.py +++ /dev/null @@ -1,66 +0,0 @@ -# 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 opentelemetry import context -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.utils import _url_quote - - -def _add_sql_comment(sql, **meta) -> str: - """ - Appends comments to the sql statement and returns it - """ - meta.update(**_add_framework_tags()) - comment = _generate_sql_comment(**meta) - sql = sql.rstrip() - if sql[-1] == ";": - sql = sql[:-1] + comment + ";" - else: - sql = sql + comment - return sql - - -def _generate_sql_comment(**meta) -> str: - """ - Return a SQL comment with comma delimited key=value pairs created from - **meta kwargs. - """ - key_value_delimiter = "," - - if not meta: # No entries added. - return "" - - # Sort the keywords to ensure that caching works and that testing is - # deterministic. It eases visual inspection as well. - return ( - " /*" - + key_value_delimiter.join( - f"{_url_quote(key)}={_url_quote(value)!r}" - for key, value in sorted(meta.items()) - if value is not None - ) - + "*/" - ) - - -def _add_framework_tags() -> dict: - """ - Returns orm related tags if any set by the context - """ - - sqlcommenter_framework_values = ( - context.get_value("SQLCOMMENTER_ORM_TAGS_AND_VALUES") - if context.get_value("SQLCOMMENTER_ORM_TAGS_AND_VALUES") - else {} - ) - return sqlcommenter_framework_values diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/urllib/__init__.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/urllib/__init__.py deleted file mode 100644 index bce63f39ec5a..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/urllib/__init__.py +++ /dev/null @@ -1,273 +0,0 @@ -# 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 functools -import types -import typing -from http import client -from timeit import default_timer -from typing import Collection, Dict -from urllib.request import ( # pylint: disable=no-name-in-module,import-error - OpenerDirector, - Request, -) - -from opentelemetry import context - -# FIXME: fix the importing of this private attribute when the location of the _SUPPRESS_HTTP_INSTRUMENTATION_KEY is defined. -from opentelemetry.context import _SUPPRESS_HTTP_INSTRUMENTATION_KEY -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.instrumentor import BaseInstrumentor -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.urllib.package import _instruments -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.urllib.version import __version__ -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.utils import ( - _SUPPRESS_INSTRUMENTATION_KEY, - http_status_to_status_code, -) -from opentelemetry.metrics import Histogram, get_meter -from opentelemetry.propagate import inject -from opentelemetry.semconv.metrics import MetricInstruments -from opentelemetry.semconv.trace import SpanAttributes -from opentelemetry.trace import Span, SpanKind, get_tracer -from opentelemetry.trace.status import Status -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.util.http import ( - ExcludeList, - get_excluded_urls, - parse_excluded_urls, - remove_url_credentials, -) - -_excluded_urls_from_env = get_excluded_urls("URLLIB") - -_RequestHookT = typing.Optional[typing.Callable[[Span, Request], None]] -_ResponseHookT = typing.Optional[ - typing.Callable[[Span, Request, client.HTTPResponse], None] -] - - -class URLLibInstrumentor(BaseInstrumentor): - """An instrumentor for urllib - See `BaseInstrumentor` - """ - - def instrumentation_dependencies(self) -> Collection[str]: - return _instruments - - def _instrument(self, **kwargs): - """Instruments urllib module - - Args: - **kwargs: Optional arguments - ``tracer_provider``: a TracerProvider, defaults to global - ``request_hook``: An optional callback invoked that is invoked right after a span is created. - ``response_hook``: An optional callback which is invoked right before the span is finished processing a response - ``excluded_urls``: A string containing a comma-delimited - list of regexes used to exclude URLs from tracking - """ - tracer_provider = kwargs.get("tracer_provider") - tracer = get_tracer(__name__, __version__, tracer_provider) - excluded_urls = kwargs.get("excluded_urls") - meter_provider = kwargs.get("meter_provider") - meter = get_meter(__name__, __version__, meter_provider) - - histograms = _create_client_histograms(meter) - - _instrument( - tracer, - histograms, - request_hook=kwargs.get("request_hook"), - response_hook=kwargs.get("response_hook"), - excluded_urls=_excluded_urls_from_env - if excluded_urls is None - else parse_excluded_urls(excluded_urls), - ) - - def _uninstrument(self, **kwargs): - _uninstrument() - - def uninstrument_opener( - self, opener: OpenerDirector - ): # pylint: disable=no-self-use - """uninstrument_opener a specific instance of urllib.request.OpenerDirector""" - _uninstrument_from(opener, restore_as_bound_func=True) - - -def _instrument( - tracer, - histograms: Dict[str, Histogram], - request_hook: _RequestHookT = None, - response_hook: _ResponseHookT = None, - excluded_urls: ExcludeList = None, -): - """Enables tracing of all requests calls that go through - :code:`urllib.Client._make_request`""" - - opener_open = OpenerDirector.open - - @functools.wraps(opener_open) - def instrumented_open(opener, fullurl, data=None, timeout=None): - if isinstance(fullurl, str): - request_ = Request(fullurl, data) - else: - request_ = fullurl - - def get_or_create_headers(): - return getattr(request_, "headers", {}) - - def call_wrapped(): - return opener_open(opener, request_, data=data, timeout=timeout) - - return _instrumented_open_call( - opener, request_, call_wrapped, get_or_create_headers - ) - - def _instrumented_open_call( - _, request, call_wrapped, get_or_create_headers - ): # pylint: disable=too-many-locals - if context.get_value( - _SUPPRESS_INSTRUMENTATION_KEY - ) or context.get_value(_SUPPRESS_HTTP_INSTRUMENTATION_KEY): - return call_wrapped() - - url = request.full_url - if excluded_urls and excluded_urls.url_disabled(url): - return call_wrapped() - - method = request.get_method().upper() - - span_name = f"HTTP {method}".strip() - - url = remove_url_credentials(url) - - labels = { - SpanAttributes.HTTP_METHOD: method, - SpanAttributes.HTTP_URL: url, - } - - with tracer.start_as_current_span( - span_name, kind=SpanKind.CLIENT, attributes=labels - ) as span: - exception = None - if callable(request_hook): - request_hook(span, request) - - headers = get_or_create_headers() - inject(headers) - - token = context.attach( - context.set_value(_SUPPRESS_HTTP_INSTRUMENTATION_KEY, True) - ) - try: - start_time = default_timer() - result = call_wrapped() # *** PROCEED - except Exception as exc: # pylint: disable=W0703 - exception = exc - result = getattr(exc, "file", None) - finally: - elapsed_time = round((default_timer() - start_time) * 1000) - context.detach(token) - - if result is not None: - code_ = result.getcode() - labels[SpanAttributes.HTTP_STATUS_CODE] = str(code_) - - if span.is_recording() and code_ is not None: - span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, code_) - span.set_status(Status(http_status_to_status_code(code_))) - - ver_ = str(getattr(result, "version", "")) - if ver_: - labels[ - SpanAttributes.HTTP_FLAVOR - ] = f"{ver_[:1]}.{ver_[:-1]}" - - _record_histograms( - histograms, labels, request, result, elapsed_time - ) - - if callable(response_hook): - response_hook(span, request, result) - - if exception is not None: - raise exception.with_traceback(exception.__traceback__) - - return result - - instrumented_open.opentelemetry_instrumentation_urllib_applied = True - OpenerDirector.open = instrumented_open - - -def _uninstrument(): - """Disables instrumentation of :code:`urllib` through this module. - - Note that this only works if no other module also patches urllib.""" - _uninstrument_from(OpenerDirector) - - -def _uninstrument_from(instr_root, restore_as_bound_func=False): - instr_func_name = "open" - instr_func = getattr(instr_root, instr_func_name) - if not getattr( - instr_func, - "opentelemetry_instrumentation_urllib_applied", - False, - ): - return - - original = instr_func.__wrapped__ # pylint:disable=no-member - if restore_as_bound_func: - original = types.MethodType(original, instr_root) - setattr(instr_root, instr_func_name, original) - - -def _create_client_histograms(meter) -> Dict[str, Histogram]: - histograms = { - MetricInstruments.HTTP_CLIENT_DURATION: meter.create_histogram( - name=MetricInstruments.HTTP_CLIENT_DURATION, - unit="ms", - description="measures the duration outbound HTTP requests", - ), - MetricInstruments.HTTP_CLIENT_REQUEST_SIZE: meter.create_histogram( - name=MetricInstruments.HTTP_CLIENT_REQUEST_SIZE, - unit="By", - description="measures the size of HTTP request messages (compressed)", - ), - MetricInstruments.HTTP_CLIENT_RESPONSE_SIZE: meter.create_histogram( - name=MetricInstruments.HTTP_CLIENT_RESPONSE_SIZE, - unit="By", - description="measures the size of HTTP response messages (compressed)", - ), - } - - return histograms - - -def _record_histograms( - histograms, metric_attributes, request, response, elapsed_time -): - histograms[MetricInstruments.HTTP_CLIENT_DURATION].record( - elapsed_time, attributes=metric_attributes - ) - - data = getattr(request, "data", None) - request_size = 0 if data is None else len(data) - histograms[MetricInstruments.HTTP_CLIENT_REQUEST_SIZE].record( - request_size, attributes=metric_attributes - ) - - if response is not None: - response_size = int(response.headers.get("Content-Length", 0)) - histograms[MetricInstruments.HTTP_CLIENT_RESPONSE_SIZE].record( - response_size, attributes=metric_attributes - ) diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/urllib/package.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/urllib/package.py deleted file mode 100644 index 942f175da139..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/urllib/package.py +++ /dev/null @@ -1,18 +0,0 @@ -# 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. - - -_instruments = tuple() - -_supports_metrics = True diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/urllib/version.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/urllib/version.py deleted file mode 100644 index 6cca9608e388..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/urllib/version.py +++ /dev/null @@ -1,17 +0,0 @@ -# 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. - -__version__ = "0.39b0" - -_instruments = tuple() diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/urllib3/__init__.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/urllib3/__init__.py deleted file mode 100644 index 903eb26198a2..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/urllib3/__init__.py +++ /dev/null @@ -1,322 +0,0 @@ -# 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 collections.abc -import contextlib -import io -import typing -from timeit import default_timer -from typing import Collection - -import urllib3.connectionpool -import wrapt - -from opentelemetry import context - -# FIXME: fix the importing of this private attribute when the location of the _SUPPRESS_HTTP_INSTRUMENTATION_KEY is defined. -from opentelemetry.context import _SUPPRESS_HTTP_INSTRUMENTATION_KEY -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.instrumentor import BaseInstrumentor -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.urllib3.package import _instruments -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.urllib3.version import __version__ -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.utils import ( - _SUPPRESS_INSTRUMENTATION_KEY, - http_status_to_status_code, - unwrap, -) -from opentelemetry.metrics import Histogram, get_meter -from opentelemetry.propagate import inject -from opentelemetry.semconv.metrics import MetricInstruments -from opentelemetry.semconv.trace import SpanAttributes -from opentelemetry.trace import Span, SpanKind, Tracer, get_tracer -from opentelemetry.trace.status import Status -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.util.http import ( - ExcludeList, - get_excluded_urls, - parse_excluded_urls, -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.util.http.httplib import set_ip_on_next_http_connection - -_excluded_urls_from_env = get_excluded_urls("URLLIB3") - -_UrlFilterT = typing.Optional[typing.Callable[[str], str]] -_RequestHookT = typing.Optional[ - typing.Callable[ - [ - Span, - urllib3.connectionpool.HTTPConnectionPool, - typing.Dict, - typing.Optional[str], - ], - None, - ] -] -_ResponseHookT = typing.Optional[ - typing.Callable[ - [ - Span, - urllib3.connectionpool.HTTPConnectionPool, - urllib3.response.HTTPResponse, - ], - None, - ] -] - -_URL_OPEN_ARG_TO_INDEX_MAPPING = { - "method": 0, - "url": 1, - "body": 2, -} - - -class URLLib3Instrumentor(BaseInstrumentor): - def instrumentation_dependencies(self) -> Collection[str]: - return _instruments - - def _instrument(self, **kwargs): - """Instruments the urllib3 module - - Args: - **kwargs: Optional arguments - ``tracer_provider``: a TracerProvider, defaults to global. - ``request_hook``: An optional callback that is invoked right after a span is created. - ``response_hook``: An optional callback which is invoked right before the span is finished processing a response. - ``url_filter``: A callback to process the requested URL prior - to adding it as a span attribute. - ``excluded_urls``: A string containing a comma-delimited - list of regexes used to exclude URLs from tracking - """ - tracer_provider = kwargs.get("tracer_provider") - tracer = get_tracer(__name__, __version__, tracer_provider) - - excluded_urls = kwargs.get("excluded_urls") - - meter_provider = kwargs.get("meter_provider") - meter = get_meter(__name__, __version__, meter_provider) - - duration_histogram = meter.create_histogram( - name=MetricInstruments.HTTP_CLIENT_DURATION, - unit="ms", - description="measures the duration outbound HTTP requests", - ) - request_size_histogram = meter.create_histogram( - name=MetricInstruments.HTTP_CLIENT_REQUEST_SIZE, - unit="By", - description="measures the size of HTTP request messages (compressed)", - ) - response_size_histogram = meter.create_histogram( - name=MetricInstruments.HTTP_CLIENT_RESPONSE_SIZE, - unit="By", - description="measures the size of HTTP response messages (compressed)", - ) - - _instrument( - tracer, - duration_histogram, - request_size_histogram, - response_size_histogram, - request_hook=kwargs.get("request_hook"), - response_hook=kwargs.get("response_hook"), - url_filter=kwargs.get("url_filter"), - excluded_urls=_excluded_urls_from_env - if excluded_urls is None - else parse_excluded_urls(excluded_urls), - ) - - def _uninstrument(self, **kwargs): - _uninstrument() - - -def _instrument( - tracer: Tracer, - duration_histogram: Histogram, - request_size_histogram: Histogram, - response_size_histogram: Histogram, - request_hook: _RequestHookT = None, - response_hook: _ResponseHookT = None, - url_filter: _UrlFilterT = None, - excluded_urls: ExcludeList = None, -): - def instrumented_urlopen(wrapped, instance, args, kwargs): - if _is_instrumentation_suppressed(): - return wrapped(*args, **kwargs) - - url = _get_url(instance, args, kwargs, url_filter) - if excluded_urls and excluded_urls.url_disabled(url): - return wrapped(*args, **kwargs) - - method = _get_url_open_arg("method", args, kwargs).upper() - headers = _prepare_headers(kwargs) - body = _get_url_open_arg("body", args, kwargs) - - span_name = f"HTTP {method.strip()}" - span_attributes = { - SpanAttributes.HTTP_METHOD: method, - SpanAttributes.HTTP_URL: url, - } - - with tracer.start_as_current_span( - span_name, kind=SpanKind.CLIENT, attributes=span_attributes - ) as span, set_ip_on_next_http_connection(span): - if callable(request_hook): - request_hook(span, instance, headers, body) - inject(headers) - - with _suppress_further_instrumentation(): - start_time = default_timer() - response = wrapped(*args, **kwargs) - elapsed_time = round((default_timer() - start_time) * 1000) - - _apply_response(span, response) - if callable(response_hook): - response_hook(span, instance, response) - - request_size = _get_body_size(body) - response_size = int(response.headers.get("Content-Length", 0)) - - metric_attributes = _create_metric_attributes( - instance, response, method - ) - - duration_histogram.record( - elapsed_time, attributes=metric_attributes - ) - if request_size is not None: - request_size_histogram.record( - request_size, attributes=metric_attributes - ) - response_size_histogram.record( - response_size, attributes=metric_attributes - ) - - return response - - wrapt.wrap_function_wrapper( - urllib3.connectionpool.HTTPConnectionPool, - "urlopen", - instrumented_urlopen, - ) - - -def _get_url_open_arg(name: str, args: typing.List, kwargs: typing.Mapping): - arg_idx = _URL_OPEN_ARG_TO_INDEX_MAPPING.get(name) - if arg_idx is not None: - try: - return args[arg_idx] - except IndexError: - pass - return kwargs.get(name) - - -def _get_url( - instance: urllib3.connectionpool.HTTPConnectionPool, - args: typing.List, - kwargs: typing.Mapping, - url_filter: _UrlFilterT, -) -> str: - url_or_path = _get_url_open_arg("url", args, kwargs) - if not url_or_path.startswith("/"): - url = url_or_path - else: - url = instance.scheme + "://" + instance.host - if _should_append_port(instance.scheme, instance.port): - url += ":" + str(instance.port) - url += url_or_path - - if url_filter: - return url_filter(url) - return url - - -def _get_body_size(body: object) -> typing.Optional[int]: - if body is None: - return 0 - if isinstance(body, collections.abc.Sized): - return len(body) - if isinstance(body, io.BytesIO): - return body.getbuffer().nbytes - return None - - -def _should_append_port(scheme: str, port: typing.Optional[int]) -> bool: - if not port: - return False - if scheme == "http" and port == 80: - return False - if scheme == "https" and port == 443: - return False - return True - - -def _prepare_headers(urlopen_kwargs: typing.Dict) -> typing.Dict: - headers = urlopen_kwargs.get("headers") - - # avoid modifying original headers on inject - headers = headers.copy() if headers is not None else {} - urlopen_kwargs["headers"] = headers - - return headers - - -def _apply_response(span: Span, response: urllib3.response.HTTPResponse): - if not span.is_recording(): - return - - span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, response.status) - span.set_status(Status(http_status_to_status_code(response.status))) - - -def _is_instrumentation_suppressed() -> bool: - return bool( - context.get_value(_SUPPRESS_INSTRUMENTATION_KEY) - or context.get_value(_SUPPRESS_HTTP_INSTRUMENTATION_KEY) - ) - - -def _create_metric_attributes( - instance: urllib3.connectionpool.HTTPConnectionPool, - response: urllib3.response.HTTPResponse, - method: str, -) -> dict: - metric_attributes = { - SpanAttributes.HTTP_METHOD: method, - SpanAttributes.HTTP_HOST: instance.host, - SpanAttributes.HTTP_SCHEME: instance.scheme, - SpanAttributes.HTTP_STATUS_CODE: response.status, - SpanAttributes.NET_PEER_NAME: instance.host, - SpanAttributes.NET_PEER_PORT: instance.port, - } - - version = getattr(response, "version") - if version: - metric_attributes[SpanAttributes.HTTP_FLAVOR] = ( - "1.1" if version == 11 else "1.0" - ) - - return metric_attributes - - -@contextlib.contextmanager -def _suppress_further_instrumentation(): - token = context.attach( - context.set_value(_SUPPRESS_HTTP_INSTRUMENTATION_KEY, True) - ) - try: - yield - finally: - context.detach(token) - - -def _uninstrument(): - unwrap(urllib3.connectionpool.HTTPConnectionPool, "urlopen") diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/urllib3/package.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/urllib3/package.py deleted file mode 100644 index 2f5df62de83c..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/urllib3/package.py +++ /dev/null @@ -1,18 +0,0 @@ -# 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. - - -_instruments = ("urllib3 >= 1.0.0, < 2.0.0",) - -_supports_metrics = True diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/urllib3/version.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/urllib3/version.py deleted file mode 100644 index a84e45c8896e..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/urllib3/version.py +++ /dev/null @@ -1,15 +0,0 @@ -# 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. - -__version__ = "0.39b0" diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/utils.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/utils.py deleted file mode 100644 index 3022e6ddd074..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/utils.py +++ /dev/null @@ -1,154 +0,0 @@ -# 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 urllib.parse -from re import escape, sub -from typing import Dict, Sequence - -from wrapt import ObjectProxy - -from opentelemetry import context, trace - -# pylint: disable=unused-import -# pylint: disable=E0611 -from opentelemetry.context import _SUPPRESS_INSTRUMENTATION_KEY # noqa: F401 -from opentelemetry.propagate import extract -from opentelemetry.trace import StatusCode -from opentelemetry.trace.propagation.tracecontext import ( - TraceContextTextMapPropagator, -) - -propagator = TraceContextTextMapPropagator() - - -def extract_attributes_from_object( - obj: any, attributes: Sequence[str], existing: Dict[str, str] = None -) -> Dict[str, str]: - extracted = {} - if existing: - extracted.update(existing) - for attr in attributes: - value = getattr(obj, attr, None) - if value is not None: - extracted[attr] = str(value) - return extracted - - -def http_status_to_status_code( - status: int, - allow_redirect: bool = True, - server_span: bool = False, -) -> StatusCode: - """Converts an HTTP status code to an OpenTelemetry canonical status code - - Args: - status (int): HTTP status code - """ - # See: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#status - if not isinstance(status, int): - return StatusCode.UNSET - - if status < 100: - return StatusCode.ERROR - if status <= 299: - return StatusCode.UNSET - if status <= 399 and allow_redirect: - return StatusCode.UNSET - if status <= 499 and server_span: - return StatusCode.UNSET - return StatusCode.ERROR - - -def unwrap(obj, attr: str): - """Given a function that was wrapped by wrapt.wrap_function_wrapper, unwrap it - - Args: - obj: Object that holds a reference to the wrapped function - attr (str): Name of the wrapped function - """ - func = getattr(obj, attr, None) - if func and isinstance(func, ObjectProxy) and hasattr(func, "__wrapped__"): - setattr(obj, attr, func.__wrapped__) - - -def _start_internal_or_server_span( - tracer, - span_name, - start_time, - context_carrier, - context_getter, - attributes=None, -): - """Returns internal or server span along with the token which can be used by caller to reset context - - - Args: - tracer : tracer in use by given instrumentation library - name (string): name of the span - start_time : start time of the span - context_carrier : object which contains values that are - used to construct a Context. This object - must be paired with an appropriate getter - which understands how to extract a value from it. - context_getter : an object which contains a get function that can retrieve zero - or more values from the carrier and a keys function that can get all the keys - from carrier. - """ - - token = ctx = span_kind = None - if trace.get_current_span() is trace.INVALID_SPAN: - ctx = extract(context_carrier, getter=context_getter) - token = context.attach(ctx) - span_kind = trace.SpanKind.SERVER - else: - ctx = context.get_current() - span_kind = trace.SpanKind.INTERNAL - span = tracer.start_span( - name=span_name, - context=ctx, - kind=span_kind, - start_time=start_time, - attributes=attributes, - ) - return span, token - - -def _url_quote(s) -> str: # pylint: disable=invalid-name - if not isinstance(s, (str, bytes)): - return s - quoted = urllib.parse.quote(s) - # Since SQL uses '%' as a keyword, '%' is a by-product of url quoting - # e.g. foo,bar --> foo%2Cbar - # thus in our quoting, we need to escape it too to finally give - # foo,bar --> foo%%2Cbar - return quoted.replace("%", "%%") - - -def _get_opentelemetry_values() -> dict: - """ - Return the OpenTelemetry Trace and Span IDs if Span ID is set in the - OpenTelemetry execution context. - """ - # Insert the W3C TraceContext generated - _headers = {} - propagator.inject(_headers) - return _headers - - -def _python_path_without_directory(python_path, directory, path_separator): - return sub( - rf"{escape(directory)}{path_separator}(?!$)", - "", - python_path, - ) diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/version.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/version.py deleted file mode 100644 index a84e45c8896e..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/version.py +++ /dev/null @@ -1,15 +0,0 @@ -# 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. - -__version__ = "0.39b0" diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/wsgi/__init__.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/wsgi/__init__.py deleted file mode 100644 index 5a730bdcb7f6..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/wsgi/__init__.py +++ /dev/null @@ -1,404 +0,0 @@ -# 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 functools -import typing -import wsgiref.util as wsgiref_util -from timeit import default_timer - -from opentelemetry import context, trace -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.utils import ( - _start_internal_or_server_span, - http_status_to_status_code, -) -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.wsgi.version import __version__ -from opentelemetry.metrics import get_meter -from opentelemetry.propagators.textmap import Getter -from opentelemetry.semconv.metrics import MetricInstruments -from opentelemetry.semconv.trace import SpanAttributes -from opentelemetry.trace.status import Status, StatusCode -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.util.http import ( - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS, - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST, - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE, - SanitizeValue, - get_custom_headers, - normalise_request_header_name, - normalise_response_header_name, - remove_url_credentials, -) - -_HTTP_VERSION_PREFIX = "HTTP/" -_CARRIER_KEY_PREFIX = "HTTP_" -_CARRIER_KEY_PREFIX_LEN = len(_CARRIER_KEY_PREFIX) - -# List of recommended attributes -_duration_attrs = [ - SpanAttributes.HTTP_METHOD, - SpanAttributes.HTTP_HOST, - SpanAttributes.HTTP_SCHEME, - SpanAttributes.HTTP_STATUS_CODE, - SpanAttributes.HTTP_FLAVOR, - SpanAttributes.HTTP_SERVER_NAME, - SpanAttributes.NET_HOST_NAME, - SpanAttributes.NET_HOST_PORT, -] - -_active_requests_count_attrs = [ - SpanAttributes.HTTP_METHOD, - SpanAttributes.HTTP_HOST, - SpanAttributes.HTTP_SCHEME, - SpanAttributes.HTTP_FLAVOR, - SpanAttributes.HTTP_SERVER_NAME, -] - - -class WSGIGetter(Getter[dict]): - def get( - self, carrier: dict, key: str - ) -> typing.Optional[typing.List[str]]: - """Getter implementation to retrieve a HTTP header value from the - PEP3333-conforming WSGI environ - - Args: - carrier: WSGI environ object - key: header name in environ object - Returns: - A list with a single string with the header value if it exists, - else None. - """ - environ_key = "HTTP_" + key.upper().replace("-", "_") - value = carrier.get(environ_key) - if value is not None: - return [value] - return None - - def keys(self, carrier): - return [ - key[_CARRIER_KEY_PREFIX_LEN:].lower().replace("_", "-") - for key in carrier - if key.startswith(_CARRIER_KEY_PREFIX) - ] - - -wsgi_getter = WSGIGetter() - - -def setifnotnone(dic, key, value): - if value is not None: - dic[key] = value - - -def collect_request_attributes(environ): - """Collects HTTP request attributes from the PEP3333-conforming - WSGI environ and returns a dictionary to be used as span creation attributes. - """ - - result = { - SpanAttributes.HTTP_METHOD: environ.get("REQUEST_METHOD"), - SpanAttributes.HTTP_SERVER_NAME: environ.get("SERVER_NAME"), - SpanAttributes.HTTP_SCHEME: environ.get("wsgi.url_scheme"), - } - - host_port = environ.get("SERVER_PORT") - if host_port is not None and not host_port == "": - result.update({SpanAttributes.NET_HOST_PORT: int(host_port)}) - - setifnotnone(result, SpanAttributes.HTTP_HOST, environ.get("HTTP_HOST")) - target = environ.get("RAW_URI") - if target is None: # Note: `"" or None is None` - target = environ.get("REQUEST_URI") - if target is not None: - result[SpanAttributes.HTTP_TARGET] = target - else: - result[SpanAttributes.HTTP_URL] = remove_url_credentials( - wsgiref_util.request_uri(environ) - ) - - remote_addr = environ.get("REMOTE_ADDR") - if remote_addr: - result[SpanAttributes.NET_PEER_IP] = remote_addr - remote_host = environ.get("REMOTE_HOST") - if remote_host and remote_host != remote_addr: - result[SpanAttributes.NET_PEER_NAME] = remote_host - - user_agent = environ.get("HTTP_USER_AGENT") - if user_agent is not None and len(user_agent) > 0: - result[SpanAttributes.HTTP_USER_AGENT] = user_agent - - setifnotnone( - result, SpanAttributes.NET_PEER_PORT, environ.get("REMOTE_PORT") - ) - flavor = environ.get("SERVER_PROTOCOL", "") - if flavor.upper().startswith(_HTTP_VERSION_PREFIX): - flavor = flavor[len(_HTTP_VERSION_PREFIX) :] - if flavor: - result[SpanAttributes.HTTP_FLAVOR] = flavor - - return result - - -def collect_custom_request_headers_attributes(environ): - """Returns custom HTTP request headers which are configured by the user - from the PEP3333-conforming WSGI environ to be used as span creation attributes as described - in the specification https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-request-and-response-headers - """ - - sanitize = SanitizeValue( - get_custom_headers( - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS - ) - ) - - headers = { - key[_CARRIER_KEY_PREFIX_LEN:].replace("_", "-"): val - for key, val in environ.items() - if key.startswith(_CARRIER_KEY_PREFIX) - } - - return sanitize.sanitize_header_values( - headers, - get_custom_headers( - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST - ), - normalise_request_header_name, - ) - - -def collect_custom_response_headers_attributes(response_headers): - """Returns custom HTTP response headers which are configured by the user from the - PEP3333-conforming WSGI environ as described in the specification - https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-request-and-response-headers - """ - - sanitize = SanitizeValue( - get_custom_headers( - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS - ) - ) - response_headers_dict = {} - if response_headers: - response_headers_dict = dict(response_headers) - - return sanitize.sanitize_header_values( - response_headers_dict, - get_custom_headers( - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE - ), - normalise_response_header_name, - ) - - -def _parse_status_code(resp_status): - status_code, _ = resp_status.split(" ", 1) - try: - return int(status_code) - except ValueError: - return None - - -def _parse_active_request_count_attrs(req_attrs): - active_requests_count_attrs = {} - for attr_key in _active_requests_count_attrs: - if req_attrs.get(attr_key) is not None: - active_requests_count_attrs[attr_key] = req_attrs[attr_key] - return active_requests_count_attrs - - -def _parse_duration_attrs(req_attrs): - duration_attrs = {} - for attr_key in _duration_attrs: - if req_attrs.get(attr_key) is not None: - duration_attrs[attr_key] = req_attrs[attr_key] - return duration_attrs - - -def add_response_attributes( - span, start_response_status, response_headers -): # pylint: disable=unused-argument - """Adds HTTP response attributes to span using the arguments - passed to a PEP3333-conforming start_response callable. - """ - if not span.is_recording(): - return - status_code, _ = start_response_status.split(" ", 1) - - try: - status_code = int(status_code) - except ValueError: - span.set_status( - Status( - StatusCode.ERROR, - "Non-integer HTTP status: " + repr(status_code), - ) - ) - else: - span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, status_code) - span.set_status( - Status(http_status_to_status_code(status_code, server_span=True)) - ) - - -def get_default_span_name(environ): - """Default implementation for name_callback, returns HTTP {METHOD_NAME}.""" - return f"HTTP {environ.get('REQUEST_METHOD', '')}".strip() - - -class OpenTelemetryMiddleware: - """The WSGI application middleware. - - This class is a PEP 3333 conforming WSGI middleware that starts and - annotates spans for any requests it is invoked with. - - Args: - wsgi: The WSGI application callable to forward requests to. - request_hook: Optional callback which is called with the server span and WSGI - environ object for every incoming request. - response_hook: Optional callback which is called with the server span, - WSGI environ, status_code and response_headers for every - incoming request. - tracer_provider: Optional tracer provider to use. If omitted the current - globally configured one is used. - """ - - def __init__( - self, - wsgi, - request_hook=None, - response_hook=None, - tracer_provider=None, - meter_provider=None, - ): - self.wsgi = wsgi - self.tracer = trace.get_tracer(__name__, __version__, tracer_provider) - self.meter = get_meter(__name__, __version__, meter_provider) - self.duration_histogram = self.meter.create_histogram( - name=MetricInstruments.HTTP_SERVER_DURATION, - unit="ms", - description="measures the duration of the inbound HTTP request", - ) - self.active_requests_counter = self.meter.create_up_down_counter( - name=MetricInstruments.HTTP_SERVER_ACTIVE_REQUESTS, - unit="requests", - description="measures the number of concurrent HTTP requests that are currently in-flight", - ) - self.request_hook = request_hook - self.response_hook = response_hook - - @staticmethod - def _create_start_response( - span, start_response, response_hook, duration_attrs - ): - @functools.wraps(start_response) - def _start_response(status, response_headers, *args, **kwargs): - add_response_attributes(span, status, response_headers) - status_code = _parse_status_code(status) - if status_code is not None: - duration_attrs[SpanAttributes.HTTP_STATUS_CODE] = status_code - if span.is_recording() and span.kind == trace.SpanKind.SERVER: - custom_attributes = collect_custom_response_headers_attributes( - response_headers - ) - if len(custom_attributes) > 0: - span.set_attributes(custom_attributes) - if response_hook: - response_hook(status, response_headers) - return start_response(status, response_headers, *args, **kwargs) - - return _start_response - - # pylint: disable=too-many-branches - def __call__(self, environ, start_response): - """The WSGI application - - Args: - environ: A WSGI environment. - start_response: The WSGI start_response callable. - """ - req_attrs = collect_request_attributes(environ) - active_requests_count_attrs = _parse_active_request_count_attrs( - req_attrs - ) - duration_attrs = _parse_duration_attrs(req_attrs) - - span, token = _start_internal_or_server_span( - tracer=self.tracer, - span_name=get_default_span_name(environ), - start_time=None, - context_carrier=environ, - context_getter=wsgi_getter, - attributes=req_attrs, - ) - if span.is_recording() and span.kind == trace.SpanKind.SERVER: - custom_attributes = collect_custom_request_headers_attributes( - environ - ) - if len(custom_attributes) > 0: - span.set_attributes(custom_attributes) - - if self.request_hook: - self.request_hook(span, environ) - - response_hook = self.response_hook - if response_hook: - response_hook = functools.partial(response_hook, span, environ) - - start = default_timer() - self.active_requests_counter.add(1, active_requests_count_attrs) - try: - with trace.use_span(span): - start_response = self._create_start_response( - span, start_response, response_hook, duration_attrs - ) - iterable = self.wsgi(environ, start_response) - return _end_span_after_iterating(iterable, span, token) - except Exception as ex: - if span.is_recording(): - span.set_status(Status(StatusCode.ERROR, str(ex))) - span.end() - if token is not None: - context.detach(token) - raise - finally: - duration = max(round((default_timer() - start) * 1000), 0) - self.duration_histogram.record(duration, duration_attrs) - self.active_requests_counter.add(-1, active_requests_count_attrs) - - -# Put this in a subfunction to not delay the call to the wrapped -# WSGI application (instrumentation should change the application -# behavior as little as possible). -def _end_span_after_iterating(iterable, span, token): - try: - with trace.use_span(span): - yield from iterable - finally: - close = getattr(iterable, "close", None) - if close: - close() - span.end() - if token is not None: - context.detach(token) - - -# TODO: inherit from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.propagators.Setter - - -class ResponsePropagationSetter: - def set(self, carrier, key, value): # pylint: disable=no-self-use - carrier.append((key, value)) - - -default_response_propagation_setter = ResponsePropagationSetter() diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/wsgi/package.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/wsgi/package.py deleted file mode 100644 index 942f175da139..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/wsgi/package.py +++ /dev/null @@ -1,18 +0,0 @@ -# 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. - - -_instruments = tuple() - -_supports_metrics = True diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/wsgi/version.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/wsgi/version.py deleted file mode 100644 index a84e45c8896e..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/instrumentation/wsgi/version.py +++ /dev/null @@ -1,15 +0,0 @@ -# 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. - -__version__ = "0.39b0" diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/util/__init__.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/util/__init__.py deleted file mode 100644 index 0bdee620366b..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/util/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# ------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License in the project root for -# license information. -# -------------------------------------------------------------------------- diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/util/http/__init__.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/util/http/__init__.py deleted file mode 100644 index f3d39ab02f02..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/util/http/__init__.py +++ /dev/null @@ -1,213 +0,0 @@ -# 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 os import environ -from re import IGNORECASE as RE_IGNORECASE -from re import compile as re_compile -from re import search -from typing import Iterable, List -from urllib.parse import urlparse, urlunparse - -from opentelemetry.semconv.trace import SpanAttributes - -OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS = ( - "OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS" -) -OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST = ( - "OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST" -) -OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE = ( - "OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE" -) - -# List of recommended metrics attributes -_duration_attrs = { - SpanAttributes.HTTP_METHOD, - SpanAttributes.HTTP_HOST, - SpanAttributes.HTTP_SCHEME, - SpanAttributes.HTTP_STATUS_CODE, - SpanAttributes.HTTP_FLAVOR, - SpanAttributes.HTTP_SERVER_NAME, - SpanAttributes.NET_HOST_NAME, - SpanAttributes.NET_HOST_PORT, -} - -_active_requests_count_attrs = { - SpanAttributes.HTTP_METHOD, - SpanAttributes.HTTP_HOST, - SpanAttributes.HTTP_SCHEME, - SpanAttributes.HTTP_FLAVOR, - SpanAttributes.HTTP_SERVER_NAME, -} - - -class ExcludeList: - """Class to exclude certain paths (given as a list of regexes) from tracing requests""" - - def __init__(self, excluded_urls: Iterable[str]): - self._excluded_urls = excluded_urls - if self._excluded_urls: - self._regex = re_compile("|".join(excluded_urls)) - - def url_disabled(self, url: str) -> bool: - return bool(self._excluded_urls and search(self._regex, url)) - - -class SanitizeValue: - """Class to sanitize (remove sensitive data from) certain headers (given as a list of regexes)""" - - def __init__(self, sanitized_fields: Iterable[str]): - self._sanitized_fields = sanitized_fields - if self._sanitized_fields: - self._regex = re_compile("|".join(sanitized_fields), RE_IGNORECASE) - - def sanitize_header_value(self, header: str, value: str) -> str: - return ( - "[REDACTED]" - if (self._sanitized_fields and search(self._regex, header)) - else value - ) - - def sanitize_header_values( - self, headers: dict, header_regexes: list, normalize_function: callable - ) -> dict: - values = {} - - if header_regexes: - header_regexes_compiled = re_compile( - "|".join("^" + i + "$" for i in header_regexes), - RE_IGNORECASE, - ) - - for header_name in list( - filter( - header_regexes_compiled.match, - headers.keys(), - ) - ): - header_values = headers.get(header_name) - if header_values: - key = normalize_function(header_name.lower()) - values[key] = [ - self.sanitize_header_value( - header=header_name, value=header_values - ) - ] - - return values - - -_root = r"OTEL_PYTHON_{}" - - -def get_traced_request_attrs(instrumentation): - traced_request_attrs = environ.get( - _root.format(f"{instrumentation}_TRACED_REQUEST_ATTRS"), [] - ) - - if traced_request_attrs: - traced_request_attrs = [ - traced_request_attr.strip() - for traced_request_attr in traced_request_attrs.split(",") - ] - - return traced_request_attrs - - -def get_excluded_urls(instrumentation: str) -> ExcludeList: - # Get instrumentation-specific excluded URLs. If not set, retrieve them - # from generic variable. - excluded_urls = environ.get( - _root.format(f"{instrumentation}_EXCLUDED_URLS"), - environ.get(_root.format("EXCLUDED_URLS"), ""), - ) - - return parse_excluded_urls(excluded_urls) - - -def parse_excluded_urls(excluded_urls: str) -> ExcludeList: - """ - Small helper to put an arbitrary url list inside an ExcludeList - """ - if excluded_urls: - excluded_url_list = [ - excluded_url.strip() for excluded_url in excluded_urls.split(",") - ] - else: - excluded_url_list = [] - - return ExcludeList(excluded_url_list) - - -def remove_url_credentials(url: str) -> str: - """Given a string url, remove the username and password only if it is a valid url""" - - try: - parsed = urlparse(url) - if all([parsed.scheme, parsed.netloc]): # checks for valid url - parsed_url = urlparse(url) - netloc = ( - (":".join(((parsed_url.hostname or ""), str(parsed_url.port)))) - if parsed_url.port - else (parsed_url.hostname or "") - ) - return urlunparse( - ( - parsed_url.scheme, - netloc, - parsed_url.path, - parsed_url.params, - parsed_url.query, - parsed_url.fragment, - ) - ) - except ValueError: # an unparsable url was passed - pass - return url - - -def normalise_request_header_name(header: str) -> str: - key = header.lower().replace("-", "_") - return f"http.request.header.{key}" - - -def normalise_response_header_name(header: str) -> str: - key = header.lower().replace("-", "_") - return f"http.response.header.{key}" - - -def get_custom_headers(env_var: str) -> List[str]: - custom_headers = environ.get(env_var, []) - if custom_headers: - custom_headers = [ - custom_headers.strip() - for custom_headers in custom_headers.split(",") - ] - return custom_headers - - -def _parse_active_request_count_attrs(req_attrs): - active_requests_count_attrs = { - key: req_attrs[key] - for key in _active_requests_count_attrs.intersection(req_attrs.keys()) - } - return active_requests_count_attrs - - -def _parse_duration_attrs(req_attrs): - duration_attrs = { - key: req_attrs[key] - for key in _duration_attrs.intersection(req_attrs.keys()) - } - return duration_attrs diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/util/http/httplib.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/util/http/httplib.py deleted file mode 100644 index 181c58b4d5e2..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/util/http/httplib.py +++ /dev/null @@ -1,179 +0,0 @@ -# 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. - -""" -This library provides functionality to enrich HTTP client spans with IPs. It does -not create spans on its own. -""" - -import contextlib -import http.client -import logging -import socket # pylint:disable=unused-import # Used for typing -import typing -from typing import Collection - -import wrapt - -from opentelemetry import context -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.instrumentor import BaseInstrumentor -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.utils import unwrap -from opentelemetry.semconv.trace import SpanAttributes -from opentelemetry.trace.span import Span - -_STATE_KEY = "httpbase_instrumentation_state" - -logger = logging.getLogger(__name__) - - -class HttpClientInstrumentor(BaseInstrumentor): - def instrumentation_dependencies(self) -> Collection[str]: - return () # This instruments http.client from stdlib; no extra deps. - - def _instrument(self, **kwargs): - """Instruments the http.client module (not creating spans on its own)""" - _instrument() - - def _uninstrument(self, **kwargs): - _uninstrument() - - -def _remove_nonrecording(spanlist: typing.List[Span]): - idx = len(spanlist) - 1 - while idx >= 0: - if not spanlist[idx].is_recording(): - logger.debug("Span is not recording: %s", spanlist[idx]) - islast = idx + 1 == len(spanlist) - if not islast: - spanlist[idx] = spanlist[len(spanlist) - 1] - spanlist.pop() - if islast: - if idx == 0: - return False # We removed everything - idx -= 1 - else: - idx -= 1 - return True - - -def trysetip(conn: http.client.HTTPConnection, loglevel=logging.DEBUG) -> bool: - """Tries to set the net.peer.ip semantic attribute on the current span from the given - HttpConnection. - - Returns False if the connection is not yet established, False if the IP was captured - or there is no need to capture it. - """ - - state = _getstate() - if not state: - return True - spanlist = state.get("need_ip") # type: typing.List[Span] - if not spanlist: - return True - - # Remove all non-recording spans from the list. - if not _remove_nonrecording(spanlist): - return True - - sock = "" - try: - sock = conn.sock # type: typing.Optional[socket.socket] - logger.debug("Got socket: %s", sock) - if sock is None: - return False - addr = sock.getpeername() - if addr and addr[0]: - ip = addr[0] - except Exception: # pylint:disable=broad-except - logger.log( - loglevel, - "Failed to get peer address from %s", - sock, - exc_info=True, - stack_info=True, - ) - else: - for span in spanlist: - span.set_attribute(SpanAttributes.NET_PEER_IP, ip) - return True - - -def _instrumented_connect( - wrapped, instance: http.client.HTTPConnection, args, kwargs -): - result = wrapped(*args, **kwargs) - trysetip(instance, loglevel=logging.WARNING) - return result - - -def instrument_connect(module, name="connect"): - """Instrument additional connect() methods, e.g. for derived classes.""" - - wrapt.wrap_function_wrapper( - module, - name, - _instrumented_connect, - ) - - -def _instrument(): - def instrumented_send( - wrapped, instance: http.client.HTTPConnection, args, kwargs - ): - done = trysetip(instance) - result = wrapped(*args, **kwargs) - if not done: - trysetip(instance, loglevel=logging.WARNING) - return result - - wrapt.wrap_function_wrapper( - http.client.HTTPConnection, - "send", - instrumented_send, - ) - - instrument_connect(http.client.HTTPConnection) - # No need to instrument HTTPSConnection, as it calls super().connect() - - -def _getstate() -> typing.Optional[dict]: - return context.get_value(_STATE_KEY) - - -@contextlib.contextmanager -def set_ip_on_next_http_connection(span: Span): - state = _getstate() - if not state: - token = context.attach( - context.set_value(_STATE_KEY, {"need_ip": [span]}) - ) - try: - yield - finally: - context.detach(token) - else: - spans = state["need_ip"] # type: typing.List[Span] - spans.append(span) - try: - yield - finally: - try: - spans.remove(span) - except ValueError: # Span might have become non-recording - pass - - -def _uninstrument(): - unwrap(http.client.HTTPConnection, "send") - unwrap(http.client.HTTPConnection, "connect") diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/util/http/version.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/util/http/version.py deleted file mode 100644 index a84e45c8896e..000000000000 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_vendor/v0_39b0/opentelemetry/util/http/version.py +++ /dev/null @@ -1,15 +0,0 @@ -# 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. - -__version__ = "0.39b0" diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/autoinstrumentation/_distro.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/autoinstrumentation/_distro.py index 2085b5f5283d..2911421ef8dd 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/autoinstrumentation/_distro.py +++ b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/autoinstrumentation/_distro.py @@ -11,15 +11,15 @@ OTEL_METRICS_EXPORTER, OTEL_TRACES_EXPORTER, ) +from opentelemetry.instrumentation.distro import ( + BaseDistro, +) from opentelemetry.sdk.environment_variables import ( _OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED, ) from azure.core.settings import settings from azure.core.tracing.ext.opentelemetry_span import OpenTelemetrySpan -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.distro import ( - BaseDistro, -) from azure.monitor.opentelemetry.diagnostics._diagnostic_logging import ( AzureDiagnosticLogging, ) diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/util/_configurations.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/util/_configurations.py index e0cfa9157dd3..5462366a902b 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/util/_configurations.py +++ b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/util/_configurations.py @@ -13,6 +13,9 @@ OTEL_METRICS_EXPORTER, OTEL_TRACES_EXPORTER, ) +from opentelemetry.instrumentation.environment_variables import ( + OTEL_PYTHON_DISABLED_INSTRUMENTATIONS, +) from opentelemetry.sdk.environment_variables import OTEL_TRACES_SAMPLER_ARG from azure.monitor.opentelemetry._constants import ( @@ -24,9 +27,6 @@ SAMPLING_RATIO_ARG, ) from azure.monitor.opentelemetry._types import ConfigurationValue -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.environment_variables import ( - OTEL_PYTHON_DISABLED_INSTRUMENTATIONS, -) _INVALID_FLOAT_MESSAGE = "Value of %s must be a float. Defaulting to %s: %s" diff --git a/sdk/monitor/azure-monitor-opentelemetry/setup.py b/sdk/monitor/azure-monitor-opentelemetry/setup.py index 9058123c8ec1..c685bf9c366b 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/setup.py +++ b/sdk/monitor/azure-monitor-opentelemetry/setup.py @@ -88,6 +88,13 @@ "azure-core-tracing-opentelemetry~=1.0.0b10", "azure-monitor-opentelemetry-exporter~=1.0.0b15", "opentelemetry-api~=1.19.0", + "opentelemetry-instrumentation-django~=0.40b0", + "opentelemetry-instrumentation-fastapi~=0.40b0", + "opentelemetry-instrumentation-flask~=0.40b0", + "opentelemetry-instrumentation-psycopg2~=0.40b0", + "opentelemetry-instrumentation-requests~=0.40b0", + "opentelemetry-instrumentation-urllib~=0.40b0", + "opentelemetry-instrumentation-urllib3~=0.40b0", "opentelemetry-sdk~=1.19.0", "wrapt >= 1.14.0, < 2.0.0", "importlib-metadata>=6.0,<6.8; python_version < '3.8'", @@ -100,14 +107,5 @@ "opentelemetry_configurator": [ "azure_monitor_opentelemetry_configurator = azure.monitor.opentelemetry.autoinstrumentation._configurator:AzureMonitorConfigurator" ], - "azure_monitor_opentelemetry_instrumentor": [ - "django = azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.django:DjangoInstrumentor", - "fastapi = azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.fastapi:FastAPIInstrumentor", - "flask = azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.flask:FlaskInstrumentor", - "psycopg2 = azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.psycopg2:Psycopg2Instrumentor", - "requests = azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.requests:RequestsInstrumentor", - "urllib = azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.urllib:URLLibInstrumentor", - "urllib3 = azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.urllib3:URLLib3Instrumentor", - ], }, ) diff --git a/sdk/monitor/azure-monitor-opentelemetry/tests/configuration/test_configure.py b/sdk/monitor/azure-monitor-opentelemetry/tests/configuration/test_configure.py index 33160ec5115c..446ce56b10df 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/tests/configuration/test_configure.py +++ b/sdk/monitor/azure-monitor-opentelemetry/tests/configuration/test_configure.py @@ -17,7 +17,7 @@ from azure.core.tracing.ext.opentelemetry_span import OpenTelemetrySpan from azure.monitor.opentelemetry._configure import ( - _SUPPORTED_INSTRUMENTED_LIBRARIES_DEPENDENCIES_MAP, + _SUPPORTED_INSTRUMENTED_LIBRARIES, _setup_instrumentations, _setup_logging, _setup_metrics, @@ -329,7 +329,7 @@ def test_setup_metrics( metric_exporter_mock.assert_called_once_with(**configurations) reader_mock.assert_called_once_with(metric_exp_init_mock) - @patch("azure.monitor.opentelemetry._configure.get_dependency_conflicts") + @patch("azure.monitor.opentelemetry._configure.get_dist_dependency_conflicts") @patch("azure.monitor.opentelemetry._configure.iter_entry_points") def test_setup_instrumentations_lib_not_supported( self, @@ -343,21 +343,17 @@ def test_setup_instrumentations_lib_not_supported( instr_class_mock = Mock() instr_class_mock.return_value = instrumentor_mock ep_mock.name = "test_instr" - ep2_mock.name = list( - _SUPPORTED_INSTRUMENTED_LIBRARIES_DEPENDENCIES_MAP.keys() - )[0] + ep2_mock.name = _SUPPORTED_INSTRUMENTED_LIBRARIES[0] ep2_mock.load.return_value = instr_class_mock dep_mock.return_value = None _setup_instrumentations({"disabled_instrumentations": []}) - dep_mock.assert_called_with( - _SUPPORTED_INSTRUMENTED_LIBRARIES_DEPENDENCIES_MAP[ep2_mock.name] - ) + dep_mock.assert_called_with(ep2_mock.dist) ep_mock.load.assert_not_called() ep2_mock.load.assert_called_once() instrumentor_mock.instrument.assert_called_once() @patch("azure.monitor.opentelemetry._configure._logger") - @patch("azure.monitor.opentelemetry._configure.get_dependency_conflicts") + @patch("azure.monitor.opentelemetry._configure.get_dist_dependency_conflicts") @patch("azure.monitor.opentelemetry._configure.iter_entry_points") def test_setup_instrumentations_conflict( self, @@ -370,21 +366,17 @@ def test_setup_instrumentations_conflict( instrumentor_mock = Mock() instr_class_mock = Mock() instr_class_mock.return_value = instrumentor_mock - ep_mock.name = list( - _SUPPORTED_INSTRUMENTED_LIBRARIES_DEPENDENCIES_MAP.keys() - )[0] + ep_mock.name = _SUPPORTED_INSTRUMENTED_LIBRARIES[0] ep_mock.load.return_value = instr_class_mock dep_mock.return_value = True _setup_instrumentations({"disabled_instrumentations": []}) - dep_mock.assert_called_with( - _SUPPORTED_INSTRUMENTED_LIBRARIES_DEPENDENCIES_MAP[ep_mock.name] - ) + dep_mock.assert_called_with(ep_mock.dist) ep_mock.load.assert_not_called() instrumentor_mock.instrument.assert_not_called() logger_mock.debug.assert_called_once() @patch("azure.monitor.opentelemetry._configure._logger") - @patch("azure.monitor.opentelemetry._configure.get_dependency_conflicts") + @patch("azure.monitor.opentelemetry._configure.get_dist_dependency_conflicts") @patch("azure.monitor.opentelemetry._configure.iter_entry_points") def test_setup_instrumentations_exception( self, @@ -397,21 +389,17 @@ def test_setup_instrumentations_exception( instrumentor_mock = Mock() instr_class_mock = Mock() instr_class_mock.return_value = instrumentor_mock - ep_mock.name = list( - _SUPPORTED_INSTRUMENTED_LIBRARIES_DEPENDENCIES_MAP.keys() - )[0] + ep_mock.name = _SUPPORTED_INSTRUMENTED_LIBRARIES[0] ep_mock.load.side_effect = Exception() dep_mock.return_value = None _setup_instrumentations({"disabled_instrumentations": []}) - dep_mock.assert_called_with( - _SUPPORTED_INSTRUMENTED_LIBRARIES_DEPENDENCIES_MAP[ep_mock.name] - ) + dep_mock.assert_called_with(ep_mock.dist) ep_mock.load.assert_called_once() instrumentor_mock.instrument.assert_not_called() logger_mock.warning.assert_called_once() @patch("azure.monitor.opentelemetry._configure._logger") - @patch("azure.monitor.opentelemetry._configure.get_dependency_conflicts") + @patch("azure.monitor.opentelemetry._configure.get_dist_dependency_conflicts") @patch("azure.monitor.opentelemetry._configure.iter_entry_points") def test_setup_instrumentations_disabled( self, @@ -425,18 +413,12 @@ def test_setup_instrumentations_disabled( instrumentor_mock = Mock() instr_class_mock = Mock() instr_class_mock.return_value = instrumentor_mock - ep_mock.name = list( - _SUPPORTED_INSTRUMENTED_LIBRARIES_DEPENDENCIES_MAP.keys() - )[0] - ep2_mock.name = list( - _SUPPORTED_INSTRUMENTED_LIBRARIES_DEPENDENCIES_MAP.keys() - )[1] + ep_mock.name = _SUPPORTED_INSTRUMENTED_LIBRARIES[0] + ep2_mock.name = _SUPPORTED_INSTRUMENTED_LIBRARIES[1] ep2_mock.load.return_value = instr_class_mock dep_mock.return_value = None _setup_instrumentations({"disabled_instrumentations": [ep_mock.name]}) - dep_mock.assert_called_with( - _SUPPORTED_INSTRUMENTED_LIBRARIES_DEPENDENCIES_MAP[ep2_mock.name] - ) + dep_mock.assert_called_with(ep2_mock.dist) ep_mock.load.assert_not_called() ep2_mock.load.assert_called_once() instrumentor_mock.instrument.assert_called_once() diff --git a/sdk/monitor/azure-monitor-opentelemetry/tests/configuration/test_util.py b/sdk/monitor/azure-monitor-opentelemetry/tests/configuration/test_util.py index 1a8f475579d1..47181905fcf2 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/tests/configuration/test_util.py +++ b/sdk/monitor/azure-monitor-opentelemetry/tests/configuration/test_util.py @@ -15,7 +15,7 @@ from unittest import TestCase from unittest.mock import patch -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.environment_variables import ( +from opentelemetry.instrumentation.environment_variables import ( OTEL_PYTHON_DISABLED_INSTRUMENTATIONS, ) from azure.monitor.opentelemetry.util._configurations import ( diff --git a/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_django.py b/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_django.py index e2b001c19545..24c639ab97c8 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_django.py +++ b/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_django.py @@ -6,7 +6,7 @@ import unittest -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.django import ( +from opentelemetry.instrumentation.django import ( DjangoInstrumentor, ) diff --git a/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_fastapi.py b/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_fastapi.py index d1b8ea2a5c51..e80b04508ed7 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_fastapi.py +++ b/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_fastapi.py @@ -6,7 +6,7 @@ import unittest -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.fastapi import ( +from opentelemetry.instrumentation.fastapi import ( FastAPIInstrumentor, ) diff --git a/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_flask.py b/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_flask.py index e1dc52a5c6e7..f7e5b1e40bf6 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_flask.py +++ b/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_flask.py @@ -6,7 +6,7 @@ import unittest -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.flask import ( +from opentelemetry.instrumentation.flask import ( FlaskInstrumentor, ) diff --git a/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_psycopg2.py b/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_psycopg2.py index f0aa4033abf2..f02e800b6883 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_psycopg2.py +++ b/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_psycopg2.py @@ -6,7 +6,7 @@ import unittest -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.psycopg2 import ( +from opentelemetry.instrumentation.psycopg2 import ( Psycopg2Instrumentor, ) diff --git a/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_requests.py b/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_requests.py index 751184aa1a5d..b3c869f22c32 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_requests.py +++ b/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_requests.py @@ -6,7 +6,7 @@ import unittest -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.requests import ( +from opentelemetry.instrumentation.requests import ( RequestsInstrumentor, ) diff --git a/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_urllib.py b/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_urllib.py index d16478bd16a5..12c18ba19e6b 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_urllib.py +++ b/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_urllib.py @@ -6,7 +6,7 @@ import unittest -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.urllib import ( +from opentelemetry.instrumentation.urllib import ( URLLibInstrumentor, ) diff --git a/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_urllib3.py b/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_urllib3.py index b4fab20fe644..fb28c82bfee2 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_urllib3.py +++ b/sdk/monitor/azure-monitor-opentelemetry/tests/instrumentation/test_urllib3.py @@ -6,7 +6,7 @@ import unittest -from azure.monitor.opentelemetry._vendor.v0_39b0.opentelemetry.instrumentation.urllib3 import ( +from opentelemetry.instrumentation.urllib3 import ( URLLib3Instrumentor, )