logfire-api 4.33.0__tar.gz → 4.35.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 (124) hide show
  1. {logfire_api-4.33.0 → logfire_api-4.35.0}/PKG-INFO +2 -2
  2. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/__init__.py +18 -10
  3. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/__init__.pyi +3 -1
  4. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/config.pyi +4 -0
  5. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/config_params.pyi +1 -2
  6. logfire_api-4.35.0/logfire_api/_internal/forwarding.pyi +85 -0
  7. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/google_genai.pyi +1 -2
  8. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/pytest.pyi +18 -18
  9. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/system_metrics.pyi +1 -1
  10. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/main.pyi +48 -2
  11. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/tracer.pyi +3 -0
  12. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/db_api.pyi +10 -22
  13. logfire_api-4.35.0/logfire_api/experimental/forwarding.pyi +25 -0
  14. logfire_api-4.35.0/logfire_api/experimental/query_client.pyi +123 -0
  15. logfire_api-4.35.0/logfire_api/query_client.pyi +3 -0
  16. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/variables/__init__.pyi +2 -2
  17. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/variables/abstract.pyi +9 -5
  18. {logfire_api-4.33.0 → logfire_api-4.35.0}/pyproject.toml +2 -2
  19. logfire_api-4.33.0/logfire_api/experimental/forwarding.pyi +0 -42
  20. logfire_api-4.33.0/logfire_api/experimental/query_client.pyi +0 -100
  21. logfire_api-4.33.0/logfire_api/query_client.pyi +0 -1
  22. {logfire_api-4.33.0 → logfire_api-4.35.0}/.gitignore +0 -0
  23. {logfire_api-4.33.0 → logfire_api-4.35.0}/README.md +0 -0
  24. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/__init__.pyi +0 -0
  25. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/ast_utils.pyi +0 -0
  26. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/async_.pyi +0 -0
  27. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/auth.pyi +0 -0
  28. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/auto_trace/__init__.pyi +0 -0
  29. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/auto_trace/import_hook.pyi +0 -0
  30. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/auto_trace/rewrite_ast.pyi +0 -0
  31. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/auto_trace/types.pyi +0 -0
  32. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/baggage.pyi +0 -0
  33. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/cli/__init__.pyi +0 -0
  34. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/cli/ai_tools.pyi +0 -0
  35. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/cli/auth.pyi +0 -0
  36. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/cli/gateway.pyi +0 -0
  37. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/cli/gateway_auth.pyi +0 -0
  38. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/cli/prompt.pyi +0 -0
  39. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/cli/run.pyi +0 -0
  40. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/cli.pyi +0 -0
  41. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/client.pyi +0 -0
  42. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/collect_system_info.pyi +0 -0
  43. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/constants.pyi +0 -0
  44. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/db_statement_summary.pyi +0 -0
  45. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/exporters/__init__.pyi +0 -0
  46. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/exporters/console.pyi +0 -0
  47. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/exporters/dynamic_batch.pyi +0 -0
  48. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/exporters/logs.pyi +0 -0
  49. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/exporters/otlp.pyi +0 -0
  50. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/exporters/processor_wrapper.pyi +0 -0
  51. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/exporters/quiet_metrics.pyi +0 -0
  52. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/exporters/remove_pending.pyi +0 -0
  53. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/exporters/tail_sampling.pyi +0 -0
  54. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/exporters/wrapper.pyi +0 -0
  55. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/formatter.pyi +0 -0
  56. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/instrument.pyi +0 -0
  57. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/__init__.pyi +0 -0
  58. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/aiohttp_client.pyi +0 -0
  59. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/aiohttp_server.pyi +0 -0
  60. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/asgi.pyi +0 -0
  61. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/asyncpg.pyi +0 -0
  62. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/aws_lambda.pyi +0 -0
  63. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/celery.pyi +0 -0
  64. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/claude_agent_sdk.pyi +0 -0
  65. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/django.pyi +0 -0
  66. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/dspy.pyi +0 -0
  67. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/executors.pyi +0 -0
  68. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/fastapi.pyi +0 -0
  69. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/flask.pyi +0 -0
  70. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/httpx.pyi +0 -0
  71. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/litellm.pyi +0 -0
  72. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/mcp.pyi +0 -0
  73. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/mysql.pyi +0 -0
  74. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/openai_agents.pyi +0 -0
  75. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/print.pyi +0 -0
  76. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/psycopg.pyi +0 -0
  77. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/pydantic_ai.pyi +0 -0
  78. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/pymongo.pyi +0 -0
  79. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/redis.pyi +0 -0
  80. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/requests.pyi +0 -0
  81. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/sqlalchemy.pyi +0 -0
  82. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/sqlite3.pyi +0 -0
  83. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/starlette.pyi +0 -0
  84. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/surrealdb.pyi +0 -0
  85. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/integrations/wsgi.pyi +0 -0
  86. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/json_encoder.pyi +0 -0
  87. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/json_formatter.pyi +0 -0
  88. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/json_schema.pyi +0 -0
  89. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/json_types.pyi +0 -0
  90. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/logs.pyi +0 -0
  91. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/metrics.pyi +0 -0
  92. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/scrubbing.pyi +0 -0
  93. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/server_response.pyi +0 -0
  94. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/stack_info.pyi +0 -0
  95. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/ulid.pyi +0 -0
  96. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/_internal/utils.pyi +0 -0
  97. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/cli.pyi +0 -0
  98. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/exceptions.pyi +0 -0
  99. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/experimental/__init__.pyi +0 -0
  100. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/experimental/annotations.pyi +0 -0
  101. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/experimental/api_client.pyi +0 -0
  102. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/experimental/datasets/__init__.pyi +0 -0
  103. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/integrations/__init__.pyi +0 -0
  104. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/integrations/aiohttp_client.pyi +0 -0
  105. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/integrations/flask.pyi +0 -0
  106. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/integrations/httpx.pyi +0 -0
  107. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/integrations/logging.pyi +0 -0
  108. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/integrations/loguru.pyi +0 -0
  109. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/integrations/psycopg.pyi +0 -0
  110. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/integrations/pydantic.pyi +0 -0
  111. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/integrations/redis.pyi +0 -0
  112. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/integrations/sqlalchemy.pyi +0 -0
  113. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/integrations/structlog.pyi +0 -0
  114. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/integrations/wsgi.pyi +0 -0
  115. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/propagate.pyi +0 -0
  116. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/py.typed +0 -0
  117. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/sampling/__init__.pyi +0 -0
  118. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/sampling/_tail_sampling.pyi +0 -0
  119. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/types.pyi +0 -0
  120. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/variables/config.pyi +1 -1
  121. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/variables/local.pyi +0 -0
  122. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/variables/remote.pyi +0 -0
  123. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/variables/variable.pyi +0 -0
  124. {logfire_api-4.33.0 → logfire_api-4.35.0}/logfire_api/version.pyi +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: logfire-api
