-
Notifications
You must be signed in to change notification settings - Fork 59
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
Add logfire-api
#268
Merged
Merged
Add logfire-api
#268
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
933bec9
Add `logfire-api`
Kludex 528264b
Update logfire-api/README.md
Kludex fbc4af9
Add `logfire-api`
Kludex 3efd5df
Add `logfire-api`
Kludex 4b2c3da
Update
Kludex 9060a1f
Publish
Kludex 458ce66
Publish
Kludex 45e22ca
remove hatch
Kludex 8a49dcf
ignore pyright
Kludex 82ede9d
fully functional
Kludex 5e94387
Tests are correct now
Kludex f8e4fbf
Ignore logfire-api
Kludex a038414
Use typec checker to specific files
Kludex 1f50d23
TailSamplingOptions added
Kludex 4e657e2
no cover
Kludex aff5a77
Add ScrubbingOptions
Kludex f593022
Use uv to install logfire-api
Kludex e8487d7
Install uv
Kludex af2c849
Install uv
Kludex 9facd63
Install uv
Kludex 15558ca
Install uv
Kludex a108256
Remove unneeded debugging logic on the CI
Kludex 2b5ec24
Coverage up
Kludex 492f779
Pin numpy<2.0.0
Kludex 1a7d6b2
numpy back to 2.0.0
Kludex 9237891
Update version
Kludex 8f42fe8
Apply Alex comments
Kludex File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,3 +6,6 @@ __pycache__ | |
*.env | ||
/scratch/ | ||
/.coverage | ||
|
||
# stubgen | ||
out |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# python generated files | ||
__pycache__/ | ||
*.py[oc] | ||
build/ | ||
dist/ | ||
wheels/ | ||
*.egg-info | ||
|
||
# venv | ||
.venv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# logfire-api | ||
|
||
Shim for the logfire SDK Python API which does nothing unless logfire is installed. | ||
|
||
This package is designed to be used by packages that want to provide opt-in integration with [Logfire](https://github.com/pydantic/logfire). | ||
|
||
The package provides a clone of the Python API exposed by the `logfire` package which does nothing if the `logfire` package is not installed, but makes real calls when it is. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
from __future__ import annotations | ||
|
||
from contextlib import contextmanager | ||
import importlib | ||
import sys | ||
from typing import TYPE_CHECKING, ContextManager, Literal | ||
from contextlib import nullcontext | ||
from unittest.mock import MagicMock | ||
|
||
try: | ||
logfire_module = importlib.import_module('logfire') | ||
sys.modules[__name__] = logfire_module | ||
|
||
except ImportError: | ||
if not TYPE_CHECKING: # pragma: no branch | ||
LevelName = Literal['trace', 'debug', 'info', 'notice', 'warn', 'warning', 'error', 'fatal'] | ||
VERSION = '0.0.0' | ||
METRICS_PREFERRED_TEMPORALITY = {} | ||
|
||
def configure(*args, **kwargs): ... | ||
|
||
class LogfireSpan: | ||
Kludex marked this conversation as resolved.
Show resolved
Hide resolved
|
||
def __getattr__(self, attr): | ||
return MagicMock() # pragma: no cover | ||
|
||
def __enter__(self): | ||
return self | ||
|
||
def __exit__(self, *args, **kwargs) -> None: ... | ||
|
||
@property | ||
def message_template(self) -> str: # pragma: no cover | ||
return '' | ||
|
||
@property | ||
def tags(self) -> Sequence[str]: # pragma: no cover | ||
return [] | ||
|
||
@property | ||
def message(self) -> str: # pragma: no cover | ||
return '' | ||
|
||
@message.setter | ||
def message(self, message: str): ... # pragma: no cover | ||
|
||
def is_recording(self) -> bool: # pragma: no cover | ||
return False | ||
|
||
class Logfire: | ||
def __getattr__(self, attr): | ||
return MagicMock() # pragma: no cover | ||
|
||
def __init__(self, *args, **kwargs) -> None: ... | ||
|
||
def span(self, *args, **kwargs) -> LogfireSpan: | ||
return LogfireSpan() | ||
|
||
def log(self, *args, **kwargs) -> None: ... | ||
|
||
def trace(self, *args, **kwargs) -> None: ... | ||
|
||
def debug(self, *args, **kwargs) -> None: ... | ||
|
||
def notice(self, *args, **kwargs) -> None: ... | ||
|
||
def info(self, *args, **kwargs) -> None: ... | ||
|
||
def warn(self, *args, **kwargs) -> None: ... | ||
|
||
def error(self, *args, **kwargs) -> None: ... | ||
|
||
def fatal(self, *args, **kwargs) -> None: ... | ||
|
||
def with_tags(self, *args, **kwargs) -> Logfire: | ||
return self | ||
|
||
def with_settings(self, *args, **kwargs) -> Logfire: | ||
return self | ||
|
||
def force_flush(self, *args, **kwargs) -> None: ... | ||
|
||
def log_slow_async_callbacks(self, *args, **kwargs) -> None: # pragma: no branch | ||
return nullcontext() | ||
|
||
def install_auto_tracing(self, *args, **kwargs) -> None: ... | ||
|
||
def instrument(self, *args, **kwargs): | ||
def decorator(func): | ||
return func | ||
|
||
return decorator | ||
|
||
def instrument_fastapi(self, *args, **kwargs) -> ContextManager[None]: | ||
return nullcontext() | ||
|
||
def instrument_pymongo(self, *args, **kwargs) -> None: ... | ||
|
||
def instrument_sqlalchemy(self, *args, **kwargs) -> None: ... | ||
|
||
def instrument_redis(self, *args, **kwargs) -> None: ... | ||
|
||
def instrument_flask(self, *args, **kwargs) -> None: ... | ||
|
||
def instrument_starlette(self, *args, **kwargs) -> None: ... | ||
|
||
def instrument_django(self, *args, **kwargs) -> None: ... | ||
|
||
def instrument_psycopg(self, *args, **kwargs) -> None: ... | ||
|
||
def instrument_requests(self, *args, **kwargs) -> None: ... | ||
|
||
def instrument_httpx(self, *args, **kwargs) -> None: ... | ||
|
||
def instrument_asyncpg(self, *args, **kwargs) -> None: ... | ||
|
||
def instrument_anthropic(self, *args, **kwargs) -> ContextManager[None]: | ||
return nullcontext() | ||
|
||
def instrument_openai(self, *args, **kwargs) -> ContextManager[None]: | ||
return nullcontext() | ||
|
||
def instrument_aiohttp_client(self, *args, **kwargs) -> None: ... | ||
|
||
def shutdown(self, *args, **kwargs) -> None: ... | ||
|
||
DEFAULT_LOGFIRE_INSTANCE = Logfire() | ||
span = DEFAULT_LOGFIRE_INSTANCE.span | ||
log = DEFAULT_LOGFIRE_INSTANCE.log | ||
trace = DEFAULT_LOGFIRE_INSTANCE.trace | ||
debug = DEFAULT_LOGFIRE_INSTANCE.debug | ||
notice = DEFAULT_LOGFIRE_INSTANCE.notice | ||
info = DEFAULT_LOGFIRE_INSTANCE.info | ||
warn = DEFAULT_LOGFIRE_INSTANCE.warn | ||
error = DEFAULT_LOGFIRE_INSTANCE.error | ||
fatal = DEFAULT_LOGFIRE_INSTANCE.fatal | ||
with_tags = DEFAULT_LOGFIRE_INSTANCE.with_tags | ||
with_settings = DEFAULT_LOGFIRE_INSTANCE.with_settings | ||
force_flush = DEFAULT_LOGFIRE_INSTANCE.force_flush | ||
log_slow_async_callbacks = DEFAULT_LOGFIRE_INSTANCE.log_slow_async_callbacks | ||
install_auto_tracing = DEFAULT_LOGFIRE_INSTANCE.install_auto_tracing | ||
instrument = DEFAULT_LOGFIRE_INSTANCE.instrument | ||
instrument_fastapi = DEFAULT_LOGFIRE_INSTANCE.instrument_fastapi | ||
instrument_openai = DEFAULT_LOGFIRE_INSTANCE.instrument_openai | ||
instrument_anthropic = DEFAULT_LOGFIRE_INSTANCE.instrument_anthropic | ||
instrument_asyncpg = DEFAULT_LOGFIRE_INSTANCE.instrument_asyncpg | ||
instrument_httpx = DEFAULT_LOGFIRE_INSTANCE.instrument_httpx | ||
instrument_requests = DEFAULT_LOGFIRE_INSTANCE.instrument_requests | ||
instrument_psycopg = DEFAULT_LOGFIRE_INSTANCE.instrument_psycopg | ||
instrument_django = DEFAULT_LOGFIRE_INSTANCE.instrument_django | ||
instrument_flask = DEFAULT_LOGFIRE_INSTANCE.instrument_flask | ||
instrument_starlette = DEFAULT_LOGFIRE_INSTANCE.instrument_starlette | ||
instrument_aiohttp_client = DEFAULT_LOGFIRE_INSTANCE.instrument_aiohttp_client | ||
instrument_sqlalchemy = DEFAULT_LOGFIRE_INSTANCE.instrument_sqlalchemy | ||
instrument_redis = DEFAULT_LOGFIRE_INSTANCE.instrument_redis | ||
instrument_pymongo = DEFAULT_LOGFIRE_INSTANCE.instrument_pymongo | ||
shutdown = DEFAULT_LOGFIRE_INSTANCE.shutdown | ||
|
||
def no_auto_trace(x): | ||
return x | ||
|
||
@contextmanager | ||
def suppress_instrumentation(): | ||
yield | ||
|
||
class ConsoleOptions: | ||
def __init__(self, *args, **kwargs) -> None: ... | ||
|
||
class TailSamplingOptions: | ||
def __init__(self, *args, **kwargs) -> None: ... | ||
|
||
class ScrubbingOptions: | ||
def __init__(self, *args, **kwargs) -> None: ... | ||
|
||
class PydanticPlugin: | ||
def __init__(self, *args, **kwargs) -> None: ... | ||
|
||
class ScrubMatch: | ||
def __init__(self, *args, **kwargs) -> None: ... | ||
|
||
class AutoTraceModule: | ||
def __init__(self, *args, **kwargs) -> None: ... | ||
|
||
class StructlogProcessor: | ||
def __init__(self, *args, **kwargs) -> None: ... | ||
|
||
class LogfireLoggingHandler: | ||
def __init__(self, *args, **kwargs) -> None: ... | ||
|
||
def load_spans_from_file(*args, **kwargs): | ||
return [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
from ._internal.auto_trace import AutoTraceModule as AutoTraceModule | ||
from ._internal.auto_trace.rewrite_ast import no_auto_trace as no_auto_trace | ||
from ._internal.config import ConsoleOptions as ConsoleOptions, METRICS_PREFERRED_TEMPORALITY as METRICS_PREFERRED_TEMPORALITY, PydanticPlugin as PydanticPlugin, configure as configure | ||
from ._internal.constants import LevelName as LevelName | ||
from ._internal.exporters.file import load_file as load_spans_from_file | ||
from ._internal.exporters.tail_sampling import TailSamplingOptions as TailSamplingOptions | ||
from ._internal.main import Logfire as Logfire, LogfireSpan as LogfireSpan | ||
from ._internal.scrubbing import ScrubMatch as ScrubMatch, ScrubbingOptions as ScrubbingOptions | ||
from ._internal.utils import suppress_instrumentation as suppress_instrumentation | ||
from .integrations.logging import LogfireLoggingHandler as LogfireLoggingHandler | ||
from .integrations.structlog import LogfireProcessor as StructlogProcessor | ||
from .version import VERSION as VERSION | ||
|
||
__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'] | ||
|
||
DEFAULT_LOGFIRE_INSTANCE = Logfire() | ||
span = DEFAULT_LOGFIRE_INSTANCE.span | ||
instrument = DEFAULT_LOGFIRE_INSTANCE.instrument | ||
force_flush = DEFAULT_LOGFIRE_INSTANCE.force_flush | ||
log_slow_async_callbacks = DEFAULT_LOGFIRE_INSTANCE.log_slow_async_callbacks | ||
install_auto_tracing = DEFAULT_LOGFIRE_INSTANCE.install_auto_tracing | ||
instrument_fastapi = DEFAULT_LOGFIRE_INSTANCE.instrument_fastapi | ||
instrument_openai = DEFAULT_LOGFIRE_INSTANCE.instrument_openai | ||
instrument_anthropic = DEFAULT_LOGFIRE_INSTANCE.instrument_anthropic | ||
instrument_asyncpg = DEFAULT_LOGFIRE_INSTANCE.instrument_asyncpg | ||
instrument_httpx = DEFAULT_LOGFIRE_INSTANCE.instrument_httpx | ||
instrument_requests = DEFAULT_LOGFIRE_INSTANCE.instrument_requests | ||
instrument_psycopg = DEFAULT_LOGFIRE_INSTANCE.instrument_psycopg | ||
instrument_django = DEFAULT_LOGFIRE_INSTANCE.instrument_django | ||
instrument_flask = DEFAULT_LOGFIRE_INSTANCE.instrument_flask | ||
instrument_starlette = DEFAULT_LOGFIRE_INSTANCE.instrument_starlette | ||
instrument_aiohttp_client = DEFAULT_LOGFIRE_INSTANCE.instrument_aiohttp_client | ||
instrument_sqlalchemy = DEFAULT_LOGFIRE_INSTANCE.instrument_sqlalchemy | ||
instrument_redis = DEFAULT_LOGFIRE_INSTANCE.instrument_redis | ||
instrument_pymongo = DEFAULT_LOGFIRE_INSTANCE.instrument_pymongo | ||
shutdown = DEFAULT_LOGFIRE_INSTANCE.shutdown | ||
with_tags = DEFAULT_LOGFIRE_INSTANCE.with_tags | ||
with_settings = DEFAULT_LOGFIRE_INSTANCE.with_settings | ||
log = DEFAULT_LOGFIRE_INSTANCE.log | ||
trace = DEFAULT_LOGFIRE_INSTANCE.trace | ||
debug = DEFAULT_LOGFIRE_INSTANCE.debug | ||
info = DEFAULT_LOGFIRE_INSTANCE.info | ||
notice = DEFAULT_LOGFIRE_INSTANCE.notice | ||
warn = DEFAULT_LOGFIRE_INSTANCE.warn | ||
error = DEFAULT_LOGFIRE_INSTANCE.error | ||
fatal = DEFAULT_LOGFIRE_INSTANCE.fatal | ||
__version__ = VERSION |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import ast | ||
from .constants import ATTRIBUTES_MESSAGE_TEMPLATE_KEY as ATTRIBUTES_MESSAGE_TEMPLATE_KEY, ATTRIBUTES_SAMPLE_RATE_KEY as ATTRIBUTES_SAMPLE_RATE_KEY, ATTRIBUTES_TAGS_KEY as ATTRIBUTES_TAGS_KEY | ||
from .stack_info import StackInfo as StackInfo, get_filepath_attribute as get_filepath_attribute | ||
from .utils import uniquify_sequence as uniquify_sequence | ||
from dataclasses import dataclass | ||
from opentelemetry.util import types as otel_types | ||
|
||
@dataclass(frozen=True) | ||
class LogfireArgs: | ||
"""Values passed to `logfire.instrument` and/or values stored in a logfire instance as basic configuration. | ||
|
||
These determine the arguments passed to the method calls added by the AST transformer. | ||
""" | ||
tags: tuple[str, ...] | ||
sample_rate: float | None | ||
msg_template: str | None = ... | ||
span_name: str | None = ... | ||
extract_args: bool = ... | ||
|
||
@dataclass | ||
class BaseTransformer(ast.NodeTransformer): | ||
"""Helper for rewriting ASTs to wrap function bodies in `with {logfire_method_name}(...):`.""" | ||
logfire_args: LogfireArgs | ||
logfire_method_name: str | ||
filename: str | ||
module_name: str | ||
qualname_stack = ... | ||
def __post_init__(self) -> None: ... | ||
def visit_ClassDef(self, node: ast.ClassDef): ... | ||
def visit_FunctionDef(self, node: ast.FunctionDef | ast.AsyncFunctionDef): ... | ||
def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef): ... | ||
def rewrite_function(self, node: ast.FunctionDef | ast.AsyncFunctionDef, qualname: str) -> ast.AST: ... | ||
def logfire_method_call_node(self, node: ast.FunctionDef | ast.AsyncFunctionDef, qualname: str) -> ast.Call: ... | ||
def logfire_method_arg_values(self, qualname: str, lineno: int) -> tuple[str, dict[str, otel_types.AttributeValue]]: ... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from .constants import ONE_SECOND_IN_NANOSECONDS as ONE_SECOND_IN_NANOSECONDS | ||
from .main import Logfire as Logfire | ||
from .stack_info import StackInfo as StackInfo, get_code_object_info as get_code_object_info, get_stack_info_from_frame as get_stack_info_from_frame | ||
from .utils import safe_repr as safe_repr | ||
from _typeshed import Incomplete | ||
from types import CoroutineType | ||
from typing import Any, ContextManager | ||
|
||
ASYNCIO_PATH: Incomplete | ||
|
||
def log_slow_callbacks(logfire: Logfire, slow_duration: float) -> ContextManager[None]: | ||
"""Log a warning whenever a function running in the asyncio event loop blocks for too long. | ||
|
||
See Logfire.log_slow_async_callbacks. | ||
Inspired by https://gitlab.com/quantlane/libs/aiodebug. | ||
""" | ||
|
||
class _CallbackAttributes(StackInfo, total=False): | ||
name: str | ||
stack: list[StackInfo] | ||
|
||
def stack_info_from_coroutine(coro: CoroutineType[Any, Any, Any]) -> StackInfo: ... |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've created the publisher... Not sure if this works.