Skip to content

Commit d48f1ea

Browse files
authored
Release v4.8.0 (#1414)
1 parent 844a34d commit d48f1ea

File tree

8 files changed

+83
-13
lines changed

8 files changed

+83
-13
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Release Notes
22

3+
## [v4.8.0] (2025-09-18)
4+
5+
* Allow capturing headers and response body with `logfire.instrument_aiohttp_client()` by @adtyavrdhn in [#1405](https://github.com/pydantic/logfire/pull/1405) and [#1409](https://github.com/pydantic/logfire/pull/1409)
6+
37
## [v4.7.0] (2025-09-12)
48

59
* Update to OpenTelemetry SDK 1.37.0, drop support for <1.35.0 by @alexmojaki in [#1398](https://github.com/pydantic/logfire/pull/1398)
@@ -901,3 +905,4 @@ First release from new repo!
901905
[v4.5.0]: https://github.com/pydantic/logfire/compare/v4.4.0...v4.5.0
902906
[v4.6.0]: https://github.com/pydantic/logfire/compare/v4.5.0...v4.6.0
903907
[v4.7.0]: https://github.com/pydantic/logfire/compare/v4.6.0...v4.7.0
908+
[v4.8.0]: https://github.com/pydantic/logfire/compare/v4.7.0...v4.8.0
Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,45 @@
1-
from logfire import Logfire as Logfire
2-
from typing import Any
1+
from aiohttp.client_reqrep import ClientResponse
2+
from aiohttp.tracing import TraceRequestEndParams, TraceRequestExceptionParams, TraceRequestStartParams
3+
from logfire import Logfire as Logfire, LogfireSpan as LogfireSpan
4+
from logfire._internal.utils import handle_internal_errors as handle_internal_errors
5+
from logfire.integrations.aiohttp_client import AioHttpRequestHeaders as AioHttpRequestHeaders, AioHttpResponseHeaders as AioHttpResponseHeaders, RequestHook as RequestHook, ResponseHook as ResponseHook
6+
from opentelemetry.trace import Span
7+
from typing import Any, Callable, Literal, ParamSpec
8+
from yarl import URL
39

4-
def instrument_aiohttp_client(logfire_instance: Logfire, **kwargs: Any):
10+
P = ParamSpec('P')
11+
12+
def instrument_aiohttp_client(logfire_instance: Logfire, capture_response_body: bool, capture_headers: bool, request_hook: RequestHook | None, response_hook: ResponseHook | None, **kwargs: Any) -> None:
513
"""Instrument the `aiohttp` module so that spans are automatically created for each client request.
614
715
See the `Logfire.instrument_aiohttp_client` method for details.
816
"""
17+
18+
class LogfireClientInfoMixin:
19+
headers: AioHttpRequestHeaders
20+
21+
class LogfireAioHttpRequestInfo(TraceRequestStartParams, LogfireClientInfoMixin):
22+
span: Span
23+
def capture_headers(self) -> None: ...
24+
25+
class LogfireAioHttpResponseInfo(LogfireClientInfoMixin):
26+
span: Span
27+
method: str
28+
url: URL
29+
headers: AioHttpRequestHeaders
30+
response: ClientResponse | None
31+
exception: BaseException | None
32+
logfire_instance: Logfire
33+
body_captured: bool
34+
def capture_headers(self) -> None: ...
35+
def capture_body_if_text(self, attr_name: str = 'http.response.body.text') -> None: ...
36+
def capture_text_as_json(self, span: LogfireSpan, *, text: str, attr_name: str) -> None: ...
37+
@classmethod
38+
def create_from_trace_params(cls, span: Span, params: TraceRequestEndParams | TraceRequestExceptionParams, logfire_instance: Logfire) -> LogfireAioHttpResponseInfo: ...
39+
40+
def make_request_hook(hook: RequestHook | None, capture_headers: bool) -> RequestHook | None: ...
41+
def make_response_hook(hook: ResponseHook | None, logfire_instance: Logfire, capture_headers: bool, capture_response_body: bool) -> ResponseHook | None: ...
42+
def capture_request(span: Span, request: TraceRequestStartParams, capture_headers: bool) -> LogfireAioHttpRequestInfo: ...
43+
def capture_response(span: Span, response: TraceRequestEndParams | TraceRequestExceptionParams, logfire_instance: Logfire, capture_headers: bool, capture_response_body: bool) -> LogfireAioHttpResponseInfo: ...
44+
def run_hook(hook: Callable[P, Any] | None, *args: P.args, **kwargs: P.kwargs) -> None: ...
45+
def capture_request_or_response_headers(span: Span, headers: AioHttpRequestHeaders | AioHttpResponseHeaders, request_or_response: Literal['request', 'response']) -> None: ...

logfire-api/logfire_api/_internal/integrations/google_genai.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ def transform_part(part: Part) -> Part: ...
2222
class SpanEventLoggerProvider(EventLoggerProvider):
2323
def get_event_logger(self, *args: Any, **kwargs: Any) -> SpanEventLogger: ...
2424

25-
def instrument_google_genai(logfire_instance: logfire.Logfire): ...
25+
def instrument_google_genai(logfire_instance: logfire.Logfire, **kwargs: Any): ...

logfire-api/logfire_api/_internal/main.pyi

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import pydantic_ai
66
import pydantic_ai.models
77
import requests
88
from . import async_ as async_
9+
from ..integrations.aiohttp_client import RequestHook as AiohttpClientRequestHook, ResponseHook as AiohttpClientResponseHook
910
from ..integrations.flask import CommenterOptions as FlaskCommenterOptions, RequestHook as FlaskRequestHook, ResponseHook as FlaskResponseHook
1011
from ..integrations.httpx import AsyncRequestHook as HttpxAsyncRequestHook, AsyncResponseHook as HttpxAsyncResponseHook, RequestHook as HttpxRequestHook, ResponseHook as HttpxResponseHook
1112
from ..integrations.psycopg import CommenterOptions as PsycopgCommenterOptions
@@ -401,10 +402,14 @@ class Logfire:
401402
Set to `'warn'` to issue a warning instead, or `'ignore'` to skip the check.
402403
"""
403404
def instrument_mcp(self, *, propagate_otel_context: bool = True) -> None:
404-
"""Instrument [MCP](https://modelcontextprotocol.io/) requests such as tool calls.
405+
"""Instrument the [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk).
406+
407+
Instruments both the client and server side. If possible, calling this in both the client and server
408+
processes is recommended for nice distributed traces.
405409
406410
Args:
407-
propagate_otel_context: Whether to enable propagation of the OpenTelemetry context.
411+
propagate_otel_context: Whether to enable propagation of the OpenTelemetry context
412+
for distributed tracing.
408413
Set to False to prevent setting extra fields like `traceparent` on the metadata of requests.
409414
"""
410415
def instrument_pydantic(self, record: PydanticPluginRecordValues = 'all', include: Iterable[str] = (), exclude: Iterable[str] = ()) -> None:
@@ -577,7 +582,17 @@ class Logfire:
577582
A context manager that will revert the instrumentation when exited.
578583
Use of this context manager is optional.
579584
"""
580-
def instrument_google_genai(self) -> None: ...
585+
def instrument_google_genai(self, **kwargs: Any):
586+
"""Instrument the [Google Gen AI SDK (`google-genai`)](https://googleapis.github.io/python-genai/).
587+
588+
!!! note
589+
To capture message contents (i.e. prompts and completions), set the environment variable
590+
`OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT` to `true`.
591+
592+
Uses the `GoogleGenAiSdkInstrumentor().instrument()` method of the
593+
[`opentelemetry-instrumentation-google-genai`](https://pypi.org/project/opentelemetry-instrumentation-google-genai/)
594+
package, to which it passes `**kwargs`.
595+
"""
581596
def instrument_litellm(self, **kwargs: Any): ...
582597
def instrument_print(self) -> AbstractContextManager[None]:
583598
"""Instrument the built-in `print` function so that calls to it are logged.
@@ -738,7 +753,7 @@ class Logfire:
738753
Returns:
739754
The instrumented WSGI application.
740755
"""
741-
def instrument_aiohttp_client(self, **kwargs: Any) -> None:
756+
def instrument_aiohttp_client(self, *, capture_headers: bool = False, capture_response_body: bool = False, request_hook: AiohttpClientRequestHook | None = None, response_hook: AiohttpClientResponseHook | None = None, **kwargs: Any) -> None:
742757
"""Instrument the `aiohttp` module so that spans are automatically created for each client request.
743758
744759
Uses the
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from aiohttp.tracing import TraceRequestEndParams, TraceRequestExceptionParams, TraceRequestStartParams
2+
from collections.abc import Callable
3+
from multidict import CIMultiDict, CIMultiDictProxy
4+
from opentelemetry.trace import Span
5+
6+
AioHttpRequestHeaders = CIMultiDict[str]
7+
AioHttpResponseHeaders = CIMultiDictProxy[str]
8+
RequestHook = Callable[[Span, TraceRequestStartParams], None]
9+
ResponseHook = Callable[[Span, TraceRequestEndParams | TraceRequestExceptionParams], None]

logfire-api/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "logfire-api"
7-
version = "4.7.0"
7+
version = "4.8.0"
88
description = "Shim for the Logfire SDK which does nothing unless Logfire is installed"
99
authors = [
1010
{ name = "Pydantic Team", email = "[email protected]" },

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "logfire"
7-
version = "4.7.0"
7+
version = "4.8.0"
88
description = "The best Python observability tool! 🪵🔥"
99
requires-python = ">=3.9"
1010
authors = [

uv.lock

Lines changed: 7 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)