3
- Version: 4.33.0
3
+ Version: 4.35.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
7
- Requires-Python: >=3.8
7
+ Requires-Python: >=3.10
8
8
  Description-Content-Type: text/markdown
9
9
 
10
10
  # logfire-api
@@ -2,11 +2,11 @@ from __future__ import annotations
2
2
 
3
3
  import importlib
4
4
  import sys
5
- from contextlib import contextmanager, nullcontext
6
- from typing import Any, ContextManager, Literal, TYPE_CHECKING, Sequence
5
+ from collections.abc import Sequence
6
+ from contextlib import AbstractContextManager, contextmanager, nullcontext
7
+ from typing import TYPE_CHECKING, Any, Literal
7
8
  from unittest.mock import MagicMock
8
9
 
9
-
10
10
  try:
11
11
  logfire_module = importlib.import_module('logfire')
12
12
  sys.modules[__name__] = logfire_module
@@ -143,7 +143,7 @@ except ImportError:
143
143
  def instrument_wsgi(self, app, *args, **kwargs):
144
144
  return app
145
145
 
146
- def instrument_fastapi(self, *args, **kwargs) -> ContextManager[None]:
146
+ def instrument_fastapi(self, *args, **kwargs) -> AbstractContextManager[None]:
147
147
  return nullcontext()
148
148
 
149
149
  def instrument_pydantic(self, *args, **kwargs) -> None: ...
@@ -176,13 +176,13 @@ except ImportError:
176
176
 
177
177
  def instrument_asyncpg(self, *args, **kwargs) -> None: ...
178
178
 
179
- def instrument_anthropic(self, *args, **kwargs) -> ContextManager[None]:
179
+ def instrument_anthropic(self, *args, **kwargs) -> AbstractContextManager[None]:
180
180
  return nullcontext()
181
181
 
182
- def instrument_openai(self, *args, **kwargs) -> ContextManager[None]:
182
+ def instrument_openai(self, *args, **kwargs) -> AbstractContextManager[None]:
183
183
  return nullcontext()
184
184
 
185
- def instrument_print(self, *args, **kwargs) -> ContextManager[None]:
185
+ def instrument_print(self, *args, **kwargs) -> AbstractContextManager[None]:
186
186
  return nullcontext()
187
187
 
188
188
  def instrument_openai_agents(self, *args, **kwargs) -> None: ...
@@ -201,11 +201,17 @@ except ImportError:
201
201
 
202
202
  def instrument_mcp(self, *args, **kwargs) -> None: ...
203
203
 
204
- def instrument_claude_agent_sdk(self, *args, **kwargs) -> ContextManager[None]:
204
+ def instrument_claude_agent_sdk(self, *args, **kwargs) -> AbstractContextManager[None]:
205
205
  return nullcontext()
206
206
 
207
207
  def url_from_eval(self, *args, **kwargs) -> str | None: ...
208
208
 
209
+ def forward_export_request(self, *args, **kwargs) -> MagicMock:
210
+ return MagicMock()
211
+
212
+ async def forward_export_request_starlette(self, *args, **kwargs) -> MagicMock:
213
+ return MagicMock()
214
+
209
215
  def shutdown(self, *args, **kwargs) -> None: ...
210
216
 
211
217
 
@@ -262,6 +268,8 @@ except ImportError:
262
268
  shutdown = DEFAULT_LOGFIRE_INSTANCE.shutdown
263
269
  suppress_scopes = DEFAULT_LOGFIRE_INSTANCE.suppress_scopes
264
270
  url_from_eval = DEFAULT_LOGFIRE_INSTANCE.url_from_eval
271
+ forward_export_request = DEFAULT_LOGFIRE_INSTANCE.forward_export_request
272
+ forward_export_request_starlette = DEFAULT_LOGFIRE_INSTANCE.forward_export_request_starlette
265
273
 
266
274
  def loguru_handler() -> dict[str, Any]:
267
275
  return {}
@@ -316,11 +324,11 @@ except ImportError:
316
324
  def get_baggage(*args, **kwargs) -> dict[str, str]:
317
325
  return {}
318
326
 
319
- def set_baggage(*args, **kwargs) -> ContextManager[None]:
327
+ def set_baggage(*args, **kwargs) -> AbstractContextManager[None]:
320
328
  return nullcontext()
321
329
 
322
330
  def get_context(*args, **kwargs) -> dict[str, Any]:
323
331
  return {}
324
332
 
325
- def attach_context(*args, **kwargs) -> ContextManager[None]:
333
+ def attach_context(*args, **kwargs) -> AbstractContextManager[None]:
326
334
  return nullcontext()
@@ -16,7 +16,7 @@ from logfire.propagate import attach_context as attach_context, get_context as g
16
16
  from logfire.sampling import SamplingOptions as SamplingOptions
17
17
  from typing import Any
18
18
 
