logfire-api 4.41.0__tar.gz → 5.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. {logfire_api-4.41.0 → logfire_api-5.0.0}/PKG-INFO +1 -1
  2. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/__init__.py +2 -1
  3. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/cli/__init__.pyi +2 -0
  4. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/config.pyi +7 -9
  5. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/exporters/otlp.pyi +6 -4
  6. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/forwarding.pyi +20 -1
  7. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/flask.pyi +0 -1
  8. logfire_api-5.0.0/logfire_api/_internal/integrations/google_genai.pyi +12 -0
  9. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/openai_agents.pyi +4 -3
  10. logfire_api-5.0.0/logfire_api/_internal/interactive.pyi +53 -0
  11. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/main.pyi +28 -24
  12. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/stack_info.pyi +12 -4
  13. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/utils.pyi +8 -0
  14. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/db_api.pyi +39 -12
  15. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/experimental/api_client.pyi +6 -6
  16. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/integrations/pydantic.pyi +1 -0
  17. logfire_api-5.0.0/logfire_api/query_client.pyi +184 -0
  18. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/sampling/_tail_sampling.pyi +4 -0
  19. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/variables/abstract.pyi +6 -6
  20. {logfire_api-4.41.0 → logfire_api-5.0.0}/pyproject.toml +1 -1
  21. logfire_api-4.41.0/logfire_api/_internal/integrations/google_genai.pyi +0 -29
  22. logfire_api-4.41.0/logfire_api/_internal/interactive.pyi +0 -26
  23. logfire_api-4.41.0/logfire_api/experimental/forwarding.pyi +0 -25
  24. logfire_api-4.41.0/logfire_api/query_client.pyi +0 -3
  25. {logfire_api-4.41.0 → logfire_api-5.0.0}/.gitignore +0 -0
  26. {logfire_api-4.41.0 → logfire_api-5.0.0}/README.md +0 -0
  27. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/__init__.pyi +0 -0
  28. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/__init__.pyi +0 -0
  29. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/ast_utils.pyi +0 -0
  30. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/async_.pyi +0 -0
  31. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/auth.pyi +0 -0
  32. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/auto_trace/__init__.pyi +0 -0
  33. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/auto_trace/import_hook.pyi +0 -0
  34. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/auto_trace/rewrite_ast.pyi +0 -0
  35. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/auto_trace/types.pyi +0 -0
  36. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/baggage.pyi +0 -0
  37. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/cli/ai_tools.pyi +0 -0
  38. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/cli/auth.pyi +0 -0
  39. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/cli/gateway.pyi +0 -0
  40. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/cli/gateway_auth.pyi +0 -0
  41. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/cli/prompt.pyi +0 -0
  42. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/cli/run.pyi +0 -0
  43. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/cli.pyi +0 -0
  44. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/client.pyi +0 -0
  45. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/collect_system_info.pyi +0 -0
  46. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/config_params.pyi +0 -0
  47. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/constants.pyi +0 -0
  48. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/db_statement_summary.pyi +0 -0
  49. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/exporters/__init__.pyi +0 -0
  50. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/exporters/console.pyi +0 -0
  51. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/exporters/dynamic_batch.pyi +0 -0
  52. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/exporters/logs.pyi +0 -0
  53. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/exporters/processor_wrapper.pyi +0 -0
  54. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/exporters/quiet_metrics.pyi +0 -0
  55. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/exporters/remove_pending.pyi +0 -0
  56. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/exporters/tail_sampling.pyi +0 -0
  57. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/exporters/wrapper.pyi +0 -0
  58. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/formatter.pyi +0 -0
  59. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/instrument.pyi +0 -0
  60. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/__init__.pyi +0 -0
  61. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/aiohttp_client.pyi +0 -0
  62. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/aiohttp_server.pyi +0 -0
  63. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/asgi.pyi +0 -0
  64. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/asyncpg.pyi +0 -0
  65. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/aws_lambda.pyi +0 -0
  66. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/celery.pyi +0 -0
  67. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/claude_agent_sdk.pyi +0 -0
  68. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/django.pyi +0 -0
  69. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/dspy.pyi +0 -0
  70. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/executors.pyi +0 -0
  71. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/fastapi.pyi +0 -0
  72. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/httpx.pyi +0 -0
  73. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/litellm.pyi +0 -0
  74. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/mcp.pyi +0 -0
  75. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/mysql.pyi +0 -0
  76. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/print.pyi +0 -0
  77. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/psycopg.pyi +0 -0
  78. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/pydantic_ai.pyi +0 -0
  79. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/pymongo.pyi +0 -0
  80. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/pytest.pyi +0 -0
  81. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/redis.pyi +0 -0
  82. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/requests.pyi +0 -0
  83. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/sqlalchemy.pyi +0 -0
  84. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/sqlite3.pyi +0 -0
  85. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/starlette.pyi +0 -0
  86. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/surrealdb.pyi +0 -0
  87. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/system_metrics.pyi +0 -0
  88. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/integrations/wsgi.pyi +0 -0
  89. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/json_encoder.pyi +0 -0
  90. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/json_formatter.pyi +0 -0
  91. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/json_schema.pyi +0 -0
  92. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/json_types.pyi +0 -0
  93. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/logs.pyi +0 -0
  94. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/metrics.pyi +0 -0
  95. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/scrubbing.pyi +0 -0
  96. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/server_response.pyi +0 -0
  97. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/tracer.pyi +0 -0
  98. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/_internal/ulid.pyi +0 -0
  99. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/cli.pyi +0 -0
  100. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/exceptions.pyi +0 -0
  101. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/experimental/__init__.pyi +0 -0
  102. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/experimental/annotations.pyi +0 -0
  103. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/experimental/datasets/__init__.pyi +0 -0
  104. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/experimental/query_client.pyi +0 -0
  105. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/integrations/__init__.pyi +0 -0
  106. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/integrations/aiohttp_client.pyi +0 -0
  107. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/integrations/flask.pyi +0 -0
  108. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/integrations/httpx.pyi +0 -0
  109. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/integrations/logging.pyi +0 -0
  110. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/integrations/loguru.pyi +0 -0
  111. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/integrations/psycopg.pyi +0 -0
  112. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/integrations/redis.pyi +0 -0
  113. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/integrations/sqlalchemy.pyi +0 -0
  114. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/integrations/structlog.pyi +0 -0
  115. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/integrations/wsgi.pyi +0 -0
  116. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/propagate.pyi +0 -0
  117. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/py.typed +0 -0
  118. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/sampling/__init__.pyi +0 -0
  119. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/types.pyi +0 -0
  120. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/variables/__init__.pyi +0 -0
  121. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/variables/_handlebars.pyi +0 -0
  122. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/variables/composition.pyi +0 -0
  123. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/variables/config.pyi +0 -0
  124. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/variables/local.pyi +0 -0
  125. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/variables/remote.pyi +0 -0
  126. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/variables/template_validation.pyi +0 -0
  127. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/variables/variable.pyi +0 -0
  128. {logfire_api-4.41.0 → logfire_api-5.0.0}/logfire_api/version.pyi +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: logfire-api
