mirror of
https://github.com/ansible/awx.git
synced 2026-06-22 15:17:44 -02:30
feat(analytics): log request_id, account_number, org_id from ingress API response (#16512)
* feat(analytics): ANSTRAT-2268 log request_id, account_number, org_id from ingress API response Log the ingress API success response fields (request_id, account_number, org_id) in the controller task log when gather_analytics tarballs are uploaded. This enables support engineers to trace uploads through to Kibana without source code modifications. * style(analytics): use f-strings in _log_shipping_response to match codebase conventions * style(analytics): fix black formatting in test assertions
This commit is contained in:
@@ -420,6 +420,18 @@ def gather(dest=None, module=None, subset=None, since=None, until=None, collecti
|
||||
return tarfiles
|
||||
|
||||
|
||||
def _log_shipping_response(response, path):
|
||||
filename = os.path.basename(path)
|
||||
try:
|
||||
data = response.json()
|
||||
request_id = data.get('request_id', 'unknown')
|
||||
account_number = data.get('account_number', 'unknown')
|
||||
org_id = data.get('org_id', 'unknown')
|
||||
logger.info(f"Analytics upload successful: file={filename} request_id={request_id} account_number={account_number} org_id={org_id}")
|
||||
except Exception:
|
||||
logger.info(f"Analytics upload successful: file={filename} status={response.status_code}")
|
||||
|
||||
|
||||
def ship(path):
|
||||
"""
|
||||
Ship gathered metrics to the Insights API
|
||||
@@ -468,6 +480,7 @@ def ship(path):
|
||||
cert_url, files=files, cert=(cert_path, key_path), verify=settings.INSIGHTS_CERT_PATH, headers=s.headers, timeout=(31, 31)
|
||||
)
|
||||
if response.status_code < 300:
|
||||
_log_shipping_response(response, path)
|
||||
return True
|
||||
else:
|
||||
logger.warning(
|
||||
@@ -484,6 +497,7 @@ def ship(path):
|
||||
response = client.make_request("POST", url, headers=s.headers, files=files, verify=settings.INSIGHTS_CERT_PATH, timeout=(31, 31))
|
||||
|
||||
if response.status_code < 300:
|
||||
_log_shipping_response(response, path)
|
||||
return True
|
||||
else:
|
||||
logger.error(f'OIDC authentication failed with status {response.status_code}, {response.text}')
|
||||
|
||||
@@ -9,7 +9,7 @@ from unittest import mock
|
||||
|
||||
from django.test.utils import override_settings
|
||||
|
||||
from awx.main.analytics.core import ship, _get_cert_upload_url
|
||||
from awx.main.analytics.core import ship, _get_cert_upload_url, _log_shipping_response
|
||||
|
||||
|
||||
class TestGetCertUploadUrl:
|
||||
@@ -70,6 +70,7 @@ class TestShipMTLS:
|
||||
# Mock successful mTLS response
|
||||
mock_response = mock.Mock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.json.return_value = {'request_id': 'abc-123', 'account_number': '12345', 'org_id': '67890'}
|
||||
mock_session = mock.Mock()
|
||||
mock_session.headers = {}
|
||||
mock_session.post.return_value = mock_response
|
||||
@@ -81,6 +82,7 @@ class TestShipMTLS:
|
||||
mock_get_cert.assert_called_once()
|
||||
mock_temp_files.assert_called_once_with('cert-pem-data', 'key-pem-data')
|
||||
mock_session.post.assert_called_once()
|
||||
mock_response.json.assert_called_once()
|
||||
|
||||
# Verify cert URL is used (cert. subdomain added)
|
||||
call_args = mock_session.post.call_args
|
||||
@@ -126,6 +128,7 @@ class TestShipMTLS:
|
||||
# Mock successful OIDC response
|
||||
mock_oidc_response = mock.Mock()
|
||||
mock_oidc_response.status_code = 200
|
||||
mock_oidc_response.json.return_value = {'request_id': 'oidc-456', 'account_number': '12345', 'org_id': '67890'}
|
||||
mock_oidc_instance = mock.Mock()
|
||||
mock_oidc_instance.make_request.return_value = mock_oidc_response
|
||||
mock_oidc_client.return_value = mock_oidc_instance
|
||||
@@ -172,6 +175,7 @@ class TestShipMTLS:
|
||||
# Mock successful OIDC response
|
||||
mock_oidc_response = mock.Mock()
|
||||
mock_oidc_response.status_code = 200
|
||||
mock_oidc_response.json.return_value = {'request_id': 'oidc-789', 'account_number': '12345', 'org_id': '67890'}
|
||||
mock_oidc_instance = mock.Mock()
|
||||
mock_oidc_instance.make_request.return_value = mock_oidc_response
|
||||
mock_oidc_client.return_value = mock_oidc_instance
|
||||
@@ -209,6 +213,7 @@ class TestShipMTLS:
|
||||
# Mock successful OIDC response
|
||||
mock_oidc_response = mock.Mock()
|
||||
mock_oidc_response.status_code = 200
|
||||
mock_oidc_response.json.return_value = {'request_id': 'oidc-no-cert', 'account_number': '12345', 'org_id': '67890'}
|
||||
mock_oidc_instance = mock.Mock()
|
||||
mock_oidc_instance.make_request.return_value = mock_oidc_response
|
||||
mock_oidc_client.return_value = mock_oidc_instance
|
||||
@@ -269,3 +274,34 @@ class TestShipMTLS:
|
||||
assert result is False
|
||||
mock_session.post.assert_called_once()
|
||||
mock_oidc_instance.make_request.assert_called_once()
|
||||
|
||||
|
||||
class TestLogShippingResponse:
|
||||
"""Test _log_shipping_response() helper function."""
|
||||
|
||||
def test_logs_response_fields(self):
|
||||
"""Test that request_id, account_number, and org_id are logged."""
|
||||
response = mock.Mock()
|
||||
response.json.return_value = {'request_id': 'req-abc', 'account_number': '99999', 'org_id': '11111'}
|
||||
with mock.patch('awx.main.analytics.core.logger') as mock_logger:
|
||||
_log_shipping_response(response, '/tmp/analytics.tar.gz')
|
||||
mock_logger.info.assert_called_once_with("Analytics upload successful: file=analytics.tar.gz request_id=req-abc account_number=99999 org_id=11111")
|
||||
|
||||
def test_logs_unknown_for_missing_fields(self):
|
||||
"""Test fallback to 'unknown' when response fields are absent."""
|
||||
response = mock.Mock()
|
||||
response.json.return_value = {}
|
||||
with mock.patch('awx.main.analytics.core.logger') as mock_logger:
|
||||
_log_shipping_response(response, '/tmp/analytics.tar.gz')
|
||||
mock_logger.info.assert_called_once_with(
|
||||
"Analytics upload successful: file=analytics.tar.gz request_id=unknown account_number=unknown org_id=unknown"
|
||||
)
|
||||
|
||||
def test_graceful_fallback_on_json_error(self):
|
||||
"""Test fallback log when response body is not valid JSON."""
|
||||
response = mock.Mock()
|
||||
response.json.side_effect = ValueError("No JSON")
|
||||
response.status_code = 202
|
||||
with mock.patch('awx.main.analytics.core.logger') as mock_logger:
|
||||
_log_shipping_response(response, '/tmp/analytics.tar.gz')
|
||||
mock_logger.info.assert_called_once_with("Analytics upload successful: file=analytics.tar.gz status=202")
|
||||
|
||||
Reference in New Issue
Block a user