Skip to content

Commit f3c50a2

Browse files
authored
Release 0.48.0 (#334)
1 parent b3ca715 commit f3c50a2

File tree

17 files changed

+130
-48
lines changed

17 files changed

+130
-48
lines changed

CHANGELOG.md

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

3+
## [v0.48.0] (2024-07-24)
4+
5+
* Add `instrument_celery` method by @Kludex in https://github.com/pydantic/logfire/pull/322
6+
* `capture_headers` by @alexmojaki in https://github.com/pydantic/logfire/pull/318
7+
* Handle message formatting errors by @alexmojaki in https://github.com/pydantic/logfire/pull/329
8+
* Handle logging `None` with `loguru` by @alexmojaki in https://github.com/pydantic/logfire/pull/331
9+
310
## [v0.47.0] (2024-07-20)
411

512
* Fix recursive logging from OTEL's `BatchSpanProcessor` by @alexmojaki in https://github.com/pydantic/logfire/pull/306
@@ -214,6 +221,7 @@ First release from new repo!
214221
* Ensure `logfire.testing` doesn't depend on pydantic and eval_type_backport by @alexmojaki in https://github.com/pydantic/logfire/pull/40
215222
* Allow using pydantic plugin with models defined before calling logfire.configure by @alexmojaki in https://github.com/pydantic/logfire/pull/36
216223

224+
[v0.48.0]: https://github.com/pydantic/logfire/compare/v0.47.0...v0.48.0
217225
[v0.47.0]: https://github.com/pydantic/logfire/compare/v0.46.1...v0.47.0
218226
[v0.46.1]: https://github.com/pydantic/logfire/compare/v0.46.0...v0.46.1
219227
[v0.46.0]: https://github.com/pydantic/logfire/compare/v0.45.1...v0.46.0

logfire-api/logfire_api/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def with_settings(self, *args, **kwargs) -> Logfire:
7979

8080
def force_flush(self, *args, **kwargs) -> None: ...
8181

82-
def log_slow_async_callbacks(self, *args, **kwargs) -> None: # pragma: no branch
82+
def log_slow_async_callbacks(self, *args, **kwargs) -> None: # pragma: no branch
8383
return nullcontext()
8484

8585
def install_auto_tracing(self, *args, **kwargs) -> None: ...
@@ -143,6 +143,7 @@ def shutdown(self, *args, **kwargs) -> None: ...
143143
instrument_openai = DEFAULT_LOGFIRE_INSTANCE.instrument_openai
144144
instrument_anthropic = DEFAULT_LOGFIRE_INSTANCE.instrument_anthropic
145145
instrument_asyncpg = DEFAULT_LOGFIRE_INSTANCE.instrument_asyncpg
146+
instrument_celery = DEFAULT_LOGFIRE_INSTANCE.instrument_celery
146147
instrument_httpx = DEFAULT_LOGFIRE_INSTANCE.instrument_httpx
147148
instrument_requests = DEFAULT_LOGFIRE_INSTANCE.instrument_requests
148149
instrument_psycopg = DEFAULT_LOGFIRE_INSTANCE.instrument_psycopg

logfire-api/logfire_api/__init__.pyi

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
from ._internal.auto_trace import AutoTraceModule as AutoTraceModule
22
from ._internal.auto_trace.rewrite_ast import no_auto_trace as no_auto_trace
3-
from ._internal.config import ConsoleOptions as ConsoleOptions, METRICS_PREFERRED_TEMPORALITY as METRICS_PREFERRED_TEMPORALITY, PydanticPlugin as PydanticPlugin, configure as configure
3+
from ._internal.config import (
4+
ConsoleOptions as ConsoleOptions,
5+
METRICS_PREFERRED_TEMPORALITY as METRICS_PREFERRED_TEMPORALITY,
6+
PydanticPlugin as PydanticPlugin,
7+
configure as configure,
8+
)
49
from ._internal.constants import LevelName as LevelName
510
from ._internal.exporters.file import load_file as load_spans_from_file
611
from ._internal.exporters.tail_sampling import TailSamplingOptions as TailSamplingOptions
@@ -11,7 +16,56 @@ from .integrations.logging import LogfireLoggingHandler as LogfireLoggingHandler
1116
from .integrations.structlog import LogfireProcessor as StructlogProcessor
1217
from .version import VERSION as VERSION
1318

14-
__all__ = ['Logfire', 'LogfireSpan', 'LevelName', 'ConsoleOptions', 'PydanticPlugin', 'configure', 'span', 'instrument', 'log', 'trace', 'debug', 'notice', 'info', 'warn', 'error', 'fatal', 'force_flush', 'log_slow_async_callbacks', 'install_auto_tracing', 'instrument_fastapi', 'instrument_openai', 'instrument_anthropic', 'instrument_asyncpg', 'instrument_httpx', 'instrument_requests', 'instrument_psycopg', 'instrument_django', 'instrument_flask', 'instrument_starlette', 'instrument_aiohttp_client', 'instrument_sqlalchemy', 'instrument_redis', 'instrument_pymongo', 'AutoTraceModule', 'with_tags', 'with_settings', 'shutdown', 'load_spans_from_file', 'no_auto_trace', 'METRICS_PREFERRED_TEMPORALITY', 'ScrubMatch', 'ScrubbingOptions', 'VERSION', 'suppress_instrumentation', 'StructlogProcessor', 'LogfireLoggingHandler', 'TailSamplingOptions']
19+
__all__ = [
20+
'Logfire',
21+
'LogfireSpan',
22+
'LevelName',
23+
'ConsoleOptions',
24+
'PydanticPlugin',
25+
'configure',
26+
'span',
27+
'instrument',
28+
'log',
29+
'trace',
30+
'debug',
31+
'notice',
32+
'info',
33+
'warn',
34+
'error',
35+
'fatal',
36+
'force_flush',
37+
'log_slow_async_callbacks',
38+
'install_auto_tracing',
39+
'instrument_fastapi',
40+
'instrument_openai',
41+
'instrument_anthropic',
42+
'instrument_asyncpg',
43+
'instrument_httpx',
44+
'instrument_celery',
45+
'instrument_requests',
46+
'instrument_psycopg',
47+
'instrument_django',
48+
'instrument_flask',
49+
'instrument_starlette',
50+
'instrument_aiohttp_client',
51+
'instrument_sqlalchemy',
52+
'instrument_redis',
53+
'instrument_pymongo',
54+
'AutoTraceModule',
55+
'with_tags',
56+
'with_settings',
57+
'shutdown',
58+
'load_spans_from_file',
59+
'no_auto_trace',
60+
'METRICS_PREFERRED_TEMPORALITY',
61+
'ScrubMatch',
62+
'ScrubbingOptions',
63+
'VERSION',
64+
'suppress_instrumentation',
65+
'StructlogProcessor',
66+
'LogfireLoggingHandler',
67+
'TailSamplingOptions',
68+
]
1569

1670
DEFAULT_LOGFIRE_INSTANCE = Logfire()
1771
span = DEFAULT_LOGFIRE_INSTANCE.span
@@ -24,6 +78,7 @@ instrument_openai = DEFAULT_LOGFIRE_INSTANCE.instrument_openai
2478
instrument_anthropic = DEFAULT_LOGFIRE_INSTANCE.instrument_anthropic
2579
instrument_asyncpg = DEFAULT_LOGFIRE_INSTANCE.instrument_asyncpg
2680
instrument_httpx = DEFAULT_LOGFIRE_INSTANCE.instrument_httpx
81+
instrument_celery = DEFAULT_LOGFIRE_INSTANCE.instrument_celery
2782
instrument_requests = DEFAULT_LOGFIRE_INSTANCE.instrument_requests
2883
instrument_psycopg = DEFAULT_LOGFIRE_INSTANCE.instrument_psycopg
2984
instrument_django = DEFAULT_LOGFIRE_INSTANCE.instrument_django

logfire-api/logfire_api/_internal/config.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ from .exporters.remove_pending import RemovePendingSpansExporter as RemovePendin
1414
from .exporters.tail_sampling import TailSamplingOptions as TailSamplingOptions, TailSamplingProcessor as TailSamplingProcessor
1515
from .integrations.executors import instrument_executors as instrument_executors
1616
from .metrics import ProxyMeterProvider as ProxyMeterProvider, configure_metrics as configure_metrics
17-
from .scrubbing import BaseScrubber as BaseScrubber, NoopScrubber as NoopScrubber, ScrubCallback as ScrubCallback, Scrubber as Scrubber, ScrubbingOptions as ScrubbingOptions
17+
from .scrubbing import BaseScrubber as BaseScrubber, NOOP_SCRUBBER as NOOP_SCRUBBER, ScrubCallback as ScrubCallback, Scrubber as Scrubber, ScrubbingOptions as ScrubbingOptions
1818
from .stack_info import get_user_frame_and_stacklevel as get_user_frame_and_stacklevel
1919
from .tracer import PendingSpanProcessor as PendingSpanProcessor, ProxyTracerProvider as ProxyTracerProvider
2020
from .utils import UnexpectedResponse as UnexpectedResponse, ensure_data_dir_exists as ensure_data_dir_exists, get_version as get_version, read_toml_file as read_toml_file, suppress_instrumentation as suppress_instrumentation

logfire-api/logfire_api/_internal/formatter.pyi

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ import ast
22
import executing
33
import types
44
from .constants import ATTRIBUTES_SCRUBBED_KEY as ATTRIBUTES_SCRUBBED_KEY, MESSAGE_FORMATTED_VALUE_LENGTH_LIMIT as MESSAGE_FORMATTED_VALUE_LENGTH_LIMIT
5-
from .scrubbing import BaseScrubber as BaseScrubber, ScrubbedNote as ScrubbedNote
6-
from .utils import truncate_string as truncate_string
5+
from .scrubbing import BaseScrubber as BaseScrubber, NOOP_SCRUBBER as NOOP_SCRUBBER, ScrubbedNote as ScrubbedNote
6+
from .utils import log_internal_error as log_internal_error, truncate_string as truncate_string
77
from _typeshed import Incomplete
88
from logfire._internal.stack_info import get_user_frame_and_stacklevel as get_user_frame_and_stacklevel
99
from string import Formatter
1010
from types import CodeType as CodeType
11-
from typing import Any, Final, Literal, Mapping
11+
from typing import Any, Final, Literal
1212
from typing_extensions import NotRequired, TypedDict
1313

1414
class LiteralChunk(TypedDict):
@@ -22,7 +22,7 @@ class ArgChunk(TypedDict):
2222

2323
class ChunksFormatter(Formatter):
2424
NONE_REPR: Final[str]
25-
def chunks(self, format_string: str, kwargs: Mapping[str, Any], *, scrubber: BaseScrubber, fstring_frame: types.FrameType | None = None) -> tuple[list[LiteralChunk | ArgChunk], dict[str, Any], str]: ...
25+
def chunks(self, format_string: str, kwargs: dict[str, Any], *, scrubber: BaseScrubber, fstring_frame: types.FrameType | None = None) -> tuple[list[LiteralChunk | ArgChunk], dict[str, Any], str]: ...
2626

2727
chunks_formatter: Incomplete
2828

@@ -48,3 +48,13 @@ def get_stacklevel(frame: types.FrameType): ...
4848
class InspectArgumentsFailedWarning(Warning): ...
4949

5050
def warn_inspect_arguments(msg: str, stacklevel: int): ...
51+
52+
class KnownFormattingError(Exception):
53+
"""An error raised when there's something wrong with a format string or the field values.
54+
55+
In other words this should correspond to errors that would be raised when using `str.format`,
56+
and generally indicate a user error, most likely that they weren't trying to pass a template string at all.
57+
"""
58+
class FormattingFailedWarning(UserWarning): ...
59+
60+
def warn_formatting(msg: str): ...
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from typing_extensions import TypedDict, Unpack
2+
3+
class CeleryInstrumentKwargs(TypedDict, total=False):
4+
skip_dep_check: bool
5+
6+
def instrument_celery(**kwargs: Unpack[CeleryInstrumentKwargs]) -> None:
7+
"""Instrument the `celery` module so that spans are automatically created for each task.
8+
9+
See the `Logfire.instrument_celery` method for details.
10+
"""

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
from logfire._internal.utils import maybe_capture_server_headers as maybe_capture_server_headers
12
from typing import Any
23

3-
def instrument_django(**kwargs: Any):
4+
def instrument_django(*, capture_headers: bool = False, **kwargs: Any):
45
"""Instrument the `django` module so that spans are automatically created for each web request.
56
67
See the `Logfire.instrument_django` method for details.

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from ..main import Logfire as Logfire
22
from ..stack_info import StackInfo as StackInfo, get_code_object_info as get_code_object_info
3+
from ..utils import maybe_capture_server_headers as maybe_capture_server_headers
34
from _typeshed import Incomplete
45
from fastapi import FastAPI
56
from starlette.requests import Request
@@ -8,7 +9,7 @@ from typing import Any, Awaitable, Callable, ContextManager, Iterable
89

910
def find_mounted_apps(app: FastAPI) -> list[FastAPI]:
1011
"""Fetch all sub-apps mounted to a FastAPI app, including nested sub-apps."""
11-
def instrument_fastapi(logfire_instance: Logfire, app: FastAPI, *, request_attributes_mapper: Callable[[Request | WebSocket, dict[str, Any]], dict[str, Any] | None] | None = None, use_opentelemetry_instrumentation: bool = True, excluded_urls: str | Iterable[str] | None = None, **opentelemetry_kwargs: Any) -> ContextManager[None]:
12+
def instrument_fastapi(logfire_instance: Logfire, app: FastAPI, *, capture_headers: bool = False, request_attributes_mapper: Callable[[Request | WebSocket, dict[str, Any]], dict[str, Any] | None] | None = None, use_opentelemetry_instrumentation: bool = True, excluded_urls: str | Iterable[str] | None = None, **opentelemetry_kwargs: Any) -> ContextManager[None]:
1213
"""Instrument a FastAPI app so that spans and logs are automatically created for each request.
1314
1415
See `Logfire.instrument_fastapi` for more details.

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from flask.app import Flask
2+
from logfire._internal.utils import maybe_capture_server_headers as maybe_capture_server_headers
23
from opentelemetry.trace import Span
34
from typing_extensions import Protocol, TypedDict, Unpack
45
from wsgiref.types import WSGIEnvironment
@@ -16,7 +17,7 @@ class FlaskInstrumentKwargs(TypedDict, total=False):
1617
enable_commenter: bool | None
1718
commenter_options: dict[str, str] | None
1819

19-
def instrument_flask(app: Flask, **kwargs: Unpack[FlaskInstrumentKwargs]):
20+
def instrument_flask(app: Flask, capture_headers: bool = False, **kwargs: Unpack[FlaskInstrumentKwargs]):
2021
"""Instrument `app` so that spans are automatically created for each request.
2122
2223
See the `Logfire.instrument_flask` method for details.

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from logfire._internal.utils import maybe_capture_server_headers as maybe_capture_server_headers
12
from opentelemetry.trace import Span
23
from starlette.applications import Starlette
34
from typing import Any
@@ -17,7 +18,7 @@ class StarletteInstrumentKwargs(TypedDict, total=False):
1718
client_request_hook: ClientRequestHook | None
1819
client_response_hook: ClientResponseHook | None
1920

20-
def instrument_starlette(app: Starlette, **kwargs: Unpack[StarletteInstrumentKwargs]):
21+
def instrument_starlette(app: Starlette, *, capture_headers: bool = False, **kwargs: Unpack[StarletteInstrumentKwargs]):
2122
"""Instrument `app` so that spans are automatically created for each request.
2223
2324
See the `Logfire.instrument_starlette` method for details.

0 commit comments

Comments
 (0)