19
- __all__ = ['Logfire', 'LogfireSpan', 'LevelName', 'AdvancedOptions', 'ConsoleOptions', 'CodeSource', 'PydanticPlugin', 'configure', 'span', 'instrument', 'log', 'trace', 'debug', 'notice', 'info', 'warn', 'warning', 'error', 'exception', 'fatal', 'force_flush', 'log_slow_async_callbacks', 'install_auto_tracing', 'instrument_asgi', 'instrument_wsgi', 'instrument_pydantic', 'instrument_pydantic_ai', 'instrument_fastapi', 'instrument_openai', 'instrument_openai_agents', 'instrument_anthropic', 'instrument_google_genai', 'instrument_litellm', 'instrument_dspy', 'instrument_print', 'instrument_asyncpg', 'instrument_httpx', 'instrument_celery', 'instrument_requests', 'instrument_psycopg', 'instrument_django', 'instrument_flask', 'instrument_starlette', 'instrument_aiohttp_client', 'instrument_aiohttp_server', 'instrument_sqlalchemy', 'instrument_sqlite3', 'instrument_aws_lambda', 'instrument_redis', 'instrument_pymongo', 'instrument_mysql', 'instrument_surrealdb', 'instrument_system_metrics', 'instrument_mcp', 'instrument_claude_agent_sdk', 'AutoTraceModule', 'with_tags', 'with_settings', 'suppress_scopes', 'shutdown', 'no_auto_trace', 'ScrubMatch', 'ScrubbingOptions', 'VERSION', 'add_non_user_code_prefix', 'suppress_instrumentation', 'StructlogProcessor', 'LogfireLoggingHandler', 'loguru_handler', 'SamplingOptions', 'MetricsOptions', 'VariablesOptions', 'LocalVariablesOptions', 'variables', 'var', 'variables_clear', 'variables_get', 'variables_push', 'variables_push_types', 'variables_validate', 'variables_push_config', 'variables_pull_config', 'variables_build_config', 'logfire_info', 'get_baggage', 'set_baggage', 'get_context', 'attach_context', 'url_from_eval']
19
+ __all__ = ['Logfire', 'LogfireSpan', 'LevelName', 'AdvancedOptions', 'ConsoleOptions', 'CodeSource', 'PydanticPlugin', 'configure', 'span', 'instrument', 'log', 'trace', 'debug', 'notice', 'info', 'warn', 'warning', 'error', 'exception', 'fatal', 'force_flush', 'log_slow_async_callbacks', 'install_auto_tracing', 'instrument_asgi', 'instrument_wsgi', 'instrument_pydantic', 'instrument_pydantic_ai', 'instrument_fastapi', 'instrument_openai', 'instrument_openai_agents', 'instrument_anthropic', 'instrument_google_genai', 'instrument_litellm', 'instrument_dspy', 'instrument_print', 'instrument_asyncpg', 'instrument_httpx', 'instrument_celery', 'instrument_requests', 'instrument_psycopg', 'instrument_django', 'instrument_flask', 'instrument_starlette', 'instrument_aiohttp_client', 'instrument_aiohttp_server', 'instrument_sqlalchemy', 'instrument_sqlite3', 'instrument_aws_lambda', 'instrument_redis', 'instrument_pymongo', 'instrument_mysql', 'instrument_surrealdb', 'instrument_system_metrics', 'instrument_mcp', 'instrument_claude_agent_sdk', 'AutoTraceModule', 'with_tags', 'with_settings', 'suppress_scopes', 'shutdown', 'no_auto_trace', 'ScrubMatch', 'ScrubbingOptions', 'VERSION', 'add_non_user_code_prefix', 'suppress_instrumentation', 'StructlogProcessor', 'LogfireLoggingHandler', 'loguru_handler', 'SamplingOptions', 'MetricsOptions', 'VariablesOptions', 'LocalVariablesOptions', 'variables', 'var', 'variables_clear', 'variables_get', 'variables_push', 'variables_push_types', 'variables_validate', 'variables_push_config', 'variables_pull_config', 'variables_build_config', 'logfire_info', 'get_baggage', 'set_baggage', 'get_context', 'attach_context', 'url_from_eval', 'forward_export_request', 'forward_export_request_starlette']
20
20
 
21
21
  DEFAULT_LOGFIRE_INSTANCE = Logfire()
22
22
  span = DEFAULT_LOGFIRE_INSTANCE.span
@@ -61,6 +61,8 @@ shutdown = DEFAULT_LOGFIRE_INSTANCE.shutdown
61
61
  with_tags = DEFAULT_LOGFIRE_INSTANCE.with_tags
62
62
  with_settings = DEFAULT_LOGFIRE_INSTANCE.with_settings
63
63
  url_from_eval = DEFAULT_LOGFIRE_INSTANCE.url_from_eval
64
+ forward_export_request = DEFAULT_LOGFIRE_INSTANCE.forward_export_request
65
+ forward_export_request_starlette = DEFAULT_LOGFIRE_INSTANCE.forward_export_request_starlette
64
66
  log = DEFAULT_LOGFIRE_INSTANCE.log
65
67
  trace = DEFAULT_LOGFIRE_INSTANCE.trace
66
68
  debug = DEFAULT_LOGFIRE_INSTANCE.debug
@@ -13,6 +13,7 @@ from .exporters.processor_wrapper import CheckSuppressInstrumentationProcessorWr
13
13
  from .exporters.quiet_metrics import QuietMetricExporter as QuietMetricExporter
14
14
  from .exporters.remove_pending import RemovePendingSpansExporter as RemovePendingSpansExporter
15
15
  from .exporters.test import TestExporter as TestExporter
16
+ from .forwarding import OTLPForwardingManager as OTLPForwardingManager
16
17
  from .integrations.executors import instrument_executors as instrument_executors
17
18
  from .logs import ProxyLoggerProvider as ProxyLoggerProvider
18
19
  from .main import Logfire as Logfire
@@ -253,6 +254,8 @@ class LogfireConfig(_LogfireConfigData):
253
254
  Returns:
254
255
  Whether the flush of spans was successful.
255
256
  """
257
+ def shutdown(self, timeout_millis: int = 30000, flush: bool = True) -> bool:
258
+ """Shut down variables, forwarding, traces, logs, and metrics."""
256
259
  def get_tracer_provider(self) -> ProxyTracerProvider:
257
260
  """Get a tracer provider from this `LogfireConfig`.
258
261
 