3
- Version: 4.41.0
3
+ Version: 5.0.0
4
4
  Summary: Shim for the Logfire SDK which does nothing unless Logfire is installed
5
5
  Author-email: Pydantic Team <engineering@pydantic.dev>, Samuel Colvin <samuel@pydantic.dev>, Hasan Ramezani <hasan@pydantic.dev>, Adrian Garcia Badaracco <adrian@pydantic.dev>, David Montague <david@pydantic.dev>, Marcelo Trylesinski <marcelo@pydantic.dev>, David Hewitt <david.hewitt@pydantic.dev>, Alex Hall <alex@pydantic.dev>
6
6
  License-Expression: MIT
@@ -124,7 +124,8 @@ except ImportError:
124
124
  def with_settings(self, *args, **kwargs) -> Logfire:
125
125
  return self
126
126
 
127
- def force_flush(self, *args, **kwargs) -> None: ...
127
+ def force_flush(self, *args, **kwargs) -> bool:
128
+ return True
128
129
 
129
130
  def log_slow_async_callbacks(self, *args, **kwargs) -> None: # pragma: no cover
130
131
  return nullcontext()
@@ -7,6 +7,8 @@ __all__ = ['main', 'logfire_info']
7
7
  class SavedReadToken(NamedTuple):
8
8
  token: str
9
9
  base_url: str
10
+ organization: str
11
+ project_name: str
10
12
 
11
13
  def logfire_info() -> str:
12
14
  """Show versions of logfire, OS and related packages."""
@@ -16,7 +16,7 @@ from .exporters.remove_pending import RemovePendingSpansExporter as RemovePendin
16
16
  from .exporters.test import TestExporter as TestExporter
17
17
  from .forwarding import OTLPForwardingManager as OTLPForwardingManager
18
18
  from .integrations.executors import instrument_executors as instrument_executors
19
- from .interactive import require_answer as require_answer
19
+ from .interactive import ask_or_default as ask_or_default, ask_required as ask_required, require_answer as require_answer
20
20
  from .logs import ProxyLoggerProvider as ProxyLoggerProvider
21
21
  from .main import Logfire as Logfire
22
22
  from .metrics import ProxyMeterProvider as ProxyMeterProvider
@@ -24,7 +24,7 @@ from .scrubbing import BaseScrubber as BaseScrubber, NOOP_SCRUBBER as NOOP_SCRUB
24
24
  from .server_response import ServerResponseCallback as ServerResponseCallback, install_logfire_response_hook as install_logfire_response_hook
25
25
  from .stack_info import warn_at_user_stacklevel as warn_at_user_stacklevel
26
26
  from .tracer import OPEN_SPANS as OPEN_SPANS, PendingSpanProcessor as PendingSpanProcessor, ProxyTracerProvider as ProxyTracerProvider
27
- from .utils import SeededRandomIdGenerator as SeededRandomIdGenerator, ensure_data_dir_exists as ensure_data_dir_exists, handle_internal_errors as handle_internal_errors, platform_is_emscripten as platform_is_emscripten, suppress_instrumentation as suppress_instrumentation
27
+ from .utils import SeededRandomIdGenerator as SeededRandomIdGenerator, ensure_data_dir_exists as ensure_data_dir_exists, handle_internal_errors as handle_internal_errors, platform_is_aws_lambda as platform_is_aws_lambda, platform_is_emscripten as platform_is_emscripten, suppress_instrumentation as suppress_instrumentation
28
28
  from _typeshed import Incomplete
29
29
  from collections.abc import Callable, Mapping, Sequence
30
30
  from dataclasses import dataclass, field
@@ -46,8 +46,8 @@ from opentelemetry.sdk.resources import ResourceDetector
46
46
  from opentelemetry.sdk.trace import SpanProcessor
47
47
  from opentelemetry.sdk.trace.id_generator import IdGenerator
48
48
  from pathlib import Path
49
- from typing import Any, ClassVar, Literal, TextIO, TypedDict
50
- from typing_extensions import Self, Unpack
49
+ from typing import Any, ClassVar, Literal, TextIO
50
+ from typing_extensions import Self
51
51
 
52
52
  CREDENTIALS_FILENAME: str
53
53
  COMMON_REQUEST_HEADERS: Incomplete
@@ -140,9 +140,7 @@ class LocalVariablesOptions:
140
140
  instrument: bool = ...
141
141
  template_mismatch_policy: TemplateMismatchPolicy = ...
142
142
 
