Skip to content

Commit 5bc1b70

Browse files
committed
Refact and fix logs
1 parent d8a81d8 commit 5bc1b70

File tree

9 files changed

+186
-54
lines changed

9 files changed

+186
-54
lines changed

santander_sdk/api_client/client.py

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,11 @@
1313
SantanderClientError,
1414
SantanderRequestError,
1515
)
16-
from .helpers import get_status_code_description, try_parse_response_to_json
16+
from .helpers import try_parse_response_to_json
1717

1818
BEFORE_EXPIRE_TOKEN_SECONDS = timedelta(seconds=60)
1919
TOKEN_ENDPOINT = "/auth/oauth/v2/token"
2020

21-
logger = logging.getLogger(__name__)
22-
2321

2422
class SantanderApiClient:
2523
"""
@@ -47,7 +45,7 @@ def __init__(self, config: SantanderClientConfiguration):
4745
self.session = BaseURLSession(base_url=config.base_url)
4846
self.session.cert = config.cert
4947
self.session.auth = SantanderAuth.from_config(config)
50-
48+
self.logger = config.logger or logging.getLogger(__name__)
5149
self._set_default_workspace_id()
5250

5351
def _set_default_workspace_id(self):
@@ -58,7 +56,9 @@ def _set_default_workspace_id(self):
5856
"Conta sem configuração de workspace na configuração e na conta."
5957
)
6058

61-
logger.info(f"Workspace obtido e configurado com sucesso: {workspace_id}")
59+
self.logger.info(
60+
f"Workspace obtido e configurado com sucesso: {workspace_id}"
61+
)
6262
self.config.set_workspace_id(workspace_id)
6363

6464
def get(self, endpoint: str, params: dict | None = None) -> dict:
@@ -94,17 +94,81 @@ def _request(
9494
params: dict | None = None,
9595
) -> dict:
9696
url = self._prepare_url(endpoint)
97+
response = None
9798
try:
9899
response = self.session.request(
99100
method, url, json=data, params=params, timeout=60
100101
)
101102
response.raise_for_status()
103+
self._log_request_success_if_needed(method, url, params, data, response)
104+
102105
return response.json()
103106
except requests.exceptions.RequestException as e:
104107
status_code = getattr(e.response, "status_code", 0)
105108
error_content = try_parse_response_to_json(e.response)
106-
status_description = get_status_code_description(status_code)
109+
self._log_error_if_needed(method, url, params, data, e)
110+
raise SantanderRequestError(
111+
"Not successful code", status_code, error_content
112+
)
107113

108-
raise SantanderRequestError(status_description, status_code, error_content)
109114
except Exception as e:
110-
raise SantanderRequestError(f"Erro na requisição: {e}", 0, None) from e
115+
self._log_error_if_needed(method, url, params, data, e)
116+
raise SantanderRequestError("Error in request: %s" % str(e), 0, None) from e
117+
118+
def _log_error_if_needed(
119+
self,
120+
method: str,
121+
url: str,
122+
params: dict | None,
123+
data: dict | None,
124+
error: Exception | None,
125+
):
126+
if not self.config.log_request_response_level in ["ALL", "ERROR"]:
127+
self.logger.info("Logging error is disabled in client configuration")
128+
129+
response = getattr(error, "response", None)
130+
extra = self._get_request_summary(
131+
method, url, response, request_data=data, request_params=params, error=error
132+
)
133+
self.logger.error("API request failed", extra=extra)
134+
135+
def _log_request_success_if_needed(
136+
self,
137+
method: str,
138+
url: str,
139+
params: dict | None,
140+
data: dict | None,
141+
response: requests.Response,
142+
):
143+
if not self.config.log_request_response_level == "ALL":
144+
self.logger.info("Request successful", url)
145+
return
146+
147+
extra = self._get_request_summary(
148+
method, url, response, request_data=data, request_params=params
149+
)
150+
self.logger.info("API request successful", extra=extra)
151+
152+
def _get_request_summary(
153+
self,
154+
method: str,
155+
url: str,
156+
response: requests.Response | None,
157+
request_data: dict | None = None,
158+
request_params: dict | None = None,
159+
error: Exception | None = None,
160+
) -> dict:
161+
return {
162+
"method": method,
163+
"url": url,
164+
"request_body": request_data,
165+
"request_params": request_params,
166+
"status_code": response.status_code if response is not None else None,
167+
"response_body": try_parse_response_to_json(response)
168+
if response is not None
169+
else None,
170+
"status": "error" if error else "success",
171+
"error": {"message": str(error), "type": type(error).__name__}
172+
if error
173+
else None,
174+
}

santander_sdk/api_client/client_configuration.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
from typing import Literal
2+
import logging
3+
4+
15
class SantanderClientConfiguration:
26
def __init__(
37
self,
@@ -6,12 +10,16 @@ def __init__(
610
cert: str,
711
base_url: str,
812
workspace_id: str = "",
13+
log_request_response_level: Literal["ERROR", "ALL", "NONE"] = "ERROR",
14+
logger: logging.Logger | None = None,
915
):
1016
self.client_id = client_id
1117
self.client_secret = client_secret
1218
self.workspace_id = workspace_id
1319
self.cert = cert
1420
self.base_url = base_url
21+
self.log_request_response_level = log_request_response_level
22+
self.logger = logger or logging.getLogger(__name__)
1523

1624
def set_workspace_id(self, workspace_id: str):
1725
self.workspace_id = workspace_id

santander_sdk/api_client/helpers.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -64,26 +64,6 @@ def try_parse_response_to_json(response) -> dict | None:
6464
return error_content
6565

6666

67-
SANTANDER_STATUS_DESCRIPTIONS = {
68-
200: "Sucesso",
69-
201: "Recurso criado",
70-
400: "Erro de informação do cliente",
71-
401: "Não autorizado/Autenticado",
72-
403: "Não Autorizado",
73-
404: "Informação não encontrada",
74-
406: "O recurso de destino não possui uma representação atual que seria aceitável",
75-
422: "Entidade não processa/inadequada",
76-
429: "O usuário enviou muitas solicitações em um determinado período",
77-
500: "Erro de Servidor, Aplicação está fora",
78-
501: "O servidor não oferece suporte à funcionalidade necessária para atender à solicitação",
79-
}
80-
81-
82-
def get_status_code_description(status_code: int | str) -> str:
83-
"""Retorna a descrição do status do Santander"""
84-
return f"{status_code} - {SANTANDER_STATUS_DESCRIPTIONS.get(int(status_code), 'Erro desconhecido')}"
85-
86-
8767
def only_numbers(s):
8868
return re.sub("[^0-9]", "", s) if s else s
8969

santander_sdk/payment_receipts.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
https://developer.santander.com.br/api/documentacao/comprovantes-visao-geral/
4343
"""
4444

