Skip to content

Commit ba62e80

Browse files
adriangbViicos
authored andcommitted
derive base urls from tokens' regions
1 parent 40816f9 commit ba62e80

File tree

4 files changed

+28
-13
lines changed

4 files changed

+28
-13
lines changed

logfire/_internal/cli.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
from .auth import DEFAULT_FILE, HOME_LOGFIRE, DefaultFile, is_logged_in, poll_for_token, request_device_code
2828
from .config import LogfireCredentials
2929
from .config_params import ParamManager
30-
from .constants import LOGFIRE_BASE_URL
3130
from .tracer import SDKTracerProvider
3231
from .utils import read_toml_file
3332

@@ -398,7 +397,7 @@ def _main(args: list[str] | None = None) -> None:
398397

399398
parser.add_argument('--version', action='store_true', help='show the version and exit')
400399
global_opts = parser.add_argument_group(title='global options')
401-
global_opts.add_argument('--logfire-url', default=LOGFIRE_BASE_URL, help=argparse.SUPPRESS)
400+
global_opts.add_argument('--logfire-url', default='', help=argparse.SUPPRESS)
402401
parser.set_defaults(func=lambda _: parser.print_help()) # type: ignore
403402
subparsers = parser.add_subparsers(title='commands', metavar='')
404403

logfire/_internal/config.py

+21-6
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ class ConsoleOptions:
158158
class AdvancedOptions:
159159
"""Options primarily used for testing by Logfire developers."""
160160

161-
base_url: str = 'https://logfire-api.pydantic.dev'
161+
base_url: str | None = None
162162
"""Root URL for the Logfire API."""
163163

164164
id_generator: IdGenerator = dataclasses.field(default_factory=lambda: SeededRandomIdGenerator(None))
@@ -173,6 +173,19 @@ class AdvancedOptions:
173173
log_record_processors: Sequence[LogRecordProcessor] = ()
174174
"""Configuration for OpenTelemetry logging. This is experimental and may be removed."""
175175

176+
def generate_base_url(self, token: str | None) -> str:
177+
if token and '-' in token:
178+
region, _ = token.split('-', maxsplit=1)
179+
else:
180+
region = None
181+
if self.base_url is not None:
182+
return self.base_url
183+
if region:
184+
return f'https://api-{region}.pydantic.dev'
185+
else:
186+
# default to us region for tokens that were created before regions were added
187+
return 'https://logfire-api.pydantic.dev'
188+
176189

