Added ability to customize logfire base url through env var (#19148)

* Added ability to customize logfire base url through env var

* Added test to check if env var is used correctly for logfire

* Document the env var

* Documented env var in config_settings.md
This commit is contained in:
Vikash 2026-01-15 13:40:59 -05:00 • committed by GitHub
parent 8b7c36c271
commit c619569604
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 54 additions and 2 deletions

View file

@ -40,6 +40,10 @@ import os
# from https://logfire.pydantic.dev/
os.environ["LOGFIRE_TOKEN"] = ""
# Optionally customize the base url
# from https://logfire.pydantic.dev/
os.environ["LOGFIRE_BASE_URL"] = ""
# LLM API Keys
os.environ['OPENAI_API_KEY']=""

View file

@ -744,6 +744,7 @@ router_settings:
| LITELLM_PRINT_STANDARD_LOGGING_PAYLOAD | If true, prints the standard logging payload to the console - useful for debugging
| LITELM_ENVIRONMENT | Environment for LiteLLM Instance. This is currently only logged to DeepEval to determine the environment for DeepEval integration.
| LOGFIRE_TOKEN | Token for Logfire logging service
| LOGFIRE_BASE_URL | Base URL for Logfire logging service (useful for self hosted deployments)
| LOGGING_WORKER_CONCURRENCY | Maximum number of concurrent coroutine slots for the logging worker on the asyncio event loop. Default is 100. Setting too high will flood the event loop with logging tasks which will lower the overall latency of the requests.
| LOGGING_WORKER_MAX_QUEUE_SIZE | Maximum size of the logging worker queue. When the queue is full, the worker aggressively clears tasks to make room instead of dropping logs. Default is 50,000
| LOGGING_WORKER_MAX_TIME_PER_COROUTINE | Maximum time in seconds allowed for each coroutine in the logging worker before timing out. Default is 20.0

View file

@ -3743,10 +3743,10 @@ def _init_custom_logger_compatible_class( # noqa: PLR0915
OpenTelemetry,
OpenTelemetryConfig,
)
logfire_base_url = os.getenv("LOGFIRE_BASE_URL", "https://logfire-api.pydantic.dev")
otel_config = OpenTelemetryConfig(
exporter="otlp_http",
endpoint="https://logfire-api.pydantic.dev/v1/traces",
endpoint = f"{logfire_base_url.rstrip('/')}/v1/traces",
headers=f"Authorization={os.getenv('LOGFIRE_TOKEN')}",
)
for callback in _in_memory_loggers:

View file

@ -196,6 +196,53 @@ async def test_datadog_logger_not_shadowed_by_llm_obs(monkeypatch):
logging_module._in_memory_loggers.clear()
@pytest.mark.asyncio
async def test_logfire_logger_accepts_env_vars_for_base_url(monkeypatch):
"""Ensure Logfire logger uses LOGFIRE_BASE_URL to build the OTLP HTTP endpoint (/v1/traces)."""
# Required env vars for Logfire integration
monkeypatch.setenv("LOGFIRE_TOKEN", "test-token")
monkeypatch.setenv("LOGFIRE_BASE_URL", "https://logfire-api-custom.pydantic.dev") # no trailing slash on purpose
# Import after env vars are set (important if module-level caching exists)
from litellm.litellm_core_utils import litellm_logging as logging_module
from litellm.integrations.opentelemetry import OpenTelemetry # logger class
logging_module._in_memory_loggers.clear()
try:
# Instantiate via the same mechanism LiteLLM uses for callbacks=["logfire"]
logger = logging_module._init_custom_logger_compatible_class(
logging_integration="logfire",
internal_usage_cache=None,
llm_router=None,
custom_logger_init_args={},
)
# Sanity: we got the right logger type and it is cached
assert type(logger) is OpenTelemetry
assert any(type(cb) is OpenTelemetry for cb in logging_module._in_memory_loggers)
# Core regression check: base URL env var should influence the exporter endpoint.
#
# OpenTelemetry integration has historically stored config on the instance.
# We defensively check a few common attribute names to avoid brittle coupling.
cfg = (
getattr(logger, "otel_config", None)
or getattr(logger, "config", None)
or getattr(logger, "_otel_config", None)
)
assert cfg is not None, "Expected OpenTelemetry logger to keep an otel config on the instance"
endpoint = getattr(cfg, "endpoint", None) or getattr(cfg, "otlp_endpoint", None)
assert endpoint is not None, "Expected otel config to expose the OTLP endpoint"
assert endpoint == "https://logfire-api-custom.pydantic.dev/v1/traces"
finally:
logging_module._in_memory_loggers.clear()
@pytest.mark.asyncio
async def test_logging_result_for_bridge_calls(logging_obj):
"""