143
- class DeprecatedKwargs(TypedDict): ...
144
-
145
- def configure(*, local: bool = False, send_to_logfire: bool | Literal['if-token-present'] | None = None, token: str | list[str] | None = None, api_key: str | None = None, service_name: str | None = None, service_version: str | None = None, environment: str | None = None, resource_attributes: Mapping[str, Any] | None = None, console: ConsoleOptions | Literal[False] | None = None, config_dir: Path | str | None = None, data_dir: Path | str | None = None, additional_span_processors: Sequence[SpanProcessor] | None = None, metrics: MetricsOptions | Literal[False] | None = None, scrubbing: ScrubbingOptions | Literal[False] | None = None, inspect_arguments: bool | None = None, sampling: SamplingOptions | None = None, min_level: int | LevelName | None = None, add_baggage_to_attributes: bool = True, code_source: CodeSource | None = None, variables: VariablesOptions | LocalVariablesOptions | None = None, distributed_tracing: bool | None = None, advanced: AdvancedOptions | None = None, **deprecated_kwargs: Unpack[DeprecatedKwargs]) -> Logfire:
143
+ def configure(*, local: bool = False, send_to_logfire: bool | Literal['if-token-present'] | None = None, token: str | list[str] | None = None, api_key: str | None = None, service_name: str | None = None, service_version: str | None = None, environment: str | None = None, resource_attributes: Mapping[str, Any] | None = None, console: ConsoleOptions | Literal[False] | None = None, config_dir: Path | str | None = None, data_dir: Path | str | None = None, additional_span_processors: Sequence[SpanProcessor] | None = None, metrics: MetricsOptions | Literal[False] | None = None, scrubbing: ScrubbingOptions | Literal[False] | None = None, inspect_arguments: bool | None = None, sampling: SamplingOptions | None = None, min_level: int | LevelName | None = None, add_baggage_to_attributes: bool = True, code_source: CodeSource | None = None, variables: VariablesOptions | LocalVariablesOptions | None = None, distributed_tracing: bool | None = None, advanced: AdvancedOptions | None = None) -> Logfire:
146
144
  """Configure the logfire SDK.
147
145
 
148
146
  Args:
@@ -270,13 +268,13 @@ class LogfireConfig(_LogfireConfigData):
270
268
  def initialize(self) -> None:
271
269
  """Configure internals to start exporting traces and metrics."""
272
270
  def force_flush(self, timeout_millis: int = 30000) -> bool:
273
- """Force flush all spans and metrics.
271
+ """Force flush all telemetry and forwarding pipelines.
274
272
 
275
273
  Args:
276
274
  timeout_millis: The timeout in milliseconds.
277
275
 
278
276
  Returns:
279
- Whether the flush of spans was successful.
277
+ Whether every component that reports a status flushed successfully.
280
278
  """
281
279
  def shutdown(self, timeout_millis: int = 30000, flush: bool = True) -> bool:
282
280
  """Shut down variables, forwarding, traces, logs, and metrics."""
@@ -1,15 +1,17 @@
1
1
  import atexit
2
2
  import requests
3
- from ..constants import HTTP_CONNECT_TIMEOUT as HTTP_CONNECT_TIMEOUT
4
- from ..utils import logger as logger, platform_is_emscripten as platform_is_emscripten
3
+ from ..constants import ATTRIBUTES_MESSAGE_KEY as ATTRIBUTES_MESSAGE_KEY, ATTRIBUTES_SPAN_TYPE_KEY as ATTRIBUTES_SPAN_TYPE_KEY, HTTP_CONNECT_TIMEOUT as HTTP_CONNECT_TIMEOUT, OTLP_MAX_INT_SIZE as OTLP_MAX_INT_SIZE, log_level_attributes as log_level_attributes
4
+ from ..stack_info import STACK_INFO_KEYS as STACK_INFO_KEYS
5
+ from ..utils import logger as logger, platform_is_emscripten as platform_is_emscripten, truncate_string as truncate_string
5
6
  from .wrapper import WrapperLogExporter as WrapperLogExporter, WrapperSpanExporter as WrapperSpanExporter
6
7
  from _typeshed import Incomplete
7
8
  from collections import deque
8
9
  from collections.abc import Mapping, Sequence
9
10
  from functools import cached_property
11
+ from logfire._internal.utils import handle_internal_errors as handle_internal_errors
10
12
  from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
11
13
  from opentelemetry.sdk._logs import ReadableLogRecord as ReadableLogRecord
12
- from opentelemetry.sdk.trace import ReadableSpan as ReadableSpan
14
+ from opentelemetry.sdk.trace import ReadableSpan
13
15
  from opentelemetry.sdk.trace.export import SpanExportResult
14
16
  from pathlib import Path
15
17
  from requests import Session
@@ -61,7 +63,7 @@ class RetryFewerSpansSpanExporter(WrapperSpanExporter):
61
63
  class BodyTooLargeError(Exception):
62
64
  size: Incomplete
63
65
  max_size: Incomplete
64
- def __init__(self, size: int, max_size: int) -> None: ...
66
+ def __init__(self, size: int, max_size: int | None) -> None: ...
65
67
 
66
68
  class SuppressedConnectionError(Exception): ...
67
69
 
@@ -4,14 +4,16 @@ from collections.abc import Callable as Callable, Mapping, Sequence
4
4
  from dataclasses import dataclass
5
5
  from enum import Enum
6
6
  from logfire._internal.exporters.otlp import OTLPExporterHttpSession as OTLPExporterHttpSession
7
+ from logfire._internal.main import Logfire as Logfire
7
8
  from logfire._internal.server_response import install_logfire_response_hook as install_logfire_response_hook
8
9
  from logfire._internal.utils import suppress_instrumentation as suppress_instrumentation
9
- from logfire.experimental.forwarding import ForwardExportRequestResponse as ForwardExportRequestResponse
10
10
  from logfire.types import ServerResponseCallback as ServerResponseCallback
11
11
  from logfire.version import VERSION as VERSION
12
12
  from opentelemetry.proto.collector.logs.v1.logs_service_pb2 import ExportLogsServiceResponse
13
13
  from opentelemetry.proto.collector.metrics.v1.metrics_service_pb2 import ExportMetricsServiceResponse
14
14
  from opentelemetry.proto.collector.trace.v1.trace_service_pb2 import ExportTraceServiceResponse
15
+ from starlette.requests import Request
16
+ from starlette.responses import Response
15
17
  from threading import Thread
16
18
  from typing import Literal
17
19
 
@@ -48,6 +50,13 @@ class ForwardingErrorResponse:
48
50
  status_code: int
49
51
  content: bytes
50
52
 
53
+ @dataclass
54
+ class ForwardExportRequestResponse:
55
+ """Response returned from a forwarded export request to Logfire."""
56
+ status_code: int
57
+ headers: Mapping[str, str]
58
+ content: bytes
59
+
51
60
  @dataclass(frozen=True)
52
61
  class ForwardingAdmissionResult:
53
62
  response: Literal['success', 'partial_success']
@@ -81,5 +90,15 @@ class OTLPForwardingManager:
81
90
 
82
91
  def parse_forwarding_content_type(content_type: str) -> ForwardingContentType | None: ...
83
92
  def build_forwarding_request(*, path: str, headers: Mapping[str, str], body: bytes, max_body_size: int = ...) -> ForwardingRequest | ForwardingErrorResponse: ...
