Skip to content

Commit

Permalink
fix: sanitize logging and refactor giveup log message
Browse files Browse the repository at this point in the history
  • Loading branch information
MountainGod2 committed Aug 9, 2024
1 parent 7355e10 commit 3de1c08
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 6 deletions.
2 changes: 2 additions & 0 deletions src/chaturbate_poller/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ async def start_polling(
url = None
while True:
response = await client.fetch_events(url)
if response is None:
break
url = str(response.next_url)


Expand Down
26 changes: 23 additions & 3 deletions src/chaturbate_poller/chaturbate_poller.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def backoff_handler(details: Details) -> None:
"""
wait = details["wait"]
tries = details["tries"]
logger.info("Backing off %0.1f seconds after %d tries", wait, tries)
logger.info("Backing off %s seconds after %s tries", int(wait), int(tries))


def giveup_handler(details: Details) -> None:
Expand All @@ -36,8 +36,27 @@ def giveup_handler(details: Details) -> None:
Args:
details (Details): The giveup details.
"""
tries = details["tries"]
logger.error("Giving up after %d tries", tries)
tries = details.get("tries", 0)
exception = details.get("exception")

if exception and hasattr(exception, "response"):
response = exception.response
status_code = response.status_code
try:
response_dict = response.json()
status_text = response_dict.get("status", "Unknown error")
except ValueError:
status_text = "Error parsing response JSON"
else:
status_code = None
status_text = "No response available"

logger.error(
"Giving up after %s tries due to server error code %s: %s",
int(tries),
status_code,
status_text,
)


class ChaturbateClient:
Expand Down Expand Up @@ -123,6 +142,7 @@ async def __aexit__(
max_tries=6,
on_backoff=backoff_handler,
logger=None,
raise_on_giveup=False,
)
async def fetch_events(self, url: str | None = None) -> EventsAPIResponse:
"""Fetch events from the Chaturbate API.
Expand Down
36 changes: 36 additions & 0 deletions src/chaturbate_poller/logging_config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,35 @@
"""Logging configuration for the application."""

import logging
import logging.handlers
import re

URL_REGEX = re.compile(r"events/([^/]+)/([^/]+)")


def sanitize_url(url: str) -> str:
"""Sanitize the URL by replacing username and token with placeholders."""
return URL_REGEX.sub(r"events/USERNAME/TOKEN", url)


class SanitizeURLFilter(logging.Filter):
"""Logging filter to sanitize sensitive information from URLs.
Args:
logging.Filter: The logging filter class.
"""

def filter(self, record: logging.LogRecord) -> bool:
"""Filter log records to sanitize URLs."""
if isinstance(record.msg, str):
record.msg = sanitize_url(record.msg)
if record.args:
record.args = tuple(sanitize_url(str(arg)) for arg in record.args)
return True

def __repr__(self) -> str:
"""Return a string representation of the filter."""
return f"{self.__class__.__name__}()"


class CustomFormatter(logging.Formatter):
Expand Down Expand Up @@ -37,18 +66,25 @@ def format(self, record: logging.LogRecord) -> str:
"datefmt": "%Y-%m-%d %H:%M:%S",
},
},
"filters": {
"sanitize_url": {
"()": SanitizeURLFilter,
},
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"formatter": "standard",
"level": "INFO",
"filters": ["sanitize_url"], # Add filter here
},
"file": {
"class": "logging.handlers.TimedRotatingFileHandler",
"filename": "app.log",
"formatter": "detailed",
"level": "DEBUG",
"when": "midnight",
"filters": ["sanitize_url"], # Add filter here
},
},
"loggers": {
Expand Down
7 changes: 4 additions & 3 deletions tests/test_chaturbate_poller.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ def test_backoff_handler(self, caplog) -> None: # noqa: ANN001
"elapsed": 0,
}
)
assert "Backing off 1.0 seconds after 1 tries" in caplog.text
assert "Backing off 1 seconds after 1 tries" in caplog.text

def test_giveup_handler(self, caplog) -> None: # noqa: ANN001
"""Test the giveup handler."""
Expand Down Expand Up @@ -943,9 +943,10 @@ async def test_http_status_error(
self,
http_client_mock, # noqa: ANN001
chaturbate_client: ChaturbateClient,
caplog, # noqa: ANN001
) -> None:
"""Test HTTP status error."""
request = Request("GET", TEST_URL)
http_client_mock.return_value = Response(500, request=request)
with pytest.raises(HTTPStatusError):
await chaturbate_client.fetch_events(TEST_URL)
await chaturbate_client.fetch_events(TEST_URL)
assert "Giving up after 6 tries due to server error code 500" in caplog.text

0 comments on commit 3de1c08

Please sign in to comment.