Skip to content

AIOHTTP Client

AIOHTTP is an asynchronous HTTP client/server framework for asyncio and Python.

The logfire.instrument_aiohttp_client() method will create a span for every request made by your AIOHTTP clients.

For AIOHTTP server instrumentation, see here.

Installation

Install logfire with the aiohttp-client extra:

pip install 'logfire[aiohttp-client]'
uv add 'logfire[aiohttp-client]'

Usage

Let's see a minimal example below. You can run it with python main.py:

main.py
import aiohttp

import logfire

logfire.configure()
logfire.instrument_aiohttp_client()


async def main():
    async with aiohttp.ClientSession() as session:
        await session.get('https://httpbin.org/get')


if __name__ == '__main__':
    import asyncio

    asyncio.run(main())

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.

Configuration

The logfire.instrument_aiohttp_client() method accepts various parameters to configure the instrumentation.

Capture Everything

You can capture all information (headers and bodies) by setting the capture_all parameter to True.

import aiohttp

import logfire

logfire.configure()
logfire.instrument_aiohttp_client(capture_all=True)


async def main():
    async with aiohttp.ClientSession() as session:
        await session.post('https://httpbin.org/post', json={'key': 'value'})


if __name__ == '__main__':
    import asyncio

    asyncio.run(main())

Capture HTTP Headers

By default, Logfire doesn't capture HTTP headers. You can enable it by setting the capture_headers parameter to True.

import aiohttp

import logfire

logfire.configure()
logfire.instrument_aiohttp_client(capture_headers=True)


async def main():
    async with aiohttp.ClientSession() as session:
        await session.get('https://httpbin.org/get')


if __name__ == '__main__':
    import asyncio

    asyncio.run(main())

Capture Only Request Headers

Instead of capturing both request and response headers, you can create a request hook to capture only the request headers:

import aiohttp
from aiohttp.tracing import TraceRequestStartParams
from opentelemetry.trace import Span

import logfire


def capture_request_headers(span: Span, request: TraceRequestStartParams):
    headers = request.headers
    span.set_attributes(
        {f'http.request.header.{header_name}': headers.getall(header_name) for header_name in headers.keys()}
    )


logfire.configure()
logfire.instrument_aiohttp_client(request_hook=capture_request_headers)


async def main():
    async with aiohttp.ClientSession() as session:
        await session.get('https://httpbin.org/get')


if __name__ == '__main__':
    import asyncio

    asyncio.run(main())

Capture Only Response Headers

Similarly, you can create a response hook to capture only the response headers:

import aiohttp
from aiohttp.tracing import TraceRequestEndParams, TraceRequestExceptionParams
from opentelemetry.trace import Span

import logfire


def capture_response_headers(span: Span, response: 'TraceRequestEndParams | TraceRequestExceptionParams'):
    if hasattr(response, 'response') and response.response:
        headers = response.response.headers
        span.set_attributes(
            {f'http.response.header.{header_name}': headers.getall(header_name) for header_name in headers.keys()}
        )


logfire.configure()
logfire.instrument_aiohttp_client(response_hook=capture_response_headers)


async def main():
    async with aiohttp.ClientSession() as session:
        await session.get('https://httpbin.org/get')


if __name__ == '__main__':
    import asyncio

    asyncio.run(main())

You can also use the hooks to filter headers or modify them before capturing them.

Capture HTTP Bodies

By default, Logfire doesn't capture HTTP bodies.

To capture bodies, you can set the capture_request_body and capture_response_body parameters to True.

import aiohttp

import logfire

logfire.configure()
logfire.instrument_aiohttp_client(
    capture_request_body=True,
    capture_response_body=True,
)


async def main():
    async with aiohttp.ClientSession() as session:
        response = await session.post('https://httpbin.org/post', data='Hello, World!')
        await response.text()


if __name__ == '__main__':
    import asyncio

    asyncio.run(main())

Hiding sensitive URL parameters

The url_filter keyword argument can be used to modify the URL that's recorded in spans. Here's an example of how to use this to redact query parameters:

from yarl import URL

import logfire


def mask_url(url: URL) -> str:
    sensitive_keys = {
        'username',
        'password',
        'token',
        'api_key',
        'api_secret',
        'apikey',
    }
    masked_query = {key: '*****' if key in sensitive_keys else value for key, value in url.query.items()}
    return str(url.with_query(masked_query))


logfire.instrument_aiohttp_client(url_filter=mask_url)