177190
@dataclass
178191
class PydanticPlugin:
@@ -864,7 +877,9 @@ def add_span_processor(span_processor: SpanProcessor) -> None:
864877
# note, we only do this if `send_to_logfire` is explicitly `True`, not 'if-token-present'
865878
if self.send_to_logfire is True and credentials is None:
866879
credentials = LogfireCredentials.initialize_project(
867-
logfire_api_url=self.advanced.base_url,
880+
# TODO: what happens here? Seems like we need to assume a region to create the new project?
881+
# Should the SDK have the region from when the user logged in to the SDK?
882+
logfire_api_url=self.advanced.generate_base_url(None),
868883
session=requests.Session(),
869884
)
870885
credentials.write_creds_file(self.data_dir)
@@ -891,7 +906,7 @@ def check_token():
891906
session = OTLPExporterHttpSession(max_body_size=OTLP_MAX_BODY_SIZE)
892907
session.headers.update(headers)
893908
span_exporter = OTLPSpanExporter(
894-
endpoint=urljoin(self.advanced.base_url, '/v1/traces'),
909+
endpoint=urljoin(self.advanced.generate_base_url(self.token), '/v1/traces'),
895910
session=session,
896911
compression=Compression.Gzip,
897912
)
@@ -915,7 +930,7 @@ def check_token():
915930
PeriodicExportingMetricReader(
916931
QuietMetricExporter(
917932
OTLPMetricExporter(
918-
endpoint=urljoin(self.advanced.base_url, '/v1/metrics'),
933+
endpoint=urljoin(self.advanced.generate_base_url(self.token), '/v1/metrics'),
919934
headers=headers,
920935
session=session,
921936
compression=Compression.Gzip,
@@ -930,7 +945,7 @@ def check_token():
930945
)
931946

932947
log_exporter = OTLPLogExporter(
933-
endpoint=urljoin(self.advanced.base_url, '/v1/logs'),
948+
endpoint=urljoin(self.advanced.generate_base_url(self.token), '/v1/logs'),
934949
session=session,
935950
compression=Compression.Gzip,
936951
)
@@ -1151,7 +1166,7 @@ def warn_if_not_initialized(self, message: str):
11511166
)
11521167

11531168
def _initialize_credentials_from_token(self, token: str) -> LogfireCredentials | None:
1154-
return LogfireCredentials.from_token(token, requests.Session(), self.advanced.base_url)
1169+
return LogfireCredentials.from_token(token, requests.Session(), self.advanced.generate_base_url(token))
11551170

11561171
def _ensure_flush_after_aws_lambda(self):
11571172
"""Ensure that `force_flush` is called after an AWS Lambda invocation.

logfire/_internal/config_params.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from logfire.exceptions import LogfireConfigError
1414

1515
from . import config
16-
from .constants import LOGFIRE_BASE_URL, LevelName
16+
from .constants import LevelName
1717
from .exporters.console import ConsoleColorsValues
1818
from .utils import read_toml_file
1919

@@ -98,7 +98,9 @@ class _DefaultCallback:
9898
"""Whether to enable the f-string magic feature. On by default for Python 3.11 and above."""
9999
IGNORE_NO_CONFIG = ConfigParam(env_vars=['LOGFIRE_IGNORE_NO_CONFIG'], allow_file_config=True, default=False, tp=bool)
100100
"""Whether to show a warning message if logfire if used without calling logfire.configure()"""
101-
BASE_URL = ConfigParam(env_vars=['LOGFIRE_BASE_URL'], allow_file_config=True, default=LOGFIRE_BASE_URL)
101+
BASE_URL = ConfigParam(env_vars=['LOGFIRE_BASE_URL'], allow_file_config=True, default=None, tp=Union[str, None])
102+
REGION = ConfigParam(env_vars=['LOGFIRE_REGION'], allow_file_config=True, default='us')
103+
"""The region of the Logfire backend."""
102104
"""The base URL of the Logfire backend. Primarily for testing purposes."""
103105
DISTRIBUTED_TRACING = ConfigParam(env_vars=['LOGFIRE_DISTRIBUTED_TRACING'], allow_file_config=True, default=None, tp=bool)
104106
"""Whether to extract incoming trace context. By default, will extract but warn about it."""
@@ -205,6 +207,8 @@ def _cast(self, value: Any, name: str, tp: type[T]) -> T | None:
205207
return float(value) # type: ignore
206208
if tp is Path:
207209
return Path(value) # type: ignore
210+
if tp in (None, type(None)) and value in (None, ''):
211+
return None
208212
if get_origin(tp) is set and get_args(tp) == (str,): # pragma: no branch
209213
return _extract_set_of_str(value) # type: ignore
210214
raise RuntimeError(f'Unexpected type {tp}') # pragma: no cover

logfire/_internal/constants.py

-3
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,6 @@ def log_level_attributes(level: LevelName | int) -> dict[str, otel_types.Attribu
137137
ATTRIBUTES_SCRUBBED_KEY = f'{LOGFIRE_ATTRIBUTES_NAMESPACE}.scrubbed'
138138
"""Key in OTEL attributes with metadata about parts of a span that have been scrubbed."""
139139

140-
LOGFIRE_BASE_URL = 'https://logfire-api.pydantic.dev'
141-
"""The Logfire API base URL."""
142-
143140
RESOURCE_ATTRIBUTES_PACKAGE_VERSIONS = 'logfire.package_versions'
144141
"""Versions of installed packages, serialized as list of json objects with keys 'name' and 'version'."""
145142

0 commit comments

Comments
 (0)