From 48c345ac6bcaaccac64cc1157543a334b509b324 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 18:47:37 +0000 Subject: [PATCH 1/2] Fix: Handle missing auth token gracefully in logfile upload - Resolves #1269 The issue was that upload_logfile() was being called when a trace ended, but the async authentication task may not have completed yet, causing the V4 client to not have the auth token set. This resulted in a 401 error. Changes: - Check if auth token is available before attempting to upload logfile - Skip upload gracefully with debug message if auth hasn't completed yet - Clear buffer even when skipping upload to prevent memory leaks - Add tests to verify the fix handles both scenarios correctly This fix ensures that short-running traces that complete before authentication finishes no longer throw 401 errors. Co-Authored-By: Alex --- agentops/logging/instrument_logging.py | 13 ++++++++ .../logging/test_upload_logfile_no_auth.py | 31 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 tests/unit/logging/test_upload_logfile_no_auth.py diff --git a/agentops/logging/instrument_logging.py b/agentops/logging/instrument_logging.py index 0c5cca53c..e255b3e4d 100644 --- a/agentops/logging/instrument_logging.py +++ b/agentops/logging/instrument_logging.py @@ -81,6 +81,7 @@ def upload_logfile(trace_id: int) -> None: Upload the log content from the memory buffer to the API. """ from agentops import get_client + from agentops.logging import logger # Get the content from the buffer log_content = _log_buffer.getvalue() @@ -88,6 +89,18 @@ def upload_logfile(trace_id: int) -> None: return client = get_client() + + # Check if authentication is complete before attempting to upload + if not client.api.v4.auth_token: + logger.debug( + "[agentops.upload_logfile] Skipping logfile upload - authentication not yet complete. " + "This is normal for short-running traces that complete before authentication finishes." + ) + # Clear the buffer even if we don't upload + _log_buffer.seek(0) + _log_buffer.truncate() + return + client.api.v4.upload_logfile(log_content, trace_id) # Clear the buffer after upload diff --git a/tests/unit/logging/test_upload_logfile_no_auth.py b/tests/unit/logging/test_upload_logfile_no_auth.py new file mode 100644 index 000000000..2ce36e0ad --- /dev/null +++ b/tests/unit/logging/test_upload_logfile_no_auth.py @@ -0,0 +1,31 @@ +import pytest +from unittest.mock import patch, MagicMock +from agentops.logging.instrument_logging import setup_print_logger, upload_logfile + + +def test_upload_logfile_skips_when_no_auth_token(): + """Test that upload_logfile skips upload gracefully when auth token is not set.""" + setup_print_logger() + test_message = "Test upload message" + print(test_message) + + mock_client = MagicMock() + mock_client.api.v4.auth_token = None + + with patch("agentops.get_client", return_value=mock_client): + upload_logfile(trace_id=123) + mock_client.api.v4.upload_logfile.assert_not_called() + + +def test_upload_logfile_uploads_when_auth_token_is_set(): + """Test that upload_logfile uploads when auth token is set.""" + setup_print_logger() + test_message = "Test upload message" + print(test_message) + + mock_client = MagicMock() + mock_client.api.v4.auth_token = "test_token" + + with patch("agentops.get_client", return_value=mock_client): + upload_logfile(trace_id=123) + mock_client.api.v4.upload_logfile.assert_called_once() From bc15c59b71845407e693df2b11298bae0d0c33fd Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 18:52:00 +0000 Subject: [PATCH 2/2] Fix: Add reset_print fixture to prevent leaked print state in tests The tests were calling setup_print_logger() which monkey-patches builtins.print, but weren't restoring it afterward. This leaked state was causing widespread CI failures across unit tests and example tests. Added reset_print fixture to properly restore builtins.print after each test, mirroring the pattern used in test_instrument_logging.py. Co-Authored-By: Alex --- .../logging/test_upload_logfile_no_auth.py | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/tests/unit/logging/test_upload_logfile_no_auth.py b/tests/unit/logging/test_upload_logfile_no_auth.py index 2ce36e0ad..1abaf858a 100644 --- a/tests/unit/logging/test_upload_logfile_no_auth.py +++ b/tests/unit/logging/test_upload_logfile_no_auth.py @@ -1,31 +1,40 @@ +import builtins import pytest from unittest.mock import patch, MagicMock from agentops.logging.instrument_logging import setup_print_logger, upload_logfile -def test_upload_logfile_skips_when_no_auth_token(): +@pytest.fixture +def reset_print(): + """Fixture to reset the print function after tests""" + original_print = builtins.print + yield + builtins.print = original_print + + +def test_upload_logfile_skips_when_no_auth_token(reset_print): """Test that upload_logfile skips upload gracefully when auth token is not set.""" setup_print_logger() test_message = "Test upload message" print(test_message) - + mock_client = MagicMock() mock_client.api.v4.auth_token = None - + with patch("agentops.get_client", return_value=mock_client): upload_logfile(trace_id=123) mock_client.api.v4.upload_logfile.assert_not_called() -def test_upload_logfile_uploads_when_auth_token_is_set(): +def test_upload_logfile_uploads_when_auth_token_is_set(reset_print): """Test that upload_logfile uploads when auth token is set.""" setup_print_logger() test_message = "Test upload message" print(test_message) - + mock_client = MagicMock() mock_client.api.v4.auth_token = "test_token" - + with patch("agentops.get_client", return_value=mock_client): upload_logfile(trace_id=123) mock_client.api.v4.upload_logfile.assert_called_once()