open-telemetry / open-telemetry/opentelemetry-python-contrib

Issue: ImportError when using OpenTelemetry ASGI Instrumentation in FastAPI

Open
#2,641 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Python
Stars
1.1k
Forks
1.1k
Avg merge
4d 15h
Merged PRs (30d)
16

Description

Describe your environment

name: opentelemetry
channels:

  • conda-forge
    dependencies:
  • _libgcc_mutex=0.1=conda_forge
  • _openmp_mutex=4.5=2_gnu
  • bzip2=1.0.8=hd590300_5
  • ca-certificates=2024.6.2=hbcca054_0
  • ld_impl_linux-64=2.40=hf3520f5_7
  • libffi=3.4.2=h7f98852_5
  • libgcc-ng=13.2.0=h77fa898_13
  • libgomp=13.2.0=h77fa898_13
  • libnsl=2.0.1=hd590300_0
  • libsqlite=3.46.0=hde9e2c9_0
  • libuuid=2.38.1=h0b41bf4_0
  • libxcrypt=4.4.36=hd590300_1
  • libzlib=1.3.1=h4ab18f5_1
  • ncurses=6.5=h59595ed_0
  • openssl=3.3.1=h4ab18f5_1
  • pip=24.0=pyhd8ed1ab_0
  • python=3.9.19=h0755675_0_cpython
  • readline=8.2=h8228510_1
  • setuptools=70.1.1=pyhd8ed1ab_0
  • tk=8.6.13=noxft_h4845f30_101
  • tzdata=2024a=h0c530f3_0
  • wheel=0.43.0=pyhd8ed1ab_1
  • xz=5.2.6=h166bdaf_0
  • pip:
    • annotated-types==0.7.0
    • anyio==4.4.0
    • asgiref==3.7.2
    • azure-core==1.30.2
    • azure-core-tracing-opentelemetry==1.0.0b11
    • azure-monitor-opentelemetry==1.6.0
    • azure-monitor-opentelemetry-exporter==1.0.0b27
    • blinker==1.8.2
    • certifi==2024.6.2
    • charset-normalizer==3.3.2
    • click==8.1.7
    • deprecated==1.2.14
    • dnspython==2.6.1
    • email-validator==2.2.0
    • exceptiongroup==1.2.1
    • fastapi==0.111.0
    • fastapi-cli==0.0.4
    • fixedint==0.1.6
    • flask==3.0.3
    • h11==0.14.0
    • httpcore==1.0.5
    • httptools==0.6.1
    • httpx==0.27.0
    • idna==3.7
    • importlib-metadata==7.1.0
    • isodate==0.6.1
    • itsdangerous==2.2.0
    • jinja2==3.1.4
    • markdown-it-py==3.0.0
    • markupsafe==2.1.5
    • mdurl==0.1.2
    • msrest==0.7.1
    • oauthlib==3.2.2
    • opentelemetry-api==1.25.0
    • opentelemetry-instrumentation==0.46b0
    • opentelemetry-instrumentation-asgi==0.46b0
    • opentelemetry-instrumentation-dbapi==0.46b0
    • opentelemetry-instrumentation-django==0.46b0
    • opentelemetry-instrumentation-fastapi==0.46b0
    • opentelemetry-instrumentation-flask==0.46b0
    • opentelemetry-instrumentation-psycopg2==0.46b0
    • opentelemetry-instrumentation-requests==0.46b0
    • opentelemetry-instrumentation-urllib==0.46b0
    • opentelemetry-instrumentation-urllib3==0.46b0
    • opentelemetry-instrumentation-wsgi==0.46b0
    • opentelemetry-resource-detector-azure==0.1.5
    • opentelemetry-sdk==1.25.0
    • opentelemetry-semantic-conventions==0.46b0
    • opentelemetry-test-utils==0.46b0
    • opentelemetry-util-http==0.46b0
    • orjson==3.10.5
    • packaging==24.1
    • psutil==5.9.8
    • pydantic==2.7.4
    • pydantic-core==2.18.4
    • pygments==2.18.0
    • python-dotenv==1.0.1
    • python-multipart==0.0.9
    • pyyaml==6.0.1
    • requests==2.32.3
    • requests-oauthlib==2.0.0
    • rich==13.7.1
    • shellingham==1.5.4
    • six==1.16.0
    • sniffio==1.3.1
    • starlette==0.37.2
    • typer==0.12.3
    • typing-extensions==4.12.2
    • ujson==5.10.0
    • urllib3==2.2.2
    • uvicorn==0.30.1
    • uvloop==0.19.0
    • watchfiles==0.22.0
    • websockets==12.0
    • werkzeug==3.0.3
    • wrapt==1.16.0
    • zipp==3.19.2
      prefix: /home/amcg809/mambaforge/envs/opentelemetry
