
    gpV                    V   d dl Z d dlZd dlmZmZ d dlmZmZmZmZ d dl	Z	d dl	m
Z
mZmZmZ d dlZd dlmZ d dl d dlmZmZ d dlmZ d d	lmZ d d
lmZ erd dlmZ neZ e
       Zej;                  ddg ee      gd      d        Zej;                  ddg ee      gd       e	j>                  dd      fdee    fd       Z!ej;                  ddg ee      gddee"   ii       e	j>                  dd       e	j>                  dd      fdee    dee    fd       Z#de$dedefd Z%ej;                  d!dg ee      gddee"   iid"       e	j>                  dd#       e	j>                  dd$       ee      fdee    dee    de$fd%       Z&de$dedefd&Z'ej;                  d'dg ee      gddee"   iid"       e	j>                  dd#       e	j>                  dd$       ee      fdee    dee    de$fd(       Z(ej;                  d)dg ee      gddee"   iid"       e	j>                  d*+       e	j>                  dd#       e	j>                  dd$      fd,e dee    dee    fd-       Z)ej;                  d.dg ee      gddee"   iid"       e	j>                  d*+       e	j>                  dd#       e	j>                  dd$      fd,e dee    dee    fd/       Z*ej;                  d0dg ee      gdddee"   ii1       e	j>                  dd#       e	j>                  dd$       ee      fdee    dee    de$fd2       Z+ej;                  d3dg ee      gddee"   ii       e	j>                  dd#       e	j>                  dd$       e	j>                  d4d5       e	j>                  dd6       e	j>                  dd7       e	j>                  dd8       e	j>                  dd9      fdee    dee    d:ee,d;      d<ee    d=ee    d>ee    d?ee    fd@       Z-ej;                  dAdg ee      gdddee"   ii1      dB        Z.ej;                  dCdg ee      gddee"   ii       e	j>                  dd       e	j>                  dd       e	j>                  ddD      fdee    dee    dEee    fdF       Z/de de fdGZ0ejc                  dHdg ee      gddIdJdKdLdMii      dNe2fdO       Z3ej;                  dPdg ee      gddee"   ii       e	j>                  ddQ       e	j>                  ddR       e	j>                  ddS       e	j>                  dd       e	j>                  dd       ee      fd<ee    dee    dTee    dee    dee    de$fdU       Z4ejc                  dVdg ee      gW      dX        Z5ejc                  dYdg ee      gd      dZ        Z6d ee      fd<ee    de$fd[Z7ej;                  d\dg ee      gd       e	j>                  dd]       ee      fd<ee    de$fd^       Z8ej;                  d_dg ee      gd      d`        Z9	 dzde$dbe:fdcZ;ej;                  dddg ee      gd       e	j>                  dde       ee      fdbe:de$fdf       Z<ej;                  dgdg ee      gd      dh        Z=ej;                  didg ee      gd      dj        Z>ejc                  dkdg ee      gd      d{dlee?   fdm       Z@	 dzde$dbe:fdnZAej;                  dodg ee      gd       e	j>                  dadp       ee      fdbe:de$fdq       ZBej;                  dres      dtefdu       ZC	 d|dvefdwZD	 	 d|de de dvee   dxee    fdyZEy)}    N)datetime	timedelta)TYPE_CHECKINGAnyListOptional)	APIRouterDependsHTTPExceptionstatus)verbose_proxy_logger)*)ProviderBudgetResponseProviderBudgetResponseObject)user_api_key_auth)get_spend_by_team_and_customer)handle_exception_on_proxyPrismaClientz/spend/keyszBudget & Spend TrackingF)tagsdependenciesinclude_in_schemac                     K   ddl m}  	 | t        d      | j                  dd       d{   }|S 7 # t        $ r+}t	        t
        j                  dt        |      i	      d}~ww xY ww)
z
    View all keys created, ordered by spend

    Example Request:
    ```
    curl -X GET "http://0.0.0.0:8000/spend/keys" -H "Authorization: Bearer sk-1234"
    ```
    r   prisma_clientNDatabase not connected. Connect a database to your proxy - https://docs.litellm.ai/docs/simple_proxy#managing-auth---virtual-keyskeyfind_all
table_name
query_typeerrorstatus_codedetaillitellm.proxy.proxy_serverr   	Exceptionget_datar   r   HTTP_400_BAD_REQUESTstr)r   key_infoes      l/var/www/openai/venv/lib/python3.12/site-packages/litellm/proxy/spend_tracking/spend_management_endpoints.pyspend_key_fnr/      s     " 9
  T  '//5Z/XX Y  
33SV$
 	

s0   A-#6 46 A-6 	A*&A%%A**A-z/spend/userszGet User Table row for user_id)defaultdescriptionuser_idc                 $  K   ddl m} 	 |t        d      | |j                  dd|        d{   }|gS |j                  dd	       d{   }|S 7 $7 # t        $ r+}t	        t
        j                  d
t        |      i      d}~ww xY ww)aD  
    View all users created, ordered by spend

    Example Request:
    ```
    curl -X GET "http://0.0.0.0:8000/spend/users" -H "Authorization: Bearer sk-1234"
    ```

    View User Table row for user_id
    ```
    curl -X GET "http://0.0.0.0:8000/spend/users?user_id=1234" -H "Authorization: Bearer sk-1234"
    ```
    r   r   Nr   userfind_unique)r    r!   r2   r   r   r"   r#   r&   )r2   r   	user_infor-   s       r.   spend_user_fnr7   ?   s     6 9
  T  +44!mW 5  I ;+44!j 5  I 
  
33SV$
 	

sT   B&A AA BA AA BA A 	B"&BBBz/spend/tags   model)r   r   	responsesz*Time from which to start viewing key spendz!Time till which to view key spend
start_dateend_datec                   K   ddl m} ddlm} 	 |t	        d      	  || ||       d{   }|S 7 # t        $ r}t        |t              rKt        t        |ddt        |       d	      d
t        |dd      t        |dt        j                              t        |t              r|t        dt        |      z   d
t        |dd      t        j                        d}~ww xY ww)ai  
    LiteLLM Enterprise - View Spend Per Request Tag

    Example Request:
    ```
    curl -X GET "http://0.0.0.0:8000/spend/tags" -H "Authorization: Bearer sk-1234"
    ```

    Spend with Start Date and End Date
    ```
    curl -X GET "http://0.0.0.0:8000/spend/tags?start_date=2022-01-01&end_date=2022-02-01" -H "Authorization: Bearer sk-1234"
    ```
    r   )get_spend_by_tagsr   Nr   )r;   r<   r   r%   /spend/tags Error()internal_errorparamNoner$   messagetyperB   code/spend/tags Error)enterprise.utilsr>   r'   r   r(   
isinstancer   ProxyExceptiongetattrr+   r   HTTP_500_INTERNAL_SERVER_ERROR)r;   r<   r>   r   responser-   s         r.   view_spend_tagsrO   u   s     D 38#
  T 
	 +!HM
 
 	

  
a' 8/A#a&-KL%a&1Qv/T/TU	  >*G'#a&0!!Wf-66	
 	

s1   C'5 35 C'5 	C$B!CC$$C'user_api_key_dictc                    K   ddl m} |t        dddi      | j                  }|t        dddi      d}|j                  j                  ||||       d {   }|S 7 w)	Nr   r     r"   No db connectedr#   No user_id founda0  
    SELECT
        date_trunc('day', "startTime") AS date,
        COUNT(*) AS api_requests,
        SUM(total_tokens) AS total_tokens
    FROM "LiteLLM_SpendLogs"
    WHERE "startTime" BETWEEN $1::date AND $2::date + interval '1 day'
    AND "user" = $3
    GROUP BY date_trunc('day', "startTime")
    r'   r   r   r2   db	query_rawrP   r;   r<   r   r2   	sql_querydb_responses          r.   !get_global_activity_internal_userr[      s      9W>O4PQQ''GW>P4QRR	I &((22:x K 	   AA#A!A#z/global/activity)r   r   r:   r   z&Time from which to start viewing spendzTime till which to view spendc                 L  K   | |t        t        j                  ddi      t        j                  | d      }t        j                  |d      }ddlm} 	 |t        d      |j                  t        j                  k(  s|j                  t        j                  k(  rt        |||       d{   }n'd	}|j                  j                  |||       d{   }|g S d}d}	g }
|D ]i  }t        j                  |d
         }|j!                  d      |d