45-
import logging
4645
from time import sleep
4746
from typing import Generator, List, cast
4847
from santander_sdk.api_client.client import SantanderApiClient
@@ -63,8 +62,6 @@
6362

6463
RECEIPTS_ENDPOINT = "/consult_payment_receipts/v1/payment_receipts"
6564

66-
logger = logging.getLogger(__name__)
67-
6865

6966
def payment_list(
7067
client: SantanderApiClient, params: ListPaymentParams
@@ -164,18 +161,20 @@ def _handle_already_created(
164161
This happens when a receipt was requested a long time ago or the previous
165162
attempt returned an error like EXPUNGED or ERROR.
166163
"""
167-
logger.info("Receipt already requested. Trying to get the receipt request ID.")
164+
client.logger.info(
165+
"Receipt already requested. Trying to get the receipt request ID."
166+
)
168167
receipt_history = receipt_creation_history(client, payment_id)
169168
if not receipt_history["paymentReceiptsFileRequests"]:
170-
logger.error("No previous receipts in history")
169+
client.logger.error("No previous receipts in history")
171170
raise
172171
last_from_history = receipt_history["paymentReceiptsFileRequests"][-1]
173172
request_id = last_from_history["request"]["requestId"]
174173
result = get_receipt(client, payment_id, request_id)
175174
if result["status"] not in [ReceiptStatus.EXPUNGED, ReceiptStatus.ERROR]:
176175
return result
177176

178-
logger.info("The last receipt is in an error state, creating another one.")
177+
client.logger.info("The last receipt is in an error state, creating another one.")
179178
sleep(0.5)
180179
endpoint = f"{RECEIPTS_ENDPOINT}/{payment_id}/file_requests"
181180
response = cast(ReceiptInfoResponse, client.post(endpoint, None))

santander_sdk/pix.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
TransferPixResult,
2020
)
2121

22-
logger = logging.getLogger("santanderLogger")
2322
PIX_ENDPOINT = "/management_payments_partners/v1/workspaces/:workspaceid/pix_payments"
2423

2524

@@ -34,7 +33,7 @@ def transfer_pix(
3433
if value is None or value <= 0:
3534
raise SantanderValueError(f"Invalid value for PIX transfer: {value}")
3635

37-
transfer_flow = SantanderPaymentFlow(client, PIX_ENDPOINT, logger)
36+
transfer_flow = SantanderPaymentFlow(client, PIX_ENDPOINT)
3837

3938
create_pix_dict = _generate_create_pix_dict(pix_key, value, description, tags)
4039
create_pix_response = transfer_flow.create_payment(create_pix_dict)
@@ -54,7 +53,7 @@ def transfer_pix(
5453
return {"success": True, "data": confirm_response, "error": ""}
5554
except Exception as e:
5655
error_message = str(e)
57-
logger.error(error_message)
56+
client.logger.error(error_message)
5857
return {"success": False, "error": error_message, "data": None}
5958

6059

santander_sdk/transfer_flow.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from time import sleep
33
from typing import List, Literal, cast
44

5+
from santander_sdk.api_client import client
56
from santander_sdk.api_client.client import SantanderApiClient
67
from santander_sdk.api_client.exceptions import (
78
SantanderClientError,
@@ -33,24 +34,22 @@ def __init__(
3334
self,
3435
client: SantanderApiClient,
3536
endpoint: str,
36-
logger: logging.Logger | None = None,
3737
):
3838
self.client = client
39-
self.logger = logger or logging.getLogger(__name__)
4039
self.endpoint = endpoint
4140

4241
def create_payment(self, data: dict) -> SantanderPixResponse:
4342
response = cast(
4443
SantanderPixResponse, self.client.post(self.endpoint, data=data)
4544
)
4645
self._check_for_rejected_error(response)
47-
self.logger.info("Payment created: ", response.get("id"))
46+
self.client.logger.info("Payment created: ", response.get("id"))
4847
return response
4948

5049
def ensure_ready_to_pay(self, confirm_data) -> None:
5150
payment_status = confirm_data.get("status")
5251
if payment_status != CreateOrderStatus.READY_TO_PAY:
53-
self.logger.info("PIX is not ready for payment", payment_status)
52+
self.client.logger.info("PIX is not ready for payment", payment_status)
5453
self._payment_status_polling(
5554
payment_id=confirm_data.get("id"),
5655
until_status=[CreateOrderStatus.READY_TO_PAY],
@@ -63,7 +62,7 @@ def confirm_payment(
6362
try:
6463
confirm_response = self._request_confirm_payment(confirm_data, payment_id)
6564
except SantanderRequestError as e:
66-
self.logger.error(str(e), payment_id, "checking current status")
65+
self.client.logger.error(str(e), payment_id, "checking current status")
6766
confirm_response = self._request_payment_status(payment_id)
6867

6968
if not confirm_response.get("status") == ConfirmOrderStatus.PAYED:
@@ -72,7 +71,9 @@ def confirm_payment(
7271
payment_id, confirm_response.get("status")
7372
)
7473
except SantanderStatusTimeoutError as e:
75-
self.logger.info("Timeout occurred while updating status:", str(e))
74+
self.client.logger.info(
75+
"Timeout occurred while updating status:", str(e)
76+
)
7677
return confirm_response
7778

7879
@retry_one_time_on_request_exception
@@ -124,7 +125,7 @@ def _payment_status_polling(
124125
) -> SantanderPixResponse:
125126
for attempt in range(1, max_update_attemps + 1):
126127
response = self._request_payment_status(payment_id)
127-
self.logger.info(
128+
self.client.logger.info(
128129
f"Checking status by polling: {payment_id} - {response.get('status')}"
129130
)
130131
if response.get("status") in until_status:

0 commit comments

Comments
 (0)