Skip to content

Commit

Permalink
fix: Improve logging messages
Browse files Browse the repository at this point in the history
  • Loading branch information
attiyaIshaque committed Dec 30, 2024
1 parent 59ab5f8 commit 26e5b6f
Show file tree
Hide file tree
Showing 17 changed files with 94 additions and 103 deletions.
13 changes: 7 additions & 6 deletions commerce_coordinator/apps/commercetools/clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ def create_return_for_order(self, order_id: str, order_version: int, order_line_
)
return returned_order
except CommercetoolsError as err:
handle_commercetools_error(err, f"Unable to create return for order {order_id}")
handle_commercetools_error("[CommercetoolsAPIClient.create_return_for_order]",err, f"Unable to create return for order {order_id}")
raise err

def update_return_payment_state_after_successful_refund(
Expand Down Expand Up @@ -497,7 +497,7 @@ def update_return_payment_state_after_successful_refund(
logger.info("Updated transaction with return item id")
return updated_order
except CommercetoolsError as err:
handle_commercetools_error(err, f"Unable to update ReturnPaymentState of order {order_id}")
handle_commercetools_error("[CommercetoolsAPIClient.update_return_payment_state_after_successful_refund]",err, f"Unable to update ReturnPaymentState of order {order_id}")
raise OpenEdxFilterException(str(err)) from err

def _preprocess_refund_object(self, refund: Refund, psp: str) -> Refund:
Expand Down Expand Up @@ -559,7 +559,7 @@ def create_return_payment_transaction(
f"Unable to create refund payment transaction for payment {payment_id}, refund {refund['id']} "
f"with PSP: {psp}"
)
handle_commercetools_error(err, context)
handle_commercetools_error("[CommercetoolsAPIClient.create_return_payment_transaction]",err, context)
raise err

def update_line_item_transition_state_on_fulfillment(
Expand Down Expand Up @@ -610,13 +610,14 @@ def update_line_item_transition_state_on_fulfillment(
return updated_fulfillment_line_item_order
else:
logger.info(
f"The line item {line_item_id} already has the correct state {new_state_key}. "
"Not attempting to transition LineItemState"
f"[CommercetoolsAPIClient] - The line item {line_item_id} already has the correct state {new_state_key}. "
f"Not attempting to transition LineItemState for order id {order_id}"
)
return self.get_order_by_id(order_id)
except CommercetoolsError as err:
context_prefix ="[CommercetoolsAPIClient.update_line_item_state_on_fulfillment_completion]"
# Logs & ignores version conflict errors due to duplicate Commercetools messages
handle_commercetools_error(err, f"Unable to update LineItemState of order {order_id}", True)
handle_commercetools_error(context_prefix, err, f"Unable to update LineItemState of order {order_id}")
return None

def retire_customer_anonymize_fields(
Expand Down
12 changes: 6 additions & 6 deletions commerce_coordinator/apps/commercetools/sub_messages/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,11 @@ def fulfill_order_placed_message_signal_task(
return False

if not (customer and order and is_edx_lms_order(order)):
logger.debug(f'[CT-{tag}] order {order_id} is not an edX order, message id: {message_id}')
logger.info(f'[CT-{tag}] order {order_id} is not an edX order, message id: {message_id}')

return True

logger.debug(f'[CT-{tag}] processing edX order {order_id}, message id: {message_id}')
logger.info(f'[CT-{tag}] processing edX order {order_id}, message id: {message_id}')

lms_user_id = get_edx_lms_user_id(customer)

Expand All @@ -99,7 +99,7 @@ def fulfill_order_placed_message_signal_task(
canvas_entry_properties.update(extract_ct_order_information_for_braze_canvas(customer, order))

for item in get_edx_items(order):
logger.debug(f'[CT-{tag}] processing edX order {order_id}, line item {item.variant.sku}, '
logger.info(f'[CT-{tag}] processing edX order {order_id}, line item {item.variant.sku}, '
f'message id: {message_id}')
updated_order = client.update_line_item_transition_state_on_fulfillment(
order.id,
Expand Down Expand Up @@ -263,7 +263,7 @@ def _prepare_segment_event_properties(in_order, return_line_item_return_id):
return False

if not (customer and order and is_edx_lms_order(order)): # pragma no cover
logger.debug(f'[CT-{tag}] order {order_id} is not an edX order, message id: {message_id}')
logger.info(f'[CT-{tag}] order {order_id} is not an edX order, message id: {message_id}')
return True

payment_intent_id = get_edx_payment_intent_id(order)
Expand All @@ -283,13 +283,13 @@ def _prepare_segment_event_properties(in_order, return_line_item_return_id):
logger.info(f'[CT-{tag}] payment intent {payment_intent_id} already has refunded transaction, '
f'sending Slack notification, message id: {message_id}')
else:
logger.debug(f'[CT-{tag}] payment intent {payment_intent_id} refunded. message id: {message_id}')
logger.info(f'[CT-{tag}] payment intent {payment_intent_id} refunded. message id: {message_id}')
segment_event_properties = _prepare_segment_event_properties(order, return_line_item_return_id)

for line_item in get_edx_items(order):
course_run = get_edx_product_course_run_key(line_item)
# TODO: Remove LMS Enrollment
logger.debug(
logger.info(
f'[CT-{tag}] calling lms to unenroll user {lms_user_name} in {course_run}'
f', message id: {message_id}'
)
Expand Down
18 changes: 10 additions & 8 deletions commerce_coordinator/apps/commercetools/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ def update_line_item_state_on_fulfillment_completion(
)
return updated_order
except CommercetoolsError as err:
logger.error(f"Unable to update line item [ {line_item_id} ] state on fulfillment "
f"result with error {err.errors} and correlation id {err.correlation_id}")
logger.error(f"[update_line_item_state] Failed to update line item {line_item_id} for order {order_id} "
f"with error: {err.errors} and Correlation ID: {err.correlation_id}")
return None


Expand All @@ -58,9 +58,12 @@ def refund_from_stripe_task(
"""
client = CommercetoolsAPIClient()
try:
logger.info(
f"[refund_from_stripe_task] Initiating creation of CT payment's refund transaction object "
f"for payment Intent ID {payment_intent_id}.")
payment = client.get_payment_by_key(payment_intent_id)
if has_full_refund_transaction(payment):
logger.info(f"Stripe charge.refunded event received, but Payment with ID {payment.id} "
logger.info(f"[refund_from_stripe_task] Event 'charge.refunded' received, but Payment with ID {payment.id} "
f"already has a full refund. Skipping task to add refund transaction")
return None
updated_payment = client.create_return_payment_transaction(
Expand All @@ -70,8 +73,8 @@ def refund_from_stripe_task(
)
return updated_payment
except CommercetoolsError as err:
logger.error(f"Unable to create refund transaction for payment [ {payment.id} ] "
f"on Stripe refund {stripe_refund['id']} "
logger.error(f"[refund_from_stripe_task] Unable to create CT payment's refund transaction "
f"object for [ {payment.id} ] on Stripe refund {stripe_refund['id']} "
f"with error {err.errors} and correlation id {err.correlation_id}")
return None

Expand All @@ -89,8 +92,6 @@ def refund_from_paypal_task(
try:
payment = client.get_payment_by_transaction_interaction_id(paypal_capture_id)
if has_full_refund_transaction(payment):
logger.info(f"PayPal PAYMENT.CAPTURE.REFUNDED event received, but Payment with ID {payment.id} "
f"already has a refund with ID: {refund.get('id')}. Skipping task to add refund transaction.")
return None
updated_payment = client.create_return_payment_transaction(
payment_id=payment.id,
Expand All @@ -100,7 +101,8 @@ def refund_from_paypal_task(
)
return updated_payment
except CommercetoolsError as err:
logger.error(f"Unable to create refund transaction for payment {payment.key} "
logger.error(f"[refund_from_paypal_task] Unable to create CT payment's refund "
f"transaction object for payment {payment.key} "
f"on PayPal refund {refund.get('id')} "
f"with error {err.errors} and correlation id {err.correlation_id}")
return None
13 changes: 7 additions & 6 deletions commerce_coordinator/apps/commercetools/tests/test_clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -470,8 +470,8 @@ def test_create_return_for_order_exception(self):
exception = cm.exception

expected_message = (
f"[CommercetoolsError] Unable to create return for "
f"order mock_order_id "
f"[CommercetoolsError] [CommercetoolsAPIClient.create_return_for_order] "
f"Unable to create return for order mock_order_id "
f"- Correlation ID: {exception.correlation_id}, Details: {exception.errors}"
)

Expand Down Expand Up @@ -604,7 +604,8 @@ def test_create_refund_transaction_exception(self):
exception = cm.exception

expected_message = (
f"[CommercetoolsError] Unable to create refund payment transaction for "
f"[CommercetoolsError] [CommercetoolsAPIClient.create_return_payment_transaction] "
f"Unable to create refund payment transaction for "
f"payment mock_payment_id, refund {mock_stripe_refund.id} with PSP: stripe_edx "
f"- Correlation ID: {exception.correlation_id}, Details: {exception.errors}"
)
Expand Down Expand Up @@ -683,7 +684,7 @@ def test_update_line_item_state_exception(self, mock_state_by_id):
)

expected_message = (
f"[CommercetoolsError] Unable to update LineItemState "
f"[CommercetoolsAPIClient] Unable to update LineItemState "
f"of order mock_order_id "
f"- Correlation ID: {mock_error_response['correlation_id']}, "
f"Details: {mock_error_response['errors']}"
Expand Down Expand Up @@ -715,8 +716,8 @@ def test_order_line_item_in_correct_state(self, mock_order_by_id, mock_state_by_
)

expected_message = (
f"The line item {line_item_id} already has the correct state {mock_line_item_state.key}. "
f"Not attempting to transition LineItemState"
f"[CommercetoolsAPIClient] - The line item {line_item_id} already has the correct state "
f"{mock_line_item_state.key}. Not attempting to transition LineItemState for order id mock_order_id"
)

log_mock.assert_called_with(expected_message)
Expand Down
34 changes: 23 additions & 11 deletions commerce_coordinator/apps/commercetools/tests/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""

import logging
from unittest.mock import patch
from unittest.mock import call, patch

import stripe
from commercetools import CommercetoolsError
Expand Down Expand Up @@ -78,8 +78,10 @@ def test_exception_handling(self, mock_logger, mock_client):
result = fulfillment_uut(*self.unpack_for_uut(EXAMPLE_UPDATE_LINE_ITEM_SIGNAL_PAYLOAD))

mock_logger.error.assert_called_once_with(
f"Unable to update line item [ {EXAMPLE_UPDATE_LINE_ITEM_SIGNAL_PAYLOAD['line_item_id']} ] "
"state on fulfillment result with error Some error message and correlation id 123456"
f"[update_line_item_state] Failed to update line item "
f"{EXAMPLE_UPDATE_LINE_ITEM_SIGNAL_PAYLOAD['line_item_id']} "
f"for order {EXAMPLE_UPDATE_LINE_ITEM_SIGNAL_PAYLOAD['order_id']} "
f"with error: Some error message and Correlation ID: 123456"
)

assert result is None
Expand Down Expand Up @@ -123,10 +125,10 @@ def test_correct_arguments_passed(self, mock_client):
)

def test_full_refund_already_exists(self, mock_client):
'''
"""
Check if the payment already has a full refund, the task logs the
appropriate message and skips creating a refund transaction.
'''
appropriate messages and skips creating a refund transaction.
"""
mock_payment = gen_payment_with_multiple_transactions(
TransactionType.CHARGE, 4900,
TransactionType.REFUND, 4900
Expand All @@ -135,13 +137,23 @@ def test_full_refund_already_exists(self, mock_client):

mock_client.return_value.get_payment_by_key.return_value = mock_payment

# Extract values from EXAMPLE_RETURNED_ORDER_STRIPE_SIGNAL_PAYLOAD
payment_intent_id = EXAMPLE_RETURNED_ORDER_STRIPE_SIGNAL_PAYLOAD['payment_intent_id']
stripe_refund_id = EXAMPLE_RETURNED_ORDER_STRIPE_SIGNAL_PAYLOAD['stripe_refund']['id']

with patch('commerce_coordinator.apps.commercetools.tasks.logger') as mock_logger:
result = refund_from_stripe_task(*self.unpack_for_uut(EXAMPLE_RETURNED_ORDER_STRIPE_SIGNAL_PAYLOAD))
self.assertIsNone(result)
mock_logger.info.assert_called_once_with(
f"Stripe charge.refunded event received, but Payment with ID {mock_payment.id} "
f"already has a full refund. Skipping task to add refund transaction"
)

# Check that both info messages were logged in the expected order
mock_logger.info.assert_has_calls([
call(
f"[refund_from_stripe_task] "
f"Initiating creation of CT payment's refund transaction object "
f"for payment Intent ID {payment_intent_id}."),
call(f"[refund_from_stripe_task] Event 'charge.refunded' received, but Payment with ID {mock_payment.id} "
f"already has a full refund. Skipping task to add refund transaction")
])

@patch('commerce_coordinator.apps.commercetools.tasks.logger')
def test_exception_handling(self, mock_logger, mock_client):
Expand All @@ -162,7 +174,7 @@ def test_exception_handling(self, mock_logger, mock_client):
returned_uut(*self.unpack_for_uut(EXAMPLE_RETURNED_ORDER_STRIPE_SIGNAL_PAYLOAD))

mock_logger.error.assert_called_once_with(
f"Unable to create refund transaction for payment [ {mock_payment.id} ] "
f"[refund_from_stripe_task] Unable to create CT payment's refund transaction object for [ {mock_payment.id} ] "
f"on Stripe refund {EXAMPLE_RETURNED_ORDER_STRIPE_CLIENT_PAYLOAD['stripe_refund']['id']} "
f"with error Some error message and correlation id 123456"
)
4 changes: 2 additions & 2 deletions commerce_coordinator/apps/commercetools/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ def get_braze_client():
)


def handle_commercetools_error(err: CommercetoolsError, context: str, is_info=False):
def handle_commercetools_error(context_prefix, err: CommercetoolsError, context: str, is_info=False):
"""Handles commercetools errors."""
error_message = f"[CommercetoolsError] {context} - Correlation ID: {err.correlation_id}, Details: {err.errors}"
error_message = f"[CommercetoolsError] {context_prefix} {context} - Correlation ID: {err.correlation_id}, Details: {err.errors}"
if is_info:
logger.info(error_message)
else:
Expand Down
6 changes: 3 additions & 3 deletions commerce_coordinator/apps/commercetools/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def post(self, request):
**request.data
}

logger.debug(f'[CT-{tag}] Message received from commercetools with details: {input_data}')
logger.info(f'[CT-{tag}] Message received from commercetools with details: {input_data}')

message_details = OrderLineItemMessageInputSerializer(data=input_data)
message_details.is_valid(raise_exception=True)
Expand Down Expand Up @@ -85,7 +85,7 @@ def post(self, request):
**request.data
}

logger.debug(f'[CT-{tag}] Message received from commercetools with details: {input_data}')
logger.info(f'[CT-{tag}] Message received from commercetools with details: {input_data}')

message_details = OrderSanctionedViewMessageInputSerializer(data=input_data)
message_details.is_valid(raise_exception=True)
Expand Down Expand Up @@ -127,7 +127,7 @@ def post(self, request):
**request.data
}

logger.debug(f'[CT-{tag}] Message received from commercetools with details: {input_data}')
logger.info(f'[CT-{tag}] Message received from commercetools with details: {input_data}')

message_details = OrderReturnedViewMessageInputSerializer(data=input_data)
message_details.is_valid(raise_exception=True)
Expand Down
30 changes: 5 additions & 25 deletions commerce_coordinator/apps/core/clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,38 +64,18 @@ def normal_timeout(self):
settings.REQUEST_READ_TIMEOUT_SECONDS
)

def log_request_response(self, ext_logger, response):
"""
Log requests.Request Response.
Args:
ext_logger: The logger of the module the Client (or Client-
derived class) is running in.
response: A successful Response object from the requests library.
"""
ext_logger.debug('Request URL: %s', response.request.url)
ext_logger.debug('Request method: %s', response.request.method)
ext_logger.debug('Request body: %s', response.request.body)
ext_logger.debug('Request headers: %s', response.request.headers)
ext_logger.debug('Response status: %s %s', response.status_code, response.reason)
ext_logger.debug('Response text: %s', response.text)

def log_request_exception(self, ext_logger, exc):
def log_request_exception(self, context_prefix, ext_logger, exc):
"""
Log requests.Request exceptions.
Args:
ext_logger: The logger of the module the Client (or Client-
derived class) is running in.
response: A RequestException object from the requests library.
exc: A RequestException object from the requests library.
"""
ext_logger.error(exc)
ext_logger.info('Request URL: %s', exc.request.url)
ext_logger.info('Request method: %s', exc.request.method)
ext_logger.info('Request body: %s', exc.request.body)
ext_logger.debug('Request headers: %s', exc.request.headers)
ext_logger.info('Response status: %s %s', exc.response.status_code, exc.response.reason)
ext_logger.info('Response body: %s', exc.response.text)
ext_logger.error(
f"{context_prefix} - The API call failed with status code: "
f"{exc.response.status_code if exc.response else ''}. Reason: {exc}.")


class BaseEdxOAuthClient(Client):
Expand Down
2 changes: 1 addition & 1 deletion commerce_coordinator/apps/core/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def log_drf_exceptions(exc, context):
'type: [%s], via [%s] on path: [%s] with exception: [%s].',
status_code, view_name, exception_type, method, path, exc,
)
logger.debug(
logger.info(
'Context for DRF Exception in APIView: status code: [%s] on '
'view: [%s] of type: [%s], via [%s] on path: [%s] with exception: [%s], '
'from request query_params: [%s], and data: [%s].',
Expand Down
2 changes: 1 addition & 1 deletion commerce_coordinator/apps/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def _is_running(view: str, identifier: str):
key = SingleInvocationAPIView._view_cache_key(view, identifier)
cache_value = TieredCache.get_cached_response(key)
if cache_value.is_found or cache_value.get_value_or_default(False):
logger.debug(f'[CT-{view}] Currently processing request for %s, ignoring invocation', identifier)
logger.info(f'[CT-{view}] Currently processing request for %s, ignoring invocation', identifier)
return True
return False

Expand Down
3 changes: 1 addition & 2 deletions commerce_coordinator/apps/ecommerce/clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@ def get_orders(self, query_params):
resource_url = urljoin_directory(self.api_base_url, '/orders')
response = self.client.get(resource_url, params=query_params)
response.raise_for_status()
self.log_request_response(logger, response)
except RequestException as exc:
self.log_request_exception(logger, exc)
self.log_request_exception("[EcommerceAPIClient.get_orders]",logger, exc)
raise

return response.json()
Loading

0 comments on commit 26e5b6f

Please sign in to comment.