Fastapi auto tests (#2860)

* ep test passes

* cleaned ep test

* Corrected mock paths.

* with installed works

* tests pass

* Clean up

* Clean up

* lint

* lint
This commit is contained in:
Jeremy Voss
2024-09-12 00:36:59 -07:00
committed by GitHub
parent 6f1a17d8dd
commit d135f20c29
2 changed files with 60 additions and 1 deletions

View File

@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased ## Unreleased
- `opentelemetry-instrumentation-fastapi` Add autoinstrumentation mechanism tests.
([#2860](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2860))
## Version 1.27.0/0.48b0 () ## Version 1.27.0/0.48b0 ()
### Added ### Added

View File

@ -16,12 +16,13 @@
import unittest import unittest
from timeit import default_timer from timeit import default_timer
from unittest.mock import patch from unittest.mock import Mock, patch
import fastapi import fastapi
from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pkg_resources import DistributionNotFound, iter_entry_points
import opentelemetry.instrumentation.fastapi as otel_fastapi import opentelemetry.instrumentation.fastapi as otel_fastapi
from opentelemetry import trace from opentelemetry import trace
@ -34,6 +35,9 @@ from opentelemetry.instrumentation._semconv import (
_server_duration_attrs_old, _server_duration_attrs_old,
) )
from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware
from opentelemetry.instrumentation.auto_instrumentation._load import (
_load_instrumentors,
)
from opentelemetry.sdk.metrics.export import ( from opentelemetry.sdk.metrics.export import (
HistogramDataPoint, HistogramDataPoint,
NumberDataPoint, NumberDataPoint,
@ -1024,6 +1028,18 @@ class TestFastAPIManualInstrumentationHooks(TestBaseManualFastAPI):
) )
def get_distribution_with_fastapi(*args, **kwargs):
dist = args[0]
if dist == "fastapi~=0.58":
# Value does not matter. Only whether an exception is thrown
return None
raise DistributionNotFound()
def get_distribution_without_fastapi(*args, **kwargs):
raise DistributionNotFound()
class TestAutoInstrumentation(TestBaseAutoFastAPI): class TestAutoInstrumentation(TestBaseAutoFastAPI):
"""Test the auto-instrumented variant """Test the auto-instrumented variant
@ -1031,6 +1047,46 @@ class TestAutoInstrumentation(TestBaseAutoFastAPI):
to both. to both.
""" """
def test_entry_point_exists(self):
eps = iter_entry_points("opentelemetry_instrumentor")
ep = next(eps)
self.assertEqual(ep.dist.key, "opentelemetry-instrumentation-fastapi")
self.assertEqual(
ep.module_name, "opentelemetry.instrumentation.fastapi"
)
self.assertEqual(ep.attrs, ("FastAPIInstrumentor",))
self.assertEqual(ep.name, "fastapi")
self.assertIsNone(next(eps, None))
@patch("opentelemetry.instrumentation.dependencies.get_distribution")
def test_instruments_with_fastapi_installed(self, mock_get_distribution):
mock_get_distribution.side_effect = get_distribution_with_fastapi
mock_distro = Mock()
_load_instrumentors(mock_distro)
mock_get_distribution.assert_called_once_with("fastapi~=0.58")
self.assertEqual(len(mock_distro.load_instrumentor.call_args_list), 1)
args = mock_distro.load_instrumentor.call_args.args
ep = args[0]
self.assertEqual(ep.dist.key, "opentelemetry-instrumentation-fastapi")
self.assertEqual(
ep.module_name, "opentelemetry.instrumentation.fastapi"
)
self.assertEqual(ep.attrs, ("FastAPIInstrumentor",))
self.assertEqual(ep.name, "fastapi")
@patch("opentelemetry.instrumentation.dependencies.get_distribution")
def test_instruments_without_fastapi_installed(
self, mock_get_distribution
):
mock_get_distribution.side_effect = get_distribution_without_fastapi
mock_distro = Mock()
_load_instrumentors(mock_distro)
mock_get_distribution.assert_called_once_with("fastapi~=0.58")
with self.assertRaises(DistributionNotFound):
mock_get_distribution("fastapi~=0.58")
self.assertEqual(len(mock_distro.load_instrumentor.call_args_list), 0)
mock_distro.load_instrumentor.assert_not_called()
def _create_app(self): def _create_app(self):
# instrumentation is handled by the instrument call # instrumentation is handled by the instrument call
resource = Resource.create({"key1": "value1", "key2": "value2"}) resource = Resource.create({"key1": "value1", "key2": "value2"})