From 9b89280a90c4cf24d4e919ed211ea0cd42a55683 Mon Sep 17 00:00:00 2001 From: Idris Mokhtarzada Date: Fri, 26 Jul 2024 16:38:54 -0400 Subject: [PATCH 1/3] Use underscores Datadog does not play nice with special characters (as in "(seconds)"). Also just makes sense to standardize on either underscores or camelCase, but not mix-and-match. --- litellm/integrations/datadog.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/litellm/integrations/datadog.py b/litellm/integrations/datadog.py index d835b3d67..98c71597d 100644 --- a/litellm/integrations/datadog.py +++ b/litellm/integrations/datadog.py @@ -91,12 +91,12 @@ class DataDogLogger: "id": id, "call_type": call_type, "cache_hit": cache_hit, - "startTime": start_time, - "endTime": end_time, - "responseTime (seconds)": response_time, + "start_time": start_time, + "end_time": end_time, + "response_time": response_time, "model": kwargs.get("model", ""), "user": kwargs.get("user", ""), - "modelParameters": optional_params, + "model_parameters": optional_params, "spend": kwargs.get("response_cost", 0), "messages": messages, "response": response_obj, From a7e877d15fc98c4ecb56cfa08fab8737faed7256 Mon Sep 17 00:00:00 2001 From: Idris Mokhtarzada Date: Fri, 26 Jul 2024 16:43:21 -0400 Subject: [PATCH 2/3] Use milliseconds for response_time in Datadog logs milliseconds is more commonly used and more standard than seconds --- litellm/integrations/datadog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litellm/integrations/datadog.py b/litellm/integrations/datadog.py index 98c71597d..01b8c81e0 100644 --- a/litellm/integrations/datadog.py +++ b/litellm/integrations/datadog.py @@ -61,7 +61,7 @@ class DataDogLogger: id = response_obj.get("id", str(uuid.uuid4())) usage = dict(usage) try: - response_time = (end_time - start_time).total_seconds() + response_time = (end_time - start_time).total_seconds() * 1000 except: response_time = None From e8d4234dbda96ff01e0c5e1a639e97c9b0b667e0 Mon Sep 17 00:00:00 2001 From: Idris Mokhtarzada Date: Fri, 26 Jul 2024 17:02:05 -0400 Subject: [PATCH 3/3] Better JSON serialization for Datadog logs Dicts are now properly serialized to JSON so that Datadog can parse the child attributes. Also, numbers and nulls are sent as numbers and nulls instead of strings. --- litellm/integrations/datadog.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/litellm/integrations/datadog.py b/litellm/integrations/datadog.py index 01b8c81e0..97ad96a5d 100644 --- a/litellm/integrations/datadog.py +++ b/litellm/integrations/datadog.py @@ -9,6 +9,20 @@ import litellm, uuid from litellm._logging import print_verbose, verbose_logger +def make_json_serializable(payload): + for key, value in payload.items(): + try: + if isinstance(value, dict): + # recursively sanitize dicts + payload[key] = make_json_serializable(value.copy()) + if not isinstance(value, (str, int, float, bool, type(None))): + # everything else becomes a string + payload[key] = str(value) + except: + # non blocking if it can't cast to a str + pass + + class DataDogLogger: # Class variables or attributes def __init__( @@ -104,13 +118,7 @@ class DataDogLogger: "metadata": clean_metadata, } - # Ensure everything in the payload is converted to str - for key, value in payload.items(): - try: - payload[key] = str(value) - except: - # non blocking if it can't cast to a str - pass + make_json_serializable(payload) import json payload = json.dumps(payload)