Beyond the core timing and telemetry API, tif1 provides several utility functions to manage its internal state, performance, and reliability layers.
Logging
setup_logging
Configure the logging level for tif1.
def setup_logging(level: int = logging.WARNING) -> None
Parameters:
level: Standard logging level from the logging module
Available Levels:
logging.DEBUG: Detailed diagnostic information
logging.INFO: General informational messages
logging.WARNING: Warning messages (default)
logging.ERROR: Error messages only
logging.CRITICAL: Critical errors only
Example:
import tif1
import logging
# Enable debug logging
tif1.setup_logging(logging.DEBUG)
# Now all tif1 operations will log debug info
session = tif1.get_session(2021, "Belgian Grand Prix", "Race")
Debug Output Example:
DEBUG:tif1.core:Loading session: 2021/Belgian_Grand_Prix/Race
DEBUG:tif1.cache:Cache hit for drivers.json
DEBUG:tif1.http:Fetching https://cdn.jsdelivr.net/...
DEBUG:tif1.core:Loaded 20 drivers
Configuration
get_config
Returns the global configuration singleton instance.
def get_config() -> Config
The Config object allows you to programmatically get and set settings that are normally loaded from .tif1rc or environment variables.
Returns:
Config singleton instance
Example:
config = tif1.get_config()
# Get current settings
print(f"Lib: {config.get('lib')}")
print(f"Cache enabled: {config.get('enable_cache')}")
print(f"Timeout: {config.get('timeout')}")
# Update settings
config.set("lib", "polars")
config.set("timeout", 60)
# Save to file
config.save() # Saves to ~/.tif1rc
Config Methods
get(key, default=None)
Retrieve a configuration value.
lib = config.get("lib", "pandas")
timeout = config.get("timeout", 30)
set(key, value)
Update a configuration value in memory.
config.set("lib", "polars")
config.set("enable_cache", True)
config.set("ultra_cold_start", True)
save(path=None)
Save current configuration to a JSON file.
# Save to default location (~/.tif1rc)
config.save()
# Save to custom location
config.save("/path/to/custom/config.json")
Available configuration keys
| Key | Type | Default | Description |
|---|
lib | str | "pandas" | DataFrame lib ("pandas" or "polars") |
enable_cache | bool | True | Enable multi-layer caching system |
cache_dir | str | ~/.tif1/cache | Cache database location |
timeout | int | 30 | Network request timeout (seconds) |
max_retries | int | 3 | Maximum retry attempts for failed requests |
validate_data | bool | True | Enable Pydantic validation of JSON data |
ultra_cold_start | bool | False | Enable ultra-low latency mode |
circuit_breaker_threshold | int | 5 | Failures before circuit breaker opens |
circuit_breaker_timeout | int | 60 | Circuit breaker reset timeout (seconds) |
Cache Management
get_cache
Returns the persistent SQLite cache singleton instance.
Returns:
Example:
cache = tif1.get_cache()
# Check cache location
print(f"Cache dir: {cache.cache_dir}")
# Check if session data exists
has_data = cache.has_session_data(2025, "Monaco_Grand_Prix", "Race")
print(f"Has cached data: {has_data}")
# Clear all cache
cache.clear()
Cache Methods
clear()
Remove all entries from both memory and SQLite cache.
cache = tif1.get_cache()
cache.clear()
print("Cache cleared")
has_session_data(year, gp, session)
Check if cache contains data for a specific session.
exists = cache.has_session_data(2021, "Belgian_Grand_Prix", "Race")
if exists:
print("Session data is cached")
close()
Close the SQLite database connection.
cache = tif1.get_cache()
# ... operations ...
cache.close()
get(key)
Get raw cached data by key.
data = cache.get("2025/Monaco_Grand_Prix/Race/drivers.json")
set(key, data)
Store data in cache.
cache.set("custom_key", {"data": "value"})
get_telemetry(year, gp, session, driver, lap)
Get cached telemetry data.
tel_data = cache.get_telemetry(2021, "Belgian_Grand_Prix", "Race", "VER", 1)
set_telemetry(year, gp, session, driver, lap, data)
Store telemetry data in cache.
cache.set_telemetry(2021, "Belgian_Grand_Prix", "Race", "VER", 1, telemetry_dict)
Data Utilities
to_timedelta
Convert various formats to pandas timedelta.
def to_timedelta(x) -> pd.Timedelta
Parameters:
x: String, float, int, or timedelta to convert
Example:
from tif1.utils import to_timedelta
# From string
td = to_timedelta("1:23.456") # 1 minute 23.456 seconds
td = to_timedelta("00:01:23.456") # Full format
# From seconds
td = to_timedelta(83.456)
# From timedelta (passthrough)
td = to_timedelta(pd.Timedelta(seconds=83.456))
to_datetime
Convert string to pandas datetime.
def to_datetime(x) -> pd.Timestamp
Example:
from tif1.utils import to_datetime
dt = to_datetime("2021-08-29 14:00:00")
recursive_dict_get
Safely navigate nested dictionaries.
def recursive_dict_get(d, *keys, default_none=False)
Parameters:
d: Dictionary to navigate
*keys: Keys to traverse
default_none: Return None instead of on missing keys
Example:
from tif1.utils import recursive_dict_get
data = {
"session": {
"info": {
"name": "Monaco Grand Prix"
}
}
}
name = recursive_dict_get(data, "session", "info", "name")
# Returns: "Monaco Grand Prix"
missing = recursive_dict_get(data, "session", "missing", "key", default_none=True)
# Returns: None
delta_time
Calculate delta time between two laps (compatibility function).
def delta_time(reference_lap, compare_lap)
Parameters:
reference_lap: Reference Lap object
compare_lap: Lap object to compare
Returns:
- Tuple of (delta_series, ref_telemetry, comp_telemetry)
Reliability & Networking
get_circuit_breaker
Returns the global circuit breaker instance used for network requests.
def get_circuit_breaker() -> CircuitBreaker
The circuit breaker prevents cascading failures by temporarily stopping requests after repeated failures.
States:
closed: Normal operation, requests allowed
open: Too many failures, requests blocked
half_open: Testing if service recovered
Example:
from tif1.retry import get_circuit_breaker
cb = get_circuit_breaker()
print(f"State: {cb.state}")
print(f"Failures: {cb.failure_count}")
reset_circuit_breaker
Reset the circuit breaker to closed state.
def reset_circuit_breaker() -> None
Example:
from tif1.retry import reset_circuit_breaker
# Reset after network issues are resolved
reset_circuit_breaker()
get_cdn_manager
Returns the CDN manager responsible for fallback and source health.
def get_cdn_manager() -> CDNManager
Example:
from tif1.cdn import get_cdn_manager
cdn = get_cdn_manager()
print(f"Primary CDN: {cdn.primary_url}")
Lap Cache Management
clear_lap_cache
Clear the in-memory LRU cache for lap DataFrames.
def clear_lap_cache() -> None
Example:
from tif1.core import clear_lap_cache
# Clear lap cache to free memory
clear_lap_cache()
Complete Examples
import tif1
# Get config
config = tif1.get_config()
# Update settings
config.set("lib", "polars")
config.set("timeout", 60)
config.set("max_retries", 5)
config.set("ultra_cold_start", True)
# Save to file
config.save()
print("Configuration saved to ~/.tif1rc")
Debug session loading
import tif1
import logging
# Enable debug logging
tif1.setup_logging(logging.DEBUG)
# Load session with debug output
session = tif1.get_session(2021, "Belgian Grand Prix", "Race")
laps = session.laps
# Disable debug logging
tif1.setup_logging(logging.WARNING)
Cache management workflow
import tif1
# Get cache instance
cache = tif1.get_cache()
# Check cache status
print(f"Cache location: {cache.cache_dir}")
# Check if specific session is cached
has_spa = cache.has_session_data(2021, "Belgian_Grand_Prix", "Race")
print(f"Belgian GP cached: {has_spa}")
# Clear cache if needed
if input("Clear cache? (y/n): ").lower() == 'y':
cache.clear()
print("Cache cleared")
Handle network issues
import tif1
from tif1.retry import get_circuit_breaker, reset_circuit_breaker
try:
session = tif1.get_session(2021, "Belgian Grand Prix", "Race")
laps = session.laps
except tif1.NetworkError as e:
print(f"Network error: {e.message}")
# Check circuit breaker state
cb = get_circuit_breaker()
print(f"Circuit breaker state: {cb.state}")
if cb.state == "open":
print("Circuit breaker is open. Waiting before retry...")
import time
time.sleep(60)
# Reset and retry
reset_circuit_breaker()
session = tif1.get_session(2021, "Belgian Grand Prix", "Race")
Custom configuration file
import tif1
from pathlib import Path
# Load custom config
config = tif1.get_config()
# Set custom cache directory
custom_cache = Path.home() / "my_f1_cache"
config.set("cache_dir", str(custom_cache))
# Set performance options
config.set("lib", "polars")
config.set("ultra_cold_start", True)
config.set("validate_data", False) # Skip validation for speed
# Save to custom location
config.save(Path.home() / ".my_tif1_config")
Best Practices
-
Enable debug logging during development: Helps understand data flow and identify issues.
-
Use polars lib for large datasets: Better memory efficiency and performance.
-
Clear cache periodically: Prevents disk space issues.
-
Increase timeout for slow connections: Default 30s may not be enough on slow networks.
-
Disable validation in production: Saves ~10-15% processing time if data quality is trusted.
-
Use ultra-cold start for single lap queries: Significantly faster when you only need one lap’s telemetry.
-
Save configuration after tuning: Persist your optimized settings.
-
Monitor circuit breaker state: Helps diagnose network issues.
-
Close cache on exit: Ensures data is flushed to disk.
import atexit
import tif1
cache = tif1.get_cache()
atexit.register(cache.close)
Last modified on March 5, 2026