Skip to content

Commit d4578ad

Browse files
authored
Release v3.1.0 (#789)
1 parent b690447 commit d4578ad

File tree

8 files changed

+49
-12
lines changed

8 files changed

+49
-12
lines changed

CHANGELOG.md

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

3+
## [v3.1.0] (2025-01-09)
4+
5+
* Add `capture_all` to `instrument_httpx` by @Kludex in [#780](https://github.com/pydantic/logfire/pull/780)
6+
* Ensure cleanup when forked process ends by @alexmojaki in [#785](https://github.com/pydantic/logfire/pull/785)
7+
* Generate trace IDs as ULIDs by default by @adriangb in [#783](https://github.com/pydantic/logfire/pull/783)
8+
39
## [v3.0.0] (2025-01-07)
410

511
* **BREAKING CHANGE**: Removed `capture_request_json_body`, `capture_request_text_body`, `capture_request_form_data`, and `capture_response_json_body` parameters from `logfire.instrument_httpx()`, replaced with `capture_request_body` `capture_response_body` by @Kludex in [#769](https://github.com/pydantic/logfire/pull/769)
@@ -517,3 +523,4 @@ First release from new repo!
517523
[v2.11.0]: https://github.com/pydantic/logfire/compare/v2.10.0...v2.11.0
518524
[v2.11.1]: https://github.com/pydantic/logfire/compare/v2.11.0...v2.11.1
519525
[v3.0.0]: https://github.com/pydantic/logfire/compare/v2.11.1...v3.0.0
526+
[v3.1.0]: https://github.com/pydantic/logfire/compare/v3.0.0...v3.1.0

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ from typing import Any, Awaitable, Callable, Literal, Mapping, ParamSpec
1313

1414
P = ParamSpec('P')
1515

16-
def instrument_httpx(logfire_instance: Logfire, client: httpx.Client | httpx.AsyncClient | None, capture_headers: bool, capture_request_body: bool, capture_response_body: bool, request_hook: RequestHook | AsyncRequestHook | None, response_hook: ResponseHook | AsyncResponseHook | None, async_request_hook: AsyncRequestHook | None, async_response_hook: AsyncResponseHook | None, **kwargs: Any) -> None:
16+
def instrument_httpx(logfire_instance: Logfire, client: httpx.Client | httpx.AsyncClient | None, capture_all: bool, capture_headers: bool, capture_request_body: bool, capture_response_body: bool, request_hook: RequestHook | AsyncRequestHook | None, response_hook: ResponseHook | AsyncResponseHook | None, async_request_hook: AsyncRequestHook | None, async_response_hook: AsyncResponseHook | None, **kwargs: Any) -> None:
1717
"""Instrument the `httpx` module so that spans are automatically created for each request.
1818
1919
See the `Logfire.instrument_httpx` method for details.

logfire-api/logfire_api/_internal/main.pyi

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -553,11 +553,11 @@ class Logfire:
553553
def instrument_asyncpg(self, **kwargs: Any) -> None:
554554
"""Instrument the `asyncpg` module so that spans are automatically created for each query."""
555555
@overload
556-
def instrument_httpx(self, client: httpx.Client, *, capture_headers: bool = False, capture_request_body: bool = False, capture_response_body: bool = False, request_hook: HttpxRequestHook | None = None, response_hook: HttpxResponseHook | None = None, **kwargs: Any) -> None: ...
556+
def instrument_httpx(self, client: httpx.Client, *, capture_all: bool = False, capture_headers: bool = False, capture_request_body: bool = False, capture_response_body: bool = False, request_hook: HttpxRequestHook | None = None, response_hook: HttpxResponseHook | None = None, **kwargs: Any) -> None: ...
557557
@overload
558-
def instrument_httpx(self, client: httpx.AsyncClient, *, capture_headers: bool = False, capture_request_body: bool = False, capture_response_body: bool = False, request_hook: HttpxRequestHook | HttpxAsyncRequestHook | None = None, response_hook: HttpxResponseHook | HttpxAsyncResponseHook | None = None, **kwargs: Any) -> None: ...
558+
def instrument_httpx(self, client: httpx.AsyncClient, *, capture_all: bool = False, capture_headers: bool = False, capture_request_body: bool = False, capture_response_body: bool = False, request_hook: HttpxRequestHook | HttpxAsyncRequestHook | None = None, response_hook: HttpxResponseHook | HttpxAsyncResponseHook | None = None, **kwargs: Any) -> None: ...
559559
@overload
560-
def instrument_httpx(self, client: None = None, *, capture_headers: bool = False, capture_request_body: bool = False, capture_response_body: bool = False, request_hook: HttpxRequestHook | None = None, response_hook: HttpxResponseHook | None = None, async_request_hook: HttpxAsyncRequestHook | None = None, async_response_hook: HttpxAsyncResponseHook | None = None, **kwargs: Any) -> None: ...
560+
def instrument_httpx(self, client: None = None, *, capture_all: bool = False, capture_headers: bool = False, capture_request_body: bool = False, capture_response_body: bool = False, request_hook: HttpxRequestHook | None = None, response_hook: HttpxResponseHook | None = None, async_request_hook: HttpxAsyncRequestHook | None = None, async_response_hook: HttpxAsyncResponseHook | None = None, **kwargs: Any) -> None: ...
561561
def instrument_celery(self, **kwargs: Any) -> None:
562562
"""Instrument `celery` so that spans are automatically created for each task.
563563
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from random import Random
2+
from typing import Callable
3+
4+
def ulid(random: Random, ms_timestamp_generator: Callable[[], int]) -> int:
5+
"""Generate an integer ULID compatible with UUID v4.
6+
7+
ULIDs as defined by the [spec](https://github.com/ulid/spec) look like this:
8+
9+
01AN4Z07BY 79KA1307SR9X4MV3
10+
|----------| |----------------|
11+
Timestamp Randomness
12+
48bits 80bits
13+
14+
In the future it would be nice to make this compatible with a UUID,
15+
e.g. v4 UUIDs by setting the version and variant bits correctly.
16+
We can't currently do this because setting these bits would leave us with only 7 bytes of randomness,
17+
which isn't enough for the Python SDK's sampler that currently expects 8 bytes of randomness.
18+
In the future OTEL will probably adopt https://www.w3.org/TR/trace-context-2/#random-trace-id-flag
19+
which relies only on the lower 7 bytes of the trace ID, then all SDKs and tooling should be updated
20+
and leaving only 7 bytes of randomness should be fine.
21+
22+
Right now we only care about:
23+
- Our SDK / Python SDK's in general.
24+
- The OTEL collector.
25+
26+
And both behave properly with 8 bytes of randomness because trace IDs were originally 64 bits
27+
so to be compatible with old trace IDs nothing in OTEL can assume >8 bytes of randomness in trace IDs
28+
unless they generated the trace ID themselves (e.g. the Go SDK _does_ expect >8 bytes of randomness internally).
29+
"""

logfire-api/logfire_api/_internal/utils.pyi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ from _typeshed import Incomplete
22
from collections.abc import Generator
33
from dataclasses import dataclass
44
from logfire._internal.stack_info import is_user_code as is_user_code
5+
from logfire._internal.ulid import ulid as ulid
56
from opentelemetry import trace as trace_api
67
from opentelemetry.sdk.resources import Resource
78
from opentelemetry.sdk.trace import Event as Event, ReadableSpan
@@ -91,7 +92,7 @@ def handle_internal_errors() -> Generator[None]: ...
9192
def maybe_capture_server_headers(capture: bool): ...
9293
def is_asgi_send_receive_span_name(name: str) -> bool: ...
9394

94-
@dataclass(repr=True)
95+
@dataclass(repr=True, eq=True)
9596
class SeededRandomIdGenerator(IdGenerator):
9697
"""Generate random span/trace IDs from a seed for deterministic tests.
9798

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 = "3.0.0"
7+
version = "3.1.0"
88
description = "Shim for the Logfire SDK which does nothing unless Logfire is installed"
99
authors = [
1010
{ name = "Pydantic Team", email = "engineering@pydantic.dev" },

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 = "3.0.0"
7+
version = "3.1.0"
88
description = "The best Python observability tool! 🪵🔥"
99
requires-python = ">=3.8"
1010
authors = [

uv.lock

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

0 commit comments

Comments
 (0)