<   |
j#                  |       ||j%                  dd      z  }|	|j%                  dd      z  }	k t'        |
d       }
|
||	d}|S 7 7 # t        $ r+}t        t        j                  dt)        |      i      d}~ww xY ww)a  
    Get number of API Requests, total tokens through proxy

    {
        "daily_data": [
                const chartdata = [
                {
                date: 'Jan 22',
                api_requests: 10,
                total_tokens: 2000
                },
                {
                date: 'Jan 23',
                api_requests: 10,
                total_tokens: 12
                },
        ],
        "sum_api_requests": 20,
        "sum_total_tokens": 2012
    }
    Nr"   &Please provide start_date and end_dater#   %Y-%m-%dr   r   r   a\  
            SELECT
                date_trunc('day', "startTime") AS date,
                COUNT(*) AS api_requests,
                SUM(total_tokens) AS total_tokens
            FROM "LiteLLM_SpendLogs"
            WHERE "startTime" BETWEEN $1::date AND $2::date + interval '1 day'
            GROUP BY date_trunc('day', "startTime")
            date%b %dapi_requeststotal_tokensc                     | d   S Nr`    xs    r.   <lambda>z%get_global_activity.<locals>.<lambda>>      ai    r   
daily_datasum_api_requestssum_total_tokens)r   r   r*   r   strptimer'   r   r(   	user_roleLitellmUserRolesINTERNAL_USERINTERNAL_USER_VIEW_ONLYr[   rV   rW   fromisoformatstrftimeappendgetsortedr+   )r;   r<   rP   start_date_objend_date_objr   rZ   rY   ro   rp   rn   row	_date_objdata_to_returnr-   s                  r.   get_global_activityr      s    T X-33EF
 	

 &&z:>N$$Xz:L8:
  T 
 ''+;+I+II **.>.V.VV A!><! K
I !. 0 0 : :><! K I
C ..s6{;I#,,W5CKc" :: ::  J,?@
 % 0 0
 U<  
33SV$
 	

s\   AF$AE- .E)/'E- E+E- F$B	E- (F$)E- +E- -	F!6&FF!!F$c                    K   ddl m} |t        dddi      | j                  }|t        dddi      d}|j                  j                  ||||       d {   }|S 7 w)	Nr   r   rR   r"   rS   r#   rT   aR  
    SELECT
        model_group,
        date_trunc('day', "startTime") AS date,
        COUNT(*) AS api_requests,
        SUM(total_tokens) AS total_tokens
    FROM "LiteLLM_SpendLogs"
    WHERE "startTime" BETWEEN $1::date AND $2::date + interval '1 day'
    AND "user" = $3
    GROUP BY model_group, date_trunc('day', "startTime")
    rU   rX   s          r.   'get_global_activity_model_internal_userr   O  s      9W>O4PQQ''GW>P4QRR
I &((22:x K 	r\   z/global/activity/modelc                 \  K   | |t        t        j                  ddi      t        j                  | d      }t        j                  |d      }ddlm} 	 |t        d      |j                  t        j                  k(  s|j                  t        j                  k(  rt        |||       d{   }n'd	}|j                  j                  |||       d{   }|g S i }|D ]  }	|	d
   }
|
|vr	g ddd||
<   t        j                  |	d         }|j!                  d      |	d<   ||
   d   j#                  |	       ||
   dxx   |	j%                  dd      z  cc<   ||
   dxx   |	j%                  dd      z  cc<    t'        t)        |j+                         d d      dd       }g }|j+                         D ]2  \  }}t)        |d   d       }|j#                  |||d   |d   d       4 |S 7 A7 # t        $ r+}t        t        j,                  dt/        |      i      d}~ww xY ww)a  
    Get number of API Requests, total tokens through proxy - Grouped by MODEL

    [
        {
            "model": "gpt-4",
            "daily_data": [
                    const chartdata = [
                    {
                    date: 'Jan 22',
                    api_requests: 10,
                    total_tokens: 2000
                    },
                    {
                    date: 'Jan 23',
                    api_requests: 10,
                    total_tokens: 12
                    },
            ],
            "sum_api_requests": 20,
            "sum_total_tokens": 2012

        },
        {
            "model": "azure/gpt-4-turbo",
            "daily_data": [
                    const chartdata = [
                    {
                    date: 'Jan 22',
                    api_requests: 10,
                    total_tokens: 2000
                    },
                    {
                    date: 'Jan 23',
                    api_requests: 10,
                    total_tokens: 12
                    },
            ],
            "sum_api_requests": 20,
            "sum_total_tokens": 2012

        },
    ]
    Nr"   r^   r#   r_   r   r   r   a  
            SELECT
                model_group,
                date_trunc('day', "startTime") AS date,
                COUNT(*) AS api_requests,
                SUM(total_tokens) AS total_tokens
            FROM "LiteLLM_SpendLogs"
            WHERE "startTime" BETWEEN $1::date AND $2::date + interval '1 day'
            GROUP BY model_group, date_trunc('day', "startTime")
            model_grouprm   r`   ra   rn   ro   rb   rp   rc   c                     | d   d   S )N   ro   rf   rg   s    r.   ri   z+get_global_activity_model.<locals>.<lambda>  s    ad#56rk   Tr   reverse
   c                     | d   S re   rf   rg   s    r.   ri   z+get_global_activity_model.<locals>.<lambda>      &	rk   rl   )r9   rn   ro   rp   )r   r   r*   r   rq   r'   r   r(   rr   rs   rt   ru   r   rV   rW   rv   rw   rx   ry   dictrz   itemsrM   r+   )r;   r<   rP   r{   r|   r   rZ   rY   model_ui_datar}   _modelr~   rN   r9   data_sort_daily_datar-   s                    r.   get_global_activity_modelr   m  s    B X-33EF
 	

 &&z:>N$$Xz:L8N
  T 
 ''+;+I+II **.>.V.VV G!><! K
	I !. 0 0 : :><! K I  	 C'F]*"$()())f%
 !..s6{;I#,,W5CK&!,/66s;&!"45QR9SS5&!"45QR9SS5   ##%6 r	
 (..0KE4%d<&8>QROO""2(,-?(@(,-?(@	 1 }b  
==SV$
 	

s\   AH,AG5 .G//'G5 G2G5 H,DG5 .H,/G5 2G5 5	H)>&H$$H))H,z&/global/activity/exceptions/deploymentzFilter by model group)r1   r   c                 l  K   ||t        t        j                  ddi      t        j                  |d      }t        j                  |d      }ddlm} 	 |t        d      d	}|j                  j                  ||||        d{   }|g S i }|D ]v  }	|	d
   }
|
|vrg dd||
<   t        j                  |	d         }|j                  d      |	d<   ||
   d   j                  |	       ||
   dxx   |	j                  dd      z  cc<   x t        t        |j!                         d d      dd       }g }|j!                         D ].  \  }}t        |d   d       }|j                  |||d   d       0 |S 7 # t        $ r+}t        t        j"                  dt%        |      i      d}~ww xY ww)a  
    Get number of 429 errors - Grouped by deployment

    [
        {
            "deployment": "https://azure-us-east-1.openai.azure.com/",
            "daily_data": [
                    const chartdata = [
                    {
                    date: 'Jan 22',
                    num_rate_limit_exceptions: 10
                    },
                    {
                    date: 'Jan 23',
                    num_rate_limit_exceptions: 12
                    },
            ],
            "sum_num_rate_limit_exceptions": 20,

        },
        {
            "deployment": "https://azure-us-east-1.openai.azure.com/",
            "daily_data": [
                    const chartdata = [
                    {
                    date: 'Jan 22',
                    num_rate_limit_exceptions: 10,
                    },
                    {
                    date: 'Jan 23',
                    num_rate_limit_exceptions: 12
                    },
            ],
            "sum_num_rate_limit_exceptions": 20,

        },
    ]
    Nr"   r^   r#   r_   r   r   r   a  
        SELECT
            api_base,
            date_trunc('day', "startTime")::date AS date,
            COUNT(*) AS num_rate_limit_exceptions
        FROM
            "LiteLLM_ErrorLogs"
        WHERE
            "startTime" >= $1::date
            AND "startTime" < ($2::date + INTERVAL '1 day')
            AND model_group = $3
            AND status_code = '429'
        GROUP BY
            api_base,
            date_trunc('day', "startTime")
        ORDER BY
            date;
        api_basern   sum_num_rate_limit_exceptionsr`   ra   rn   r   num_rate_limit_exceptionsc                     | d   d   S )Nr   r   rf   rg   s    r.   ri   z?get_global_activity_exceptions_per_deployment.<locals>.<lambda>  s    ad#BCrk   Tr   r   c                     | d   S re   rf   rg   s    r.   ri   z?get_global_activity_exceptions_per_deployment.<locals>.<lambda>  r   rk   rl   )r   rn   r   )r   r   r*   r   rq   r'   r   r(   rV   rW   rv   rw   rx   ry   r   rz   r   rM   r+   )r   r;   r<   r{   r|   r   rY   rZ   r   r}   r   r~   rN   r9   r   r   r-   s                    r.   -get_global_activity_exceptions_per_deploymentr   
  s    z X-33EF
 	

 &&z:>N$$Xz:L8N
  T 	$ *,,66~|[
 
 I  	 C_F]*"$56)f% !..s6{;I#,,W5CK&!,/66s;&!"ABcgg+QG B   ##%C r	
 (..0KE4%d<&8>QROO %"25976 1 a
d  
==SV$
 	

sI   AF40E= E;E= F4C*E= :F4;E= =	F1&F,,F11F4z/global/activity/exceptionsc                 z  K   ||t        t        j                  ddi      t        j                  |d      }t        j                  |d      }ddlm} 	 |t        d      d	}|j                  j                  ||||        d{   }|g S d}g }	|D ]T  }
t        j                  |
d
         }|j                  d      |
d
<   |	j                  |
       ||
j                  dd      z  }V t        |	d       }	|	|d}|S 7 z# t        $ r+}t        t        j                  dt        |      i      d}~ww xY ww)a  
    Get number of API Requests, total tokens through proxy

    {
        "daily_data": [
                const chartdata = [
                {
                date: 'Jan 22',
                num_rate_limit_exceptions: 10,
                },
                {
                date: 'Jan 23',
                num_rate_limit_exceptions: 10,
                },
        ],
        "sum_api_exceptions": 20,
    }
    Nr"   r^   r#   r_   r   r   r   a  
        SELECT
            date_trunc('day', "startTime")::date AS date,
            COUNT(*) AS num_rate_limit_exceptions
        FROM
            "LiteLLM_ErrorLogs"
        WHERE
            "startTime" >= $1::date
            AND "startTime" < ($2::date + INTERVAL '1 day')
            AND model_group = $3
            AND status_code = '429'
        GROUP BY
            date_trunc('day', "startTime")
        ORDER BY
            date;
        r`   ra   r   c                     | d   S re   rf   rg   s    r.   ri   z0get_global_activity_exceptions.<locals>.<lambda>  rj   rk   rl   r   )r   r   r*   r   rq   r'   r   r(   rV   rW   rv   rw   rx   ry   rz   r+   )r   r;   r<   r{   r|   r   rY   rZ   r   rn   r}   r~   r   r-   s                 r.   get_global_activity_exceptionsr     su    R X-33EF
 	

 &&z:>N$$Xz:L85
  T 	  *,,66~|[
 
 I()%
C ..s6{;I#,,W5CKc")SWW5PRS-TT)  J,?@
 %-J

 3
6  
33SV$
 	

sI   AD;0D DD D;A1D D;D 	D8&D33D88D;z/global/spend/provider)r   r   r   r:   c                 v  K   ddl m} | |t        t        j                  ddi      t        j                  | d      }t        j                  |d      }ddlm}m	} 	 |t        d	      |j                  t        j                  k(  s|j                  t        j                  k(  rF|j                  }|t        d
ddi      d}	|j                   j#                  |	|||       d{   }
n'd}	|j                   j#                  |	||       d{   }
|
g S g } |t$              }|
D ]  }|d   }d}||j'                  |      }|"	 t)        j*                  |j,                  j.                  |j,                  j0                  |j,                  j2                  |j,                        \  }}}}||xx   |d   z  cc<    |j5                         D ]  \  }}|j7                  ||d        |S 7 7 # t        $ r Y w xY w# t        $ r+}t        t        j                  dt9        |      i      d}~ww xY ww)a-  
    Get breakdown of spend per provider
    [
        {
            "provider": "Azure OpenAI",
            "spend": 20
        },
        {
            "provider": "OpenAI",
            "spend": 10
        },
        {
            "provider": "VertexAI",
            "spend": 30
        }
    ]
    r   )defaultdictNr"   r^   r#   r_   )
