diff --git a/litellm/integrations/newrelic/newrelic.py b/litellm/integrations/newrelic/newrelic.py index d864cb50787..d7bf446ce8c 100644 --- a/litellm/integrations/newrelic/newrelic.py +++ b/litellm/integrations/newrelic/newrelic.py @@ -91,16 +91,6 @@ class NewRelicLogger(CustomLogger): self.license_key = os.getenv("NEW_RELIC_LICENSE_KEY") self.app_name = os.getenv("NEW_RELIC_APP_NAME") - # Determine if message content should be recorded - # Both turn_off_message_logging param AND env var must agree to record content - # If either disables recording, content will not be recorded - # Default: Messages ARE recorded (record_content=True) unless explicitly disabled by either method - self.record_content = ( - not self.turn_off_message_logging - ) and self._parse_bool_env( - "NEW_RELIC_AI_MONITORING_RECORD_CONTENT_ENABLED", True - ) - # Validate configuration if not self.license_key or not self.app_name: verbose_logger.warning( @@ -117,7 +107,9 @@ class NewRelicLogger(CustomLogger): self.enabled = False else: try: - _newrelic_agent.register_application() + # timeout=0 forces non-blocking startup: the agent connects in a + # background thread regardless of newrelic.ini / NEW_RELIC_STARTUP_TIMEOUT. + _newrelic_agent.register_application(timeout=0) self.enabled = True verbose_logger.info( @@ -148,6 +140,19 @@ class NewRelicLogger(CustomLogger): ).model_dump() return dict_newrelic_params + @property + def record_content(self) -> bool: + """Whether to record message content in New Relic. + + Both turn_off_message_logging param AND NEW_RELIC_AI_MONITORING_RECORD_CONTENT_ENABLED + env var must agree to record content. If either disables recording, content will not + be recorded. Read at call time so UI config changes take effect without a restart. + Default: True (record content) unless explicitly disabled by either method. + """ + return (not self.turn_off_message_logging) and self._parse_bool_env( + "NEW_RELIC_AI_MONITORING_RECORD_CONTENT_ENABLED", True + ) + 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, "") diff --git a/tests/test_litellm/integrations/newrelic/test_newrelic.py b/tests/test_litellm/integrations/newrelic/test_newrelic.py index 543cc890987..56ce97c421d 100644 --- a/tests/test_litellm/integrations/newrelic/test_newrelic.py +++ b/tests/test_litellm/integrations/newrelic/test_newrelic.py @@ -152,7 +152,7 @@ class TestNewRelicLoggerInit: {**NR_ENV, "NEW_RELIC_AI_MONITORING_RECORD_CONTENT_ENABLED": "false"}, ): logger = NewRelicLogger() - assert logger.record_content is False + assert logger.record_content is False def test_record_content_requires_both_enabled(self): """param says record, but env var says no — result is False.""" @@ -162,7 +162,7 @@ class TestNewRelicLoggerInit: {**NR_ENV, "NEW_RELIC_AI_MONITORING_RECORD_CONTENT_ENABLED": "false"}, ): logger = NewRelicLogger(turn_off_message_logging=False) - assert logger.record_content is False + assert logger.record_content is False def test_constructor_kwargs_take_priority_over_global_params(self): """Constructor turn_off_message_logging=True must not be overwritten by