File tree Expand file tree Collapse file tree 5 files changed +71
-18
lines changed
litellm/proxy/spend_tracking
ui/litellm-dashboard/src/components/view_logs Expand file tree Collapse file tree 5 files changed +71
-18
lines changed Original file line number Diff line number Diff line change 1
1
#### SPEND MANAGEMENT #####
2
2
import collections
3
3
import os
4
- from datetime import datetime , timedelta
4
+ from datetime import datetime , timedelta , timezone
5
5
from typing import TYPE_CHECKING , Any , List , Optional
6
6
7
7
import fastapi
@@ -1688,13 +1688,18 @@ async def ui_view_spend_logs( # noqa: PLR0915
1688
1688
)
1689
1689
1690
1690
try :
1691
+
1691
1692
# Convert the date strings to datetime objects
1692
- start_date_obj = datetime .strptime (start_date , "%Y-%m-%d %H:%M:%S" )
1693
- end_date_obj = datetime .strptime (end_date , "%Y-%m-%d %H:%M:%S" )
1693
+ start_date_obj = datetime .strptime (start_date , "%Y-%m-%d %H:%M:%S" ).replace (
1694
+ tzinfo = timezone .utc
1695
+ )
1696
+ end_date_obj = datetime .strptime (end_date , "%Y-%m-%d %H:%M:%S" ).replace (
1697
+ tzinfo = timezone .utc
1698
+ )
1694
1699
1695
1700
# Convert to ISO format strings for Prisma
1696
- start_date_iso = start_date_obj .isoformat () + "Z" # Add Z to indicate UTC
1697
- end_date_iso = end_date_obj .isoformat () + "Z" # Add Z to indicate UTC
1701
+ start_date_iso = start_date_obj .isoformat () # Already in UTC, no need to add Z
1702
+ end_date_iso = end_date_obj .isoformat () # Already in UTC, no need to add Z
1698
1703
1699
1704
# Build where conditions
1700
1705
where_conditions : dict [str , Any ] = {
Original file line number Diff line number Diff line change 1
1
import json
2
2
import secrets
3
+ from datetime import datetime
3
4
from datetime import datetime as dt
5
+ from datetime import timezone
4
6
from typing import Optional , cast
5
7
6
8
from pydantic import BaseModel
@@ -153,9 +155,9 @@ def get_logging_payload( # noqa: PLR0915
153
155
call_type = call_type or "" ,
154
156
api_key = str (api_key ),
155
157
cache_hit = str (cache_hit ),
156
- startTime = start_time ,
157
- endTime = end_time ,
158
- completionStartTime = completion_start_time ,
158
+ startTime = _ensure_datetime_utc ( start_time ) ,
159
+ endTime = _ensure_datetime_utc ( end_time ) ,
160
+ completionStartTime = _ensure_datetime_utc ( completion_start_time ) ,
159
161
model = kwargs .get ("model" , "" ) or "" ,
160
162
user = kwargs .get ("litellm_params" , {})
161
163
.get ("metadata" , {})
@@ -195,6 +197,12 @@ def get_logging_payload( # noqa: PLR0915
195
197
raise e
196
198
197
199
200
+ def _ensure_datetime_utc (timestamp : datetime ) -> datetime :
201
+ """Helper to ensure datetime is in UTC"""
202
+ timestamp = timestamp .astimezone (timezone .utc )
203
+ return timestamp
204
+
205
+
198
206
async def get_spend_by_team_and_customer (
199
207
start_date : dt ,
200
208
end_date : dt ,
Original file line number Diff line number Diff line change @@ -5,6 +5,7 @@ import React from "react";
5
5
import { CountryCell } from "./country_cell" ;
6
6
import { getProviderLogoAndName } from "../provider_info_helpers" ;
7
7
import { Tooltip } from "antd" ;
8
+ import { TimeCell } from "./time_cell" ;
8
9
9
10
export type LogEntry = {
10
11
request_id : string ;
@@ -53,17 +54,17 @@ export const columns: ColumnDef<LogEntry>[] = [
53
54
{
54
55
header : "Time" ,
55
56
accessorKey : "startTime" ,
56
- cell : ( info : any ) => (
57
- < span > { moment ( info . getValue ( ) ) . format ( "MMM DD HH:mm:ss" ) } </ span >
58
- ) ,
57
+ cell : ( info : any ) => < TimeCell utcTime = { info . getValue ( ) } /> ,
59
58
} ,
60
59
{
61
60
header : "Request ID" ,
62
61
accessorKey : "request_id" ,
63
62
cell : ( info : any ) => (
64
- < span className = "font-mono text-xs max-w-[100px] truncate block" >
65
- { String ( info . getValue ( ) || "" ) }
66
- </ span >
63
+ < Tooltip title = { String ( info . getValue ( ) || "" ) } >
64
+ < span className = "font-mono text-xs max-w-[100px] truncate block" >
65
+ { String ( info . getValue ( ) || "" ) }
66
+ </ span >
67
+ </ Tooltip >
67
68
) ,
68
69
} ,
69
70
{
Original file line number Diff line number Diff line change @@ -105,10 +105,11 @@ export default function SpendLogsTable({
105
105
} ;
106
106
}
107
107
108
- const formattedStartTime = moment ( startTime ) . format ( "YYYY-MM-DD HH:mm:ss" ) ;
108
+ // Convert times to UTC before formatting
109
+ const formattedStartTime = moment ( startTime ) . utc ( ) . format ( "YYYY-MM-DD HH:mm:ss" ) ;
109
110
const formattedEndTime = isCustomDate
110
- ? moment ( endTime ) . format ( "YYYY-MM-DD HH:mm:ss" )
111
- : moment ( ) . format ( "YYYY-MM-DD HH:mm:ss" ) ;
111
+ ? moment ( endTime ) . utc ( ) . format ( "YYYY-MM-DD HH:mm:ss" )
112
+ : moment ( ) . utc ( ) . format ( "YYYY-MM-DD HH:mm:ss" ) ;
112
113
113
114
return await uiSpendLogsCall (
114
115
accessToken ,
@@ -176,7 +177,7 @@ export default function SpendLogsTable({
176
177
< h1 className = "text-xl font-semibold" > Request Logs</ h1 >
177
178
</ div >
178
179
179
- < div className = "bg-white rounded-lg shadow overflow-hidden " >
180
+ < div className = "bg-white rounded-lg shadow" >
180
181
< div className = "border-b px-6 py-4" >
181
182
< div className = "flex flex-col md:flex-row items-start md:items-center justify-between space-y-4 md:space-y-0" >
182
183
< div className = "flex flex-wrap items-center gap-3" >
Original file line number Diff line number Diff line change
1
+ import * as React from "react" ;
2
+
3
+ interface TimeCellProps {
4
+ utcTime : string ;
5
+ }
6
+
7
+ const getLocalTime = ( utcTime : string ) : string => {
8
+ try {
9
+ const date = new Date ( utcTime ) ;
10
+ return date . toLocaleString ( 'en-US' , {
11
+ year : 'numeric' ,
12
+ month : '2-digit' ,
13
+ day : '2-digit' ,
14
+ hour : '2-digit' ,
15
+ minute : '2-digit' ,
16
+ second : '2-digit' ,
17
+ hour12 : true
18
+ } ) . replace ( ',' , '' ) ;
19
+ } catch ( e ) {
20
+ return "Error converting time" ;
21
+ }
22
+ } ;
23
+
24
+ export const TimeCell : React . FC < TimeCellProps > = ( { utcTime } ) => {
25
+ return (
26
+ < span style = { {
27
+ fontFamily : 'monospace' ,
28
+ width : '180px' ,
29
+ display : 'inline-block'
30
+ } } >
31
+ { getLocalTime ( utcTime ) }
32
+ </ span >
33
+ ) ;
34
+ } ;
35
+
36
+ export const getTimeZone = ( ) : string => {
37
+ return Intl . DateTimeFormat ( ) . resolvedOptions ( ) . timeZone ;
38
+ } ;
You can’t perform that action at this time.
0 commit comments