llm_routerr   r     rT   a  
            SELECT
            model_id,
            SUM(spend) AS spend
            FROM "LiteLLM_SpendLogs"
            WHERE "startTime" BETWEEN $1::date AND $2::date 
            AND length(model_id) > 0
            AND "user" = $3
            GROUP BY model_id
            z
            SELECT
            model_id,
            SUM(spend) AS spend
            FROM "LiteLLM_SpendLogs"
            WHERE "startTime" BETWEEN $1::date AND $2::date AND length(model_id) > 0
            GROUP BY model_id
            model_idUnknown)r   )r9   custom_llm_providerr   litellm_paramsspend)providerr   )collectionsr   r   r   r*   r   rq   r'   r   r   r(   rr   rs   rt   ru   r2   rV   rW   intget_deploymentlitellmget_llm_providerr   r9   r   r   r   rx   r+   )r;   r<   rP   r   r{   r|   r   r   r2   rY   rZ   ui_responseprovider_spend_mappingr}   	_model_id	_provider_deployment_r   r   r-   s                        r.   get_global_spend_providerr     sp    J (X-33EF
 	

 &&z:>N$$Xz:LDN
  T 
 ''+;+I+II **.>.V.VV'//G# #W6H,I 	I !. 0 0 : :><! KI !. 0 0 : :><! K I .9#.>CJI!I%(777K*	-4-E-E"-"<"<"B"B0;0J0J0^0^%0%?%?%H%H+6+E+E	.*9a /y9S\I9 "  6;;=OHeHuEF  > ]8 %   
33SV$
 	

s   AH9BH &G.''H G1H H9H 4H 
A4G3>/H -H9.H 1H 3	G?<H >G??H 	H6&H11H66H9z/global/spend/reportteamz3Group spend by internal team or customer or api_keyz;View spend for a specific api_key. Example api_key='sk-1234zJView spend for a specific internal_user_id. Example internal_user_id='1234z8View spend for a specific team_id. Example team_id='1234zrView spend for a specific customer_id. Example customer_id='1234. Can be used in conjunction with team_id as well.group_by)r   customerapi_keyr   internal_user_idteam_idcustomer_idc                   K   | |t        t        j                  ddi      t        j                  | d      }t        j                  |d      }ddlm}	m}
 	 |
t        d      |	d	ur;t        j                  d
       t        dt        j                  j                  z         |at        j                  d|       |j                  d      rt!        |      }d}|
