refactor(logging): use logger.exception to preserve stack traces
Unify error logging across services: replace logger.error(f"...{e}")
and logger.error(..., exc_info=True) with logger.exception() so the
stack trace is consistently captured.
This commit is contained in:
@@ -121,16 +121,16 @@ class CryptoPayService:
|
||||
str(invoice.status),
|
||||
)
|
||||
await session.commit()
|
||||
except Exception as e_db_update:
|
||||
except Exception:
|
||||
await session.rollback()
|
||||
logging.error(
|
||||
f"Failed to update cryptopay payment record {payment_record.payment_id}: {e_db_update}",
|
||||
exc_info=True,
|
||||
logging.exception(
|
||||
"Failed to update cryptopay payment record %s.",
|
||||
payment_record.payment_id,
|
||||
)
|
||||
return None
|
||||
return invoice.bot_invoice_url
|
||||
except Exception as e:
|
||||
logging.error(f"CryptoPay invoice creation failed: {e}", exc_info=True)
|
||||
except Exception:
|
||||
logging.exception("CryptoPay invoice creation failed.")
|
||||
return None
|
||||
|
||||
async def _invoice_paid_handler(self, update: Update, app: web.Application):
|
||||
@@ -145,8 +145,8 @@ class CryptoPayService:
|
||||
payment_db_id = int(meta["payment_db_id"])
|
||||
sale_mode = meta.get("sale_mode") or ("traffic" if self.settings.traffic_sale_mode else "subscription")
|
||||
traffic_gb = float(meta.get("traffic_gb")) if meta.get("traffic_gb") else months
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to parse CryptoPay payload: {e}")
|
||||
except Exception:
|
||||
logging.exception("Failed to parse CryptoPay payload.")
|
||||
return
|
||||
|
||||
async_session_factory: sessionmaker = app["async_session_factory"]
|
||||
@@ -184,9 +184,9 @@ class CryptoPayService:
|
||||
skip_if_active_before_payment=False,
|
||||
)
|
||||
await session.commit()
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
await session.rollback()
|
||||
logging.error(f"Failed to process CryptoPay invoice: {e}", exc_info=True)
|
||||
logging.exception("Failed to process CryptoPay invoice.")
|
||||
return
|
||||
|
||||
db_user = await user_dal.get_user_by_id(session, user_id)
|
||||
@@ -247,8 +247,8 @@ class CryptoPayService:
|
||||
parse_mode="HTML",
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to send CryptoPay success message: {e}")
|
||||
except Exception:
|
||||
logging.exception("Failed to send CryptoPay success message.")
|
||||
|
||||
# Send notification about payment
|
||||
try:
|
||||
@@ -263,8 +263,8 @@ class CryptoPayService:
|
||||
payment_provider="crypto_pay",
|
||||
username=user.username if user else None
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to send crypto_pay payment notification: {e}")
|
||||
except Exception:
|
||||
logging.exception("Failed to send crypto_pay payment notification.")
|
||||
|
||||
def _validate_webhook_signature(self, raw_body: bytes, signature: str) -> bool:
|
||||
if not self.token:
|
||||
|
||||
@@ -137,7 +137,7 @@ class FreeKassaService:
|
||||
|
||||
return True, response_data
|
||||
except Exception as exc:
|
||||
logging.error("FreeKassa create_order: request failed: %s", exc, exc_info=True)
|
||||
logging.exception("FreeKassa create_order: request failed.")
|
||||
return False, {"message": str(exc)}
|
||||
|
||||
async def _get_session(self) -> ClientSession:
|
||||
@@ -196,8 +196,8 @@ class FreeKassaService:
|
||||
return web.Response(status=403)
|
||||
|
||||
raw_body = await request.read()
|
||||
except Exception as e:
|
||||
logging.error("FreeKassa webhook: failed to read request body: %s", e)
|
||||
except Exception:
|
||||
logging.exception("FreeKassa webhook: failed to read request body.")
|
||||
return web.Response(status=400, text="bad_request")
|
||||
|
||||
payload_dict: Dict[str, Any] = {}
|
||||
@@ -299,9 +299,9 @@ class FreeKassaService:
|
||||
)
|
||||
|
||||
await session.commit()
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
await session.rollback()
|
||||
logging.error(f"FreeKassa webhook: failed to process payment {payment_db_id}: {e}", exc_info=True)
|
||||
logging.exception("FreeKassa webhook: failed to process payment %s.", payment_db_id)
|
||||
return web.Response(status=500, text="processing_error")
|
||||
|
||||
db_user = payment.user or await user_dal.get_user_by_id(session, payment.user_id)
|
||||
@@ -385,8 +385,8 @@ class FreeKassaService:
|
||||
parse_mode="HTML",
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error(f"FreeKassa notification: failed to send message to user {payment.user_id}: {e}")
|
||||
except Exception:
|
||||
logging.exception("FreeKassa notification: failed to send message to user %s.", payment.user_id)
|
||||
|
||||
try:
|
||||
notification_service = NotificationService(self.bot, self.settings, self.i18n)
|
||||
@@ -399,8 +399,8 @@ class FreeKassaService:
|
||||
payment_provider="freekassa",
|
||||
username=db_user.username if db_user else None,
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error(f"FreeKassa notification: failed to notify admins: {e}")
|
||||
except Exception:
|
||||
logging.exception("FreeKassa notification: failed to notify admins.")
|
||||
|
||||
return web.Response(text="YES")
|
||||
|
||||
|
||||
@@ -120,8 +120,8 @@ class NotificationService:
|
||||
logging.error(
|
||||
f"Failed to send notification to log channel {self.settings.LOG_CHAT_ID}: {exc}"
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to send notification to log channel {self.settings.LOG_CHAT_ID}: {e}")
|
||||
except Exception:
|
||||
logging.exception("Failed to send notification to log channel %s.", self.settings.LOG_CHAT_ID)
|
||||
return
|
||||
|
||||
try:
|
||||
@@ -143,8 +143,8 @@ class NotificationService:
|
||||
# Queue message for sending (groups are rate limited to 15/minute)
|
||||
await queue_manager.send_message(self.settings.LOG_CHAT_ID, **kwargs)
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to queue notification to log channel {self.settings.LOG_CHAT_ID}: {e}")
|
||||
except Exception:
|
||||
logging.exception("Failed to queue notification to log channel %s.", self.settings.LOG_CHAT_ID)
|
||||
|
||||
async def _send_to_admins(self, message: str):
|
||||
"""Send message to all admin users using message queue"""
|
||||
@@ -162,8 +162,8 @@ class NotificationService:
|
||||
parse_mode="HTML",
|
||||
disable_web_page_preview=True
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to send notification to admin {admin_id}: {e}")
|
||||
except Exception:
|
||||
logging.exception("Failed to send notification to admin %s.", admin_id)
|
||||
return
|
||||
|
||||
for admin_id in self.settings.ADMIN_IDS:
|
||||
@@ -174,8 +174,8 @@ class NotificationService:
|
||||
parse_mode="HTML",
|
||||
disable_web_page_preview=True
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to queue notification to admin {admin_id}: {e}")
|
||||
except Exception:
|
||||
logging.exception("Failed to queue notification to admin %s.", admin_id)
|
||||
|
||||
async def notify_new_user_registration(self, user_id: int, username: Optional[str] = None,
|
||||
first_name: Optional[str] = None,
|
||||
|
||||
@@ -174,7 +174,7 @@ class PanelApiService:
|
||||
"message": f"Connection error: {str(e)}"
|
||||
}
|
||||
except aiohttp.ClientError as e:
|
||||
logging.error(f"Panel API ClientError to {url_for_request}: {e}")
|
||||
logging.exception("Panel API ClientError to %s.", url_for_request)
|
||||
return {
|
||||
"error": True,
|
||||
"status_code": -2,
|
||||
|
||||
@@ -127,7 +127,7 @@ class PlategaService:
|
||||
|
||||
return True, response_data
|
||||
except Exception as exc:
|
||||
logging.error("Platega create_transaction: request failed: %s", exc, exc_info=True)
|
||||
logging.exception("Platega create_transaction: request failed.")
|
||||
return False, {"message": str(exc)}
|
||||
|
||||
async def webhook_route(self, request: web.Request) -> web.Response:
|
||||
@@ -136,8 +136,8 @@ class PlategaService:
|
||||
|
||||
try:
|
||||
data = await request.json()
|
||||
except Exception as exc:
|
||||
logging.error("Platega webhook: failed to parse JSON: %s", exc)
|
||||
except Exception:
|
||||
logging.exception("Platega webhook: failed to parse JSON.")
|
||||
return web.Response(status=400, text="bad_request")
|
||||
|
||||
header_merchant = request.headers.get("X-MerchantId")
|
||||
@@ -215,9 +215,9 @@ class PlategaService:
|
||||
)
|
||||
|
||||
await session.commit()
|
||||
except Exception as exc:
|
||||
except Exception:
|
||||
await session.rollback()
|
||||
logging.error("Platega webhook: failed to process payment %s: %s", transaction_id, exc, exc_info=True)
|
||||
logging.exception("Platega webhook: failed to process payment %s.", transaction_id)
|
||||
return web.Response(status=500, text="processing_error")
|
||||
|
||||
db_user = await user_dal.get_user_by_id(session, payment.user_id)
|
||||
@@ -296,8 +296,8 @@ class PlategaService:
|
||||
parse_mode="HTML",
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
except Exception as exc:
|
||||
logging.error("Platega webhook: failed to notify user %s: %s", payment.user_id, exc)
|
||||
except Exception:
|
||||
logging.exception("Platega webhook: failed to notify user %s.", payment.user_id)
|
||||
|
||||
try:
|
||||
notification_service = NotificationService(self.bot, self.settings, self.i18n)
|
||||
@@ -310,8 +310,8 @@ class PlategaService:
|
||||
payment_provider="platega",
|
||||
username=db_user.username if db_user else None,
|
||||
)
|
||||
except Exception as exc:
|
||||
logging.error("Platega webhook: failed to notify admins: %s", exc)
|
||||
except Exception:
|
||||
logging.exception("Platega webhook: failed to notify admins.")
|
||||
|
||||
return web.Response(text="ok")
|
||||
|
||||
@@ -324,9 +324,9 @@ class PlategaService:
|
||||
"canceled",
|
||||
)
|
||||
await session.commit()
|
||||
except Exception as exc:
|
||||
except Exception:
|
||||
await session.rollback()
|
||||
logging.error("Platega webhook: failed to cancel payment %s: %s", transaction_id, exc)
|
||||
logging.exception("Platega webhook: failed to cancel payment %s.", transaction_id)
|
||||
return web.Response(status=500, text="processing_error")
|
||||
|
||||
db_user = await user_dal.get_user_by_id(session, payment.user_id)
|
||||
|
||||
@@ -142,7 +142,7 @@ class SeverPayService:
|
||||
|
||||
return True, response_data.get("data") or response_data
|
||||
except Exception as exc:
|
||||
logging.error("SeverPay create_payment: request failed: %s", exc, exc_info=True)
|
||||
logging.exception("SeverPay create_payment: request failed.")
|
||||
return False, {"message": str(exc)}
|
||||
|
||||
async def webhook_route(self, request: web.Request) -> web.Response:
|
||||
@@ -151,8 +151,8 @@ class SeverPayService:
|
||||
|
||||
try:
|
||||
payload = await request.json()
|
||||
except Exception as exc:
|
||||
logging.error("SeverPay webhook: failed to parse JSON: %s", exc)
|
||||
except Exception:
|
||||
logging.exception("SeverPay webhook: failed to parse JSON.")
|
||||
return web.json_response({"status": False, "msg": "bad_request"}, status=400)
|
||||
|
||||
if not isinstance(payload, dict) or not self._validate_signature(payload):
|
||||
@@ -223,9 +223,9 @@ class SeverPayService:
|
||||
)
|
||||
|
||||
await session.commit()
|
||||
except Exception as exc:
|
||||
except Exception:
|
||||
await session.rollback()
|
||||
logging.error("SeverPay webhook: failed to process payment %s: %s", provider_payment_id, exc, exc_info=True)
|
||||
logging.exception("SeverPay webhook: failed to process payment %s.", provider_payment_id)
|
||||
return web.json_response({"status": False, "msg": "processing_error"}, status=500)
|
||||
|
||||
db_user = payment.user or await user_dal.get_user_by_id(session, payment.user_id)
|
||||
@@ -304,8 +304,8 @@ class SeverPayService:
|
||||
parse_mode="HTML",
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
except Exception as exc:
|
||||
logging.error("SeverPay webhook: failed to notify user %s: %s", payment.user_id, exc)
|
||||
except Exception:
|
||||
logging.exception("SeverPay webhook: failed to notify user %s.", payment.user_id)
|
||||
|
||||
try:
|
||||
notification_service = NotificationService(self.bot, self.settings, self.i18n)
|
||||
@@ -318,8 +318,8 @@ class SeverPayService:
|
||||
payment_provider="severpay",
|
||||
username=db_user.username if db_user else None,
|
||||
)
|
||||
except Exception as exc:
|
||||
logging.error("SeverPay webhook: failed to notify admins: %s", exc)
|
||||
except Exception:
|
||||
logging.exception("SeverPay webhook: failed to notify admins.")
|
||||
|
||||
return web.json_response({"status": True})
|
||||
|
||||
@@ -332,9 +332,9 @@ class SeverPayService:
|
||||
"failed",
|
||||
)
|
||||
await session.commit()
|
||||
except Exception as exc:
|
||||
except Exception:
|
||||
await session.rollback()
|
||||
logging.error("SeverPay webhook: failed to mark payment %s as failed: %s", provider_payment_id, exc)
|
||||
logging.exception("SeverPay webhook: failed to mark payment %s as failed.", provider_payment_id)
|
||||
return web.json_response({"status": False, "msg": "processing_error"}, status=500)
|
||||
|
||||
db_user = payment.user or await user_dal.get_user_by_id(session, payment.user_id)
|
||||
@@ -355,9 +355,9 @@ class SeverPayService:
|
||||
"pending_severpay",
|
||||
)
|
||||
await session.commit()
|
||||
except Exception as exc:
|
||||
except Exception:
|
||||
await session.rollback()
|
||||
logging.error("SeverPay webhook: failed to update pending status for %s: %s", provider_payment_id, exc)
|
||||
logging.exception("SeverPay webhook: failed to update pending status for %s.", provider_payment_id)
|
||||
return web.json_response({"status": True})
|
||||
|
||||
logging.warning("SeverPay webhook: unhandled status '%s' for payment %s", status, provider_payment_id)
|
||||
|
||||
@@ -55,7 +55,7 @@ class StarsService:
|
||||
title=description,
|
||||
description=description,
|
||||
payload=payload,
|
||||
provider_token="",
|
||||
provider_token="", # Required to be empty for Telegram Stars (XTR) per Telegram Bot API.
|
||||
currency="XTR",
|
||||
prices=prices,
|
||||
)
|
||||
|
||||
@@ -35,9 +35,8 @@ class YooKassaService:
|
||||
self.configured = True
|
||||
logging.info(
|
||||
f"YooKassa SDK configured for shop_id: {shop_id[:5]}...")
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to configure YooKassa SDK: {e}",
|
||||
exc_info=True)
|
||||
except Exception:
|
||||
logging.exception("Failed to configure YooKassa SDK.")
|
||||
self.configured = False
|
||||
|
||||
if configured_return_url:
|
||||
@@ -201,9 +200,8 @@ class YooKassaService:
|
||||
response.test if hasattr(response, 'test') else None,
|
||||
"payment_method": getattr(response, 'payment_method', None),
|
||||
}
|
||||
except Exception as e:
|
||||
logging.error(f"YooKassa payment creation failed: {e}",
|
||||
exc_info=True)
|
||||
except Exception:
|
||||
logging.exception("YooKassa payment creation failed.")
|
||||
return None
|
||||
|
||||
async def get_payment_info(
|
||||
@@ -266,10 +264,9 @@ class YooKassaService:
|
||||
f"No payment info found in YooKassa for ID: {payment_id_in_yookassa}"
|
||||
)
|
||||
return None
|
||||
except Exception as e:
|
||||
logging.error(
|
||||
f"YooKassa get payment info for {payment_id_in_yookassa} failed: {e}",
|
||||
exc_info=True)
|
||||
except Exception:
|
||||
logging.exception(
|
||||
"YooKassa get payment info for %s failed.", payment_id_in_yookassa)
|
||||
return None
|
||||
|
||||
async def cancel_payment(self, payment_id_in_yookassa: str) -> bool:
|
||||
@@ -280,6 +277,6 @@ class YooKassaService:
|
||||
await asyncio.to_thread(YooKassaPayment.cancel, payment_id_in_yookassa)
|
||||
logging.info(f"Cancelled YooKassa payment {payment_id_in_yookassa}")
|
||||
return True
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to cancel YooKassa payment {payment_id_in_yookassa}: {e}")
|
||||
except Exception:
|
||||
logging.exception("Failed to cancel YooKassa payment %s.", payment_id_in_yookassa)
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user