Skip to content

Commit c042352

Browse files
feature: remove otel-wrapper and increase unittests
1 parent 07d4c42 commit c042352

12 files changed

+464
-1379
lines changed

CLAUDE.md

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# API-TO-DATAFRAME DEVELOPMENT GUIDE
2+
3+
## Build & Test Commands
4+
- Setup: `poetry install`
5+
- Run all tests: `poetry run pytest`
6+
- Run single test: `poetry run pytest tests/test_file.py::test_function`
7+
- Coverage: `poetry run coverage run -m pytest && poetry run coverage report`
8+
- Lint: `poetry run pylint src/`
9+
- Format: `poetry run black src/ tests/`
10+
11+
## Code Style Guidelines
12+
- Use Python 3.9+ features
13+
- Import order: stdlib → third-party → local
14+
- Type hints required for function parameters and return values
15+
- Follow black formatting (max line length 88)
16+
- Variable naming: snake_case for variables/functions, PascalCase for classes
17+
- Error handling: use try/except with specific exceptions, log errors
18+
- Use f-strings for string formatting
19+
- Test coverage target: 90%+
20+
- Use dataclasses or typed dictionaries for structured data
21+
22+
## Architecture
23+
- MVC-like pattern: controllers, models, utils
24+
- Core functionality in models package
25+
- Client interactions in controller package

poetry.lock

+136-765
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "api-to-dataframe"
3-
version = "1.5.2"
3+
version = "2.0.0"
44
description = "A package to convert API responses to pandas dataframe"
55
authors = ["IvanildoBarauna <[email protected]>"]
66
readme = "README.md"
@@ -27,7 +27,6 @@ python = "^3.9"
2727
pandas = "^2.2.3"
2828
requests = "^2.32.3"
2929
logging = "^0.4.9.6"
30-
otel-wrapper = "^0.1.1"
3130

3231
[tool.poetry.group.dev.dependencies]
3332
poetry-dynamic-versioning = "^1.3.0"
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from api_to_dataframe.models.retainer import retry_strategies, Strategies
22
from api_to_dataframe.models.get_data import GetData
3-
from api_to_dataframe.utils.logger import logger, telemetry
4-
import time
3+
from api_to_dataframe.utils.logger import logger
54

65