j"                  j%                  ||||       d{   }|g S |S |Dt        j                  d|       d}|
j"                  j%                  ||||       d{   }|g S |S ||t'        |||||
       d{   S |dk(  r-d}|
j"                  j%                  |||       d{   }|g S |S |dk(  r-d}|
j"                  j%                  |||       d{   }|g S |S |dk(  r-d}|
j"                  j%                  |||       d{   }|g S |S y7 7 7 7 v7 F7 # t        $ r+}t        t        j                  dt)        |      i      d}~ww xY ww)a  
    Get Daily Spend per Team, based on specific startTime and endTime. Per team, view usage by each key, model
    [
        {
            "group-by-day": "2024-05-10",
            "teams": [
                {
                    "team_name": "team-1"
                    "spend": 10,
                    "keys": [
                        "key": "1213",
                        "usage": {
                            "model-1": {
                                    "cost": 12.50,
                                    "input_tokens": 1000,
                                    "output_tokens": 5000,
                                    "requests": 100
                                },
                                "audio-modelname1": {
                                "cost": 25.50,
                                "seconds": 25,
                                "requests": 50
                        },
                        }
                    }
            ]
        ]
    }
    Nr"   r^   r#   r_   r   )premium_userr   r   Tz.accessing /spend/report but not a premium userz/spend/report endpoint zGetting /spend for api_key: %ssk-tokenad  
                WITH SpendByModelApiKey AS (
                    SELECT
                        sl.api_key,
                        sl.model,
                        SUM(sl.spend) AS model_cost,
                        SUM(sl.prompt_tokens) AS model_input_tokens,
                        SUM(sl.completion_tokens) AS model_output_tokens
                    FROM
                        "LiteLLM_SpendLogs" sl
                    WHERE
                        sl."startTime" BETWEEN $1::date AND $2::date AND sl.api_key = $3
                    GROUP BY
                        sl.api_key,
                        sl.model
                )
                SELECT
                    api_key,
                    SUM(model_cost) AS total_cost,
                    SUM(model_input_tokens) AS total_input_tokens,
                    SUM(model_output_tokens) AS total_output_tokens,
                    jsonb_agg(jsonb_build_object(
                        'model', model,
                        'total_cost', model_cost,
                        'total_input_tokens', model_input_tokens,
                        'total_output_tokens', model_output_tokens
                    )) AS model_details
                FROM
                    SpendByModelApiKey
                GROUP BY
                    api_key
                ORDER BY
                    total_cost DESC;
            z'Getting /spend for internal_user_id: %saa  
                WITH SpendByModelApiKey AS (
                    SELECT
                        sl.api_key,
                        sl.model,
                        SUM(sl.spend) AS model_cost,
                        SUM(sl.prompt_tokens) AS model_input_tokens,
                        SUM(sl.completion_tokens) AS model_output_tokens
                    FROM
                        "LiteLLM_SpendLogs" sl
                    WHERE
                        sl."startTime" BETWEEN $1::date AND $2::date AND sl.user = $3
                    GROUP BY
                        sl.api_key,
                        sl.model
                )
                SELECT
                    api_key,
                    SUM(model_cost) AS total_cost,
                    SUM(model_input_tokens) AS total_input_tokens,
                    SUM(model_output_tokens) AS total_output_tokens,
                    jsonb_agg(jsonb_build_object(
                        'model', model,
                        'total_cost', model_cost,
                        'total_input_tokens', model_input_tokens,
                        'total_output_tokens', model_output_tokens
                    )) AS model_details
                FROM
                    SpendByModelApiKey
                GROUP BY
                    api_key
                ORDER BY
                    total_cost DESC;
            r   a  

            WITH SpendByModelApiKey AS (
                SELECT
                    date_trunc('day', sl."startTime") AS group_by_day,
                    COALESCE(tt.team_alias, 'Unassigned Team') AS team_name,
                    sl.model,
                    sl.api_key,
                    SUM(sl.spend) AS model_api_spend,
                    SUM(sl.total_tokens) AS model_api_tokens
                FROM 
                    "LiteLLM_SpendLogs" sl
                LEFT JOIN 
                    "LiteLLM_TeamTable" tt 
                ON 
                    sl.team_id = tt.team_id
                WHERE
                    sl."startTime" BETWEEN $1::date AND $2::date
                GROUP BY
                    date_trunc('day', sl."startTime"),
                    tt.team_alias,
                    sl.model,
                    sl.api_key
            )
                SELECT
                    group_by_day,
                    jsonb_agg(jsonb_build_object(
                        'team_name', team_name,
                        'total_spend', total_spend,
                        'metadata', metadata
                    )) AS teams
                FROM (
                    SELECT
                        group_by_day,
                        team_name,
                        SUM(model_api_spend) AS total_spend,
                        jsonb_agg(jsonb_build_object(
                            'model', model,
                            'api_key', api_key,
                            'spend', model_api_spend,
                            'total_tokens', model_api_tokens
                        )) AS metadata
                    FROM 
                        SpendByModelApiKey
                    GROUP BY
                        group_by_day,
                        team_name
                ) AS aggregated
                GROUP BY
                    group_by_day
                ORDER BY
                    group_by_day;
                r   a  

            WITH SpendByModelApiKey AS (
                SELECT
                    date_trunc('day', sl."startTime") AS group_by_day,
                    sl.end_user AS customer,
                    sl.model,
                    sl.api_key,
                    SUM(sl.spend) AS model_api_spend,
                    SUM(sl.total_tokens) AS model_api_tokens
                FROM
                    "LiteLLM_SpendLogs" sl
                WHERE
                    sl."startTime" BETWEEN $1::date AND $2::date
                GROUP BY
                    date_trunc('day', sl."startTime"),
                    customer,
                    sl.model,
                    sl.api_key
            )
            SELECT
                group_by_day,
                jsonb_agg(jsonb_build_object(
                    'customer', customer,
                    'total_spend', total_spend,
                    'metadata', metadata
                )) AS customers
            FROM
                (
                    SELECT
                        group_by_day,
                        customer,
                        SUM(model_api_spend) AS total_spend,
                        jsonb_agg(jsonb_build_object(
                            'model', model,
                            'api_key', api_key,
                            'spend', model_api_spend,
                            'total_tokens', model_api_tokens
                        )) AS metadata
                    FROM
                        SpendByModelApiKey
                    GROUP BY
                        group_by_day,
                        customer
                ) AS aggregated
            GROUP BY
                group_by_day
            ORDER BY
                group_by_day;
                r   aP  
                WITH SpendByModelApiKey AS (
                    SELECT
                        sl.api_key,
                        sl.model,
                        SUM(sl.spend) AS model_cost,
                        SUM(sl.prompt_tokens) AS model_input_tokens,
                        SUM(sl.completion_tokens) AS model_output_tokens
                    FROM
                        "LiteLLM_SpendLogs" sl
                    WHERE
                        sl."startTime" BETWEEN $1::date AND $2::date
                    GROUP BY
                        sl.api_key,
                        sl.model
                )
                SELECT
                    api_key,
                    SUM(model_cost) AS total_cost,
                    SUM(model_input_tokens) AS total_input_tokens,
                    SUM(model_output_tokens) AS total_output_tokens,
                    jsonb_agg(jsonb_build_object(
                        'model', model,
                        'total_cost', model_cost,
                        'total_input_tokens', model_input_tokens,
                        'total_output_tokens', model_output_tokens
                    )) AS model_details
                FROM
                    SpendByModelApiKey
                GROUP BY
                    api_key
                ORDER BY
                    total_cost DESC;
            )r   r   r*   r   rq   r'   r   r   r(   r   debug
ValueErrorCommonProxyErrorsnot_premium_uservalue
startswith
hash_tokenrV   rW   r   r+   )r;   r<   r   r   r   r   r   r{   r|   r   r   rY   rZ   r-   s                 r.   get_global_spend_reportr     s    F X-33EF
 	

 &&z:>N$$Xz:LFU
  T  t# &&'WX),=,N,N,T,TT   &&'GQ!!%($73!ID !. 0 0 : :><! K "	) &&9;K!ID !. 0 0 : :><9I! K "	 [%<7g{M   v4Il !. 0 0 : :><! K "	#1If !. 0 0 : :><! K "	"!ID !. 0 0 : :><! K "	S #kZzxT  
33SV$
 	

s  AIB$H =H >H IH I;H HH IH IH $H%H (I)'H HH IH I'H H	H 
IH I'H 4H5H <I=H >I H H H H 	H H 	I&H<<IIz/global/spend/all_tag_namesc                  F  K   	 ddl m}  | t        d      d}| j                  j	                  |       d {   }|g S g }|D ]"  }|j                  |j                  d             $ d|iS 7 5# t        $ r}t        |t              rKt        t        |ddt        |       d	      d
t        |dd      t        |dt        j                              t        |t              r|t        dt        |      z   d
t        |dd      t        j                        d }~ww xY ww)Nr   r   r   z
        SELECT DISTINCT
            jsonb_array_elements_text(request_tags) AS individual_request_tag
        FROM "LiteLLM_SpendLogs";
        individual_request_tag	tag_namesr%   z/spend/all_tag_names Error(r@   rA   rB   rC   r$   rD   z/spend/all_tag_names Error)r'   r   r(   rV   rW   rx   ry   rJ   r   rK   rL   r+   r   rM   )r   rY   rZ   
_tag_namesr}   r-   s         r.   global_get_all_tag_namesr     s4    '
<  T 	 *,,66yAAI
Ccgg&>?@  Z(( B  
a' 8/J3q6(RS-TU%a&1Qv/T/TU	  >*G03q69!!Wf-66	
 	

sD   D!3A/ A-A/ D! ,A/ ,D!-A/ /	D8B!DDD!z/global/spend/tagsz"comman separated tags to filter onr   c                 4  K   ddl }ddlm} 	 |t        d      || t	        dddt
        j                        t        | |||       d{   }|S 7 # t        $ r}|j                         }t        |      d	z   |z   }t        |t              rBt	        t        |d
d| d      dt        |dd      t        |dt
        j                              t        |t              r|t	        d|z   dt        |dd      t
        j                        d}~ww xY ww)a}  
    LiteLLM Enterprise - View Spend Per Request Tag. Used by LiteLLM UI

    Example Request:
    ```
    curl -X GET "http://0.0.0.0:4000/spend/tags" -H "Authorization: Bearer sk-1234"
    ```

    Spend with Start Date and End Date
    ```
    curl -X GET "http://0.0.0.0:4000/spend/tags?start_date=2022-01-01&end_date=2022-02-01" -H "Authorization: Bearer sk-1234"
    ```
    r   Nr   r   r^   bad_requestrD   )r;   r<   tags_strr   