93
+ def forward_export_request(*, path: str, headers: Mapping[str, str], body: bytes, logfire_instance: Logfire | None = None, max_body_size: int = ...) -> ForwardExportRequestResponse:
94
+ """Forward an export request to the Logfire API.
95
+
96
+ See the Logfire.forward_export_request method for more details.
97
+ """
98
+ async def logfire_proxy(request: Request, *, logfire_instance: Logfire | None = None, max_body_size: int = ...) -> Response:
99
+ """A Starlette/FastAPI handler to proxy requests to Logfire.
100
+
101
+ See the Logfire.forward_export_request_starlette method for more details.
102
+ """
84
103
  def build_success_response(request: ForwardingRequest) -> ForwardExportRequestResponse: ...
85
104
  def build_partial_success_response(request: ForwardingRequest, *, message: str) -> ForwardExportRequestResponse: ...
@@ -1,5 +1,4 @@
1
1
  from flask.app import Flask
2
- from logfire._internal.stack_info import warn_at_user_stacklevel as warn_at_user_stacklevel
3
2
  from logfire._internal.utils import maybe_capture_server_headers as maybe_capture_server_headers
4
3
  from logfire.integrations.flask import CommenterOptions as CommenterOptions, RequestHook as RequestHook, ResponseHook as ResponseHook
5
4
  from typing import Any
@@ -0,0 +1,12 @@
1
+ import logfire
2
+ from _typeshed import Incomplete
3
+ from logfire._internal.utils import safe_repr as safe_repr
4
+ from typing import Any
5
+
6
+ CAPTURE_MESSAGE_CONTENT_ENV_VAR: str
7
+ LEGACY_CAPTURE_MESSAGE_CONTENT_VALUES: Incomplete
8
+ EMIT_EVENT_ENV_VAR: str
9
+ original_flatten_compound_value: Incomplete
10
+
11
+ def wrapped_flatten_compound_value(key: str, value: Any, *args: Any, **kwargs: Any): ...
12
+ def instrument_google_genai(logfire_instance: logfire.Logfire, **kwargs: Any): ...
@@ -7,7 +7,7 @@ from agents.tracing.spans import SpanError, TSpanData
7
7
  from dataclasses import dataclass
8
8
  from logfire import Logfire as Logfire, LogfireSpan as LogfireSpan
9
9
  from logfire._internal.formatter import logfire_format as logfire_format
10
- from logfire._internal.integrations.llm_providers.openai import inputs_to_events as inputs_to_events, responses_output_events as responses_output_events
10
+ from logfire._internal.integrations.llm_providers.openai import get_openai_usage_attributes as get_openai_usage_attributes, inputs_to_events as inputs_to_events, responses_output_events as responses_output_events
11
11
  from logfire._internal.scrubbing import NOOP_SCRUBBER as NOOP_SCRUBBER
12
12
  from logfire._internal.utils import handle_internal_errors as handle_internal_errors, log_internal_error as log_internal_error, truncate_string as truncate_string
13
13
  from openai.types.responses import Response
@@ -29,6 +29,7 @@ class LogfireTraceProviderWrapper:
29
29
  class LogfireSpanHelper:
30
30
  span: LogfireSpan
31
31
  parent: Trace | Span[Any] | None = ...
32
+ openai_cost_provider_url: str | None = ...
32
33
  def start(self, mark_as_current: bool): ...
33
34
  def end(self, reset_current: bool): ...
34
35
  def maybe_detach(self, reset_current: bool): ...
@@ -94,7 +95,7 @@ class LogfireSpanWrapper(LogfireWrapperBase[Span[TSpanData]], Span[TSpanData]):
94
95
  @property
95
96
  def tracing_api_key(self) -> str | None: ...
96
97
 
97
- def attributes_from_span_data(span_data: SpanData, msg_template: str) -> dict[str, Any]: ...
98
+ def attributes_from_span_data(span_data: SpanData, msg_template: str, openai_cost_provider_url: str | None = None) -> dict[str, Any]: ...
98
99
  def get_basic_response_attributes(response: Response): ...
99
- def get_magic_response_attributes() -> dict[str, Any]: ...
100
+ def get_magic_response_attributes() -> tuple[dict[str, Any], str | None]: ...
100
101
  def get_response_span_events(span: ResponseSpanData): ...
@@ -0,0 +1,53 @@
1
+ from collections.abc import Callable
2
+ from logfire.exceptions import LogfireConfigError as LogfireConfigError
3
+ from typing import TypeVar
4
+
5
+ T = TypeVar('T')
6
+
7
+ class NonInteractiveError(LogfireConfigError):
8
+ """A prompt was needed, but nobody could answer it.
9
+
10
+ Carries the guidance the user needs rather than a traceback: the CLI catches this and
11
+ prints `message` before exiting non-zero. Raised either because `--non-interactive`
12
+ said so up front (`require_answer`), or because stdin ran out before an answer arrived
13
+ (`ask_required`) -- the same question/remedy structure either way (only the reason
14
+ line differs), since both mean the same thing to whoever reads it.
15
+ """
16
+
17
+ def set_non_interactive(value: bool) -> None:
18
+ """Record whether prompts are allowed. Called once, from CLI argument parsing."""
19
+ def is_non_interactive() -> bool:
20
+ """Whether the caller declared that it cannot answer prompts."""
21
+ def require_answer(question: str, remedy: str, *more_remedies: str) -> None:
22
+ """Fail instead of prompting, when the caller said it cannot answer.
23
+
24
+ At least one remedy is required by the signature: refusing to prompt while offering no
25
+ way forward just moves the dead end, and telling the caller what to pass is the entire
26
+ value of failing here rather than blocking.
27
+
28
+ Args:
29
+ question: what would have been asked, in plain terms.
30
+ remedy: a runnable suggestion.
31
+ more_remedies: further suggestions. Each is printed on its own line, so each must
32
+ be individually pasteable -- `--org a|b` is a shell pipeline, not a suggestion.
33
+ """
34
+ def ask_or_default(ask: Callable[[], T], default: T) -> T:
35
+ '''Run a prompt, falling back to `default` when stdin runs out before an answer does.
36
+
37
+ Mirrors accepting a blank Enter keypress: the caller already declared what "no answer"
38
+ means by passing this SAME value as the prompt\'s own `default=`, so an exhausted stdin
39
+ reaches the outcome a person pressing Enter would, rather than an `EOFError` traceback.
40
+ Only for prompts where that default is genuinely safe to assume -- see `ask_required`
41
+ for one that has no safe default to fall back on.
42
+ '''
43
+ def ask_required(ask: Callable[[], T], question: str, remedy: str, *more_remedies: str) -> T:
44
+ """Run a prompt that has no safe default, raising if stdin runs out before an answer does.
45
+
46
+ The reactive half of `require_answer`'s proactive check: that covers a caller who
47
+ declared `--non-interactive` up front, this covers one that did not but ran out of
48
+ input anyway -- a command copied out of the docs into an agent, mid-conversation.
49
+ Raises the same `NonInteractiveError` structure `require_answer` would -- question,
50
+ then reason, then remedies -- with a reason line naming stdin instead of the flag,
51
+ since both mean the same thing to whoever reads it: there was no answer, and here is
52
+ how to supply one.
53
+ """
@@ -7,7 +7,6 @@ import pydantic_ai
7
7
  import pydantic_ai.models
8
8
  import requests
9
9
  from . import async_ as async_
10
- from ..experimental.forwarding import ForwardExportRequestResponse as ForwardExportRequestResponse
11
10
  from ..integrations.aiohttp_client import RequestHook as AiohttpClientRequestHook, ResponseHook as AiohttpClientResponseHook
12
11
  from ..integrations.flask import CommenterOptions as FlaskCommenterOptions, RequestHook as FlaskRequestHook, ResponseHook as FlaskResponseHook
13
12
  from ..integrations.httpx import AsyncRequestHook as HttpxAsyncRequestHook, AsyncResponseHook as HttpxAsyncResponseHook, RequestHook as HttpxRequestHook, ResponseHook as HttpxResponseHook
@@ -22,6 +21,7 @@ from .config import GLOBAL_CONFIG as GLOBAL_CONFIG, LogfireConfig as LogfireConf
22
21
  from .config_params import PydanticPluginRecordValues as PydanticPluginRecordValues
23
22
  from .constants import ATTRIBUTES_JSON_SCHEMA_KEY as ATTRIBUTES_JSON_SCHEMA_KEY, ATTRIBUTES_LOG_LEVEL_NUM_KEY as ATTRIBUTES_LOG_LEVEL_NUM_KEY, ATTRIBUTES_MESSAGE_KEY as ATTRIBUTES_MESSAGE_KEY, ATTRIBUTES_MESSAGE_TEMPLATE_KEY as ATTRIBUTES_MESSAGE_TEMPLATE_KEY, ATTRIBUTES_SAMPLE_RATE_KEY as ATTRIBUTES_SAMPLE_RATE_KEY, ATTRIBUTES_SPAN_TYPE_KEY as ATTRIBUTES_SPAN_TYPE_KEY, ATTRIBUTES_TAGS_KEY as ATTRIBUTES_TAGS_KEY, DISABLE_CONSOLE_KEY as DISABLE_CONSOLE_KEY, LEVEL_NUMBERS as LEVEL_NUMBERS, LevelName as LevelName, OTLP_MAX_INT_SIZE as OTLP_MAX_INT_SIZE, log_level_attributes as log_level_attributes
24
23
  from .formatter import logfire_format as logfire_format, logfire_format_with_magic as logfire_format_with_magic
24
+ from .forwarding import ForwardExportRequestResponse as ForwardExportRequestResponse
25
25
  from .instrument import instrument as instrument
26
26
  from .integrations.asgi import ASGIApp as ASGIApp, ASGIInstrumentKwargs as ASGIInstrumentKwargs
27
27
  from .integrations.aws_lambda import LambdaEvent as LambdaEvent, LambdaHandler as LambdaHandler
@@ -367,13 +367,13 @@ class Logfire:
367
367
  A new Logfire instance with the given settings applied.
368
368
  """
369
369
  def force_flush(self, timeout_millis: int = 3000) -> bool:
370
- """Force flush all spans and metrics.
370
+ """Force flush all telemetry and forwarding pipelines.
371
371
 
372
372
  Args:
373
373
  timeout_millis: The timeout in milliseconds.
374
374
 
375
375
  Returns:
376
- Whether the flush of spans was successful.
376
+ Whether every component that reports a status flushed successfully.
377
377
  """
378
378
  def url_from_eval(self, report: EvaluationReport[Any, Any, Any]) -> str | None:
379
379
  """Generate a Logfire URL to view an evaluation report.
@@ -478,8 +478,10 @@ class Logfire:
478
478
  - `off`: Disable instrumentation.
479
479
  include:
480
480
  By default, third party modules are not instrumented. This option allows you to include specific modules.
481
+ Each entry is a regular expression matched against `module::ModelName` and anchored at the end,
482
+ so use e.g. `openai.*` rather than `openai`, which would only match a model named `openai`.
481
483
  exclude:
482
- Exclude specific modules from instrumentation.
484
+ Exclude specific modules from instrumentation. Matched the same way as `include`.
483
485
  """
484
486
  @overload
485
487
  def instrument_pydantic_ai(self, obj: pydantic_ai.Agent | None = None, /, *, include_binary_content: bool | None = None, include_content: bool | None = None, version: Literal[1, 2, 3, 4, 5] | None = None, event_mode: Literal['attributes', 'logs'] | None = None, **kwargs: Any) -> None: ...
@@ -528,7 +530,7 @@ class Logfire:
528
530
  without waiting for the context manager to be opened,
529
531
  i.e. it's not necessary to use this as a context manager.