76
class ClientBuilder:
@@ -37,38 +36,18 @@ def __init__( # pylint: disable=too-many-positional-arguments,too-many-argument
3736
if endpoint == "":
3837
error_msg = "endpoint cannot be an empty string"
3938
logger.error(error_msg)
40-
telemetry.logs().new_log(
41-
msg=error_msg,
42-
tags={"component": "ClientBuilder", "method": "__init__"},
43-
level=40 # ERROR level
44-
)
4539
raise ValueError
4640
if not isinstance(retries, int) or retries < 0:
4741
error_msg = "retries must be a non-negative integer"
4842
logger.error(error_msg)
49-
telemetry.logs().new_log(
50-
msg=error_msg,
51-
tags={"component": "ClientBuilder", "method": "__init__"},
52-
level=40 # ERROR level
53-
)
5443
raise ValueError
5544
if not isinstance(initial_delay, int) or initial_delay < 0:
5645
error_msg = "initial_delay must be a non-negative integer"
5746
logger.error(error_msg)
58-
telemetry.logs().new_log(
59-
msg=error_msg,
60-
tags={"component": "ClientBuilder", "method": "__init__"},
61-
level=40 # ERROR level
62-
)
6347
raise ValueError
6448
if not isinstance(connection_timeout, int) or connection_timeout < 0:
6549
error_msg = "connection_timeout must be a non-negative integer"
6650
logger.error(error_msg)
67-
telemetry.logs().new_log(
68-
msg=error_msg,
69-
tags={"component": "ClientBuilder", "method": "__init__"},
70-
level=40 # ERROR level
71-
)
7251
raise ValueError
7352

7453
self.endpoint = endpoint
@@ -78,28 +57,6 @@ def __init__( # pylint: disable=too-many-positional-arguments,too-many-argument
7857
self.retries = retries
7958
self.delay = initial_delay
8059

81-
# Record client initialization metric
82-
telemetry.metrics().metric_increment(
83-
name="client.initialization",
84-
tags={
85-
"endpoint": endpoint,
86-
"retry_strategy": retry_strategy.name,
87-
"connection_timeout": str(connection_timeout)
88-
}
89-
)
90-
91-
# Log initialization
92-
telemetry.logs().new_log(
93-
msg=f"ClientBuilder initialized with endpoint {endpoint}",
94-
tags={
95-
"endpoint": endpoint,
96-
"retry_strategy": retry_strategy.name,
97-
"connection_timeout": str(connection_timeout),
98-
"component": "ClientBuilder"
99-
},
100-
level=20 # INFO level
101-
)
102-
10360
@retry_strategies
10461
def get_api_data(self):
10562
"""
@@ -112,67 +69,13 @@ def get_api_data(self):
11269
Returns:
11370
dict: The JSON response from the API as a dictionary.
11471
"""
115-
# Use the telemetry spans with new API
116-
span = telemetry.traces().new_span("get_api_data")
117-
try:
118-
# Add span attributes
119-
span.set_attribute("endpoint", self.endpoint)
120-
span.set_attribute("retry_strategy", self.retry_strategy.name)
121-
span.set_attribute("connection_timeout", self.connection_timeout)
122-
123-
# Log the API request
124-
telemetry.logs().new_log(
125-
msg=f"Making API request to {self.endpoint}",
126-
tags={
127-
"endpoint": self.endpoint,
128-
"component": "ClientBuilder",
129-
"method": "get_api_data"
130-
},
131-
level=20 # INFO level
132-
)
133-
134-
# Record the start time for response time measurement
135-
start_time = time.time()
136-
137-
# Make the API request
138-
response = GetData.get_response(
139-
endpoint=self.endpoint,
140-
headers=self.headers,
141-
connection_timeout=self.connection_timeout,
142-
)
143-
144-
# Calculate response time
145-
response_time = time.time() - start_time
146-
147-
# Record response time as histogram
148-
telemetry.metrics().record_histogram(
149-
name="api.response_time",
150-
tags={"endpoint": self.endpoint},
151-
value=response_time
152-
)
153-
154-
# Record successful request metric
155-
telemetry.metrics().metric_increment(
156-
name="api.request.success",
157-
tags={"endpoint": self.endpoint}
158-
)
159-
160-
# Log success
161-
telemetry.logs().new_log(
162-
msg=f"API request to {self.endpoint} successful",
163-
tags={
164-
"endpoint": self.endpoint,
165-
"response_status": response.status_code,
166-
"response_time": response_time,
167-
"component": "ClientBuilder",
168-
"method": "get_api_data"
169-
},
170-
level=20 # INFO level
171-
)
72+
response = GetData.get_response(
73+
endpoint=self.endpoint,
74+
headers=self.headers,
75+
connection_timeout=self.connection_timeout,
76+
)
17277

173-
return response.json()
174-
finally:
175-
span.end()
78+
return response.json()
17679

17780
@staticmethod
17881
def api_to_dataframe(response: dict):
@@ -189,69 +92,4 @@ def api_to_dataframe(response: dict):
18992
Returns:
19093
DataFrame: A pandas DataFrame containing the data from the API response.
19194
"""
192-
# Use telemetry with new API
193-
span = telemetry.traces().new_span("api_to_dataframe")
194-
try:
195-
response_size = len(response) if isinstance(response, list) else 1
196-
span.set_attribute("response_size", response_size)
197-
198-
# Log conversion start
199-
telemetry.logs().new_log(
200-
msg="Converting API response to DataFrame",
201-
tags={
202-
"response_size": response_size,
203-
"response_type": type(response).__name__,
204-
"component": "ClientBuilder",
205-
"method": "api_to_dataframe"
206-
},
207-
level=20 # INFO level
208-
)
209-
210-
try:
211-
# Convert to dataframe
212-
df = GetData.to_dataframe(response)
213-
214-
# Record metrics
215-
telemetry.metrics().metric_increment(
216-
name="dataframe.conversion.success",
217-
tags={"size": len(df)}
218-
)
219-
220-
# Log success
221-
telemetry.logs().new_log(
222-
msg="Successfully converted API response to DataFrame",
223-
tags={
224-
"dataframe_rows": len(df),
225-
"dataframe_columns": len(df.columns),
226-
"component": "ClientBuilder",
227-
"method": "api_to_dataframe"
228-
},
229-
level=20 # INFO level
230-
)
231-
232-
return df
233-
234-
except Exception as e:
235-
# Record failure metric
236-
telemetry.metrics().metric_increment(
237-
name="dataframe.conversion.failure",
238-
tags={"error_type": type(e).__name__}
239-
)
240-
241-
# Log error
242-
error_msg = f"Failed to convert API response to DataFrame: {str(e)}"
243-
telemetry.logs().new_log(
244-
msg=error_msg,
245-
tags={
246-
"error": str(e),
247-
"error_type": type(e).__name__,
248-
"component": "ClientBuilder",
249-
"method": "api_to_dataframe"
250-
},
251-
level=40 # ERROR level
252-
)
253-
254-
# Re-raise the exception
255-
raise
256-
finally:
257-
span.end()
95+
return GetData.to_dataframe(response)

0 commit comments

Comments
 (0)