From 8d01872b639408b956e32ed62babf8a154d15eeb Mon Sep 17 00:00:00 2001 From: Josh Bonczkowski Date: Mon, 29 Dec 2025 16:33:37 -0500 Subject: [PATCH] Implementing a configuration so that users can use litellm configuration to disable sending LLM messages to New Relic. There is a second method to do this via New Relic env var. --- litellm/__init__.py | 2 + litellm/integrations/newrelic/newrelic.py | 45 ++++++++++++++++++++--- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/litellm/__init__.py b/litellm/__init__.py index 7520bb825fd..a724b675873 100644 --- a/litellm/__init__.py +++ b/litellm/__init__.py @@ -28,6 +28,7 @@ from typing import ( ) from litellm.types.integrations.datadog_llm_obs import DatadogLLMObsInitParams from litellm.types.integrations.datadog import DatadogInitParams +from litellm.types.integrations.newrelic import NewRelicInitParams from litellm._logging import ( set_verbose, _turn_on_debug, @@ -350,6 +351,7 @@ dynamodb_table_name: Optional[str] = None s3_callback_params: Optional[Dict] = None datadog_llm_observability_params: Optional[Union[DatadogLLMObsInitParams, Dict]] = None datadog_params: Optional[Union[DatadogInitParams, Dict]] = None +newrelic_params: Optional[Union[NewRelicInitParams, Dict]] = None aws_sqs_callback_params: Optional[Dict] = None generic_logger_headers: Optional[Dict] = None default_key_generate_params: Optional[Dict] = None diff --git a/litellm/integrations/newrelic/newrelic.py b/litellm/integrations/newrelic/newrelic.py index ae816b4503e..4d3a113bfd9 100644 --- a/litellm/integrations/newrelic/newrelic.py +++ b/litellm/integrations/newrelic/newrelic.py @@ -7,14 +7,16 @@ LLM requests, responses, and usage metrics. Environment Variables: NEW_RELIC_LICENSE_KEY: Your New Relic license key (required) NEW_RELIC_APP_NAME: Your application name (required) - NEW_RELIC_AI_MONITORING_RECORD_CONTENT_ENABLED: Whether to record message content (optional, default: false) + NEW_RELIC_AI_MONITORING_RECORD_CONTENT_ENABLED: Whether to record message content (optional, default: true) Configuration: Message logging can be controlled via: - 1. turn_off_message_logging parameter (takes priority) - pass via callback initialization + 1. turn_off_message_logging parameter (takes priority) - pass via callback initialization or config YAML 2. NEW_RELIC_AI_MONITORING_RECORD_CONTENT_ENABLED env var (fallback) -Usage: + Default behavior: Messages ARE recorded unless explicitly disabled + +Usage - Python SDK: import litellm litellm.callbacks = ["newrelic"] @@ -22,6 +24,12 @@ Usage: from litellm.integrations.newrelic import NewRelicLogger litellm.callbacks = [NewRelicLogger(turn_off_message_logging=True)] +Usage - Proxy Server (config.yaml): + litellm_settings: + callbacks: ["newrelic"] + newrelic_params: + turn_off_message_logging: true + # Ensure New Relic agent is initialized (use newrelic-admin or initialize manually) # newrelic-admin run-program python your_app.py """ @@ -33,8 +41,10 @@ import time import uuid from typing import Any, Dict, List, Optional, Tuple, Union +import litellm from litellm._logging import verbose_logger from litellm.integrations.custom_logger import CustomLogger +from litellm.types.integrations.newrelic import NewRelicInitParams from litellm.types.utils import ModelResponse, Message import newrelic.agent @@ -56,7 +66,13 @@ class NewRelicLogger(CustomLogger): """ def __init__(self, **kwargs): - # Check if turn_off_message_logging was explicitly provided before calling super() + ######################################################### + # Handle newrelic_params set as litellm.newrelic_params + ######################################################### + dict_newrelic_params = self._get_newrelic_params() + kwargs.update(dict_newrelic_params) + + # Check if turn_off_message_logging was explicitly provided (after merging params) turn_off_message_logging_provided = "turn_off_message_logging" in kwargs # CustomLogger.__init__ will set self.turn_off_message_logging from kwargs @@ -69,13 +85,15 @@ class NewRelicLogger(CustomLogger): # Determine if message content should be recorded # Priority: turn_off_message_logging param > env var # Note: turn_off_message_logging=True means record_content=False (inverted logic) + # Default: Messages ARE recorded (record_content=True) unless explicitly disabled if turn_off_message_logging_provided: # Use the parameter value set by CustomLogger.__init__ (inverted for record_content) self.record_content = not self.turn_off_message_logging else: # Fall back to env var when parameter not provided + # Default to True to match Pydantic default (turn_off_message_logging=False) self.record_content = self._parse_bool_env( - "NEW_RELIC_AI_MONITORING_RECORD_CONTENT_ENABLED", False + "NEW_RELIC_AI_MONITORING_RECORD_CONTENT_ENABLED", True ) # Validate configuration @@ -103,6 +121,23 @@ class NewRelicLogger(CustomLogger): ) self.enabled = False + def _get_newrelic_params(self) -> Dict: + """ + Get the newrelic_params from litellm.newrelic_params + + These are params specific to initializing the NewRelicLogger e.g. turn_off_message_logging + """ + dict_newrelic_params: Dict = {} + if litellm.newrelic_params is not None: + if isinstance(litellm.newrelic_params, NewRelicInitParams): + dict_newrelic_params = litellm.newrelic_params.model_dump() + elif isinstance(litellm.newrelic_params, Dict): + # only allow params that are of NewRelicInitParams + dict_newrelic_params = NewRelicInitParams( + **litellm.newrelic_params + ).model_dump() + return dict_newrelic_params + def _parse_bool_env(self, var_name: str, default: bool = False) -> bool: """Parse boolean environment variable. Accepts 'true' (case-insensitive) per spec.""" value = os.getenv(var_name, "")