530
532
  """
531
- def instrument_openai(self, openai_client: openai.OpenAI | openai.AsyncOpenAI | type[openai.OpenAI] | type[openai.AsyncOpenAI] | None = None, *, suppress_other_instrumentation: bool = True, version: SemconvVersion | Sequence[SemconvVersion] = 1) -> AbstractContextManager[None]:
533
+ def instrument_openai(self, openai_client: openai.OpenAI | openai.AsyncOpenAI | type[openai.OpenAI] | type[openai.AsyncOpenAI] | None = None, *, suppress_other_instrumentation: bool = True, version: SemconvVersion | Sequence[SemconvVersion] = 2) -> AbstractContextManager[None]:
532
534
  '''Instrument an OpenAI client so that spans are automatically created for each request.
533
535
 
534
536
  This instruments the [standard OpenAI SDK](https://pypi.org/project/openai/) package, for instrumentation
@@ -579,14 +581,15 @@ class Logfire:
579
581
 
580
582
  version: The version(s) of the span attribute format to use:
581
583
 
582
- - `1` (the default): Uses `request_data` and `response_data` attributes.
583
- - `\'latest\'`: Uses OpenTelemetry Gen AI semantic convention attributes
584
+ - `1`: Uses the legacy `request_data` and `response_data` attributes.
585
+ - `2` (the default): Uses OpenTelemetry Gen AI semantic convention attributes
584
586
  (`gen_ai.input.messages`, `gen_ai.output.messages`, etc.) and omits the full
585
587
  `response_data` attribute. A minimal `request_data` (e.g. `{"model": ...}`) is
586
- still recorded for message template compatibility. This format may change between
587
- releases.
588
- - `[1, \'latest\']`: Emits both the full legacy attributes and the semantic convention
589
- attributes simultaneously, useful for migration and testing.
588
+ still recorded for message template compatibility.
589
+ - `\'latest\'`: Uses the latest format, which is currently identical to version 2.
590
+ Unlike a numbered version, this format may change between releases.
591
+ - `[1, 2]` or `[1, \'latest\']`: Emits both the full legacy attributes and the semantic
592
+ convention attributes simultaneously, useful for migration and testing.
590
593
 
591
594
  Returns:
592
595
  A context manager that will revert the instrumentation when exited.
@@ -598,7 +601,7 @@ class Logfire:
598
601
  For instrumentation of the standard OpenAI SDK package,
599
602
  see [`instrument_openai()`][logfire.Logfire.instrument_openai].
600
603
  """
