Support PEP 561 to opentelemetry-instrumentation-urllib (#3131)

* Support PEP 561 to `opentelemetry-instrumentation-urllib`

* add future

---------

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
This commit is contained in:
Marcelo Trylesinski
2025-01-14 16:28:11 +00:00
committed by GitHub
parent c59b514cda
commit e54256ddb7
5 changed files with 36 additions and 25 deletions

View File

@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#3100](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3100))
- Add support to database stability opt-in in `_semconv` utilities and add tests
([#3111](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3111))
- `opentelemetry-instrumentation-urllib` Add `py.typed` file to enable PEP 561
([#3131](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3131))
- `opentelemetry-opentelemetry-pymongo` Add `py.typed` file to enable PEP 561
([#3136](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3136))
- `opentelemetry-opentelemetry-requests` Add `py.typed` file to enable PEP 561

View File

@ -43,17 +43,24 @@ The hooks can be configured as follows:
.. code:: python
# `request_obj` is an instance of urllib.request.Request
def request_hook(span, request_obj):
from http.client import HTTPResponse
from urllib.request import Request
from opentelemetry.instrumentation.urllib import URLLibInstrumentor
from opentelemetry.trace import Span
def request_hook(span: Span, request: Request):
pass
# `request_obj` is an instance of urllib.request.Request
# `response` is an instance of http.client.HTTPResponse
def response_hook(span, request_obj, response)
def response_hook(span: Span, request: Request, response: HTTPResponse):
pass
URLLibInstrumentor.instrument(
request_hook=request_hook, response_hook=response_hook)
URLLibInstrumentor().instrument(
request_hook=request_hook,
response_hook=response_hook
)
Exclude lists
@ -74,12 +81,14 @@ API
---
"""
from __future__ import annotations
import functools
import types
import typing
from http import client
from timeit import default_timer
from typing import Collection, Dict
from typing import Any, Collection
from urllib.request import ( # pylint: disable=no-name-in-module,import-error
OpenerDirector,
Request,
@ -107,7 +116,7 @@ from opentelemetry.instrumentation.utils import (
is_http_instrumentation_enabled,
suppress_http_instrumentation,
)
from opentelemetry.metrics import Histogram, get_meter
from opentelemetry.metrics import Histogram, Meter, get_meter
from opentelemetry.propagate import inject
from opentelemetry.semconv._incubating.metrics.http_metrics import (
HTTP_CLIENT_REQUEST_BODY_SIZE,
@ -121,7 +130,7 @@ from opentelemetry.semconv.metrics.http_metrics import (
HTTP_CLIENT_REQUEST_DURATION,
)
from opentelemetry.semconv.trace import SpanAttributes
from opentelemetry.trace import Span, SpanKind, get_tracer
from opentelemetry.trace import Span, SpanKind, Tracer, get_tracer
from opentelemetry.util.http import (
ExcludeList,
get_excluded_urls,
@ -129,6 +138,7 @@ from opentelemetry.util.http import (
remove_url_credentials,
sanitize_method,
)
from opentelemetry.util.types import Attributes
_excluded_urls_from_env = get_excluded_urls("URLLIB")
@ -146,7 +156,7 @@ class URLLibInstrumentor(BaseInstrumentor):
def instrumentation_dependencies(self) -> Collection[str]:
return _instruments
def _instrument(self, **kwargs):
def _instrument(self, **kwargs: Any):
"""Instruments urllib module
Args:
@ -194,7 +204,7 @@ class URLLibInstrumentor(BaseInstrumentor):
sem_conv_opt_in_mode=sem_conv_opt_in_mode,
)
def _uninstrument(self, **kwargs):
def _uninstrument(self, **kwargs: Any):
_uninstrument()
def uninstrument_opener(self, opener: OpenerDirector): # pylint: disable=no-self-use
@ -204,11 +214,11 @@ class URLLibInstrumentor(BaseInstrumentor):
# pylint: disable=too-many-statements
def _instrument(
tracer,
histograms: Dict[str, Histogram],
tracer: Tracer,
histograms: dict[str, Histogram],
request_hook: _RequestHookT = None,
response_hook: _ResponseHookT = None,
excluded_urls: ExcludeList = None,
excluded_urls: ExcludeList | None = None,
sem_conv_opt_in_mode: _StabilityMode = _StabilityMode.DEFAULT,
):
"""Enables tracing of all requests calls that go through
@ -345,7 +355,7 @@ def _uninstrument():
_uninstrument_from(OpenerDirector)
def _uninstrument_from(instr_root, restore_as_bound_func=False):
def _uninstrument_from(instr_root, restore_as_bound_func: bool = False):
instr_func_name = "open"
instr_func = getattr(instr_root, instr_func_name)
if not getattr(
@ -371,7 +381,7 @@ def _get_span_name(method: str) -> str:
def _set_status_code_attribute(
span: Span,
status_code: int,
metric_attributes: dict = None,
metric_attributes: dict[str, Any] | None = None,
sem_conv_opt_in_mode: _StabilityMode = _StabilityMode.DEFAULT,
) -> None:
status_code_str = str(status_code)
@ -394,8 +404,8 @@ def _set_status_code_attribute(
def _create_client_histograms(
meter, sem_conv_opt_in_mode=_StabilityMode.DEFAULT
) -> Dict[str, Histogram]:
meter: Meter, sem_conv_opt_in_mode: _StabilityMode = _StabilityMode.DEFAULT
) -> dict[str, Histogram]:
histograms = {}
if _report_old(sem_conv_opt_in_mode):
histograms[MetricInstruments.HTTP_CLIENT_DURATION] = (
@ -436,9 +446,9 @@ def _create_client_histograms(
def _record_histograms(
histograms: Dict[str, Histogram],
metric_attributes_old: dict,
metric_attributes_new: dict,
histograms: dict[str, Histogram],
metric_attributes_old: Attributes,
metric_attributes_new: Attributes,
request_size: int,
response_size: int,
duration_s: float,

View File

@ -12,8 +12,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import annotations
_instruments = tuple()
_instruments: tuple[str, ...] = tuple()
_supports_metrics = True

View File

@ -13,5 +13,3 @@
# limitations under the License.
__version__ = "0.51b0.dev"
_instruments = tuple()