r%   r?   r@   rA   rB   rC   r$   rH   )	tracebackr'   r   r(   rK   r   r*   ui_get_spend_by_tags
format_excr+   rJ   r   rL   rM   )	r;   r<   r   r   r   rN   r-   error_trace	error_strs	            r.   global_view_spend_tagsr   ,  s?    J 8&
  T  z1 @"00	  .!'	
 
 
  
**,FTMK/	a' 8/A)A-NO%a&1Qv/T/TU	  >*G')3!!Wf-66	
 	

s<   DA A AA DA 	D B0DDDc                 z  K   ddl m} |t        j                  d       y 	 d}|j                  j                  || |       d {   }d}|j                  j                  || |       d {   }||fS 7 /7 
# t        $ r7}t        j                  dj                  t        |                   Y d }~y d }~ww xY ww)Nr   r   zZDatabase not connected. Connect a database to your proxy for weekly, monthly spend reportsa  
        SELECT
            t.team_alias,
            SUM(s.spend) AS total_spend
        FROM
            "LiteLLM_SpendLogs" s
        LEFT JOIN
            "LiteLLM_TeamTable" t ON s.team_id = t.team_id
        WHERE
            s."startTime"::DATE >= $1::date AND s."startTime"::DATE <= $2::date
        GROUP BY
            t.team_alias
        ORDER BY
            total_spend DESC;
        a@  
        SELECT 
        jsonb_array_elements_text(request_tags) AS individual_request_tag,
        SUM(spend) AS total_spend
        FROM "LiteLLM_SpendLogs"
        WHERE "startTime"::DATE >= $1::date AND "startTime"::DATE <= $2::date
        GROUP BY individual_request_tag
        ORDER BY total_spend DESC;
        z(Exception in _get_daily_spend_reports {})	r'   r   r   r"   rV   rW   r(   formatr+   )r;   r<   r   rY   rN   spend_per_tagr-   s          r.    _get_spend_report_for_time_ranger   ~  s      9""h	
 %
	 '))33Iz8TT	 ,..88z8
 
 &&# U

  
""6==c!fE	
 	

sR   B;"A8 A4&A8 +A6,A8 3B;4A8 6A8 8	B8-B3.B;3B88B;z/spend/calculatecostzThe calculated cost        float)r1   examplerF   requestc                   K   	 ddl m} ddlm} ddlm} d}| j                  A| j                  t        dd      d}d}||j                  Z| j                  |j                  v rB|j                  | j                     }|j                  D ]  }|j                  d	      |k(  s|} n2|j                  D ]#  }|j                  d	      | j                  k(  s"|}% 	 |h|j                  d
      }	|	j                  d      }
|	j                  d      }|	j                  d      }||
 |||      } ||
| j                  |      }na || j                  | j                        }nB| j                  )t        j                  di | j                  } ||      }nt        dd      d|iS # t        $ r}t        |t              rRt!        t#        |dt%        |            t#        |dd      t#        |dd      t#        |dt&        j(                              t%        |       }t!        t#        |d|      t#        |dd      t#        |dd      t#        |dd            d}~ww xY ww)a  
    Accepts all the params of completion_cost.

    Calculate spend **before** making call:

    Note: If you see a spend of $0.0 you need to set custom_pricing for your model: https://docs.litellm.ai/docs/proxy/custom_pricing

    ```
    curl --location 'http://localhost:4000/spend/calculate'
    --header 'Authorization: Bearer sk-1234'
    --header 'Content-Type: application/json'
    --data '{
        "model": "anthropic.claude-v2",
        "messages": [{"role": "user", "content": "Hey, how'''s it going?"}]
    }'
    ```

    Calculate spend **after** making call:

    ```
    curl --location 'http://localhost:4000/spend/calculate'
    --header 'Authorization: Bearer sk-1234'
    --header 'Content-Type: application/json'
    --data '{
        "completion_response": {
            "id": "chatcmpl-123",
            "object": "chat.completion",
            "created": 1677652288,
            "model": "gpt-3.5-turbo-0125",
            "system_fingerprint": "fp_44709d6fcb",
            "choices": [{
                "index": 0,
                "message": {
                    "role": "assistant",
                    "content": "Hello there, how may I assist you today?"
                },
                "logprobs": null,
                "finish_reason": "stop"
            }]
            "usage": {
                "prompt_tokens": 9,
                "completion_tokens": 12,
                "total_tokens": 21
            }
        }
    }'
    ```
    r   )completion_cost)CostPerTokenr   Nr   z>Bad Request - messages must be provided if 'model' is providedr#   
model_namer   r9   input_cost_per_tokenoutput_cost_per_token)r   r   )r9   messagescustom_cost_per_token)r9   r   )completion_responsezFBad Request - Either 'model' or 'completion_response' must be providedr   r%   rF   rC   rB   r$   rD   rE   rR   rf   )r   r   litellm.cost_calculatorr   r'   r   r9   r   r   model_group_alias
model_listry   r   ModelResponser(   rJ   rK   rL   r+   r   r*   )r   r   r   r   _cost_model_in_llm_routercost_per_token_model_group_namer9   _litellm_params_litellm_model_namer   r   _completion_responser-   	error_msgs                   r.   calculate_spendr     s}    ~V
+89==$'# #[  $( 59N%00<)E)EE )3(D(DW]](S%!+!6!6 99\26GG380 "7 ",!6!6 99\2gmmC380 "7 $/"6":":;K"L&5&9&9'&B#'6':':;Q'R$(7(;(;<S(T%(4,8%1-A.C&N
 (-$--*8 (gmmgFVFVW((4#*#8#8#W7;V;V#W #8LME_   
a' 8SV4Q/a&1Qv/J/JK	  1vh	Ay)4FF+!Wf-M3/	
 	

s7   I&B F, %2F, CF, +I&,	I#5B)II##I&z/spend/logszGet spend logs based on api keyzGet spend logs based on user_idzjrequest_id to get spend logs for specific request_id. If none passed then pass spend logs for all requests
request_idc                 (
  K   ddl m} |j                  t        j                  k(  s|j                  t        j
                  k(  r|j                  }	 t        j                  d       |t        d      g }|t        |t              r|t        |t              rt        j                  |d      }t        j                  |d      }	d||	di}
| t        | t              r| |
d	<   n/|t        |t              r||
d
<   n|t        |t              r||
d<   |j                  j                  j!                  g d|
ddi       d{   }t        |t"              rt%        |      dkD  rt        |d   t&              ri }|D ]T  }t        j                  t        |d         d      }|j)                         }||vri i d||<   |d	   } |d   }|d   }||   j+                  dd      |j+                  di       j+                  dd      z   ||   d<   ||   j+                  | d      |j+                  di       j+                  dd      z   ||   | <   ||   d   j+                  |d      |j+                  di       j+                  dd      z   ||   d   |<   ||   d   j+                  |d      |j+                  di       j+                  dd      z   ||   d   |<   W g }d}t-        |j/                               D ]  \  }}|j1                  i |d|i       |}  |	j)                         }|D||k  r?|t3        d      z   }||k  r+|j1                  |di i d       |t3        d      z  }||k  r+|S |S | jt        | t              rZ| j5                  d      r|j7                  |       }n| }|j9                  ddd	|d       d{   }t        |t"              r|S |gS |"|j9                  ddd
|d       d{   }|gS |4|j9                  ddd|d       d{   }t        |t"              r|S |gS |j9                  dd       d{   }|S 7 7 7 _7 =7 # t        $ r}t        |t:              rKt=        t?        |d d!t        |       d"      d#t?        |d$d%      t?        |d&t@        jB                        '      t        |t<              r|t=        d(t        |      z   d#t?        |d$d%      t@        jB                  '      d}~ww xY ww))a  
    View all spend logs, if request_id is provided, only logs for that request_id will be returned

    Example Request for all logs
    ```
    curl -X GET "http://0.0.0.0:8000/spend/logs" -H "Authorization: Bearer sk-1234"
    ```

    Example Request for specific request_id
    ```
    curl -X GET "http://0.0.0.0:8000/spend/logs?request_id=chatcmpl-6dcb2540-d3d7-4e49-bb27-291f863f112e" -H "Authorization: Bearer sk-1234"
    ```

    Example Request for specific api_key
    ```
    curl -X GET "http://0.0.0.0:8000/spend/logs?api_key=sk-Fn8Ej39NkBQmUagFEoUWPQ" -H "Authorization: Bearer sk-1234"
    ```

    Example Request for specific user_id
    ```
    curl -X GET "http://0.0.0.0:8000/spend/logs?user_id=ishaan@berri.ai" -H "Authorization: Bearer sk-1234"
    ```
    r   r   zinside view_spend_logsNr   r_   	startTime)gtelter   r   r4   )r   r4   r9   r   r   T)bywheresumz%Y-%m-%dT%H:%M:%S.%fZ)usersmodelsr9   _sumr   r   r   days)r   r   r   r   r   r   r   )r   r   )r    r!   key_valr5   r   r%   z/spend/logs Error(r@   rA   rB   rC   r$   rD   z/spend/logs Error)"r'   r   rr   rs   rt   ru   r2   r   r   r(   rJ   r+   r   rq   rV   litellm_spendlogsr   listlenr   r`   ry   rz   r   rx   r   r   r   r)   r   rK   rL   r   rM   )r   r2   r   r;   r<   rP   r   