601
- def instrument_anthropic(self, anthropic_client: anthropic.Anthropic | anthropic.AsyncAnthropic | _AnthropicBedrock | _AsyncAnthropicBedrock | type[anthropic.Anthropic] | type[anthropic.AsyncAnthropic] | type[_AnthropicBedrock] | type[_AsyncAnthropicBedrock] | None = None, *, suppress_other_instrumentation: bool = True, version: SemconvVersion | Sequence[SemconvVersion] = 1) -> AbstractContextManager[None]:
604
+ def instrument_anthropic(self, anthropic_client: anthropic.Anthropic | anthropic.AsyncAnthropic | _AnthropicBedrock | _AsyncAnthropicBedrock | type[anthropic.Anthropic] | type[anthropic.AsyncAnthropic] | type[_AnthropicBedrock] | type[_AsyncAnthropicBedrock] | None = None, *, suppress_other_instrumentation: bool = True, version: SemconvVersion | Sequence[SemconvVersion] = 2) -> AbstractContextManager[None]:
602
605
  '''Instrument an Anthropic client so that spans are automatically created for each request.
603
606
 
604
607
  The following methods are instrumented for both the sync and async clients:
@@ -644,14 +647,15 @@ class Logfire:
644
647
 
645
648
  version: The version(s) of the span attribute format to use:
646
649
 
647
- - `1` (the default): Uses `request_data` and `response_data` attributes.
648
- - `\'latest\'`: Uses OpenTelemetry Gen AI semantic convention attributes
650
+ - `1`: Uses the legacy `request_data` and `response_data` attributes.
651
+ - `2` (the default): Uses OpenTelemetry Gen AI semantic convention attributes
649
652
  (`gen_ai.input.messages`, `gen_ai.output.messages`, etc.) and omits the full
650
653
  `response_data` attribute. A minimal `request_data` (e.g. `{"model": ...}`) is
651
- still recorded for message template compatibility. This format may change between
652
- releases.
653
- - `[1, \'latest\']`: Emits both the full legacy attributes and the semantic convention
654
- attributes simultaneously, useful for migration and testing.
654
+ still recorded for message template compatibility.
655
+ - `\'latest\'`: Uses the latest format, which is currently identical to version 2.
656
+ Unlike a numbered version, this format may change between releases.
657
+ - `[1, 2]` or `[1, \'latest\']`: Emits both the full legacy attributes and the semantic
658
+ convention attributes simultaneously, useful for migration and testing.
655
659
 
656
660
  Returns:
657
661
  A context manager that will revert the instrumentation when exited.
@@ -662,7 +666,7 @@ class Logfire:
662
666
 
663
667
  !!! note
664
668
  To capture message contents (i.e. prompts and completions), set the environment variable
665
- `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT` to `true`.
669
+ `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT` to `SPAN_ONLY`.
666
670
 
667
671
  Uses the `GoogleGenAiSdkInstrumentor().instrument()` method of the
668
672
  [`opentelemetry-instrumentation-google-genai`](https://pypi.org/project/opentelemetry-instrumentation-google-genai/)
@@ -1231,7 +1235,7 @@ class Logfire:
1231
1235
  """
1232
1236
  def variables_get(self) -> list[Variable[Any] | TemplateVariable[Any, Any]]:
1233
1237
  """Get all variables registered with this Logfire instance's config."""
1234
- def variables_push(self, variables: list[Variable[Any] | TemplateVariable[Any, Any]] | None = None, *, dry_run: bool = False, yes: bool = False, strict: bool = False) -> bool:
1238
+ def variables_push(self, variables: list[Variable[Any] | TemplateVariable[Any, Any]] | None = None, *, dry_run: bool = False, yes: bool = False, strict: bool = True) -> bool:
1235
1239
  """Push variable definitions (metadata only) to the configured variable provider.
1236
1240
 
1237
1241
  This method syncs local variable definitions with the provider:
@@ -1248,8 +1252,8 @@ class Logfire:
1248
1252
  variables registered on `with_settings()` siblings.
1249
1253
  dry_run: If True, only show what would change without applying.
1250
1254
  yes: If True, skip confirmation prompt.
1251
- strict: If True, fail if any existing label values are incompatible with new schemas
1252
- or any reference errors are found.
1255
+ strict: If True, fail on incompatible label values, missing references, or template-field issues.
1256
+ Set to False to publish despite those issues. Reference cycles always block the push.
1253
1257
 
1254
1258
  Returns:
1255
1259
  True if changes were applied (or would be applied in dry_run mode), False otherwise.
@@ -1269,7 +1273,7 @@ class Logfire:
1269
1273
  logfire.variables_push([feature_enabled])
1270
1274
  ```
1271
1275
  """
1272
- def variables_push_types(self, types: Sequence[type[Any] | tuple[type[Any], str]], *, dry_run: bool = False, yes: bool = False, strict: bool = False) -> bool:
1276
+ def variables_push_types(self, types: Sequence[type[Any] | tuple[type[Any], str]], *, dry_run: bool = False, yes: bool = False, strict: bool = True) -> bool:
1273
1277
  """Push variable type definitions to the configured variable provider.
1274
1278
 
1275
1279
  Variable types are reusable schema definitions that can be referenced by variables.
@@ -1291,7 +1295,7 @@ class Logfire:
1291
1295
  dry_run: If True, only show what would change without applying.
1292
1296
  yes: If True, skip confirmation prompt.
1293
1297
  strict: If True, abort when existing label values are incompatible with
1294
- the new type schema.
1298
+ the new type schema. Set to False to publish despite these issues.
1295
1299
 
1296
1300
  Returns:
1297
1301
  True if changes were applied (or would be applied in dry_run mode), False otherwise.
@@ -10,7 +10,11 @@ NON_USER_CODE_PREFIXES: tuple[str, ...]
10
10
  def add_non_user_code_prefix(path: str | Path) -> None:
11
11
  """Add a path to the list of prefixes that are considered non-user code.
12
12
 
13
- This prevents the stack info from including frames from the given path.
13
+ This has two effects for code under the given path:
14
+
15
+ - Its frames are left out of the stack info recorded on spans and logs.
16
+ - Its pydantic models aren't instrumented by `logfire.instrument_pydantic` unless
17
+ [`include`][logfire.PydanticPlugin.include] names them explicitly.
14
18
 
15
19
  This is for advanced users and shouldn't often be needed.
16
20
  By default, the following prefixes are already included:
@@ -38,14 +42,18 @@ def get_user_frame_and_stacklevel() -> tuple[FrameType | None, int]:
38
42
  See is_user_code for details.
39
43
  Returns `(None, 0)` if no such frame is found.
40
44
  """
45
+ def is_non_user_path(path: str | Path) -> bool:
46
+ """Check if the file path is in a location that doesn't contain user code.
47
+
48
+ Specifically the standard library, site-packages (wherever opentelemetry is installed),
49
+ the logfire package, and anything registered with `add_non_user_code_prefix`.
50
+ """
41
51
  def is_user_code(code: CodeType) -> bool:
42
52
  """Check if the code object is from user code.
43
53
 
44
54
  A code object is not user code if:
45
55
  - It is from a file in
46
- - the standard library
47
- - site-packages (specifically wherever opentelemetry is installed)
48
- - the logfire package
56
+ - a non-user location, see `is_non_user_path`
49
57
  - an unknown location (e.g. a dynamically generated code object) indicated by a filename starting with '<'
50
58
  - It is a list/dict/set comprehension.
51
59
  These are artificial frames only created before Python 3.12,
@@ -132,6 +132,14 @@ def platform_is_emscripten() -> bool:
132
132
 
133
133
  Threads cannot be created on Emscripten, so we need to avoid any code that creates threads.
134
134
  """
135
+ def platform_is_aws_lambda() -> bool:
136
+ """Return True when running inside an AWS Lambda function.
137
+
138
+ Lambda freezes the execution environment between the end of the init phase and the first
139
+ invocation (and between invocations), so background work started during init may be
140
+ interrupted for minutes. `AWS_LAMBDA_FUNCTION_NAME` is set by the runtime in every Lambda
141
+ execution environment.
142
+ """
135
143
  def canonicalize_exception_traceback(exc: BaseException, seen: set[int] | None = None) -> str:
136
144
  """Return a canonical string representation of an exception traceback.
137
145
 
@@ -1,8 +1,12 @@
1
1
  from _typeshed import Incomplete
2
2
  from collections.abc import Sequence
3
3
  from datetime import datetime, timedelta
4
- from logfire.experimental.query_client import ColumnDetails as ColumnDetails, LogfireQueryClient as LogfireQueryClient
5
- from typing import Any, overload
4
+ from enum import Enum
5
+ from logfire.query_client import ColumnDetails as ColumnDetails, LogfireQueryClient as LogfireQueryClient
6
+ from typing import Any
7
+
8
+ class _Unset(Enum):
9
+ UNSET: str
6
10
 
7
11
  apilevel: str
8
12
  threadsafety: int
@@ -33,7 +37,7 @@ class Connection:
33
37
  min_timestamp: Incomplete
34
38
  max_timestamp: Incomplete
35
39
  limit: Incomplete
36
- def __init__(self, client: LogfireQueryClient, *, min_timestamp: datetime | timedelta | None = ..., max_timestamp: datetime | None = None, limit: int = ...) -> None: ...
40
+ def __init__(self, client: LogfireQueryClient, *, min_timestamp: datetime | timedelta = ..., max_timestamp: datetime | None = None, limit: int = ...) -> None: ...
37
41
  def close(self) -> None:
38
42
  """Close the connection and the underlying HTTP client."""
39
43
  def commit(self) -> None:
@@ -49,14 +53,22 @@ class Cursor:
49
53
  """PEP 249 Cursor that executes queries via `LogfireQueryClient.query_json_rows()`."""
50
54
  rowcount: int
51
55
  arraysize: int
52
- max_timestamp: datetime | None
53
- limit: int
54
56
  def __init__(self, connection: Connection) -> None: ...
55
57
  @property
56
- def min_timestamp(self) -> datetime | None:
57
- """Per-cursor override for the lower `start_timestamp` bound."""
58
+ def min_timestamp(self) -> datetime:
59
+ """Lower `start_timestamp` bound, inherited from the connection unless overridden."""
58
60
  @min_timestamp.setter
59
- def min_timestamp(self, value: datetime | None) -> None: ...
61
+ def min_timestamp(self, value: datetime) -> None: ...
62
+ @property
63
+ def max_timestamp(self) -> datetime | None:
64
+ """Upper `start_timestamp` bound, inherited from the connection unless overridden."""
65
+ @max_timestamp.setter
66
+ def max_timestamp(self, value: datetime | None) -> None: ...
67
+ @property
68
+ def limit(self) -> int:
69
+ """Row limit, inherited from the connection unless overridden."""
70
+ @limit.setter
71
+ def limit(self, value: int) -> None: ...
60
72
  @property
61
73
  def description(self) -> list[tuple[Any, ...]] | None:
62
74
  """Column description as a list of 7-tuples per PEP 249.
@@ -92,7 +104,22 @@ class Cursor:
92
104
  def __enter__(self) -> Cursor: ...
93
105
  def __exit__(self, *args: Any) -> None: ...
94
106
 
95
- @overload
96
- def connect(read_token: str, base_url: str | None = None, timeout: float = 30.0, *, min_timestamp: None, max_timestamp: datetime | None = None, limit: int = ..., **kwargs: Any) -> Connection: ...
97
- @overload
98
- def connect(read_token: str, base_url: str | None = None, timeout: float = 30.0, *, min_timestamp: datetime | timedelta = ..., max_timestamp: datetime | None = None, limit: int = ..., **kwargs: Any) -> Connection: ...
107
+ def connect(read_token: str, base_url: str | None = None, timeout: float = 30.0, *, min_timestamp: datetime | timedelta = ..., max_timestamp: datetime | None = None, limit: int = ..., **kwargs: Any) -> Connection:
108
+ """Create a PEP 249 connection to the Logfire query API.
109
+
110
+ Args:
111
+ read_token: A Logfire read token for authentication.
112
+ base_url: Override the default API base URL (inferred from token region).
113
+ timeout: HTTP request timeout in seconds.
114
+ min_timestamp: Default lower bound for `start_timestamp` filtering.
115
+ Accepts a `datetime` for an exact bound, a `timedelta` for a
116
+ relative window (computed as `now - timedelta`). Defaults to 1 day ago.
117
+ max_timestamp: Default upper bound for `start_timestamp` filtering.
118
+ limit: Default row limit per query (max 10,000). When the number of
119
+ returned rows equals the limit a warning is emitted.
120
+ **kwargs: Additional keyword arguments forwarded to the underlying
121
+ `httpx.Client`.
122
+
123
+ Returns:
124
+ A PEP 249 `Connection` object.
125
+ """
@@ -8,8 +8,8 @@ from logfire._internal.stack_info import warn_at_user_stacklevel as warn_at_user
8
8
  from pydantic_evals import Case, Dataset
9
9
  from pydantic_evals.evaluators import Evaluator, ReportEvaluator
10
10
  from types import TracebackType
11
- from typing import Any, Generic, Literal, TypeVar, overload
12
- from typing_extensions import NotRequired, Self, TypedDict
11
+ from typing import Any, Generic, Literal, overload
12
+ from typing_extensions import NotRequired, Self, TypeForm, TypeVar, TypedDict
13
13
  from uuid import UUID
14
14
 
15
15
  Case = Any
@@ -19,8 +19,8 @@ ReportEvaluator = Any
19
19
  DEFAULT_TIMEOUT: Incomplete
20
20
  T = TypeVar('T', bound=BaseClient)
21
21
  InputsT = TypeVar('InputsT')
22
- OutputT = TypeVar('OutputT')
23
- MetadataT = TypeVar('MetadataT')
22
+ OutputT = TypeVar('OutputT', default=Any)
23
+ MetadataT = TypeVar('MetadataT', default=Any)
24
24
  ResponseT = TypeVar('ResponseT')
25
25
 
26
26
  class EvaluatorSpec(TypedDict):
@@ -424,7 +424,7 @@ class LogfireAPIClient(_BaseLogfireAPIClient[Client]):
424
424
  @overload
425
425
  def get_dataset(self, id_or_name: str, *, include_cases: Literal[True] = ...) -> ExportedDataset: ...
426
426
  @overload
427
- def get_dataset(self, id_or_name: str, input_type: type[InputsT], output_type: type[OutputT] | None = None, metadata_type: type[MetadataT] | None = None, *, custom_evaluator_types: Sequence[type[Evaluator[InputsT, OutputT, MetadataT]]] = (), custom_report_evaluator_types: Sequence[type[Any]] = ()) -> Dataset[InputsT, OutputT, MetadataT]: ...
427
+ def get_dataset(self, id_or_name: str, input_type: TypeForm[InputsT], output_type: TypeForm[OutputT] = ..., metadata_type: TypeForm[MetadataT] = ..., *, custom_evaluator_types: Sequence[type[Evaluator[InputsT, OutputT, MetadataT]]] = (), custom_report_evaluator_types: Sequence[type[Any]] = ()) -> Dataset[InputsT, OutputT, MetadataT]: ...
428
428
 
429
429
  class AsyncLogfireAPIClient(_BaseLogfireAPIClient[AsyncClient]):
430
430
  """Asynchronous client for managing Logfire datasets.
@@ -494,4 +494,4 @@ class AsyncLogfireAPIClient(_BaseLogfireAPIClient[AsyncClient]):
494
494
  @overload
495
495
  async def get_dataset(self, id_or_name: str, *, include_cases: Literal[True] = ...) -> ExportedDataset: ...
496
496
  @overload
497
- async def get_dataset(self, id_or_name: str, input_type: type[InputsT], output_type: type[OutputT] | None = None, metadata_type: type[MetadataT] | None = None, *, custom_evaluator_types: Sequence[type[Evaluator[InputsT, OutputT, MetadataT]]] = (), custom_report_evaluator_types: Sequence[type[Any]] = ()) -> Dataset[InputsT, OutputT, MetadataT]: ...
497
+ async def get_dataset(self, id_or_name: str, input_type: TypeForm[InputsT], output_type: TypeForm[OutputT] = ..., metadata_type: TypeForm[MetadataT] = ..., *, custom_evaluator_types: Sequence[type[Evaluator[InputsT, OutputT, MetadataT]]] = (), custom_report_evaluator_types: Sequence[type[Any]] = ()) -> Dataset[InputsT, OutputT, MetadataT]: ...
@@ -1,4 +1,5 @@
1
1
  from .._internal.config import GLOBAL_CONFIG as GLOBAL_CONFIG, PydanticPlugin as PydanticPlugin
2
+ from .._internal.stack_info import is_non_user_path as is_non_user_path
2
3
  from .._internal.utils import get_version as get_version
3
4
  from _typeshed import Incomplete
4
5
  from dataclasses import dataclass