Skip to content

feat: implement structured error handling and logging#77

Open
emmanuelmingo wants to merge 1 commit into
indictechcom:masterfrom
emmanuelmingo:Implementation-of-Error-Handling
Open

feat: implement structured error handling and logging#77
emmanuelmingo wants to merge 1 commit into
indictechcom:masterfrom
emmanuelmingo:Implementation-of-Error-Handling

Conversation

@emmanuelmingo
Copy link
Copy Markdown

Introduces a custom exception hierarchy, structured rotating file-based logging, standardised API error responses, and proper error tracking for asynchronous Celery tasks.

Changes

exceptions.py (new)

  • WikifileTransferError as root base for all application exceptions
  • APIError(HTTPException) as base for HTTP-facing errors; subclasses: ValidationError (422), NotFoundError (404), AuthenticationError (401), UploadError (502), ExternalAPIError (502)
  • Internal exceptions: DownloadError, DatabaseError, TaskError

logging_config.py (new)

  • configure_logging() sets up a RotatingFileHandler (5 MB / 3 backups) writing to logs/app.log plus a console handler
  • Extracted from app.py so logging config lives in its own module

error_handlers.py (updated)

  • register_error_handlers() now logs HTTP errors at WARNING and unexpected exceptions at ERROR with full traceback
  • All responses follow a consistent envelope: {"success": bool, "data": {}, "errors": [...]}

app.py (updated)

  • Import and call configure_logging() from logging_config
  • Raise ValidationError / AuthenticationError / ExternalAPIError / DownloadError / DatabaseError at every failure point instead of returning manual JSON error responses
  • /api/task_status: fix PROGRESS state data (use task.info) and SUCCESS state data (use task.result); remove non-serialisable result
  • Replace bare except: clauses with specific exception types
  • Standardise response envelope to use "errors" list throughout

utils.py (updated)

  • download_image: raise DownloadError instead of returning None; specific messages for network errors, missing imageinfo, disk failures
  • process_upload: raise UploadError instead of returning None; specific messages for CSRF, network, file-read, and wiki-rejection
  • get_localized_wikitext: replace bare except with RequestException and (KeyError, IndexError) handlers; log at appropriate levels
  • All file handles opened with context managers (with open(...))

tasks.py (updated)

  • Add structured logging with task_id on every log line
  • Wrap each stage (CSRF fetch, file upload, response parse) in try/except raising TaskError so Celery marks the task FAILURE
  • File opened with context manager to prevent handle leaks
  • Remove unused import os

tests/ (new)

  • tests/conftest.py: session-scoped Flask test client with MWOAuth and Celery mocked out; auth_client fixture for authenticated routes
  • tests/test_exceptions.py: 33 tests covering inheritance chain, HTTP status codes, werkzeug compatibility, and message handling

Introduces a custom exception hierarchy, structured rotating file-based
logging, standardised API error responses, and proper error tracking for
asynchronous Celery tasks.

Changes
-------
exceptions.py (new)
  - WikifileTransferError as root base for all application exceptions
  - APIError(HTTPException) as base for HTTP-facing errors; subclasses:
    ValidationError (422), NotFoundError (404), AuthenticationError (401),
    UploadError (502), ExternalAPIError (502)
  - Internal exceptions: DownloadError, DatabaseError, TaskError

logging_config.py (new)
  - configure_logging() sets up a RotatingFileHandler (5 MB / 3 backups)
    writing to logs/app.log plus a console handler
  - Extracted from app.py so logging config lives in its own module

error_handlers.py (updated)
  - register_error_handlers() now logs HTTP errors at WARNING and
    unexpected exceptions at ERROR with full traceback
  - All responses follow a consistent envelope:
    {"success": bool, "data": {}, "errors": [...]}

app.py (updated)
  - Import and call configure_logging() from logging_config
  - Raise ValidationError / AuthenticationError / ExternalAPIError /
    DownloadError / DatabaseError at every failure point instead of
    returning manual JSON error responses
  - /api/task_status: fix PROGRESS state data (use task.info) and
    SUCCESS state data (use task.result); remove non-serialisable result
  - Replace bare except: clauses with specific exception types
  - Standardise response envelope to use "errors" list throughout

utils.py (updated)
  - download_image: raise DownloadError instead of returning None;
    specific messages for network errors, missing imageinfo, disk failures
  - process_upload: raise UploadError instead of returning None;
    specific messages for CSRF, network, file-read, and wiki-rejection
  - get_localized_wikitext: replace bare except with RequestException
    and (KeyError, IndexError) handlers; log at appropriate levels
  - All file handles opened with context managers (with open(...))

tasks.py (updated)
  - Add structured logging with task_id on every log line
  - Wrap each stage (CSRF fetch, file upload, response parse) in
    try/except raising TaskError so Celery marks the task FAILURE
  - File opened with context manager to prevent handle leaks
  - Remove unused import os

tests/ (new)
  - tests/conftest.py: session-scoped Flask test client with MWOAuth
    and Celery mocked out; auth_client fixture for authenticated routes
  - tests/test_exceptions.py: 33 tests covering inheritance chain,
    HTTP status codes, werkzeug compatibility, and message handling
@emmanuelmingo emmanuelmingo force-pushed the Implementation-of-Error-Handling branch from 0722cd7 to 11fe84c Compare March 25, 2026 06:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant