mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-12 23:01:41 +00:00
WIP: Add overhead breakdown infrastructure for UI logs
[INCOMPLETE] This commit adds the infrastructure to display overhead breakdown in UI logs but does NOT yet collect all the timing data. What's implemented: - Added overhead_breakdown field to SpendLogsMetadata - Added extraction logic for cache_read_time_ms and retry_count (from existing data) - Added UI component to display overhead breakdown in LogDetailsDrawer What's NOT implemented (data collection missing): - Auth time tracking (auth_time_ms) - Request translation time tracking (request_translation_time_ms) - Response translation time tracking (response_translation_time_ms) The infrastructure follows existing patterns (same as cost_breakdown) and is backward compatible. Currently only displays cache timing and retry count. Auth and translation timing need to be added in follow-up commits.
This commit is contained in:
parent
59cab4d2aa
commit
d86346c65b
3 changed files with 109 additions and 0 deletions
|
|
@ -2845,6 +2845,9 @@ class SpendLogsMetadata(TypedDict):
|
|||
cost_breakdown: Optional[
|
||||
CostBreakdown
|
||||
] # Detailed cost breakdown (input_cost, output_cost, margin, discount, etc.)
|
||||
overhead_breakdown: Optional[
|
||||
dict
|
||||
] # Detailed overhead breakdown: auth_time_ms, cache_read_time_ms, request_translation_time_ms, response_translation_time_ms, retry_count
|
||||
|
||||
|
||||
class SpendLogsPayload(TypedDict):
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ def _get_spend_logs_metadata(
|
|||
cold_storage_object_key: Optional[str] = None,
|
||||
litellm_overhead_time_ms: Optional[float] = None,
|
||||
cost_breakdown: Optional[CostBreakdown] = None,
|
||||
overhead_breakdown: Optional[dict] = None,
|
||||
) -> SpendLogsMetadata:
|
||||
if metadata is None:
|
||||
return SpendLogsMetadata(
|
||||
|
|
@ -87,6 +88,7 @@ def _get_spend_logs_metadata(
|
|||
cold_storage_object_key=cold_storage_object_key,
|
||||
litellm_overhead_time_ms=None,
|
||||
cost_breakdown=None,
|
||||
overhead_breakdown=None,
|
||||
)
|
||||
verbose_proxy_logger.debug(
|
||||
"getting payload for SpendLogs, available keys in metadata: "
|
||||
|
|
@ -113,6 +115,7 @@ def _get_spend_logs_metadata(
|
|||
clean_metadata["cold_storage_object_key"] = cold_storage_object_key
|
||||
clean_metadata["litellm_overhead_time_ms"] = litellm_overhead_time_ms
|
||||
clean_metadata["cost_breakdown"] = cost_breakdown
|
||||
clean_metadata["overhead_breakdown"] = overhead_breakdown
|
||||
|
||||
return clean_metadata
|
||||
|
||||
|
|
@ -311,9 +314,50 @@ def get_logging_payload( # noqa: PLR0915
|
|||
|
||||
# Extract overhead from hidden_params if available
|
||||
litellm_overhead_time_ms = None
|
||||
overhead_breakdown = None
|
||||
if standard_logging_payload is not None:
|
||||
hidden_params = standard_logging_payload.get("hidden_params", {})
|
||||
litellm_overhead_time_ms = hidden_params.get("litellm_overhead_time_ms")
|
||||
|
||||
# Extract overhead breakdown from metadata or hidden_params
|
||||
overhead_breakdown = (
|
||||
standard_logging_payload.get("metadata", {}).get("overhead_breakdown")
|
||||
or hidden_params.get("overhead_breakdown")
|
||||
)
|
||||
|
||||
# If overhead_breakdown doesn't exist, try to construct it from available data
|
||||
if overhead_breakdown is None:
|
||||
overhead_breakdown = {}
|
||||
|
||||
# Extract cache read time from caching_details
|
||||
caching_details = standard_logging_payload.get("metadata", {}).get("caching_details")
|
||||
if caching_details and isinstance(caching_details, dict):
|
||||
cache_duration_ms = caching_details.get("cache_duration_ms")
|
||||
if cache_duration_ms is not None:
|
||||
overhead_breakdown["cache_read_time_ms"] = cache_duration_ms
|
||||
|
||||
# Extract retry count from previous_models
|
||||
previous_models = metadata.get("previous_models", [])
|
||||
if previous_models and isinstance(previous_models, list):
|
||||
overhead_breakdown["retry_count"] = len(previous_models)
|
||||
|
||||
# Extract auth time from metadata if available
|
||||
auth_time_ms = metadata.get("auth_time_ms")
|
||||
if auth_time_ms is not None:
|
||||
overhead_breakdown["auth_time_ms"] = auth_time_ms
|
||||
|
||||
# Extract translation times from metadata if available
|
||||
request_translation_time_ms = metadata.get("request_translation_time_ms")
|
||||
if request_translation_time_ms is not None:
|
||||
overhead_breakdown["request_translation_time_ms"] = request_translation_time_ms
|
||||
|
||||
response_translation_time_ms = metadata.get("response_translation_time_ms")
|
||||
if response_translation_time_ms is not None:
|
||||
overhead_breakdown["response_translation_time_ms"] = response_translation_time_ms
|
||||
|
||||
# Only set overhead_breakdown if we have at least one value
|
||||
if not overhead_breakdown:
|
||||
overhead_breakdown = None
|
||||
|
||||
# clean up litellm metadata
|
||||
clean_metadata = _get_spend_logs_metadata(
|
||||
|
|
@ -366,6 +410,7 @@ def get_logging_payload( # noqa: PLR0915
|
|||
if standard_logging_payload is not None
|
||||
else None
|
||||
),
|
||||
overhead_breakdown=overhead_breakdown,
|
||||
)
|
||||
|
||||
special_usage_fields = ["completion_tokens", "prompt_tokens", "total_tokens"]
|
||||
|
|
|
|||
|
|
@ -190,6 +190,9 @@ export function LogDetailsDrawer({
|
|||
{/* Metrics Section */}
|
||||
<MetricsSection logEntry={logEntry} metadata={metadata} />
|
||||
|
||||
{/* Overhead Breakdown - Show if overhead breakdown data is available */}
|
||||
<OverheadBreakdownSection metadata={metadata} />
|
||||
|
||||
{/* Cost Breakdown - Show if cost breakdown data is available */}
|
||||
<CostBreakdownViewer costBreakdown={metadata?.cost_breakdown} totalSpend={logEntry.spend || 0} />
|
||||
|
||||
|
|
@ -337,6 +340,64 @@ function MetricsSection({ logEntry, metadata }: { logEntry: LogEntry; metadata:
|
|||
);
|
||||
}
|
||||
|
||||
function OverheadBreakdownSection({ metadata }: { metadata: Record<string, any> }) {
|
||||
const overheadBreakdown = metadata?.overhead_breakdown;
|
||||
|
||||
if (!overheadBreakdown || typeof overheadBreakdown !== 'object') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const hasAnyData =
|
||||
overheadBreakdown.auth_time_ms !== undefined ||
|
||||
overheadBreakdown.cache_read_time_ms !== undefined ||
|
||||
overheadBreakdown.request_translation_time_ms !== undefined ||
|
||||
overheadBreakdown.response_translation_time_ms !== undefined ||
|
||||
overheadBreakdown.retry_count !== undefined;
|
||||
|
||||
if (!hasAnyData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const formatTime = (ms: number | undefined) => {
|
||||
if (ms === undefined || ms === null) return "-";
|
||||
return `${ms.toFixed(2)} ms`;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="bg-white rounded-lg shadow w-full max-w-full overflow-hidden mb-6">
|
||||
<Card title="Overhead Breakdown" size="small" bordered={false} style={{ marginBottom: 0 }}>
|
||||
<Descriptions column={2} size="small">
|
||||
{overheadBreakdown.auth_time_ms !== undefined && (
|
||||
<Descriptions.Item label="Time in Auth">
|
||||
{formatTime(overheadBreakdown.auth_time_ms)}
|
||||
</Descriptions.Item>
|
||||
)}
|
||||
{overheadBreakdown.cache_read_time_ms !== undefined && (
|
||||
<Descriptions.Item label="Time Reading Cache">
|
||||
{formatTime(overheadBreakdown.cache_read_time_ms)}
|
||||
</Descriptions.Item>
|
||||
)}
|
||||
{overheadBreakdown.request_translation_time_ms !== undefined && (
|
||||
<Descriptions.Item label="Time in Request Translation">
|
||||
{formatTime(overheadBreakdown.request_translation_time_ms)}
|
||||
</Descriptions.Item>
|
||||
)}
|
||||
{overheadBreakdown.response_translation_time_ms !== undefined && (
|
||||
<Descriptions.Item label="Time in Response Translation">
|
||||
{formatTime(overheadBreakdown.response_translation_time_ms)}
|
||||
</Descriptions.Item>
|
||||
)}
|
||||
{overheadBreakdown.retry_count !== undefined && overheadBreakdown.retry_count !== null && (
|
||||
<Descriptions.Item label="Number of Retries">
|
||||
{overheadBreakdown.retry_count}
|
||||
</Descriptions.Item>
|
||||
)}
|
||||
</Descriptions>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
interface RequestResponseSectionProps {
|
||||
hasResponse: boolean;
|
||||
getRawRequest: () => any;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue