open-telemetry / opentelemetry-python

OpenTelemetry Python API and SDK
https://opentelemetry.io
Apache License 2.0
1.8k stars 625 forks source link

MyPy Complains About "TracerProvider" has no attribute "add_span_processor" #3713

Open kashifkhan opened 8 months ago

kashifkhan commented 8 months ago

When running mypy 1.8 on some of our samples, an error is generated saying that "TracerProvider" has no attribute "add_span_processor"

From the looks of it, seems like get_tracer_provider is returning the opentelemetry.trace.TracerProvider ABC, however opentelemetry.sdk.trace.TracerProvider has more methods defined than the ABC

Repro:

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter
from opentelemetry.sdk.trace.export import SimpleSpanProcessor

# Simple console exporter
exporter = ConsoleSpanExporter()

trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer(__name__)
trace.get_tracer_provider().add_span_processor(SimpleSpanProcessor(exporter))

pip list

Package                                Version
-------------------------------------- -------
Deprecated                             1.2.14
importlib-metadata                     6.11.0
mypy                                   1.8.0
mypy-extensions                        1.0.0
opentelemetry-api                      1.23.0
opentelemetry-instrumentation          0.44b0
opentelemetry-instrumentation-requests 0.44b0
opentelemetry-sdk                      1.23.0
opentelemetry-semantic-conventions     0.44b0
opentelemetry-util-http                0.44b0
pip                                    23.0.1
setuptools                             56.0.0
tomli                                  2.0.1
typing_extensions                      4.10.0
wrapt                                  1.16.0
zipp                                   3.17.0
mypy main.py
main.py:11: error: "TracerProvider" has no attribute "add_span_processor"  [attr-defined]

The code snippet above is from our samples, but it looks similar to the one in the cookbook.

yogesh-ti commented 8 months ago

Facing the same issue. Although I'm using mypy 1.0.0.

Did you find any resolution yet @kashifkhan ?

xrmx commented 8 months ago

Does something like this work for you?

diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py
index 9f9abe0f..e9ee0cae 100644
--- a/opentelemetry-api/src/opentelemetry/trace/__init__.py
+++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py
@@ -527,7 +527,10 @@ def set_tracer_provider(tracer_provider: TracerProvider) -> None:
     _set_tracer_provider(tracer_provider, log=True)

-def get_tracer_provider() -> TracerProvider:
+_TracerProviderType = typing.TypeVar("_TracerProviderType", bound=TracerProvider)
+
+
+def get_tracer_provider() -> _TracerProviderType:
     """Gets the current global :class:`~.TracerProvider` object."""
     if _TRACER_PROVIDER is None:
         # if a global tracer provider has not been set either via code or env
Doommius commented 7 months ago

I had the same issue. I made a "fix" like this.

        tracerProvider = TracerProvider()
        tracerProvider.add_span_processor(BatchSpanProcessor(AzureMonitorTraceExporter()))
        trace.set_tracer_provider(tracerProvider)
pmcollins commented 7 months ago

Yeah, there are several examples that use this pattern where the example script creates a TracerProvider, hands it to the API, then immediately asks for it from the API but with the type of the abstract base class, from which it calls a method that doesn't exist on that type.

Does anyone know why? I thought maybe the intent was to demonstrate how to get the tracer provider via the API, but if that's true I don't think this is the best way.