spend_logsr{   r|   filter_queryrN   resultrecord	dt_objectr`   r9   return_list
final_datekvend_date_datecurrent_datehashed_token	spend_logr-   s                             r.   view_spend_logsr  J  s    t 9 	##'7'E'EE&&*:*R*RR#++T
""#;<  T  
":s+$8S) &..z:FN#,,XzBL )'L "z'3'?*1Y''Jz3,G-7\*$GS)A'.V$ +--??HH<"T I  H 8T*MA%x{D1!&F ( 1 1F;/02I!I %>>+D6)13r'Bt$Y/G$VnG"7OE,24L,<,<Wa,H6::Lc'1o-&F4L) -34L,<,<Wa,H6::Lc'1o-&F4L) 6<D\'5J5N5N6

62.227A>6?F4L)'2 5;4L4J4N4Nq5

62.227A>5?F4L*51' ', !!
"6<<>2DAq&&'<!'<[!'<=!"J 3 !- 1 1 3)j=.H#-	q0A#AL&-7#**-9)*)+*,	 %	q(99 '-7 #"O Z%=!!%(,77g7F&+44"% )LA 5  I
 )T*  !{"#+44"( ,zB 5  I
 ; +44"% &9 5  I
 )T*  !{",55"z  6   J CD  
a' 8/A#a&-KL%a&1Qv/T/TU	  >*G'#a&0!!Wf-66	
 	

s   ATC5Q  QH'Q  .Q  /T0Q  1T2AQ  QQ  TQ  TQ  :Q;Q  TQ  QQ  4T5Q  7T8Q  QQ  TQ  Q  Q  Q  Q   	T)B!T

TTz/global/spend/reset)r   r   c                  *  K   ddl m}  | t        dddt        j                        | j
                  j                  j                  dd	ii 
       d{    | j
                  j                  j                  dd	ii 
       d{    dddS 7 :7 w)aC  
    ADMIN ONLY / MASTER KEY Only Endpoint

    Globally reset spend for All API Keys and Teams, maintain LiteLLM_SpendLogs

    1. LiteLLM_SpendLogs will maintain the logs on spend, no data gets deleted from there
    2. LiteLLM_VerificationTokens spend will be set = 0
    3. LiteLLM_TeamTable spend will be set = 0

    r   r   N Prisma Client is not initializedrA   rC   rD   r   r   )r   r   z3Spend for all API Keys and Teams reset successfullysuccessrE   r   )	r'   r   rK   r   HTTP_401_UNAUTHORIZEDrV   litellm_verificationtokenupdate_manylitellm_teamtabler   s    r.   global_spend_resetr  #  s       96!--	
 	
 


4
4
@
@s^2 A    


,
,
8
8wnTV
8
WWW I  Xs$   ABB0BB
BBz/global/spend/refreshc                    	K   ddl m	 	t        dddt        j                        dt
        f	fd	}  |         d{   }|rd
}	 ddlm} ddl m} ddl	m
} t        j                  d      }|t        |j                  j                         |||ddi      }|j                   j#                          d{    |j                   j%                  |       d{    t'        j(                  d       dddS y7 7 D7 ## t        $ r<}t'        j*                  dj-                  t/        |                   dddcY d}~S d}~ww xY ww)zc
    ADMIN ONLY / MASTER KEY Only Endpoint

    Globally refresh spend MonthlyGlobalSpend view
    r   r   Nr  rA   rC   rD   returnc                     K   d} 	 j                   j                  |        d{   }|d   d   dk(  sJ y7 # t        $ r Y yw xY ww)zM
        Return True if materialized view exists

        Else False
        zy
        SELECT relname, relkind
        FROM pg_class
        WHERE relname = 'MonthlyGlobalSpend';            
        Nr   relkindmTF)rV   rW   r(   )rY   respr   s     r.   !is_materialized_global_spend_viewz?global_spend_refresh.<locals>.is_materialized_global_spend_view_  s^     	
	&))33I>>D79%,,, ?  		s1   A	: 8: A	: 	AA	AA	zE
        REFRESH MATERIALIZED VIEW "MonthlyGlobalSpend";    
        )r   )proxy_logging_objr   DATABASE_URLtimeoutip  )database_urlr&  http_clientz!MonthlyGlobalSpend view refreshedr  r  z(Failed to refresh materialized view - {}z#Failed to refresh materialized viewfailure)r'   r   rK   r   r  boollitellm.proxy._typesr   r&  litellm.proxy.utilsr   osgetenvr(   db_not_connected_errorr   rV   connectrW   r   info	exceptionr   r+   )
r%  view_existsrY   r   r&  r   db_url
new_clientr-   r   s
            @r.   global_spend_refreshr8  H  sN     96!--	
 	
T & :;;K		>D8YY~.F~ 1 H H N NOO%#"3tJ --'')))--)))444 %%&IJ># /  <, *4  	 **:AA#a&I A# 		se   <EC> E	A2D ;D <"D DD <E D D 	E	1E>E	?EE		Ec                   K   ddl m} |t        dddt        j                        	 |j
                  }|t        d      | )d}|j                  j                  || |       d {   }|S d	}|j                  j                  ||       d {   }|S 7 .7 # t        $ r(}t        j                  d
t        |              |d }~ww xY ww)Nr   r   r  rA   rC   rD   z)/global/spend/logs Error: User ID is Nonez
                SELECT * FROM "MonthlyGlobalSpendPerUserPerKey"
                WHERE "api_key" = $1 AND "user" = $2
                ORDER BY "date";
                zSSELECT * FROM "MonthlyGlobalSpendPerUserPerKey"  WHERE "user" = $1 ORDER BY "date";/global/spend/logs Error: )r'   r   rK   r   rM   r2   r   rV   rW   r(   r   r"   r+   )r   rP   r   r2   rY   rN   r-   s          r.   global_spend_for_internal_userr;    s      96!66	
 	
#++?HIII +--77	7GTTHOm	&))33IwGG U H  ""%?Ax#HIsX   &C=B &B'B ,C-!B BB CB B 	C
"#CC

Cz/global/spend/logszMAPI Key to get global spend (spend per day for last 30d). Admin-only endpointc                   K   ddl }ddlm}m} ddlm} 	 |t        dddt        j                        |j                  t        j                  k(  s|j                  t        j                  k(  rt        | |	       d{   }|S  |       }|r || 
       d{   }|S | (d}|j                  j                  |       d{   }|S d}|j                  j                  ||        d{   }|S 7 t7 Z7 27 # t         $ r}	|j#                         }
t%        |	      dz   |
z   }t'        j(                  d|        t+        |	t,              rBt        t/        |	dd| d      dt/        |	dd      t/        |	dt        j                              t+        |	t              r|	t        d|z   dt/        |	dd      t        j                        d}	~	ww xY ww)z
    [BETA] This is a beta endpoint. It will change.

    Use this to get global spend (spend per day for last 30d). Admin-only endpoint

    More efficient implementation of /spend/logs, by creating a view over the spend logs table.
    r   N)get_daily_spend_from_prometheusis_prometheus_connectedr   r  rA   rC   rD   )r   rP   )r   z3SELECT * FROM "MonthlyGlobalSpend" ORDER BY "date";queryz
                    SELECT * FROM "MonthlyGlobalSpendPerKey"
                    WHERE "api_key" = $1
                    ORDER BY "date";
                    r   r:  r%   z/global/spend/logs Error(r@   rB   r$   z/global/spend/logs Error)r   6litellm.integrations.prometheus_helpers.prometheus_apir=  r>  r'   r   rK   r   rM   rr   rs   rt   ru   r;  rV   rW   r(   r   r+   r   r"   rJ   r   rL   )r   rP   r   r=  r>  r   rN   prometheus_api_enabledrY   r-   r   r   s               r.   global_spend_logsrC    s    (  9<
  :%::	  ''+;+I+II **.>.V.VV;3D H O!8!:!<WMMHOU	!.!1!1!;!;)!;!LL	 "/!1!1!;!;Iw!OO7 N M P  
**,FTMK/	""%?	{#KLa' 8/HST-UV%a&1Qv/T/TU	  >*G.:!!Wf-66	
 	

s   GA)C< ?C4 C< GC< C6C< !G"#C< C8C< G!C< -C:.C< 3G4C< 6C< 8C< :C< <	GCGGGz/global/spendc                    K   ddl } ddlm} 	 d}|t        dddi      d	}|j                  j                  |
       d{   }|3t        |t              r#t        |      dkD  r|d   j                  dd      }|t        j                  dS 7 L# t        $ r}| j                         }t        |      dz   |z   }t        |t              rBt        t!        |dd| d      dt!        |dd      t!        |dt"        j$                              t        |t              r|t        d|z   dt!        |dd      t"        j$                        d}~ww xY ww)ze
    [BETA] This is a beta endpoint. It will change.

    View total spend across all proxy keys
    r   Nr   r   rR   r"   rS   r#   z;SELECT SUM(spend) as total_spend FROM "MonthlyGlobalSpend";r?  total_spend)r   
max_budgetr   r%   z/global/spend Error(r@   rA   rB   rC   r$   rD   z/global/spend Error)r   r'   r   r   rV   rW   rJ   r  r  ry   r   rF  r(   r   r+   rK   rL   r   rM   )r   r   rE  rY   rN   r-   r   r   s           r.   global_spendrG    sU     8
 CBS8TUUU	&))33)3DD(D)c(ma.?&qkoomSA$G4F4FGG E  
**,FTMK/	a' 8/CI;a-PQ%a&1Qv/T/TU	  >*G)I5!!Wf-66	
 	

s<   E4B BAB EB 	EB0E

EEr   limitc                    K   ddl m} |t        dddi      | j                  }|t        dddi      d}|j                  j                  |||       d {   }|S 7 w)	Nr   r   rR   r"   rS   r#   rT   a  
            WITH top_api_keys AS (
            SELECT 
                api_key,
                SUM(spend) as total_spend
            FROM 
                "LiteLLM_SpendLogs"
            WHERE 
                "user" = $1
            GROUP BY 
                api_key
            ORDER BY 
                total_spend DESC
            LIMIT $2  -- Adjust this number to get more or fewer top keys
        )
        SELECT 
            t.api_key,
            t.total_spend,
            v.key_alias,
            v.key_name
        FROM 
            top_api_keys t
        LEFT JOIN 
            "LiteLLM_VerificationToken" v ON t.api_key = v.token
        ORDER BY 
            t.total_spend DESC;
    
    rU   rP   rH  r   r2   rY   rN   s         r.   global_spend_key_internal_userrK  M  sx      9W>O4PQQ''GW>P4QRRI: #%%//	7EJJHO K   AA"A A"z/global/spend/keysz0Number of keys to get. Will return Top 'n' keys.c                 8  K   ddl m} |j                  t        j                  k(  s|j                  t        j
                  k(  rt        |       d{   }|S |t        dddi      d	|  d
}|j                  j                  |       d{   }|S 7 C7 w)
    [BETA] This is a beta endpoint. It will change.

    Use this to get the top 'n' keys with the highest spend, ordered by spend.
    r   r   )rP   NrR   r"   rS   r#   z)SELECT * FROM "Last30dKeysBySpend" LIMIT ;r?  )
r'   r   rr   rs   rt   ru   rK  r   rV   rW   rH  rP   r   rN   rY   s        r.   global_spend_keysrQ  {  s     $ 9 	##'7'E'EE&&*:*R*RR7/
 
 W>O4PQQ=eWAHI"%%//i/@@HO
 As$   ABB<BBBBz/global/spend/teamsc                    K   ddl m}  | t        dddi      d}| j                  j	                  |	       d{   }i }t               }i }|D ]s  }|d
   }||d   }|d}|j                  |       ||v r|d   }	t        |	d      }	||   }
|	|
|<   n|d   }	t        |	d      }	||	i||<   ||v r||xx   |	z  cc<   o|	||<   u g }t        t        |j                         d d            }|D ]-  }t        |      dk\  r n|d}|j                  |||   d       / g }|D ]  }||   }|j                  d|i|        |t        |      |dS 7 w)z{
    [BETA] This is a beta endpoint. It will change.

    Use this to get daily spend, grouped by `team_id` and `date`
    r   r   NrR   r"   rS   r#   a  
        SELECT
            t.team_alias as team_alias,
            DATE(s."startTime") AS spend_date,
            SUM(s.spend) AS total_spend
        FROM
            "LiteLLM_SpendLogs" s
        LEFT JOIN
            "LiteLLM_TeamTable" t ON s.team_id = t.team_id
        WHERE
            s."startTime" >= CURRENT_DATE - INTERVAL '30 days'
        GROUP BY
            t.team_alias,
            DATE(s."startTime")
        ORDER BY
            spend_date;
        r?  
spend_date
team_alias
UnassignedrE     c                     | d   S Nr   rf   )items    r.   ri   z'global_spend_per_team.<locals>.<lambda>  s    d1grk   Tr   r   )r   rE  r`   )daily_spendteamstotal_spend_per_team)r'   r   r   rV   rW   setaddroundr   rz   r   r  rx   r  )r   rY   rN   spend_by_dateteam_aliasesr\  r}   row_daterT  r   current_date_entriestotal_spend_per_team_uir   response_datar   r   s                   r.   global_spend_per_teamrf    s     9W>O4PQQI" #%%//i/@@H M5L|$&
%J$}$ &E%OE#0#: /4 ,&E%OE'15&9M(#-- ,5,/4 ,/ 2 !#))+1EtT (&'2-?"G&&0DW0MN	
 ( Mc"fc3U34 
 %l# 7 k As   9EEDEz/global/all_end_usersc                     K   ddl m}  | t        dddi      d}| j                  j	                  |	       d{   }|g S g }|D ]  }|j                  |d
           d|iS 7 )w)zn
    [BETA] This is a beta endpoint. It will change.

    Use this to just get all the unique `end_users`
    r   r   NrR   r"   rS   r#   z;
    SELECT DISTINCT end_user FROM "LiteLLM_SpendLogs"
    r?  end_user	end_users)r'   r   r   rV   rW   rx   )r   rY   rZ   
