feat(opentelemetry): add fastapi instumentation

This commit is contained in:
Julius Unverfehrt 2024-01-24 14:26:10 +01:00
parent a415666830
commit da163897c4
4 changed files with 109 additions and 7 deletions

63
poetry.lock generated
View File

@ -101,6 +101,23 @@ cffi = ">=1.0.1"
dev = ["cogapp", "pre-commit", "pytest", "wheel"]
tests = ["pytest"]
[[package]]
name = "asgiref"
version = "3.7.2"
description = "ASGI specs, helper code, and adapters"
optional = false
python-versions = ">=3.7"
files = [
{file = "asgiref-3.7.2-py3-none-any.whl", hash = "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e"},
{file = "asgiref-3.7.2.tar.gz", hash = "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed"},
]
[package.dependencies]
typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""}
[package.extras]
tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
[[package]]
name = "astroid"
version = "3.0.2"
@ -1287,6 +1304,50 @@ opentelemetry-api = ">=1.4,<2.0"
setuptools = ">=16.0"
wrapt = ">=1.0.0,<2.0.0"
[[package]]
name = "opentelemetry-instrumentation-asgi"
version = "0.43b0"
description = "ASGI instrumentation for OpenTelemetry"
optional = false
python-versions = ">=3.7"
files = [
{file = "opentelemetry_instrumentation_asgi-0.43b0-py3-none-any.whl", hash = "sha256:1f593829fa039e9367820736fb063e92acd15c25b53d7bcb5d319971b8e93fd7"},
{file = "opentelemetry_instrumentation_asgi-0.43b0.tar.gz", hash = "sha256:3f6f19333dca31ef696672e4e36cb1c2613c71dc7e847c11ff36a37e1130dadc"},
]
[package.dependencies]
asgiref = ">=3.0,<4.0"
opentelemetry-api = ">=1.12,<2.0"
opentelemetry-instrumentation = "0.43b0"
opentelemetry-semantic-conventions = "0.43b0"
opentelemetry-util-http = "0.43b0"
[package.extras]
instruments = ["asgiref (>=3.0,<4.0)"]
test = ["opentelemetry-instrumentation-asgi[instruments]", "opentelemetry-test-utils (==0.43b0)"]
[[package]]
name = "opentelemetry-instrumentation-fastapi"
version = "0.43b0"
description = "OpenTelemetry FastAPI Instrumentation"
optional = false
python-versions = ">=3.7"
files = [
{file = "opentelemetry_instrumentation_fastapi-0.43b0-py3-none-any.whl", hash = "sha256:b79c044df68a52e07b35fa12a424e7cc0dd27ff0a171c5fdcc41dea9de8fc938"},
{file = "opentelemetry_instrumentation_fastapi-0.43b0.tar.gz", hash = "sha256:2afaaf470622e1a2732182c68f6d2431ffe5e026a7edacd0f83605632b66347f"},
]
[package.dependencies]
opentelemetry-api = ">=1.12,<2.0"
opentelemetry-instrumentation = "0.43b0"
opentelemetry-instrumentation-asgi = "0.43b0"
opentelemetry-semantic-conventions = "0.43b0"
opentelemetry-util-http = "0.43b0"
[package.extras]
instruments = ["fastapi (>=0.58,<1.0)"]
test = ["httpx (>=0.22,<1.0)", "opentelemetry-instrumentation-fastapi[instruments]", "opentelemetry-test-utils (==0.43b0)", "requests (>=2.23,<3.0)"]
[[package]]
name = "opentelemetry-instrumentation-flask"
version = "0.43b0"
@ -2470,4 +2531,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
[metadata]
lock-version = "2.0"
python-versions = ">=3.10,<3.11"
content-hash = "1b4d543363bcda2ec51a2e29e849ceac983fa0e7933de58ec6bf881614bb939f"
content-hash = "2e56e0e3c159f5d8fcc95b8623d56b1dbf94318230f5550a4c5aa15c288dfc84"

View File

@ -1,8 +1,10 @@
import json
from dynaconf import Dynaconf
from fastapi import FastAPI
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry.instrumentation.pika import PikaInstrumentor
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
@ -37,6 +39,9 @@ def setup_trace(settings: Dynaconf, service_name: str = None, exporter: SpanExpo
provider.add_span_processor(processor)
# TODO: This produces a warning if trying to set the provider twice.
# "WARNING opentelemetry.trace:__init__.py:521 Overriding of current TracerProvider is not allowed"
# This doesn't affect our current usage but should be fixed eventually.
trace.set_tracer_provider(provider)
@ -60,5 +65,5 @@ def instrument_pika():
PikaInstrumentor().instrument()
# def instrument_app(app: FastAPI):
# FastAPIInstrumentor().instrument_app(app)
def instrument_app(app: FastAPI):
FastAPIInstrumentor().instrument_app(app)

View File

@ -42,6 +42,7 @@ opentelemetry-sdk = "^1.22.0"
opentelemetry-exporter-otlp-proto-http = "^1.22.0"
opentelemetry-instrumentation-flask = "^0.43b0"
opentelemetry-instrumentation-requests = "^0.43b0"
opentelemetry-instrumentation-fastapi = "^0.43b0"
[tool.pytest.ini_options]
minversion = "6.0"

View File

@ -1,13 +1,39 @@
from time import sleep
from pyinfra.utils.opentelemetry import get_exporter, setup_trace, instrument_pika
import pytest
import requests
from fastapi import FastAPI
from pyinfra.utils.opentelemetry import get_exporter, setup_trace, instrument_pika, instrument_app
from pyinfra.webserver.utils import create_webserver_thread_from_settings
@pytest.fixture(scope="class")
def app_with_tracing(settings):
app = FastAPI()
@app.get("/test")
def test():
return {"flat": "earth"}
instrument_app(app)
thread = create_webserver_thread_from_settings(app, settings)
thread.start()
sleep(1)
yield
thread.join(timeout=1)
@pytest.fixture(scope="session")
def exporter(settings):
settings.tracing.opentelemetry.exporter = "json"
return get_exporter(settings)
class TestOpenTelemetry:
def test_queue_messages_are_traced(self, queue_manager, input_message, stop_message, settings):
settings.tracing.opentelemetry.exporter = "json"
def test_queue_messages_are_traced(self, queue_manager, input_message, stop_message, settings, exporter):
exporter = get_exporter(settings)
setup_trace(settings, exporter=exporter)
instrument_pika()
@ -26,3 +52,12 @@ class TestOpenTelemetry:
assert (
exported_trace["resource"]["attributes"]["service.name"] == settings.tracing.opentelemetry.service_name
)
def test_webserver_requests_are_traced(self, settings, app_with_tracing, exporter):
settings.tracing.opentelemetry.exporter = "json"
setup_trace(settings, exporter=exporter)
requests.get(f"http://{settings.webserver.host}:{settings.webserver.port}/test")
print(exporter.traces)