What happened?

What happened?
When attempting to use the opentelemetry-instrumentation-asgi package in a FastAPI application, an ImportError occurs due to missing imports for ClientRequestHook, ClientResponseHook, and ServerRequestHook.

https://github.com/open-telemetry/opentelemetry-python-contrib/blob/main/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py

Steps to Reproduce

Run the file https://github.com/open-telemetry/opentelemetry-python-contrib/blob/main/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py

with the package pip install fastapi opentelemetry-instrumentation-asgi

Expected Result

The application should run without any import errors, and the OpenTelemetry ASGI middleware should be applied to the FastAPI application.

Actual Result

ImportError: cannot import name 'ClientRequestHook' from 'opentelemetry.instrumentation.asgi'

Additional context

Additional context
The ClientRequestHook, ClientResponseHook, and ServerRequestHook are not available in the opentelemetry-instrumentation-asgi package, causing the import error.

Solution
To resolve this issue, you can remove the imports for ClientRequestHook, ClientResponseHook, and ServerRequestHook and adjust the middleware setup accordingly. Here is the updated code:

// ... existing code ...
from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware
// ... existing code ...

class FastAPIInstrumentor(BaseInstrumentor):
// ... existing code ...

@staticmethod
def instrument_app(
    app: fastapi.FastAPI,
    server_request_hook=None,
    client_request_hook=None,
    client_response_hook=None,
    tracer_provider=None,
    meter_provider=None,
    excluded_urls=None,
):
    """Instrument an uninstrumented FastAPI application."""
    // ... existing code ...

// ... existing code ...

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

// ... existing code ...

class _InstrumentedFastAPI(fastapi.FastAPI):
_tracer_provider = None
_meter_provider = None
_excluded_urls = None
_server_request_hook = None
_client_request_hook = None
_client_response_hook = None
_instrumented_fastapi_apps = set()

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    tracer = get_tracer(
        __name__,
        __version__,
        _InstrumentedFastAPI._tracer_provider,
        schema_url="https://opentelemetry.io/schemas/1.11.0",
    )
    meter = get_meter(
        __name__,
        __version__,
        _InstrumentedFastAPI._meter_provider,
        schema_url="https://opentelemetry.io/schemas/1.11.0",
    )
    self.add_middleware(
        OpenTelemetryMiddleware,
        excluded_urls=_InstrumentedFastAPI._excluded_urls,
        default_span_details=_get_default_span_details,
        server_request_hook=_InstrumentedFastAPI._server_request_hook,
        client_request_hook=_InstrumentedFastAPI._client_request_hook,
        client_response_hook=_InstrumentedFastAPI._client_response_hook,
        tracer=tracer,
        meter=meter,
    )
    self._is_instrumented_by_opentelemetry = True
    _InstrumentedFastAPI._instrumented_fastapi_apps.add(self)

// ... existing code ...

Explanation
  1. Import Change: Removed the imports for ClientRequestHook, ClientResponseHook, and ServerRequestHook.
  2. Method Signatures: Updated the method signatures to remove the specific hook types.
  3. Middleware Setup: Adjusted the middleware setup to use the OpenTelemetryMiddleware directly without the removed hooks.
Would you like to implement a fix?

Yes

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/init.py and reproduce the import using pip install fastapi opentelemetry-instrumentation-asgi. Check the imported ASGI symbols and middleware setup; done means a FastAPI application starts without the ImportError and the OpenTelemetry ASGI middleware is applied.

Written by the indexing model from the issue text.

Assessment

Tech stack
fastapi, python
Domain
backend, observability
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.