From db20c23adc43911b6560c5e9e95299ae7b1cff3b Mon Sep 17 00:00:00 2001 From: James Hargreaves Date: Wed, 17 Jun 2026 16:47:24 +0100 Subject: [PATCH] feat(posthog): surface Anthropic cache token counts in StandardLoggingPayload and $ai_generation events --- litellm/integrations/posthog.py | 6 ++++++ litellm/litellm_core_utils/litellm_logging.py | 12 ++++++++++-- litellm/types/utils.py | 2 ++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/litellm/integrations/posthog.py b/litellm/integrations/posthog.py index 072ae4945a0..1651e3b5ba7 100644 --- a/litellm/integrations/posthog.py +++ b/litellm/integrations/posthog.py @@ -229,6 +229,12 @@ class PostHogLogger(CustomBatchLogger): properties["$ai_output_tokens"] = self._safe_get( standard_logging_object, "completion_tokens", 0 ) + cache_read = self._safe_get(standard_logging_object, "cache_read_input_tokens", 0) or 0 + cache_creation = self._safe_get(standard_logging_object, "cache_creation_input_tokens", 0) or 0 + if cache_read: + properties["$ai_cache_read_input_tokens"] = cache_read + if cache_creation: + properties["$ai_cache_creation_input_tokens"] = cache_creation # Cost and performance response_cost = self._safe_get(standard_logging_object, "response_cost") diff --git a/litellm/litellm_core_utils/litellm_logging.py b/litellm/litellm_core_utils/litellm_logging.py index d750a509054..1a79bd2b753 100644 --- a/litellm/litellm_core_utils/litellm_logging.py +++ b/litellm/litellm_core_utils/litellm_logging.py @@ -5174,7 +5174,10 @@ class StandardLoggingPayloadSetup: """ _empty: dict = {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0} if combined_usage_object is not None: - return combined_usage_object.model_dump() + d = combined_usage_object.model_dump() + d["cache_read_input_tokens"] = combined_usage_object._cache_read_input_tokens + d["cache_creation_input_tokens"] = combined_usage_object._cache_creation_input_tokens + return d if not response_obj: return _empty _raw = response_obj.get("usage", None) @@ -5193,7 +5196,10 @@ class StandardLoggingPayloadSetup: ) return _raw if isinstance(_raw, Usage): - return _raw.model_dump() + d = _raw.model_dump() + d["cache_read_input_tokens"] = _raw._cache_read_input_tokens + d["cache_creation_input_tokens"] = _raw._cache_creation_input_tokens + return d return _empty @staticmethod @@ -5890,6 +5896,8 @@ def get_standard_logging_object_payload( total_tokens=usage_dict.get("total_tokens", 0), prompt_tokens=usage_dict.get("prompt_tokens", 0), completion_tokens=usage_dict.get("completion_tokens", 0), + cache_read_input_tokens=usage_dict.get("cache_read_input_tokens", 0), + cache_creation_input_tokens=usage_dict.get("cache_creation_input_tokens", 0), request_tags=request_tags, end_user=end_user_id or "", api_base=StandardLoggingPayloadSetup.strip_trailing_slash( diff --git a/litellm/types/utils.py b/litellm/types/utils.py index 32bfc8835fe..b83fb9b38e6 100644 --- a/litellm/types/utils.py +++ b/litellm/types/utils.py @@ -2979,6 +2979,8 @@ class StandardLoggingPayload(TypedDict): total_tokens: int prompt_tokens: int completion_tokens: int + cache_read_input_tokens: int + cache_creation_input_tokens: int startTime: float # Note: making this camelCase was a mistake, everything should be snake case endTime: float completionStartTime: float