Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v1.3.0 #539

Merged
merged 2 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Release Notes

## [v1.3.0] (2024-10-24)

* Add Code Source links by @Kludex in [#451](https://github.com/pydantic/logfire/pull/451) and [#505](https://github.com/pydantic/logfire/pull/505)
* Add fastapi arguments attributes directly on the root OTEL span, remove `use_opentelemetry_instrumentation` kwarg by @alexmojaki in [#509](https://github.com/pydantic/logfire/pull/509)
alexmojaki marked this conversation as resolved.
Show resolved Hide resolved
* Allow setting tags on logfire spans by @AdolfoVillalobos in [#497](https://github.com/pydantic/logfire/pull/497)
* Add logger name to `LogfireLoggingHandler` spans by @samuelcolvin in [#534](https://github.com/pydantic/logfire/pull/534)
* Format `None` as `None` instead of `null` in messages by @alexmojaki in [#525](https://github.com/pydantic/logfire/pull/525)
* Use `PYTEST_VERSION` instead of `PYTEST_CURRENT_TEST` to detect `logfire.configure()` being called within a pytest run but outside any test by @Kludex in [#531](https://github.com/pydantic/logfire/pull/531)

## [v1.2.0] (2024-10-17)

* Add `local` parameter to `logfire.configure()` by @alexmojaki in [#508](https://github.com/pydantic/logfire/pull/508)
Expand Down Expand Up @@ -358,3 +367,4 @@ First release from new repo!
[v1.0.1]: https://github.com/pydantic/logfire/compare/v1.0.0...v1.0.1
[v1.1.0]: https://github.com/pydantic/logfire/compare/v1.0.1...v1.1.0
[v1.2.0]: https://github.com/pydantic/logfire/compare/v1.1.0...v1.2.0
[v1.3.0]: https://github.com/pydantic/logfire/compare/v1.2.0...v1.3.0
1 change: 1 addition & 0 deletions logfire-api/logfire_api/_internal/constants.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ ATTRIBUTES_MESSAGE_KEY: Incomplete
DISABLE_CONSOLE_KEY: Incomplete
ATTRIBUTES_JSON_SCHEMA_KEY: Incomplete
ATTRIBUTES_LOGGING_ARGS_KEY: Incomplete
ATTRIBUTES_LOGGING_NAME: Incomplete
ATTRIBUTES_VALIDATION_ERROR_KEY: str
ATTRIBUTES_SCRUBBED_KEY: Incomplete
NULL_ARGS_KEY: str
Expand Down
3 changes: 1 addition & 2 deletions logfire-api/logfire_api/_internal/formatter.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ from .utils import log_internal_error as log_internal_error, truncate_string as
from _typeshed import Incomplete
from string import Formatter
from types import CodeType as CodeType
from typing import Any, Final, Literal
from typing import Any, Literal
from typing_extensions import NotRequired, TypedDict

class LiteralChunk(TypedDict):
Expand All @@ -21,7 +21,6 @@ class ArgChunk(TypedDict):
spec: NotRequired[str]

class ChunksFormatter(Formatter):
NONE_REPR: Final[str]
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]: ...

chunks_formatter: Incomplete
Expand Down
9 changes: 5 additions & 4 deletions logfire-api/logfire_api/_internal/integrations/fastapi.pyi
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from ..main import Logfire as Logfire
from ..main import Logfire as Logfire, set_user_attributes_on_raw_span as set_user_attributes_on_raw_span
from ..stack_info import StackInfo as StackInfo, get_code_object_info as get_code_object_info
from ..utils import maybe_capture_server_headers as maybe_capture_server_headers
from .asgi import tweak_asgi_spans_tracer_provider as tweak_asgi_spans_tracer_provider
Expand All @@ -10,7 +10,7 @@ from typing import Any, Awaitable, Callable, ContextManager, Iterable

def find_mounted_apps(app: FastAPI) -> list[FastAPI]:
"""Fetch all sub-apps mounted to a FastAPI app, including nested sub-apps."""
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, record_send_receive: bool = False, **opentelemetry_kwargs: Any) -> ContextManager[None]:
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, excluded_urls: str | Iterable[str] | None = None, record_send_receive: bool = False, **opentelemetry_kwargs: Any) -> ContextManager[None]:
"""Instrument a FastAPI app so that spans and logs are automatically created for each request.

See `Logfire.instrument_fastapi` for more details.
Expand All @@ -21,10 +21,11 @@ def patch_fastapi():
class FastAPIInstrumentation:
logfire_instance: Incomplete
request_attributes_mapper: Incomplete
excluded_urls_list: Incomplete
def __init__(self, logfire_instance: Logfire, request_attributes_mapper: Callable[[Request | WebSocket, dict[str, Any]], dict[str, Any] | None], excluded_urls: str | None) -> None: ...
def __init__(self, logfire_instance: Logfire, request_attributes_mapper: Callable[[Request | WebSocket, dict[str, Any]], dict[str, Any] | None]) -> None: ...
async def solve_dependencies(self, request: Request | WebSocket, original: Awaitable[Any]) -> Any: ...
async def run_endpoint_function(self, original_run_endpoint_function: Any, request: Request, dependant: Any, values: dict[str, Any], **kwargs: Any) -> Any: ...

class _InstrumentedValues(dict):
request: Request

LOGFIRE_SPAN_SCOPE_KEY: str
16 changes: 8 additions & 8 deletions logfire-api/logfire_api/_internal/main.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ from django.http import HttpRequest as HttpRequest, HttpResponse as HttpResponse
from fastapi import FastAPI
from flask.app import Flask
from opentelemetry.metrics import CallbackT as CallbackT, Counter, Histogram, UpDownCounter, _Gauge as Gauge
from opentelemetry.sdk.trace import ReadableSpan, Span as Span
from opentelemetry.sdk.trace import ReadableSpan, Span
from opentelemetry.trace import Tracer
from opentelemetry.util import types as otel_types
from starlette.applications import Starlette
Expand Down Expand Up @@ -386,9 +386,12 @@ class Logfire:
exclude:
Exclude specific modules from instrumentation.
"""
def instrument_fastapi(self, 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, record_send_receive: bool = False, **opentelemetry_kwargs: Any) -> ContextManager[None]:
def instrument_fastapi(self, app: FastAPI, *, capture_headers: bool = False, request_attributes_mapper: Callable[[Request | WebSocket, dict[str, Any]], dict[str, Any] | None] | None = None, excluded_urls: str | Iterable[str] | None = None, record_send_receive: bool = False, **opentelemetry_kwargs: Any) -> ContextManager[None]:
"""Instrument a FastAPI app so that spans and logs are automatically created for each request.

Uses the [OpenTelemetry FastAPI Instrumentation](https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/fastapi/fastapi.html)
under the hood, with some additional features.

Args:
app: The FastAPI app to instrument.
capture_headers: Set to `True` to capture all request and response headers.
Expand All @@ -411,11 +414,6 @@ class Logfire:
matches any of the regexes. This applies to both the Logfire and OpenTelemetry instrumentation.
If not provided, the environment variables
`OTEL_PYTHON_FASTAPI_EXCLUDED_URLS` and `OTEL_PYTHON_EXCLUDED_URLS` will be checked.
use_opentelemetry_instrumentation: If True (the default) then
[`FastAPIInstrumentor`][opentelemetry.instrumentation.fastapi.FastAPIInstrumentor]
will also instrument the app.

See [OpenTelemetry FastAPI Instrumentation](https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/fastapi/fastapi.html).
record_send_receive: Set to True to allow the OpenTelemetry ASGI to create send/receive spans.
These are disabled by default to reduce overhead and the number of spans created,
since many can be created for a single request, and they are not often useful.
Expand Down Expand Up @@ -934,7 +932,8 @@ class LogfireSpan(ReadableSpan):
@property
def tags(self) -> tuple[str, ...]: ...
@tags.setter
def tags(self, new_tags: Sequence[str]) -> None: ...
def tags(self, new_tags: Sequence[str]) -> None:
"""Set or add tags to the span."""
@property
def message(self) -> str: ...
@message.setter
Expand Down Expand Up @@ -1008,5 +1007,6 @@ def set_user_attribute(otlp_attributes: dict[str, otel_types.AttributeValue], ke
Returns the final key and value that was added to the dictionary.
The key will be the original key unless the value was `None`, in which case it will be `NULL_ARGS_KEY`.
"""
def set_user_attributes_on_raw_span(span: Span, attributes: dict[str, Any]) -> None: ...
P = ParamSpec('P')
R = TypeVar('R')
4 changes: 2 additions & 2 deletions logfire-api/logfire_api/_internal/utils.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,10 @@ def is_instrumentation_suppressed() -> bool:

This means that any logs/spans generated by logfire or OpenTelemetry will not be logged in any way.
"""
def suppress_instrumentation() -> Generator[None, None, None]:
def suppress_instrumentation() -> Generator[None]:
"""Context manager to suppress all logs/spans generated by logfire or OpenTelemetry."""
def log_internal_error() -> None: ...
def handle_internal_errors() -> Generator[None, None, None]: ...
def handle_internal_errors() -> Generator[None]: ...
def maybe_capture_server_headers(capture: bool): ...
def is_asgi_send_receive_span_name(name: str) -> bool: ...

Expand Down
2 changes: 1 addition & 1 deletion logfire-api/logfire_api/integrations/logging.pyi
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .. import Logfire as Logfire
from .._internal.constants import ATTRIBUTES_LOGGING_ARGS_KEY as ATTRIBUTES_LOGGING_ARGS_KEY, ATTRIBUTES_MESSAGE_KEY as ATTRIBUTES_MESSAGE_KEY, ATTRIBUTES_MESSAGE_TEMPLATE_KEY as ATTRIBUTES_MESSAGE_TEMPLATE_KEY, LOGGING_TO_OTEL_LEVEL_NUMBERS as LOGGING_TO_OTEL_LEVEL_NUMBERS
from .._internal.constants import ATTRIBUTES_LOGGING_ARGS_KEY as ATTRIBUTES_LOGGING_ARGS_KEY, ATTRIBUTES_LOGGING_NAME as ATTRIBUTES_LOGGING_NAME, ATTRIBUTES_MESSAGE_KEY as ATTRIBUTES_MESSAGE_KEY, ATTRIBUTES_MESSAGE_TEMPLATE_KEY as ATTRIBUTES_MESSAGE_TEMPLATE_KEY, LOGGING_TO_OTEL_LEVEL_NUMBERS as LOGGING_TO_OTEL_LEVEL_NUMBERS
from .._internal.utils import is_instrumentation_suppressed as is_instrumentation_suppressed
from _typeshed import Incomplete
from logging import Handler as LoggingHandler, LogRecord
Expand Down
2 changes: 1 addition & 1 deletion logfire-api/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "logfire-api"
version = "1.2.0"
version = "1.3.0"
description = "Shim for the Logfire SDK which does nothing unless Logfire is installed"
authors = [
{ name = "Pydantic Team", email = "engineering@pydantic.dev" },
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "logfire"
version = "1.2.0"
version = "1.3.0"
description = "The best Python observability tool! 🪵🔥"
requires-python = ">=3.8"
authors = [
Expand Down
6 changes: 3 additions & 3 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.