@@ -300,6 +303,7 @@ def emit_configuration_span(config: LogfireConfig, logfire_instance: Logfire, *,
300
303
  non-sensitive configuration fields.
301
304
  """
302
305
  def exit_open_spans() -> None: ...
306
+ def shutdown_otlp_forwarding(timeout_millis: int = 30000) -> None: ...
303
307
 
304
308
  original_os_exit: Incomplete
305
309
 
@@ -11,10 +11,9 @@ from pathlib import Path
11
11
  from typing import Any, TypeVar
12
12
 
13
13
  T = TypeVar('T')
14
- slots_true: Incomplete
15
14
  PydanticPluginRecordValues: Incomplete
16
15
 
17
- @dataclass(**slots_true)
16
+ @dataclass(slots=True)
18
17
  class ConfigParam:
19
18
  """A parameter that can be configured for a Logfire instance."""
20
19
  env_vars: list[str]
@@ -0,0 +1,85 @@
1
+ from _typeshed import Incomplete
2
+ from collections import deque
3
+ from collections.abc import Callable as Callable, Mapping, Sequence
4
+ from dataclasses import dataclass
5
+ from enum import Enum
6
+ from logfire._internal.exporters.otlp import OTLPExporterHttpSession as OTLPExporterHttpSession
7
+ from logfire._internal.server_response import install_logfire_response_hook as install_logfire_response_hook
8
+ from logfire._internal.utils import suppress_instrumentation as suppress_instrumentation
9
+ from logfire.experimental.forwarding import ForwardExportRequestResponse as ForwardExportRequestResponse
10
+ from logfire.types import ServerResponseCallback as ServerResponseCallback
11
+ from logfire.version import VERSION as VERSION
12
+ from opentelemetry.proto.collector.logs.v1.logs_service_pb2 import ExportLogsServiceResponse
13
+ from opentelemetry.proto.collector.metrics.v1.metrics_service_pb2 import ExportMetricsServiceResponse
14
+ from opentelemetry.proto.collector.trace.v1.trace_service_pb2 import ExportTraceServiceResponse
15
+ from threading import Thread
16
+ from typing import Literal
17
+
18
+ OTLP_FORWARDING_MAX_QUEUED_BODY_BYTES: Incomplete
19
+ OTLP_FORWARDING_MAX_QUEUED_ITEMS: int
20
+ OTLP_FORWARDING_MAX_REQUEST_BODY_BYTES: Incomplete
21
+ ForwardingPath: Incomplete
22
+
23
+ @dataclass(frozen=True)
24
+ class ForwardingPathConfig:
25
+ timeout_env: str
26
+ default_timeout: float
27
+ partial_success_rejected_attribute: str
28
+ response_message_type: type[ExportTraceServiceResponse] | type[ExportLogsServiceResponse] | type[ExportMetricsServiceResponse]
29
+ def timeout(self) -> float: ...
30
+
31
+ FORWARDING_CONFIGS: dict[ForwardingPath, ForwardingPathConfig]
32
+
33
+ class ForwardingContentType(Enum):
34
+ PROTOBUF: str
35
+ JSON: str
36
+
37
+ @dataclass(frozen=True)
38
+ class ForwardingRequest:
39
+ path: ForwardingPath
40
+ body: bytes
41
+ content_type: ForwardingContentType
42
+ headers: Mapping[str, str]
43
+ @property
44
+ def path_config(self) -> ForwardingPathConfig: ...
45
+
46
+ @dataclass(frozen=True)
47
+ class ForwardingErrorResponse:
48
+ status_code: int
49
+ content: bytes
50
+
51
+ @dataclass(frozen=True)
52
+ class ForwardingAdmissionResult:
53
+ response: Literal['success', 'partial_success']
54
+ message: str | None
55
+
56
+ class OTLPForwardingPipeline:
57
+ base_url: Incomplete
58
+ session: Incomplete
59
+ max_queued_body_bytes: Incomplete
60
+ max_queued_items: Incomplete
61
+ queue: deque[ForwardingRequest]
62
+ worker: Thread | None
63
+ closed: bool
64
+ condition: Incomplete
65
+ tokens: list[str]
66
+ def __init__(self, *, base_url: str, session: OTLPExporterHttpSession, max_queued_body_bytes: int, max_queued_items: int = ...) -> None: ...
67
+ @property
68
+ def queued_body_bytes(self) -> int: ...
69
+ def enqueue(self, queued_request: ForwardingRequest) -> bool: ...
70
+ def force_flush(self, timeout_millis: int) -> bool: ...
71
+ def shutdown(self, timeout_millis: int, *, drain_queued: bool = True) -> bool: ...
72
+
73
+ class OTLPForwardingManager:
74
+ pipelines: dict[str, OTLPForwardingPipeline]
75
+ closed: bool
76
+ def __init__(self, destinations: Sequence[tuple[str, str]], *, server_response_hook: ServerResponseCallback | None = None) -> None: ...
77
+ def has_destinations(self) -> bool: ...
78
+ def submit(self, request: ForwardingRequest) -> ForwardingAdmissionResult: ...
79
+ def force_flush(self, timeout_millis: int) -> bool: ...
80
+ def shutdown(self, timeout_millis: int, *, drain_queued: bool = True) -> bool: ...
81
+
82
+ def parse_forwarding_content_type(content_type: str) -> ForwardingContentType | None: ...
83
+ def build_forwarding_request(*, path: str, headers: Mapping[str, str], body: bytes, max_body_size: int = ...) -> ForwardingRequest | ForwardingErrorResponse: ...
84
+ def build_success_response(request: ForwardingRequest) -> ForwardExportRequestResponse: ...
85
+ def build_partial_success_response(request: ForwardingRequest, *, message: str) -> ForwardExportRequestResponse: ...
@@ -2,8 +2,7 @@ import logfire
2
2
  from _typeshed import Incomplete
3
3
  from logfire._internal.utils import handle_internal_errors as handle_internal_errors, safe_repr as safe_repr
4
4
  from opentelemetry._logs import LogRecord, Logger, LoggerProvider
5
- from typing import Any
6
- from typing_extensions import TypeAlias
5
+ from typing import Any, TypeAlias
7
6
 
8
7
  original_flatten_compound_value: Incomplete
9
8
 
@@ -18,22 +18,22 @@ def pytest_configure(config: pytest.Config) -> None:
18
18
  def pytest_xdist_setupnodes(config: Any, specs: Any) -> None:
19
19
  """Inject TRACEPARENT into env before xdist spawns workers.
20
20
 
21
- Called in the controller before any ``makegateway()`` call, so all workers
22
- inherit the session-level trace context via ``os.environ``.
21
+ Called in the controller before any `makegateway()` call, so all workers
22
+ inherit the session-level trace context via `os.environ`.
23
23
 
24
- NOTE: This relies on ``pytest_sessionstart`` (which creates the session span)
25
- running at default priority, *before* xdist's ``DSession.pytest_sessionstart``
26
- which uses ``trylast=True`` and calls ``setup_nodes()``
27
- ``pytest_xdist_setupnodes``. Do not add ``trylast=True`` to our
28
- ``pytest_sessionstart`` or this ordering guarantee breaks.
24
+ NOTE: This relies on `pytest_sessionstart` (which creates the session span)
25
+ running at default priority, *before* xdist's `DSession.pytest_sessionstart`
26
+ which uses `trylast=True` and calls `setup_nodes()`
27
+ `pytest_xdist_setupnodes`. Do not add `trylast=True` to our
28
+ `pytest_sessionstart` or this ordering guarantee breaks.
29
29
  """
30
30
  def pytest_sessionstart(session: pytest.Session) -> None:
31
31
  """Create a session span when the test session starts.
32
32
 
33
- IMPORTANT: This hook must run at default priority (no ``trylast=True``).
34
- ``pytest_xdist_setupnodes`` depends on the session span being active when
35
- it injects TRACEPARENT into ``os.environ`` for worker processes. xdist's
36
- ``DSession.pytest_sessionstart`` uses ``trylast=True``, so our default-priority
33
+ IMPORTANT: This hook must run at default priority (no `trylast=True`).
34
+ `pytest_xdist_setupnodes` depends on the session span being active when
35
+ it injects TRACEPARENT into `os.environ` for worker processes. xdist's
36
+ `DSession.pytest_sessionstart` uses `trylast=True`, so our default-priority
37
37
  hook is guaranteed to run first.
38
38
  """
39
39
  def pytest_runtest_protocol(item: pytest.Item, nextitem: pytest.Item | None) -> Generator[None]:
@@ -62,16 +62,16 @@ def logfire_pytest(request: pytest.FixtureRequest) -> Logfire:
62
62
  def pytest_pyfunc_call(pyfuncitem: pytest.Function) -> Generator[None]:
63
63
  """Re-attach the per-test span context for async test functions.
64
64
 
65
- The ``pytest_runtest_protocol`` hook creates a span per test and attaches it
66
- to the OTel context via ``context_api.attach()`` in the **synchronous** hook
65
+ The `pytest_runtest_protocol` hook creates a span per test and attaches it
66
+ to the OTel context via `context_api.attach()` in the **synchronous** hook
67
67
  thread. However, when tests are async (e.g. with anyio/pytest-asyncio), they
68
- may run inside an event-loop task whose ``contextvars`` snapshot was taken
69
- before the per-test span was attached (e.g. when ``asyncio.Runner`` reuses a
70
- saved context on Python 3.11+). As a result, ``logfire.get_context()`` inside
68
+ may run inside an event-loop task whose `contextvars` snapshot was taken
69
+ before the per-test span was attached (e.g. when `asyncio.Runner` reuses a
70
+ saved context on Python 3.11+). As a result, `logfire.get_context()` inside
71
71
  an async test can return a stale traceparent from a previous test (or no
72
72
  context at all).
73
73
 
74
- This hook wraps async test functions so that ``context_api.attach()`` is called
74
+ This hook wraps async test functions so that `context_api.attach()` is called
75
75
  *inside* the coroutine body, making the span visible to the test and any
76
- callbacks (e.g. httpx event hooks) that call ``logfire.get_context()``.
76
+ callbacks (e.g. httpx event hooks) that call `logfire.get_context()`.
77
77
  """
@@ -4,7 +4,7 @@ from logfire import Logfire as Logfire
4
4
  from typing import Literal
5
5
  from typing_extensions import LiteralString
6
6
 
7
- MetricName: type[Literal['system.cpu.simple_utilization', 'system.cpu.time', 'system.cpu.utilization', 'system.memory.usage', 'system.memory.utilization', 'system.swap.usage', 'system.swap.utilization', 'system.disk.io', 'system.disk.operations', 'system.disk.time', 'system.network.dropped.packets', 'system.network.packets', 'system.network.errors', 'system.network.io', 'system.network.connections', 'system.thread_count', 'process.open_file_descriptor.count', 'process.context_switches', 'process.cpu.time', 'process.cpu.utilization', 'process.cpu.core_utilization', 'process.memory.usage', 'process.memory.virtual', 'process.thread.count', 'process.runtime.gc_count', 'cpython.gc.collected_objects', 'cpython.gc.collections', 'cpython.gc.uncollectable_objects']]
7
+ MetricName: type[Literal['system.cpu.simple_utilization', 'system.cpu.time', 'system.cpu.utilization', 'system.memory.usage', 'system.memory.utilization', 'system.swap.usage', 'system.swap.utilization', 'system.disk.io', 'system.disk.operations', 'system.disk.time', 'system.network.dropped.packets', 'system.network.packets', 'system.network.errors', 'system.network.io', 'system.network.connections', 'system.thread_count', 'process.open_file_descriptor.count', 'process.context_switches', 'process.cpu.time', 'process.cpu.utilization', 'process.cpu.core_utilization', 'process.disk.io', 'process.memory.usage', 'process.memory.virtual', 'process.thread.count', 'process.runtime.gc_count', 'cpython.gc.collected_objects', 'cpython.gc.collections', 'cpython.gc.uncollectable_objects']]
8
8
  Config = dict[MetricName, Iterable[str] | None]
9
9
  CPU_FIELDS: list[LiteralString]
10
10
  MEMORY_FIELDS: list[LiteralString]
@@ -6,6 +6,7 @@ import pydantic_ai
6
6
  import pydantic_ai.models
7
7
  import requests
8
8
  from . import async_ as async_
9
+ from ..experimental.forwarding import ForwardExportRequestResponse as ForwardExportRequestResponse
9
10
  from ..integrations.aiohttp_client import RequestHook as AiohttpClientRequestHook, ResponseHook as AiohttpClientResponseHook
10
11
  from ..integrations.flask import CommenterOptions as FlaskCommenterOptions, RequestHook as FlaskRequestHook, ResponseHook as FlaskResponseHook
11
12
  from ..integrations.httpx import AsyncRequestHook as HttpxAsyncRequestHook, AsyncResponseHook as HttpxAsyncResponseHook, RequestHook as HttpxRequestHook, ResponseHook as HttpxResponseHook
@@ -51,7 +52,8 @@ from pymongo.monitoring import CommandFailedEvent as CommandFailedEvent, Command
51
52
  from sqlalchemy import Engine
52
53
  from sqlalchemy.ext.asyncio import AsyncEngine
53
54
  from starlette.applications import Starlette
54
- from starlette.requests import Request as Request
55
+ from starlette.requests import Request
56
+ from starlette.responses import Response
55
57
  from starlette.websockets import WebSocket as WebSocket
56
58
  from surrealdb.connections.async_template import AsyncTemplate
57
59
  from surrealdb.connections.sync_template import SyncTemplate
@@ -398,7 +400,7 @@ class Logfire:
398
400
  def install_auto_tracing(self, modules: Sequence[str] | Callable[[AutoTraceModule], bool], *, min_duration: float, check_imported_modules: Literal['error', 'warn', 'ignore'] = 'error') -> None:
399
401
  """Install automatic tracing.
400
402
 
401
- See the [Auto-Tracing guide](https://logfire.pydantic.dev/docs/guides/onboarding_checklist/add_auto_tracing/)
403
+ See the [Auto-Tracing guide](https://pydantic.dev/docs/logfire/instrument/add-auto-tracing/)
402
404
  for more info.
403
405
 
404
406
  This will trace all non-generator function calls in the modules specified by the modules argument.
@@ -1418,6 +1420,50 @@ class Logfire:
1418
1420
  print(config.model_dump_json(indent=2))
1419
1421
  ```
1420
1422
  '''
1423
+ def forward_export_request(self, *, path: str, headers: Mapping[str, str], body: bytes, max_body_size: int = ...) -> ForwardExportRequestResponse:
1424
+ '''Forward an OpenTelemetry export request to the Logfire backend.
1425
+
1426
+ This method is generic and can be used for any web framework.
1427
+ For Starlette/FastAPI, use `forward_export_request_starlette` instead for extra protection and convenience.
1428
+
1429
+ This is for proxying telemetry from a browser to Logfire so that the write token doesn\'t need to be
1430
+ exposed in the frontend code.
1431
+ See https://pydantic.dev/docs/logfire/typescript-sdk/packages/browser/#python-backend-proxy
1432
+ for more details.
1433
+
1434
+ We recommend protecting the endpoint that uses this method with authentication, rate limiting, and CORS.
1435
+
1436
+ Args:
1437
+ path: one of "/v1/traces", "/v1/metrics", or "/v1/logs"
1438
+ headers: the request headers, as a mapping of header names to values
1439
+ body: the request body, as bytes
1440
+ max_body_size: the maximum allowed body size, in bytes.
1441
+ If the body exceeds this size, the response will be a 413, rejecting the payload.
1442
+
1443
+ Returns:
1444
+ A `ForwardExportRequestResponse` containing the repsonse status code, body, and headers.
1445
+ '''
1446
+ async def forward_export_request_starlette(self, request: Request, *, max_body_size: int = ...) -> Response:
1447
+ """Forward an OpenTelemetry export request to the Logfire backend.
1448
+
1449
+ This method is designed for Starlette/FastAPI.
1450
+ For other web frameworks, use `forward_export_request` instead and adapt the request/response handling as needed.
1451
+
1452
+ This is for proxying telemetry from a browser to Logfire so that the write token doesn't need to be
1453
+ exposed in the frontend code.
1454
+ See https://pydantic.dev/docs/logfire/typescript-sdk/packages/browser/#python-backend-proxy
1455
+ for more details.
1456
+
1457
+ We recommend protecting the endpoint that uses this method with authentication, rate limiting, and CORS.
1458
+
1459
+ Args:
1460
+ request: The Starlette/FastAPI `Request` object.
1461
+ max_body_size: the maximum allowed body size, in bytes.
1462
+ If the body exceeds this size, the response will be a 413, rejecting the payload.
1463
+
1464
+ Returns:
1465
+ A Starlette/FastAPI `Response` object.
1466
+ """
1421
1467
 
1422
1468
  class FastLogfireSpan:
1423
1469
  """A simple version of `LogfireSpan` optimized for auto-tracing."""
@@ -113,4 +113,7 @@ def get_sample_rate_from_attributes(attributes: otel_types.Attributes) -> float
113
113
  @handle_internal_errors
114
114
  def record_exception(span: trace_api.Span, exception: BaseException, *, attributes: otel_types.Attributes = None, timestamp: int | None = None, escaped: bool = False, callback: ExceptionCallback | None = None) -> None:
115
115
  """Similar to the OTEL SDK Span.record_exception method, with our own additions."""
116
+
117
+ original_format_exception: Incomplete
118
+
116
119
  def set_exception_status(span: trace_api.Span, exception: BaseException): ...
@@ -2,7 +2,7 @@ from _typeshed import Incomplete
2
2
  from collections.abc import Sequence
3
3
  from datetime import datetime, timedelta
4
4
  from logfire.experimental.query_client import ColumnDetails as ColumnDetails, LogfireQueryClient as LogfireQueryClient
5
- from typing import Any
5
+ from typing import Any, overload
6
6
 
7
7
  apilevel: str
8
8
  threadsafety: int
@@ -49,11 +49,15 @@ class Cursor:
49
49
  """PEP 249 Cursor that executes queries via `LogfireQueryClient.query_json_rows()`."""
50
50
  rowcount: int
51
51
  arraysize: int
52
- min_timestamp: datetime | None
53
52
  max_timestamp: datetime | None
54
53
  limit: int
55
54
  def __init__(self, connection: Connection) -> None: ...
56
55
  @property
56
+ def min_timestamp(self) -> datetime | None:
57
+ """Per-cursor override for the lower `start_timestamp` bound."""
58
+ @min_timestamp.setter
59
+ def min_timestamp(self, value: datetime | None) -> None: ...
60
+ @property
57
61
  def description(self) -> list[tuple[Any, ...]] | None:
58
62
  """Column description as a list of 7-tuples per PEP 249.
59
63
 
@@ -88,23 +92,7 @@ class Cursor:
88
92
  def __enter__(self) -> Cursor: ...
89
93
  def __exit__(self, *args: Any) -> None: ...
90
94
 
91
- def connect(read_token: str, base_url: str | None = None, timeout: float = 30.0, *, min_timestamp: datetime | timedelta | None = ..., max_timestamp: datetime | None = None, limit: int = ..., **kwargs: Any) -> Connection:
92
- """Create a PEP 249 connection to the Logfire query API.
93
-
94
- Args:
95
- read_token: A Logfire read token for authentication.
96
- base_url: Override the default API base URL (inferred from token region).
97
- timeout: HTTP request timeout in seconds.
98
- min_timestamp: Default lower bound for `start_timestamp` filtering.
99
- Accepts a `datetime` for an exact bound, a `timedelta` for a
100
- relative window (computed as `now - timedelta`), or `None` to
101
- disable the filter. Defaults to 1 day ago.
102
- max_timestamp: Default upper bound for `start_timestamp` filtering.
103
- limit: Default row limit per query (max 10,000). When the number of
104
- returned rows equals the limit a warning is emitted.
105
- **kwargs: Additional keyword arguments forwarded to the underlying
106
- `httpx.Client`.
107
-
108
- Returns:
109
- A PEP 249 `Connection` object.
110
- """
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: ...
@@ -0,0 +1,25 @@
1
+ import logfire
2
+ from collections.abc import Mapping
3
+ from dataclasses import dataclass
4
+ from starlette.requests import Request
5
+ from starlette.responses import Response
6
+
7
+ __all__ = ['ForwardExportRequestResponse', 'forward_export_request', 'logfire_proxy']
8
+
9
+ @dataclass
10
+ class ForwardExportRequestResponse:
11
+ """Response returned from a forwarded export request to Logfire."""
12
+ status_code: int
13
+ headers: Mapping[str, str]
14
+ content: bytes
15
+
16
+ def forward_export_request(*, path: str, headers: Mapping[str, str], body: bytes, logfire_instance: logfire.Logfire | None = None, max_body_size: int = ...) -> ForwardExportRequestResponse:
17
+ """Forward an export request to the Logfire API.
18
+
19
+ See the Logfire.forward_export_request method for more details.
20
+ """
21
+ async def logfire_proxy(request: Request, *, logfire_instance: logfire.Logfire | None = None, max_body_size: int = ...) -> Response:
22
+ """A Starlette/FastAPI handler to proxy requests to Logfire.
23
+
24
+ See the Logfire.forward_export_request_starlette method for more details.
25
+ """
@@ -0,0 +1,123 @@
1
+ from _typeshed import Incomplete
2
+ from datetime import datetime
3
+ from httpx import AsyncClient, Client, Response, Timeout
4
+ from httpx._client import BaseClient
5
+ from logfire import VERSION as VERSION
6
+ from logfire._internal.config import get_base_url_from_token as get_base_url_from_token
7
+ from logfire._internal.stack_info import warn_at_user_stacklevel as warn_at_user_stacklevel
8
+ from pyarrow import Table
9
+ from types import TracebackType
10
+ from typing import Any, Generic, TypeVar, TypedDict, overload
11
+ from typing_extensions import Self
12
+
13
+ DEFAULT_TIMEOUT: Incomplete
14
+
15
+ class QueryExecutionError(RuntimeError):
16
+ """Raised when the query execution fails on the server."""
17
+ class QueryRequestError(RuntimeError):
18
+ """Raised when the query request is invalid."""
19
+ class InfoRequestError(RuntimeError):
20
+ """Raised when the request for read token info fails because of unavailable information."""
21
+
22
+ class ReadTokenInfo(TypedDict, total=False):
23
+ """Information about the read token."""
24
+ organization_name: str
25
+ project_name: str
26
+
27
+ class ColumnDetails(TypedDict):
28
+ """The details of a column in the row-oriented JSON-format query results."""
29
+ name: str
30
+ datatype: Any
31
+ nullable: bool
32
+
33
+ class ColumnData(ColumnDetails):
34
+ """The data of a column in the column-oriented JSON-format query results."""
35
+ values: list[Any]
36
+
37
+ class QueryResults(TypedDict):
38
+ """The (column-oriented) results of a JSON-format query."""
39
+ columns: list[ColumnData]
40
+
41
+ class RowQueryResults(TypedDict):
42
+ """The row-oriented results of a JSON-format query."""
43
+ columns: list[ColumnDetails]
44
+ rows: list[dict[str, Any]]
45
+ T = TypeVar('T', bound=BaseClient)
46
+
47
+ class _BaseLogfireQueryClient(Generic[T]):
48
+ base_url: Incomplete
49
+ read_token: Incomplete
50
+ timeout: Incomplete
51
+ client: T
52
+ def __init__(self, base_url: str, read_token: str, timeout: Timeout, client: type[T], **client_kwargs: Any) -> None: ...
53
+ def handle_response_errors(self, response: Response) -> None: ...
54
+
55
+ class LogfireQueryClient(_BaseLogfireQueryClient[Client]):
56
+ """A synchronous client for querying Logfire data."""
57
+ def __init__(self, read_token: str, base_url: str | None = None, timeout: Timeout = ..., **client_kwargs: Any) -> None: ...
58
+ def __enter__(self) -> Self: ...
59
+ def __exit__(self, exc_type: type[BaseException] | None = None, exc_value: BaseException | None = None, traceback: TracebackType | None = None) -> None: ...
60
+ def info(self) -> ReadTokenInfo:
61
+ """Get information about the read token."""
62
+ def query_json(self, sql: str, min_timestamp: datetime | None = None, max_timestamp: datetime | None = None, limit: int | None = None) -> QueryResults:
63
+ """Query Logfire data and return the results as a column-oriented dictionary."""
64
+ @overload
65
+ def query_json_rows(self, sql: str, min_timestamp: None = None, max_timestamp: datetime | None = None, limit: int | None = None, *, timezone: str | None = None, environment: str | list[str] | None = None) -> RowQueryResults: ...
66
+ @overload
67
+ def query_json_rows(self, sql: str, min_timestamp: datetime, max_timestamp: datetime | None = None, limit: int | None = None, *, timezone: str | None = None, environment: str | list[str] | None = None) -> RowQueryResults: ...
68
+ @overload
69
+ def query_arrow(self, sql: str, min_timestamp: None = None, max_timestamp: datetime | None = None, limit: int | None = None, *, timezone: str | None = None, environment: str | list[str] | None = None) -> Table: ...
70
+ @overload
71
+ def query_arrow(self, sql: str, min_timestamp: datetime, max_timestamp: datetime | None = None, limit: int | None = None, *, timezone: str | None = None, environment: str | list[str] | None = None) -> Table: ...
72
+ @overload
73
+ def query_csv(self, sql: str, min_timestamp: None = None, max_timestamp: datetime | None = None, limit: int | None = None, *, timezone: str | None = None, environment: str | list[str] | None = None) -> str: ...
74
+ @overload
75
+ def query_csv(self, sql: str, min_timestamp: datetime, max_timestamp: datetime | None = None, limit: int | None = None, *, timezone: str | None = None, environment: str | list[str] | None = None) -> str: ...
76
+
77
+ class AsyncLogfireQueryClient(_BaseLogfireQueryClient[AsyncClient]):
78
+ """An asynchronous client for querying Logfire data."""
79
+ def __init__(self, read_token: str, base_url: str | None = None, timeout: Timeout = ..., **async_client_kwargs: Any) -> None: ...
80
+ async def __aenter__(self) -> Self: ...
81
+ async def __aexit__(self, exc_type: type[BaseException] | None = None, exc_value: BaseException | None = None, traceback: TracebackType | None = None) -> None: ...
82
+ async def info(self) -> ReadTokenInfo:
83
+ """Get information about the read token."""
84
+ @overload
85
+ async def query_json_rows(self, sql: str, min_timestamp: None = None, max_timestamp: datetime | None = None, limit: int | None = None, *, timezone: str | None = None, environment: str | list[str] | None = None) -> RowQueryResults: ...
86
+ @overload
87
+ async def query_json_rows(self, sql: str, min_timestamp: datetime, max_timestamp: datetime | None = None, limit: int | None = None, *, timezone: str | None = None, environment: str | list[str] | None = None) -> RowQueryResults: ...
88
+ async def query_json(self, sql: str, min_timestamp: datetime | None = None, max_timestamp: datetime | None = None, limit: int | None = None) -> QueryResults:
89
+ """Query Logfire data and return the results as a column-oriented dictionary."""
90
+ async def query_json_rows(self, sql: str, min_timestamp: datetime | None = None, max_timestamp: datetime | None = None, limit: int | None = None, *, timezone: str | None = None, environment: str | list[str] | None = None) -> RowQueryResults:
91
+ """Query Logfire data and return the results as a row-oriented dictionary.
92
+
93
+ Args:
94
+ sql: The SQL `SELECT` query to execute.
95
+ min_timestamp: The minimum timestamp to use when querying data. If the provided
96
+ [`datetime`][datetime.datetime] doesn't have a timezone set, it is assumed to
97
+ be UTC.
98
+
99
+ /// version-deprecated | v4.35.0
100
+ Not providing a `min_timestamp` is deprecated.
101
+ ///
102
+ max_timestamp: The maximum timestamp to use when querying data. If the provided
103
+ [`datetime`][datetime.datetime] doesn't have a timezone set, it is assumed to
104
+ be UTC.
105
+ limit: The maximum number of rows to query. This value takes priority over the
106
+ `LIMIT` clause in the `sql` query.
107
+ timezone: The timezone to use for the query execution context.
108
+ environment: Restrict rows to the provided environment(s). To only query rows where no environment is set,
109
+ use the empty string (`''`).
110
+
111
+ Returns:
112
+ A dictionary with two entries:
113
+ * `columns`: A list of column details including the name, datatype and whether the column is nullable.
114
+ * `rows`: The list of rows matching the query.
115
+ """
116
+ @overload
117
+ async def query_arrow(self, sql: str, min_timestamp: None = None, max_timestamp: datetime | None = None, limit: int | None = None, *, timezone: str | None = None, environment: str | list[str] | None = None) -> Table: ...
118
+ @overload
119
+ async def query_arrow(self, sql: str, min_timestamp: datetime, max_timestamp: datetime | None = None, limit: int | None = None, *, timezone: str | None = None, environment: str | list[str] | None = None) -> Table: ...
120
+ @overload
121
+ async def query_csv(self, sql: str, min_timestamp: None = None, max_timestamp: datetime | None = None, limit: int | None = None, *, timezone: str | None = None, environment: str | list[str] | None = None) -> str: ...
122
+ @overload
123
+ async def query_csv(self, sql: str, min_timestamp: datetime, max_timestamp: datetime | None = None, limit: int | None = None, *, timezone: str | None = None, environment: str | list[str] | None = None) -> str: ...
@@ -0,0 +1,3 @@
1
+ from .experimental.query_client import AsyncLogfireQueryClient as AsyncLogfireQueryClient, ColumnData as ColumnData, ColumnDetails as ColumnDetails, InfoRequestError as InfoRequestError, LogfireQueryClient as LogfireQueryClient, QueryExecutionError as QueryExecutionError, QueryRequestError as QueryRequestError, QueryResults as QueryResults, ReadTokenInfo as ReadTokenInfo, RowQueryResults as RowQueryResults
2
+
3
+ __all__ = ['QueryExecutionError', 'QueryRequestError', 'InfoRequestError', 'ReadTokenInfo', 'ColumnDetails', 'ColumnData', 'QueryResults', 'RowQueryResults', 'LogfireQueryClient', 'AsyncLogfireQueryClient']
@@ -1,5 +1,5 @@
1
- from logfire.variables.abstract import ResolvedVariable as ResolvedVariable, SyncMode as SyncMode, ValidationReport as ValidationReport, VariableAlreadyExistsError as VariableAlreadyExistsError, VariableNotFoundError as VariableNotFoundError, VariableWriteError as VariableWriteError
1
+ from logfire.variables.abstract import ResolutionReason as ResolutionReason, ResolvedVariable as ResolvedVariable, SyncMode as SyncMode, ValidationReport as ValidationReport, VariableAlreadyExistsError as VariableAlreadyExistsError, VariableNotFoundError as VariableNotFoundError, VariableWriteError as VariableWriteError
2
2
  from logfire.variables.config import KeyIsNotPresent as KeyIsNotPresent, KeyIsPresent as KeyIsPresent, LabelRef as LabelRef, LabeledValue as LabeledValue, LatestVersion as LatestVersion, LocalVariablesOptions as LocalVariablesOptions, Rollout as Rollout, RolloutOverride as RolloutOverride, ValueDoesNotEqual as ValueDoesNotEqual, ValueDoesNotMatchRegex as ValueDoesNotMatchRegex, ValueEquals as ValueEquals, ValueIsIn as ValueIsIn, ValueIsNotIn as ValueIsNotIn, ValueMatchesRegex as ValueMatchesRegex, VariableConfig as VariableConfig, VariableTypeConfig as VariableTypeConfig, VariablesConfig as VariablesConfig
3
3
  from logfire.variables.variable import ResolveFunction as ResolveFunction, Variable as Variable, targeting_context as targeting_context
4
4
 
5
- __all__ = ['Variable', 'ResolvedVariable', 'ResolveFunction', 'VariablesConfig', 'VariableConfig', 'VariableTypeConfig', 'LocalVariablesOptions', 'LabeledValue', 'LabelRef', 'LatestVersion', 'Rollout', 'RolloutOverride', 'KeyIsPresent', 'KeyIsNotPresent', 'ValueEquals', 'ValueDoesNotEqual', 'ValueIsIn', 'ValueIsNotIn', 'ValueMatchesRegex', 'ValueDoesNotMatchRegex', 'targeting_context', 'SyncMode', 'ValidationReport', 'VariableAlreadyExistsError', 'VariableNotFoundError', 'VariableWriteError']
5
+ __all__ = ['Variable', 'ResolvedVariable', 'ResolveFunction', 'VariablesConfig', 'VariableConfig', 'VariableTypeConfig', 'LocalVariablesOptions', 'LabeledValue', 'LabelRef', 'LatestVersion', 'Rollout', 'RolloutOverride', 'KeyIsPresent', 'KeyIsNotPresent', 'ValueEquals', 'ValueDoesNotEqual', 'ValueIsIn', 'ValueIsNotIn', 'ValueMatchesRegex', 'ValueDoesNotMatchRegex', 'targeting_context', 'ResolutionReason', 'SyncMode', 'ValidationReport', 'VariableAlreadyExistsError', 'VariableNotFoundError', 'VariableWriteError']