mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-11 08:38:24 +00:00
feat(daily-activity): read guardrail spend per key from the daily guardrail usage table
Adds DailyActivityRepository.guardrail_spend, which sums LiteLLM_DailyGuardrailUsageUnits.cost by date, guardrail and key. A guardrail row counts only when its key has a spend row on that day under the same scope filters as the rest of the daily activity response, so user, key and date filters apply to guardrail cost too
This commit is contained in:
parent
41336b09e2
commit
c864255f33
3 changed files with 30 additions and 0 deletions
|
|
@ -19,6 +19,7 @@ from litellm.repositories.daily_activity_sql import (
|
|||
build_cache_leakage_keys_sql,
|
||||
build_entity_rollup_sql,
|
||||
build_export_sql,
|
||||
build_guardrail_spend_sql,
|
||||
build_key_page_sql,
|
||||
build_key_search_sql,
|
||||
build_model_top_keys_sql,
|
||||
|
|
@ -36,6 +37,7 @@ from litellm.types.repositories.daily_activity import (
|
|||
ExportRow,
|
||||
ExportType,
|
||||
GroupingSetsRow,
|
||||
GuardrailSpendRow,
|
||||
KeyMetadataRow,
|
||||
KeyPage,
|
||||
KeySpendRow,
|
||||
|
|
@ -100,6 +102,7 @@ class DailyActivityDatabase(Protocol):
|
|||
|
||||
_GROUPING_ADAPTER: Final = TypeAdapter(tuple[GroupingSetsRow, ...])
|
||||
_ENTITY_ADAPTER: Final = TypeAdapter(tuple[EntityRollupRow, ...])
|
||||
_GUARDRAIL_SPEND_ADAPTER: Final = TypeAdapter(tuple[GuardrailSpendRow, ...])
|
||||
_KEY_SPEND_ADAPTER: Final = TypeAdapter(tuple[KeySpendRow, ...])
|
||||
_KEY_PAGE_TOTAL_ADAPTER: Final[TypeAdapter[int]] = TypeAdapter(int)
|
||||
_USER_SPEND_ADAPTER: Final = TypeAdapter(tuple[UserSpendRow, ...])
|
||||
|
|
@ -191,6 +194,9 @@ class DailyActivityRepository:
|
|||
distinct_api_keys=distinct_api_keys,
|
||||
)
|
||||
|
||||
async def guardrail_spend(self, scope: DailyActivityScope) -> tuple[GuardrailSpendRow, ...]:
|
||||
return _GUARDRAIL_SPEND_ADAPTER.validate_python(await self._query(build_guardrail_spend_sql(scope)))
|
||||
|
||||
async def search_keys(self, scope: DailyActivityScope, *, search: str, limit: int) -> tuple[str, ...]:
|
||||
if not 1 <= limit <= constants.USAGE_KEY_SEARCH_MAX:
|
||||
raise ValueError(f"limit must be between 1 and {constants.USAGE_KEY_SEARCH_MAX}")
|
||||
|
|
|
|||
|
|
@ -261,6 +261,22 @@ def build_entity_rollup_sql(scope: DailyActivityScope, *, api_key_limit: int) ->
|
|||
return SqlQuery(sql=sql, params=(*where_params, PTU_SENTINEL_API_KEY, api_key_limit))
|
||||
|
||||
|
||||
def build_guardrail_spend_sql(scope: DailyActivityScope) -> SqlQuery:
|
||||
pg_table: Final = PRISMA_TO_PG_TABLE[scope.table]
|
||||
where_clause, where_params = build_where_clause(scope)
|
||||
sql: Final = f"""
|
||||
SELECT g.date, g.guardrail_id, g.api_key, COALESCE(SUM(g.cost), 0)::float AS spend
|
||||
FROM "LiteLLM_DailyGuardrailUsageUnits" g
|
||||
WHERE g.date >= $1 AND g.date <= $2
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM "{pg_table}"
|
||||
WHERE {where_clause} AND "{pg_table}".date = g.date AND "{pg_table}".api_key = g.api_key
|
||||
)
|
||||
GROUP BY g.date, g.guardrail_id, g.api_key
|
||||
"""
|
||||
return SqlQuery(sql=sql, params=where_params)
|
||||
|
||||
|
||||
def _key_spend_select() -> str:
|
||||
return """
|
||||
COALESCE(SUM(spend), 0)::float AS spend,
|
||||
|
|
|
|||
|
|
@ -168,6 +168,14 @@ class EntityRollupRow(RollupMetricsRow):
|
|||
distinct_api_keys: int | None
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class GuardrailSpendRow:
|
||||
date: str
|
||||
guardrail_id: str
|
||||
api_key: str
|
||||
spend: float
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class AggregatedRows:
|
||||
grouping_rows: tuple[GroupingSetsRow, ...]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue