Skip to content

Commit

Permalink
feature: implement logger
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanildoBarauna committed Jul 3, 2024
1 parent ef8557a commit 43cfabd
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 10 deletions.
12 changes: 11 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "api-to-dataframe"
version = "1.3.1a0"
version = "1.3.0"
description = "A package to convert API responses to pandas dataframe"
authors = ["IvanildoBarauna <[email protected]>"]
readme = "README.md"
Expand All @@ -26,6 +26,7 @@ Repository = "https://github.com/IvanildoBarauna/api-to-dataframe"
python = "^3.9"
pandas = "^2.2.2"
requests = "^2.32.3"
logging = "^0.4.9.6"

[tool.poetry.group.dev.dependencies]
poetry-dynamic-versioning = "^1.3.0"
Expand Down
15 changes: 11 additions & 4 deletions src/api_to_dataframe/controller/client_builder.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from api_to_dataframe.models.retainer import retry_strategies, Strategies
from api_to_dataframe.models.get_data import GetData
from api_to_dataframe.utils.logger import log, LogLevel


class ClientBuilder:
Expand Down Expand Up @@ -33,13 +34,17 @@ def __init__( # pylint: disable=too-many-arguments
if headers is None:
headers = {}
if endpoint == "":
raise ValueError("::: endpoint param is mandatory :::")
log("endpoint param is mandatory", LogLevel.ERROR)
raise ValueError
if not isinstance(retries, int) or retries < 0:
raise ValueError("retries must be a non-negative integer")
log("retries must be a non-negative integer", LogLevel.ERROR)
raise ValueError
if not isinstance(initial_delay, int) or initial_delay < 0:
raise ValueError("delay must be a non-negative integer")
log("delay must be a non-negative integer", LogLevel.ERROR)
raise ValueError
if not isinstance(connection_timeout, int) or connection_timeout < 0:
raise ValueError("connection_timeout must be a non-negative integer")
log("connection_timeout must be a non-negative integer", LogLevel.ERROR)
raise ValueError

self.endpoint = endpoint
self.retry_strategy = retry_strategy
Expand All @@ -61,6 +66,7 @@ def get_api_data(self):
headers=self.headers,
connection_timeout=self.connection_timeout,
)

return response.json()

def _get_raw_api_data(self):
Expand All @@ -74,4 +80,5 @@ def _get_raw_api_data(self):
@staticmethod
def api_to_dataframe(response: dict):
df = GetData.to_dataframe(response)
log("serialized to dataframe: OK", LogLevel.INFO)
return df
5 changes: 5 additions & 0 deletions src/api_to_dataframe/models/get_data.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
import requests
import pandas as pd

from api_to_dataframe.utils.logger import log, LogLevel


class GetData:
@staticmethod
def get_response(endpoint: str, headers: dict, connection_timeout: int):
response = requests.get(endpoint, timeout=connection_timeout, headers=headers)
response.raise_for_status()
log("get_response: ok", LogLevel.INFO)
return response

@staticmethod
def to_dataframe(response):
try:
df = pd.DataFrame(response)
except Exception as err:
log(f"Error serializing to dataframe: {err}", LogLevel.ERROR)
raise TypeError(
f"Invalid response for transform in dataframe: {err}"
) from err

if df.empty:
log("DataFrame is empty", LogLevel.ERROR)
raise ValueError("::: DataFrame is empty :::")

return df
11 changes: 7 additions & 4 deletions src/api_to_dataframe/models/retainer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import time
from enum import Enum
from requests.exceptions import RequestException
from api_to_dataframe.utils.logger import log, LogLevel


class Strategies(Enum):
Expand All @@ -14,9 +15,10 @@ def wrapper(*args, **kwargs): # pylint: disable=inconsistent-return-statements
retry_number = 0
while retry_number < args[0].retries:
try:
print(
log(
f"Trying for the {retry_number + 1} of {args[0].retries} retries. "
f"Using {args[0].retry_strategy}"
f"Using {args[0].retry_strategy}",
LogLevel.INFO,
)
return func(*args, **kwargs)
except RequestException as e:
Expand All @@ -30,8 +32,9 @@ def wrapper(*args, **kwargs): # pylint: disable=inconsistent-return-statements
time.sleep(args[0].delay * 2**retry_number)

if retry_number == args[0].retries:
print(
f"Failed after {retry_number} retries using {args[0].retry_strategy}"
log(
f"Failed after {retry_number} retries using {args[0].retry_strategy}",
LogLevel.ERROR,
)
raise e

Expand Down
27 changes: 27 additions & 0 deletions src/api_to_dataframe/utils/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import logging
from enum import Enum


class LogLevel(Enum):
INFO = logging.INFO
WARNING = logging.WARNING
ERROR = logging.ERROR


# Configure logging once at the start of your program
logging.basicConfig(
encoding="utf-8",
format="%(asctime)s :: %(levelname)s :: %(message)s",
datefmt="%Y-%m-%d %H:%M:%S %Z",
level=logging.DEBUG,
)


def log(message: str, level: LogLevel):
logger = logging.getLogger("api-to-dataframe")
logger.log(level.value, message)


log("This is an info message", LogLevel.INFO)
log("This is a warning message", LogLevel.WARNING)
log("This is an error message", LogLevel.ERROR)
Empty file.

0 comments on commit 43cfabd

Please sign in to comment.