Skip to content

feat(logging): add centralized logger factory and replace print statements#21

Open
Kunal-Somani wants to merge 1 commit into
ruxailab:mainfrom
Kunal-Somani:feat/structured-logging
Open

feat(logging): add centralized logger factory and replace print statements#21
Kunal-Somani wants to merge 1 commit into
ruxailab:mainfrom
Kunal-Somani:feat/structured-logging

Conversation

@Kunal-Somani

Copy link
Copy Markdown

Summary

The codebase had two observability gaps:

  1. app.py only configured logging inside if __name__ == "__main__",
    meaning Cloud Run deployments received zero logging output — every
    logger.info() call in video_routes.py silently did nothing in production.

  2. utils/utils.py used raw print() statements which cannot be filtered
    by log level, routed to external sinks, or controlled via environment variables.

Changes

utils/logger.py (new file)

  • Introduces a get_logger(name) factory function
  • Configures the root handler exactly once using a _configured guard flag
  • Log level is controlled via the LOG_LEVEL environment variable (default: INFO)
  • Outputs to stdout in a structured format compatible with Cloud Run log ingestion
  • Safe to call from multiple modules — no duplicate handlers

app.py (modified)

  • Removed coloredlogs dependency (was only active in __main__ block)
  • Replaced with get_logger(__name__) at module level
  • Logging now initializes on every deployment path, not just local runs

utils/utils.py (modified)

  • Replaced all print() calls with logger.info(), logger.debug(), and logger.error()
  • Added docstrings to delete_video() and split_video_into_clips()
  • Error handling in delete_video() now uses logger.error() with %s formatting

Testing

LOG_LEVEL=DEBUG python app.py

Confirmed structured log output appears at startup:

2026-03-20T10:00:00 | INFO     | app | Application initialised (routes registered, CORS configured)
2026-03-20T10:00:00 | INFO     | app | Starting development server on localhost:5000

Motivation

This directly supports the Unified Logging and Traceability System outlined in the GSoC 2026 ideas — establishing a structured, environment-aware logging foundation that future traceability features can build on.

- Add utils/logger.py: a get_logger() factory that configures the root
  handler once via LOG_LEVEL env var, ensuring consistent structured
  output both locally and on Cloud Run
- Refactor app.py: move logging init to module level so it applies on
  all deployment paths, not just __main__
- Refactor utils/utils.py: replace all print() calls with logger.info()
  / logger.debug() / logger.error() for production-grade observability
Kunal-Somani added a commit to Kunal-Somani/facial-sentiment-analysis-api that referenced this pull request Mar 21, 2026
- Remove coloredlogs.install() calls from EmotionsAnalysisImp.__init__()
  and FirebaseImp.__init__() — reinstalling the log handler on every
  object instantiation was causing duplicate log entries
- Replace instance-level self.logger with module-level logger via
  get_logger(__name__) for consistency with utils/logger.py (PR ruxailab#21)
- Switch all f-string log calls to % formatting (Python logging best
  practice — avoids string interpolation when log level is disabled)
- Add debug log to FirebaseImp._initialize_app() for the already-
  initialized path
- Add logger.info() to upload_to_firestore() on successful Firestore write
- Remove unused logging and coloredlogs imports from both files
Kunal-Somani added a commit to Kunal-Somani/facial-sentiment-analysis-api that referenced this pull request Apr 3, 2026
Adds schemas/multimodal_output_schema.py — a Pydantic wrapper around
GetEmotionPercentagesResponse that standardizes the facial API output
for consumption by the MultimodalSentimentEngine in sentiment-analysis-api.

Key additions:
- FacialEmotionOutput.from_response(): converts GetEmotionPercentagesResponse
  into a validated Pydantic model with field-level range constraints (0-100%)
- to_multimodal_dict(): produces the {emotion_label: percentage} dict
  format expected by MultimodalSentimentEngine.analyze(facial_emotions=...)
- dominant_emotion(): returns the top emotion and its confidence as a
  (label, float) tuple — useful for logging and single-label summaries

This is the integration boundary between the two RUXAILAB sentiment repos:
the facial API produces GetEmotionPercentagesResponse, FacialEmotionOutput
converts it, and the multimodal engine fuses it with text and prosody.
Closes the gap identified in PR ruxailab#21 and ruxailab#22 where the two pipelines
had no shared contract.
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