mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-10 03:28:53 +00:00
(UI + SpendLogs) - Store SpendLogs in UTC Timezone, Fix filtering logs by start/end time (#8190)
* fix request_id field * spend logs store time in UTC * fix ui_view_spend_logs * UI make time filter queries in UTC * fix time filters * fix TimeCellProps * ui use UTC for filtering time
This commit is contained in:
parent
c0f3100934
commit
8ba60bf13c
5 changed files with 71 additions and 18 deletions
|
|
@ -1,7 +1,7 @@
|
|||
#### SPEND MANAGEMENT #####
|
||||
import collections
|
||||
import os
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import TYPE_CHECKING, Any, List, Optional
|
||||
|
||||
import fastapi
|
||||
|
|
@ -1688,13 +1688,18 @@ async def ui_view_spend_logs( # noqa: PLR0915
|
|||
)
|
||||
|
||||
try:
|
||||
|
||||
# Convert the date strings to datetime objects
|
||||
start_date_obj = datetime.strptime(start_date, "%Y-%m-%d %H:%M:%S")
|
||||
end_date_obj = datetime.strptime(end_date, "%Y-%m-%d %H:%M:%S")
|
||||
start_date_obj = datetime.strptime(start_date, "%Y-%m-%d %H:%M:%S").replace(
|
||||
tzinfo=timezone.utc
|
||||
)
|
||||
end_date_obj = datetime.strptime(end_date, "%Y-%m-%d %H:%M:%S").replace(
|
||||
tzinfo=timezone.utc
|
||||
)
|
||||
|
||||
# Convert to ISO format strings for Prisma
|
||||
start_date_iso = start_date_obj.isoformat() + "Z" # Add Z to indicate UTC
|
||||
end_date_iso = end_date_obj.isoformat() + "Z" # Add Z to indicate UTC
|
||||
start_date_iso = start_date_obj.isoformat() # Already in UTC, no need to add Z
|
||||
end_date_iso = end_date_obj.isoformat() # Already in UTC, no need to add Z
|
||||
|
||||
# Build where conditions
|
||||
where_conditions: dict[str, Any] = {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import json
|
||||
import secrets
|
||||
from datetime import datetime
|
||||
from datetime import datetime as dt
|
||||
from datetime import timezone
|
||||
from typing import Optional, cast
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
|
@ -153,9 +155,9 @@ def get_logging_payload( # noqa: PLR0915
|
|||
call_type=call_type or "",
|
||||
api_key=str(api_key),
|
||||
cache_hit=str(cache_hit),
|
||||
startTime=start_time,
|
||||
endTime=end_time,
|
||||
completionStartTime=completion_start_time,
|
||||
startTime=_ensure_datetime_utc(start_time),
|
||||
endTime=_ensure_datetime_utc(end_time),
|
||||
completionStartTime=_ensure_datetime_utc(completion_start_time),
|
||||
model=kwargs.get("model", "") or "",
|
||||
user=kwargs.get("litellm_params", {})
|
||||
.get("metadata", {})
|
||||
|
|
@ -195,6 +197,12 @@ def get_logging_payload( # noqa: PLR0915
|
|||
raise e
|
||||
|
||||
|
||||
def _ensure_datetime_utc(timestamp: datetime) -> datetime:
|
||||
"""Helper to ensure datetime is in UTC"""
|
||||
timestamp = timestamp.astimezone(timezone.utc)
|
||||
return timestamp
|
||||
|
||||
|
||||
async def get_spend_by_team_and_customer(
|
||||
start_date: dt,
|
||||
end_date: dt,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import React from "react";
|
|||
import { CountryCell } from "./country_cell";
|
||||
import { getProviderLogoAndName } from "../provider_info_helpers";
|
||||
import { Tooltip } from "antd";
|
||||
import { TimeCell } from "./time_cell";
|
||||
|
||||
export type LogEntry = {
|
||||
request_id: string;
|
||||
|
|
@ -53,17 +54,17 @@ export const columns: ColumnDef<LogEntry>[] = [
|
|||
{
|
||||
header: "Time",
|
||||
accessorKey: "startTime",
|
||||
cell: (info: any) => (
|
||||
<span>{moment(info.getValue()).format("MMM DD HH:mm:ss")}</span>
|
||||
),
|
||||
cell: (info: any) => <TimeCell utcTime={info.getValue()} />,
|
||||
},
|
||||
{
|
||||
header: "Request ID",
|
||||
accessorKey: "request_id",
|
||||
cell: (info: any) => (
|
||||
<span className="font-mono text-xs max-w-[100px] truncate block">
|
||||
{String(info.getValue() || "")}
|
||||
</span>
|
||||
<Tooltip title={String(info.getValue() || "")}>
|
||||
<span className="font-mono text-xs max-w-[100px] truncate block">
|
||||
{String(info.getValue() || "")}
|
||||
</span>
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -105,10 +105,11 @@ export default function SpendLogsTable({
|
|||
};
|
||||
}
|
||||
|
||||
const formattedStartTime = moment(startTime).format("YYYY-MM-DD HH:mm:ss");
|
||||
// Convert times to UTC before formatting
|
||||
const formattedStartTime = moment(startTime).utc().format("YYYY-MM-DD HH:mm:ss");
|
||||
const formattedEndTime = isCustomDate
|
||||
? moment(endTime).format("YYYY-MM-DD HH:mm:ss")
|
||||
: moment().format("YYYY-MM-DD HH:mm:ss");
|
||||
? moment(endTime).utc().format("YYYY-MM-DD HH:mm:ss")
|
||||
: moment().utc().format("YYYY-MM-DD HH:mm:ss");
|
||||
|
||||
return await uiSpendLogsCall(
|
||||
accessToken,
|
||||
|
|
@ -176,7 +177,7 @@ export default function SpendLogsTable({
|
|||
<h1 className="text-xl font-semibold">Request Logs</h1>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-lg shadow overflow-hidden">
|
||||
<div className="bg-white rounded-lg shadow">
|
||||
<div className="border-b px-6 py-4">
|
||||
<div className="flex flex-col md:flex-row items-start md:items-center justify-between space-y-4 md:space-y-0">
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
|
|
|
|||
38
ui/litellm-dashboard/src/components/view_logs/time_cell.tsx
Normal file
38
ui/litellm-dashboard/src/components/view_logs/time_cell.tsx
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import * as React from "react";
|
||||
|
||||
interface TimeCellProps {
|
||||
utcTime: string;
|
||||
}
|
||||
|
||||
const getLocalTime = (utcTime: string): string => {
|
||||
try {
|
||||
const date = new Date(utcTime);
|
||||
return date.toLocaleString('en-US', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
hour12: true
|
||||
}).replace(',', '');
|
||||
} catch (e) {
|
||||
return "Error converting time";
|
||||
}
|
||||
};
|
||||
|
||||
export const TimeCell: React.FC<TimeCellProps> = ({ utcTime }) => {
|
||||
return (
|
||||
<span style={{
|
||||
fontFamily: 'monospace',
|
||||
width: '180px',
|
||||
display: 'inline-block'
|
||||
}}>
|
||||
{getLocalTime(utcTime)}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
export const getTimeZone = (): string => {
|
||||
return Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
};
|
||||
Loading…
Add table
Reference in a new issue