_end_usersr}   s        r.   global_view_all_end_usersrk    s      9W>O4PQQI &((222CCK	J#j/*  $$ Ds   9A'A%*A'z/global/spend/end_usersr   c                 d  K   ddl m} |t        dddi      	 d}d}d}| $| j                  }| j                  }| j
                  }|xs! t        j                         t        d	      z
  }|xs t        j                         }d
}|j                  j                  ||||       d{   }|S 7 w)rN  r   r   NrR   r"   rS   r#      r  a8  
SELECT end_user, COUNT(*) AS total_count, SUM(spend) AS total_spend
FROM "LiteLLM_SpendLogs"
WHERE "startTime" >= $1::timestamp
  AND "startTime" < $2::timestamp
  AND (
    CASE
      WHEN $3::TEXT IS NULL THEN TRUE
      ELSE api_key = $3
    END
  )
GROUP BY end_user
ORDER BY total_spend DESC
LIMIT 100
    )r'   r   r   r   endTimer   r   nowr   rV   rW   )r   r   r   rn  selected_api_keyrY   rN   s          r.   global_spend_end_usersrq  	  s      9W>O4PQQ IGNN	,,<<@X\\^iR.@@I'GI #%%//9g'7 H O	s   B%B0'B.(B0c                    K   ddl m} |t        dddi      | j                  }|t        dddi      d}|j                  j                  |||       d {   }|S 7 w)	Nr   r   rR   r"   rS   r#   rT   a7  
        SELECT 
            model,
            SUM(spend) as total_spend,
            SUM(total_tokens) as total_tokens
        FROM 
            "LiteLLM_SpendLogs"
        WHERE 
            "user" = $1
        GROUP BY 
            model
        ORDER BY 
            total_spend DESC
        LIMIT $2;
    rU   rJ  s         r.   !global_spend_models_internal_userrs  S	  sx      9W>O4PQQ''GW>P4QRRI  #%%//	7EJJHO KrL  z/global/spend/modelsz4Number of models to get. Will return Top 'n' models.c                 :  K   ddl m} |j                  t        j                  k(  s|j                  t        j
                  k(  rt        ||        d{   }|S |t        dddi      d	|  d
}|j                  j                  |       d{   }|S 7 C7 w)z
    [BETA] This is a beta endpoint. It will change.

    Use this to get the top 'n' models with the highest spend, ordered by spend.
    r   r   )rP   rH  NrR   r"   rS   r#   z+SELECT * FROM "Last30dModelsBySpend" LIMIT rO  r?  )
r'   r   rr   rs   rt   ru   rs  r   rV   rW   rP  s        r.   global_spend_modelsru  t	  s     $ 9 	##'7'E'EE&&*:*R*RR:/u
 
 W>O4PQQ?waJI"%%//i/@@HO
 As$   ABB<BBBBz/provider/budgets)response_modelr   c                  d  K   ddl m}  	 | t        dddi      | j                  }|t	        d      i }|j                         D ]  \  }}| j                  t	        d	      | j                  j                  |       d{   xs d
}| j                  j                  |       d{   }t        |j                  |j                  ||      }|||<    t        |      S 7 a7 <# t        $ r=}t        j                  dj!                  t#        |                   t%        |      d}~ww xY ww)a  
    Provider Budget Routing - Get Budget, Spend Details https://docs.litellm.ai/docs/proxy/provider_budget_routing

    Use this endpoint to check current budget, spend and budget reset time for a provider

    Example Request

    ```bash
    curl -X GET http://localhost:4000/provider/budgets     -H "Content-Type: application/json"     -H "Authorization: Bearer sk-1234"
    ```

    Example Response

    ```json
    {
        "providers": {
            "openai": {
                "budget_limit": 1e-12,
                "time_period": "1d",
                "spend": 0.0,
                "budget_reset_at": null
            },
            "azure": {
                "budget_limit": 100.0,
                "time_period": "1d",
                "spend": 0.0,
                "budget_reset_at": null
            },
            "anthropic": {
                "budget_limit": 100.0,
                "time_period": "10d",
                "spend": 0.0,
                "budget_reset_at": null
            },
            "vertex_ai": {
                "budget_limit": 100.0,
                "time_period": "12d",
                "spend": 0.0,
                "budget_reset_at": null
            }
        }
    }
    ```

    r   r   NrR   r"   zNo llm_router foundr#   zNo provider budget config found. Please set a provider budget config in the router settings. https://docs.litellm.ai/docs/proxy/provider_budget_routingzNo router budget logger foundr   )budget_limittime_periodr   budget_reset_at)	providersz)/provider/budgets: Exception occured - {})r'   r   r   provider_budget_configr   r   router_budget_logger_get_current_provider_spend%_get_current_provider_budget_reset_atr   rF  budget_durationr   r(   r   r4  r   r+   r   )	r   r|  provider_budget_response_dictr   _budget_info_provider_spend_provider_budget_ttlprovider_budget_response_objectr-   s	            r.   provider_budgetsr  	  sh    b 6%+2G(H  ",!B!B!) j  RT%'='C'C'E#I|..6 !@AA 55QQ   	  *4)H)H)n)n* $  /K)44(88% 4	/+ 8W))4% (F& &0MNN
$  +&&7>>s1vF	
 (**	+sM   D0A7C' C#&C' (C%)9C' "D0#C' %C' '	D-08D((D--D0r   c                 X   K   | j                   j                  d       d {   }|S 7 w)Nz
        SELECT
        jsonb_array_elements_text(request_tags) AS individual_request_tag,
        COUNT(*) AS log_count,
        SUM(spend) AS total_spend
        FROM "LiteLLM_SpendLogs"
        GROUP BY individual_request_tag;
        )rV   rW   )r   r;   r<   rN   s       r.   r>   r>   	  s4      #%%//		 	H O	s   *(*r   c                   K   d}|t        |      dkD  r|j                  d      }|t        dddi      d}|t        |t              r,d|v r(d	}|j
                  j                  || |       d{   }n(d
}|j
                  j                  || ||       d{   }t        j                  t              }t        j                  t              }|D ])  }	|	d   }
|	d   }||
xx   |z  cc<   ||
xx   |	d   z  cc<   + t        |j                         d d      }g }|D ]C  }|d   }|t        |t              rt        |d      }|j                  |d   |||d      d       E d|iS 7 7 ѭw)z
    Should cover 2 cases:
    1. When user is getting spend for all_tags. "all_tags" in tags_list
    2. When user is getting spend for specific tags.
    Nr   ,rR   r"   rS   r#   zall-tagsa  
        SELECT
            individual_request_tag,
            spend_date,
            log_count,
            total_spend
        FROM DailyTagSpend
        WHERE spend_date >= $1::date AND spend_date <= $2::date
        ORDER BY total_spend DESC;
        an  
        SELECT
            individual_request_tag,
            SUM(log_count) AS log_count,
            SUM(total_spend) AS total_spend
        FROM DailyTagSpend
        WHERE spend_date >= $1::date AND spend_date <= $2::date
          AND individual_request_tag = ANY($3::text[])
        GROUP BY individual_request_tag
        ORDER BY total_spend DESC;
        r   rE  	log_countc                     | d   S rX  rf   rg   s    r.   ri   z&ui_get_spend_by_tags.<locals>.<lambda>O
  s    AaDrk   Tr   r      )namer   r  r   )r  splitr   rJ   r  rV   rW   r   r   r   r   rz   r   r_  rx   )r;   r<   r   r   	tags_listrN   rY   total_spend_per_tagtotal_requests_per_tagr}   tag_name	tag_spendsorted_tagsui_tagstagcurrent_spends                   r.   r   r   
  s     &*IH 1NN3'	W>O4PQQHZ	48Z9=T		 '))33
 

	 '))33	
 
 4?3J3J53Q6A6M6Mc6R/0&	H%2%x(C,<<(  ,224.RVWKGA$M5)I!-3MA&3CF;	
	  W%%i
$
s%   A/E.1E*2(E.E,CE.,E.)r   )N)NN)Fr   r/  r   r   typingr   r   r   r   fastapir	   r
   r   r   r   litellm._loggingr   r-  r   r   $litellm.proxy.auth.user_api_key_authr   1litellm.proxy.spend_tracking.spend_tracking_utilsr   r.  r   r'   r   routerry   r/   Queryr+   r7   LiteLLM_SpendLogsrO   UserAPIKeyAuthr[   r   r   r   r   r   r   Literalr   r   r   r   postSpendCalculateRequestr   r  r  r8  r;  rC  rG  r   rK  rQ  rf  rk  GlobalEndUsersSpendrq  rs  ru  r  r>   r   rf   rk   r.   <module>r     s    	 ( 5 5  = =  1 " U B :7L	 
#	$+,-	  

: 
#	$+,-	   +W]]4-
c]-
-
` 
#	$+,-gt-./	   !.@! ,gmm7@
@

 sm@
@
F%3;GO: 
#	$+,-gt-./    !.<! ,gmm3 )00A(Bf
f

 smf
 &f
f
R%3;GO< 
#	$+,-gt-./    !.<! ,gmm3 )00A(BQ
Q

 smQ
 &Q
Q
h ,
#	$+,-gt-./    %w}}+ !.<! ,gmm3M
M
 	M
 smM
M
` !
#	$+,-gt-./    %w}}+ !.<! ,gmm3`
`
 	`
 sm`
`
F 
#	$+,-gt-./   !.<! ,gmm3 )00A(Bw
w

 smw
 &w
w
t 
#	$+,-gt-./	   !.<! ,gmm3 BOIB +W]]Q '4gmm`' +W]]N "/ I"3[
[

 sm[
 w<=>[
 c][
" sm#[
* c]+[
2 #3[
[
|
 !
#	$+,-gt-./  (
(
V 
#	$+,-gt-./	   !.@! ,gmm7 ('--8G
G

 smG
 3-G
G
T1
1
1
h 
#	$+,-4
	  G
#8 G
G
T 
#	$+,-gt-./	   +W]]5 +W]]5 !. A! !.@! ,gmm7 )00A(B+N
c]N

 c]N
 N
 N
" sm#N
* &+N
N
b 
#	$+,-  

@ 
#	$+,-	  IIZ "(/0A(B$c]$%$N 
#	$+,-	   +W]]c )00A(BR
c]R

 &R
R
j 
#	$+,-	  (
(
X 57+%+.1+\ 
#	$+,-	   F )00A(B
 &@ 
#	$+,-	  TTn 
#	$+,-	  %%4 
#	$+,-	  ,x0C'D ,,` 57%.1B 
#	$+,-	   J )00A(B
 &B 0FGW+ 6 W+ HW+v <@( -1"	W&W&W& L)W& sm	W&rk   