diff --git a/docs/integrations/aiohttp.md b/docs/integrations/aiohttp.md index da19299cd..eda00f8b3 100644 --- a/docs/integrations/aiohttp.md +++ b/docs/integrations/aiohttp.md @@ -2,7 +2,7 @@ [AIOHTTP][aiohttp] is an asynchronous HTTP client/server framework for asyncio and Python. -The [OpenTelemetry Instrumentation AIOHTTP][opentelemetry-aiohttp] package can be used to instrument AIOHTTP. +The [`logfire.instrument_aiohttp_client()`][logfire.Logfire.instrument_aiohttp_client] method will create a span for every request made by your AIOHTTP clients. !!! question "What about AIOHTTP Server?" The AIOHTTP server instrumentation is not supported yet. You can track the progress [here][aiohttp-server]. @@ -20,11 +20,10 @@ Let's see a minimal example below. You can run it with `python main.py`: ```py title="main.py" import logfire import aiohttp -from opentelemetry.instrumentation.aiohttp_client import AioHttpClientInstrumentor logfire.configure() -AioHttpClientInstrumentor().instrument() +logfire.instrument_aiohttp_client() async def main(): @@ -38,7 +37,7 @@ if __name__ == "__main__": asyncio.run(main()) ``` -You can read more about the AIOHTTP OpenTelemetry package [here][opentelemetry-aiohttp]. +The keyword arguments of `logfire.instrument_aiohttp_client()` are passed to the `AioHttpClientInstrumentor().instrument()` method of the OpenTelemetry aiohttp client Instrumentation package, read more about it [here][opentelemetry-aiohttp]. [aiohttp]: https://docs.aiohttp.org/en/stable/ [aiohttp-server]: https://github.com/open-telemetry/opentelemetry-python-contrib/issues/501 diff --git a/docs/integrations/flask.md b/docs/integrations/flask.md index e47df70a3..68311d0f4 100644 --- a/docs/integrations/flask.md +++ b/docs/integrations/flask.md @@ -1,6 +1,7 @@ # Flask -The [OpenTelemetry Instrumentation Flask][opentelemetry-flask] package can be used to instrument [Flask][flask]. +The [`logfire.instrument_flask()`][logfire.Logfire.instrument_flask] method +will create a span for every request to your [Flask][flask] application. ## Install @@ -15,13 +16,12 @@ Let's see a minimal example below. You can run it with `python main.py`: ```py title="main.py" import logfire from flask import Flask -from opentelemetry.instrumentation.flask import FlaskInstrumentor logfire.configure() app = Flask(__name__) -FlaskInstrumentor().instrument_app(app) +logfire.instrument_flask(app) @app.route("/") @@ -33,7 +33,8 @@ if __name__ == "__main__": app.run(debug=True) ``` -You can read more about the Flask OpenTelemetry package [here][opentelemetry-flask]. +The keyword arguments of `logfire.instrument_flask()` are passed to the `FlaskInstrumentor().instrument_app()` method +of the OpenTelemetry Flask Instrumentation package, read more about it [here][opentelemetry-flask]. ## Capturing request and response headers diff --git a/docs/integrations/pymongo.md b/docs/integrations/pymongo.md index a287f3144..fbaed4ed5 100644 --- a/docs/integrations/pymongo.md +++ b/docs/integrations/pymongo.md @@ -1,6 +1,6 @@ # PyMongo -The [OpenTelemetry Instrumentation PyMongo][opentelemetry-pymongo] package can be used to instrument [PyMongo][pymongo]. +The [`logfire.instrument_pymongo()`][logfire.Logfire.instrument_pymongo] method will create a span for every operation performed using your [PyMongo][pymongo] clients. ## Installation @@ -28,10 +28,9 @@ The following script connects to a MongoDB database, inserts a document, and que ```py import logfire from pymongo import MongoClient -from opentelemetry.instrumentation.pymongo import PymongoInstrumentor logfire.configure() -PymongoInstrumentor().instrument(capture_statement=True) # (1)! +logfire.instrument_pymongo(capture_statement=True) # (1)! client = MongoClient() db = client["database"] @@ -47,7 +46,7 @@ collection.find_one() --- -You can read more about the PyMongo OpenTelemetry package [here][opentelemetry-pymongo]. +The keyword arguments of `logfire.instrument_pymongo()` are passed to the `PymongoInstrumentor().instrument()` method of the OpenTelemetry pymongo Instrumentation package, read more about it [here][opentelemetry-pymongo]. [pymongo]: https://pymongo.readthedocs.io/en/stable/ [opentelemetry-pymongo]: https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/pymongo/pymongo.html diff --git a/docs/integrations/redis.md b/docs/integrations/redis.md index daad84f4c..ab7285cfd 100644 --- a/docs/integrations/redis.md +++ b/docs/integrations/redis.md @@ -1,6 +1,6 @@ # Redis -The [OpenTelemetry Instrumentation Redis][opentelemetry-redis] package can be used to instrument [Redis][redis]. +The [`logfire.instrument_redis()`][logfire.Logfire.instrument_redis] method will create a span for every command executed by your [Redis][redis] clients. ## Installation @@ -17,11 +17,10 @@ Let's see a minimal example below: ```py title="main.py" import logfire import redis -from opentelemetry.instrumentation.redis import RedisInstrumentor logfire.configure() -RedisInstrumentor().instrument() +logfire.instrument_redis() # This will report a span with the default settings client = redis.StrictRedis(host="localhost", port=6379) @@ -38,7 +37,7 @@ if __name__ == "__main__": asyncio.run(main()) ``` -You can read more about the Redis OpenTelemetry package [here][opentelemetry-redis]. +The keyword arguments of `logfire.instrument_redis()` are passed to the `RedisInstrumentor().instrument()` method of the OpenTelemetry Redis Instrumentation package, read more about it [here][opentelemetry-redis]. [redis]: https://redis.readthedocs.io/en/stable/ [opentelemetry-redis]: https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/redis/redis.html diff --git a/docs/integrations/sqlalchemy.md b/docs/integrations/sqlalchemy.md index 57a2b9350..071d8b8f3 100644 --- a/docs/integrations/sqlalchemy.md +++ b/docs/integrations/sqlalchemy.md @@ -1,7 +1,6 @@ # SQLAlchemy -The [OpenTelemetry Instrumentation SQLAlchemy][opentelemetry-sqlalchemy] package can be used to -instrument [SQLAlchemy][sqlalchemy]. +The [`logfire.instrument_sqlalchemy()`][logfire.Logfire.instrument_sqlalchemy] method will create a span for every query executed by a [SQLAlchemy][sqlalchemy] engine. ## Installation @@ -16,15 +15,14 @@ Let's see a minimal example below. You can run it with `python main.py`: ```py title="main.py" import logfire from sqlalchemy import create_engine -from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor logfire.configure() engine = create_engine("sqlite:///:memory:") -SQLAlchemyInstrumentor().instrument(engine=engine) +logfire.instrument_sqlalchemy(engine=engine) ``` -You can read more about the SQLAlchemy OpenTelemetry package [here][opentelemetry-sqlalchemy]. +The keyword arguments of `logfire.instrument_sqlalchemy()` are passed to the `SQLAlchemyInstrumentor().instrument()` method of the OpenTelemetry SQLAlchemy Instrumentation package, read more about it [here][opentelemetry-sqlalchemy]. !!! tip If you use [SQLModel][sqlmodel], you can use the same `SQLAlchemyInstrumentor` to instrument it. diff --git a/docs/integrations/starlette.md b/docs/integrations/starlette.md index 99918dad0..eee759199 100644 --- a/docs/integrations/starlette.md +++ b/docs/integrations/starlette.md @@ -1,6 +1,6 @@ # Starlette -The [OpenTelemetry Instrumentation Starlette][opentelemetry-starlette] package can be used to instrument [Starlette][starlette]. +The [`logfire.instrument_starlette()`][logfire.Logfire.instrument_starlette] method will create a span for every request to your [Starlette][starlette] application. ## Installation @@ -20,7 +20,6 @@ You can run it with `python main.py`: ```py title="main.py" import logfire -from opentelemetry.instrumentation.starlette import StarletteInstrumentor from starlette.applications import Starlette from starlette.responses import PlainTextResponse from starlette.requests import Request @@ -34,7 +33,7 @@ async def home(request: Request) -> PlainTextResponse: app = Starlette(routes=[Route("/", home)]) -StarletteInstrumentor.instrument_app(app) +logfire.instrument_starlette(app) if __name__ == "__main__": import uvicorn @@ -42,6 +41,8 @@ if __name__ == "__main__": uvicorn.run(app) ``` +The keyword arguments of `logfire.instrument_starlette()` are passed to the `StarletteInstrumentor.instrument_app()` method of the OpenTelemetry Starlette Instrumentation package, read more about it [here][opentelemetry-starlette]. + !!! question "What about the OpenTelemetry ASGI middleware?" If you are a more experienced user, you might be wondering why we are not using the [OpenTelemetry ASGI middleware][opentelemetry-asgi]. The reason is that the diff --git a/logfire/__init__.py b/logfire/__init__.py index ceb3de821..60b2c160e 100644 --- a/logfire/__init__.py +++ b/logfire/__init__.py @@ -35,6 +35,12 @@ instrument_requests = DEFAULT_LOGFIRE_INSTANCE.instrument_requests instrument_psycopg = DEFAULT_LOGFIRE_INSTANCE.instrument_psycopg instrument_django = DEFAULT_LOGFIRE_INSTANCE.instrument_django +instrument_flask = DEFAULT_LOGFIRE_INSTANCE.instrument_flask +instrument_starlette = DEFAULT_LOGFIRE_INSTANCE.instrument_starlette +instrument_aiohttp_client = DEFAULT_LOGFIRE_INSTANCE.instrument_aiohttp_client +instrument_sqlalchemy = DEFAULT_LOGFIRE_INSTANCE.instrument_sqlalchemy +instrument_redis = DEFAULT_LOGFIRE_INSTANCE.instrument_redis +instrument_pymongo = DEFAULT_LOGFIRE_INSTANCE.instrument_pymongo shutdown = DEFAULT_LOGFIRE_INSTANCE.shutdown with_tags = DEFAULT_LOGFIRE_INSTANCE.with_tags # with_trace_sample_rate = DEFAULT_LOGFIRE_INSTANCE.with_trace_sample_rate diff --git a/logfire/_internal/integrations/aiohttp_client.py b/logfire/_internal/integrations/aiohttp_client.py new file mode 100644 index 000000000..b010476ac --- /dev/null +++ b/logfire/_internal/integrations/aiohttp_client.py @@ -0,0 +1,11 @@ +from typing import Any + +from opentelemetry.instrumentation.aiohttp_client import AioHttpClientInstrumentor + + +def instrument_aiohttp_client(**kwargs: Any): + """Instrument the `aiohttp` module so that spans are automatically created for each client request. + + See the `Logfire.instrument_aiohttp_client` method for details. + """ + AioHttpClientInstrumentor().instrument(**kwargs) # type: ignore[reportUnknownMemberType] diff --git a/logfire/_internal/integrations/flask.py b/logfire/_internal/integrations/flask.py new file mode 100644 index 000000000..2363f18ae --- /dev/null +++ b/logfire/_internal/integrations/flask.py @@ -0,0 +1,12 @@ +from typing import Any + +from flask.app import Flask +from opentelemetry.instrumentation.flask import FlaskInstrumentor + + +def instrument_flask(app: Flask, **kwargs: Any): + """Instrument `app` so that spans are automatically created for each request. + + See the `Logfire.instrument_flask` method for details. + """ + FlaskInstrumentor().instrument_app(app, **kwargs) # type: ignore[reportUnknownMemberType] diff --git a/logfire/_internal/integrations/pymongo.py b/logfire/_internal/integrations/pymongo.py new file mode 100644 index 000000000..6480aeefb --- /dev/null +++ b/logfire/_internal/integrations/pymongo.py @@ -0,0 +1,11 @@ +from typing import Any + +from opentelemetry.instrumentation.pymongo import PymongoInstrumentor + + +def instrument_pymongo(**kwargs: Any): + """Instrument the `pymongo` module so that spans are automatically created for each operation. + + See the `Logfire.instrument_pymongo` method for details. + """ + PymongoInstrumentor().instrument(**kwargs) # type: ignore[reportUnknownMemberType] diff --git a/logfire/_internal/integrations/redis.py b/logfire/_internal/integrations/redis.py new file mode 100644 index 000000000..479fa725f --- /dev/null +++ b/logfire/_internal/integrations/redis.py @@ -0,0 +1,11 @@ +from typing import Any + +from opentelemetry.instrumentation.redis import RedisInstrumentor + + +def instrument_redis(**kwargs: Any): + """Instrument the `redis` module so that spans are automatically created for each operation. + + See the `Logfire.instrument_redis` method for details. + """ + RedisInstrumentor().instrument(**kwargs) # type: ignore[reportUnknownMemberType] diff --git a/logfire/_internal/integrations/sqlalchemy.py b/logfire/_internal/integrations/sqlalchemy.py new file mode 100644 index 000000000..5a3918188 --- /dev/null +++ b/logfire/_internal/integrations/sqlalchemy.py @@ -0,0 +1,11 @@ +from typing import Any + +from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor + + +def instrument_sqlalchemy(**kwargs: Any): + """Instrument the `sqlalchemy` module so that spans are automatically created for each query. + + See the `Logfire.instrument_sqlalchemy` method for details. + """ + SQLAlchemyInstrumentor().instrument(**kwargs) # type: ignore[reportUnknownMemberType] diff --git a/logfire/_internal/integrations/starlette.py b/logfire/_internal/integrations/starlette.py new file mode 100644 index 000000000..92e51700f --- /dev/null +++ b/logfire/_internal/integrations/starlette.py @@ -0,0 +1,12 @@ +from typing import Any + +from opentelemetry.instrumentation.starlette import StarletteInstrumentor +from starlette.applications import Starlette + + +def instrument_starlette(app: Starlette, **kwargs: Any): + """Instrument `app` so that spans are automatically created for each request. + + See the `Logfire.instrument_starlette` method for details. + """ + StarletteInstrumentor().instrument_app(app, **kwargs) # type: ignore[reportUnknownMemberType] diff --git a/logfire/_internal/main.py b/logfire/_internal/main.py index f14b8b172..b2e81644f 100644 --- a/logfire/_internal/main.py +++ b/logfire/_internal/main.py @@ -68,7 +68,9 @@ import openai from django.http import HttpRequest, HttpResponse from fastapi import FastAPI + from flask.app import Flask from opentelemetry.metrics import _Gauge as Gauge + from starlette.applications import Starlette from starlette.requests import Request from starlette.websockets import WebSocket @@ -1115,6 +1117,78 @@ def instrument_psycopg(self, conn_or_module: Any = None, **kwargs: Any): self._warn_if_not_initialized_for_instrumentation() return instrument_psycopg(conn_or_module, **kwargs) + def instrument_flask(self, app: Flask, **kwargs: Any): + """Instrument `app` so that spans are automatically created for each request. + + Uses the + [OpenTelemetry Flask Instrumentation](https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/flask/flask.html) + library, specifically `FlaskInstrumentor().instrument_app()`, to which it passes `**kwargs`. + """ + from .integrations.flask import instrument_flask + + self._warn_if_not_initialized_for_instrumentation() + return instrument_flask(app, **kwargs) + + def instrument_starlette(self, app: Starlette, **kwargs: Any): + """Instrument `app` so that spans are automatically created for each request. + + Uses the + [OpenTelemetry Starlette Instrumentation](https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/starlette/starlette.html) + library, specifically `StarletteInstrumentor.instrument_app()`, to which it passes `**kwargs`. + """ + from .integrations.starlette import instrument_starlette + + self._warn_if_not_initialized_for_instrumentation() + return instrument_starlette(app, **kwargs) + + def instrument_aiohttp_client(self, **kwargs: Any): + """Instrument the `aiohttp` module so that spans are automatically created for each client request. + + Uses the + [OpenTelemetry aiohttp client Instrumentation](https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/aiohttp_client/aiohttp_client.html) + library, specifically `AioHttpClientInstrumentor().instrument()`, to which it passes `**kwargs`. + """ + from .integrations.aiohttp_client import instrument_aiohttp_client + + self._warn_if_not_initialized_for_instrumentation() + return instrument_aiohttp_client(**kwargs) + + def instrument_sqlalchemy(self, **kwargs: Any): + """Instrument the `sqlalchemy` module so that spans are automatically created for each query. + + Uses the + [OpenTelemetry SQLAlchemy Instrumentation](https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/sqlalchemy/sqlalchemy.html) + library, specifically `SQLAlchemyInstrumentor().instrument()`, to which it passes `**kwargs`. + """ + from .integrations.sqlalchemy import instrument_sqlalchemy + + self._warn_if_not_initialized_for_instrumentation() + return instrument_sqlalchemy(**kwargs) + + def instrument_pymongo(self, **kwargs: Any): + """Instrument the `pymongo` module so that spans are automatically created for each operation. + + Uses the + [OpenTelemetry pymongo Instrumentation](https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/pymongo/pymongo.html) + library, specifically `PymongoInstrumentor().instrument()`, to which it passes `**kwargs`. + """ + from .integrations.pymongo import instrument_pymongo + + self._warn_if_not_initialized_for_instrumentation() + return instrument_pymongo(**kwargs) + + def instrument_redis(self, **kwargs: Any): + """Instrument the `redis` module so that spans are automatically created for each operation. + + Uses the + [OpenTelemetry Redis Instrumentation](https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/redis/redis.html) + library, specifically `RedisInstrumentor().instrument()`, to which it passes `**kwargs`. + """ + from .integrations.redis import instrument_redis + + self._warn_if_not_initialized_for_instrumentation() + return instrument_redis(**kwargs) + def metric_counter(self, name: str, *, unit: str = '', description: str = '') -> Counter: """Create a counter metric. diff --git a/pyproject.toml b/pyproject.toml index c248f710d..8338f46ed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "logfire" -version = "0.38.0" +version = "0.39.0" description = "The best Python observability tool! 🪵🔥" authors = [ { name = "Pydantic Team", email = "engineering@pydantic.dev" }, @@ -81,6 +81,9 @@ managed = true dev-dependencies = [ "anyio", "httpx", + "aiohttp", + "redis", + "pymongo", "starlette", "fastapi", "Flask", @@ -109,6 +112,8 @@ dev-dependencies = [ "opentelemetry-instrumentation-asyncpg", "opentelemetry-instrumentation-psycopg", "opentelemetry-instrumentation-psycopg2", + "opentelemetry-instrumentation-redis", + "opentelemetry-instrumentation-pymongo", "gitpython", "eval-type-backport", "requests-mock", diff --git a/requirements-dev.lock b/requirements-dev.lock index e240fd0f4..95e856b0c 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -8,6 +8,9 @@ # with-sources: false -e file:. +aiohttp==3.9.5 +aiosignal==1.3.1 + # via aiohttp annotated-types==0.6.0 # via pydantic anthropic==0.25.8 @@ -23,6 +26,7 @@ asttokens==2.4.1 # via inline-snapshot asyncpg==0.29.0 attrs==23.2.0 + # via aiohttp babel==2.14.0 # via mkdocs-material black==24.4.0 @@ -58,6 +62,8 @@ distro==1.9.0 # via anthropic # via openai django==5.0.4 +dnspython==2.6.1 + # via pymongo eval-type-backport==0.2.0 executing==2.0.1 # via inline-snapshot @@ -67,6 +73,9 @@ filelock==3.13.4 # via huggingface-hub # via virtualenv flask==3.0.3 +frozenlist==1.4.1 + # via aiohttp + # via aiosignal fsspec==2024.3.1 # via huggingface-hub ghp-import==2.1.0 @@ -95,6 +104,7 @@ idna==3.7 # via anyio # via httpx # via requests + # via yarl importlib-metadata==7.0.0 # via opentelemetry-api # via opentelemetry-instrumentation-flask @@ -140,6 +150,9 @@ mkdocs-material-extensions==1.3.1 mkdocstrings==0.24.3 # via mkdocstrings-python mkdocstrings-python==1.10.0 +multidict==6.0.5 + # via aiohttp + # via yarl mypy-extensions==1.0.0 # via black nodeenv==1.8.0 @@ -161,6 +174,8 @@ opentelemetry-api==1.24.0 # via opentelemetry-instrumentation-httpx # via opentelemetry-instrumentation-psycopg # via opentelemetry-instrumentation-psycopg2 + # via opentelemetry-instrumentation-pymongo + # via opentelemetry-instrumentation-redis # via opentelemetry-instrumentation-requests # via opentelemetry-instrumentation-sqlalchemy # via opentelemetry-instrumentation-starlette @@ -183,6 +198,8 @@ opentelemetry-instrumentation==0.45b0 # via opentelemetry-instrumentation-httpx # via opentelemetry-instrumentation-psycopg # via opentelemetry-instrumentation-psycopg2 + # via opentelemetry-instrumentation-pymongo + # via opentelemetry-instrumentation-redis # via opentelemetry-instrumentation-requests # via opentelemetry-instrumentation-sqlalchemy # via opentelemetry-instrumentation-starlette @@ -202,6 +219,8 @@ opentelemetry-instrumentation-flask==0.45b0 opentelemetry-instrumentation-httpx==0.45b0 opentelemetry-instrumentation-psycopg==0.45b0 opentelemetry-instrumentation-psycopg2==0.45b0 +opentelemetry-instrumentation-pymongo==0.45b0 +opentelemetry-instrumentation-redis==0.45b0 opentelemetry-instrumentation-requests==0.45b0 opentelemetry-instrumentation-sqlalchemy==0.45b0 opentelemetry-instrumentation-starlette==0.45b0 @@ -225,6 +244,8 @@ opentelemetry-semantic-conventions==0.45b0 # via opentelemetry-instrumentation-fastapi # via opentelemetry-instrumentation-flask # via opentelemetry-instrumentation-httpx + # via opentelemetry-instrumentation-pymongo + # via opentelemetry-instrumentation-redis # via opentelemetry-instrumentation-requests # via opentelemetry-instrumentation-sqlalchemy # via opentelemetry-instrumentation-starlette @@ -283,6 +304,7 @@ pygments==2.17.2 pymdown-extensions==10.8 # via mkdocs-material # via mkdocstrings +pymongo==4.7.2 pyright==1.1.360 pytest==8.1.1 # via pytest-django @@ -303,6 +325,7 @@ pyyaml==6.0.1 # via pyyaml-env-tag pyyaml-env-tag==0.1 # via mkdocs +redis==5.0.4 regex==2024.4.16 # via mkdocs-material requests==2.31.0 @@ -369,6 +392,9 @@ wrapt==1.16.0 # via opentelemetry-instrumentation # via opentelemetry-instrumentation-aiohttp-client # via opentelemetry-instrumentation-dbapi + # via opentelemetry-instrumentation-redis # via opentelemetry-instrumentation-sqlalchemy +yarl==1.9.4 + # via aiohttp zipp==3.18.1 # via importlib-metadata diff --git a/tests/otel_integrations/test_aiohttp_client.py b/tests/otel_integrations/test_aiohttp_client.py new file mode 100644 index 000000000..abb3bd408 --- /dev/null +++ b/tests/otel_integrations/test_aiohttp_client.py @@ -0,0 +1,14 @@ +import aiohttp +import pytest + +import logfire + + +# TODO real test +@pytest.mark.anyio +async def test_instrument_aiohttp(): + cls = aiohttp.ClientSession + original_init = cls.__init__ + assert cls.__init__ is original_init + logfire.instrument_aiohttp_client() + assert cls.__init__ is not original_init diff --git a/tests/otel_integrations/test_flask.py b/tests/otel_integrations/test_flask.py index a2b6ea380..d531c7c67 100644 --- a/tests/otel_integrations/test_flask.py +++ b/tests/otel_integrations/test_flask.py @@ -1,7 +1,6 @@ import opentelemetry.instrumentation.flask from flask import Flask from inline_snapshot import snapshot -from opentelemetry.instrumentation.flask import FlaskInstrumentor from opentelemetry.propagate import inject from werkzeug.test import Client @@ -11,7 +10,7 @@ def test_flask_instrumentation(exporter: TestExporter, time_generator: TimeGenerator) -> None: app = Flask(__name__) - FlaskInstrumentor().instrument_app(app) # type: ignore + logfire.instrument_flask(app) @app.route('/') def homepage(): # type: ignore diff --git a/tests/otel_integrations/test_pymongo.py b/tests/otel_integrations/test_pymongo.py new file mode 100644 index 000000000..7cffb97ec --- /dev/null +++ b/tests/otel_integrations/test_pymongo.py @@ -0,0 +1,11 @@ +from pymongo import monitoring + +import logfire + + +# TODO real test +def test_instrument_pymongo(): + command_listeners = monitoring._LISTENERS.command_listeners # type: ignore + assert len(command_listeners) == 0 # type: ignore + logfire.instrument_pymongo() + assert len(command_listeners) == 1 # type: ignore diff --git a/tests/otel_integrations/test_redis.py b/tests/otel_integrations/test_redis.py new file mode 100644 index 000000000..36055b44c --- /dev/null +++ b/tests/otel_integrations/test_redis.py @@ -0,0 +1,11 @@ +from redis import Redis + +import logfire + + +# TODO real test +def test_instrument_redis(): + original = Redis.execute_command # type: ignore + assert Redis.execute_command is original # type: ignore + logfire.instrument_redis() + assert Redis.execute_command is not original # type: ignore diff --git a/tests/otel_integrations/test_sqlalchemy.py b/tests/otel_integrations/test_sqlalchemy.py index 557204af8..d3466096a 100644 --- a/tests/otel_integrations/test_sqlalchemy.py +++ b/tests/otel_integrations/test_sqlalchemy.py @@ -8,6 +8,7 @@ from sqlalchemy.sql import text from sqlalchemy.types import Integer, String +import logfire from logfire.testing import TestExporter @@ -26,7 +27,7 @@ def test_sqlalchemy_instrumentation(exporter: TestExporter): # Need to ensure this import happens _after_ importing sqlalchemy from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor - SQLAlchemyInstrumentor().instrument(engine=engine, enable_commenter=True, commenter_options={}) # type: ignore + logfire.instrument_sqlalchemy(engine=engine, enable_commenter=True, commenter_options={}) class Base(DeclarativeBase): pass diff --git a/tests/otel_integrations/test_starlette.py b/tests/otel_integrations/test_starlette.py index 90e17bf29..482f04170 100644 --- a/tests/otel_integrations/test_starlette.py +++ b/tests/otel_integrations/test_starlette.py @@ -8,6 +8,7 @@ from starlette.testclient import TestClient from starlette.websockets import WebSocket +import logfire from logfire.testing import TestExporter @@ -31,7 +32,7 @@ def app(): app = Starlette(routes=routes) try: - StarletteInstrumentor.instrument_app(app) # type: ignore + logfire.instrument_starlette(app) yield app finally: StarletteInstrumentor.uninstrument_app(app)