Merge pull request 'update Python version to 3.12 in Dockerfiles; enhance logging in content, devops, notification, and payment services' (#71) from Nicolas_service_hub into dev

Reviewed-on: freeleaps/freeleaps-service-hub#71
Reviewed-by: jingyao1991 <jingyao1991@noreply.gitea.freeleaps.mathmast.com>
This commit is contained in:
icecheng 2025-09-25 06:53:40 +00:00
commit 11c52d6470
12 changed files with 68 additions and 10 deletions

View File

@ -1,4 +1,4 @@
FROM python:3.10-slim-buster FROM python:3.12-slim
# docker settings # docker settings
ARG CONTAINER_APP_ROOT="/app" ARG CONTAINER_APP_ROOT="/app"

View File

@ -6,15 +6,18 @@ from common.constants.region import UserRegion
from backend.document.document_manager import DocumentManager from backend.document.document_manager import DocumentManager
from .content_sharepoint_manager import ContentSharePointManager from .content_sharepoint_manager import ContentSharePointManager
from backend.content.constants import ContentSource from backend.content.constants import ContentSource
from common.log.module_logger import ModuleLogger
class ContentService: class ContentService:
def __init__(self) -> None: def __init__(self) -> None:
pass self.module_logger = ModuleLogger(sender_id="ContentService")
async def retrieve_content_directories_for_folder( async def retrieve_content_directories_for_folder(
self, folder_name: str, region: UserRegion self, folder_name: str, region: UserRegion
) -> List[ContentDirectory]: ) -> List[ContentDirectory]:
await self.module_logger.log_info(f"Retrieving content directories for folder: {folder_name}, region: {region.name}")
folder = ( folder = (
await ContentFolderDoc.find( await ContentFolderDoc.find(
ContentFolderDoc.folder_name == folder_name, ContentFolderDoc.folder_name == folder_name,
@ -26,12 +29,18 @@ class ContentService:
if folder is None or folder.valid_thru.replace( if folder is None or folder.valid_thru.replace(
tzinfo=timezone.utc tzinfo=timezone.utc
) < datetime.now(timezone.utc): ) < datetime.now(timezone.utc):
await self.module_logger.log_info(f"Folder cache expired or not found, fetching from SharePoint: {folder_name}")
folder = await ContentSharePointManager().retrieve_directories_for_folder( folder = await ContentSharePointManager().retrieve_directories_for_folder(
folder_name=folder_name, region=region folder_name=folder_name, region=region
) )
return folder.content_directories if folder else None result = folder.content_directories if folder else None
await self.module_logger.log_info(f"Successfully retrieved {len(result) if result else 0} content directories for folder: {folder_name}")
return result
async def retrieve_content_as_media_data(self, document_id: str) -> Optional[str]: async def retrieve_content_as_media_data(self, document_id: str) -> Optional[str]:
await self.module_logger.log_info(f"Retrieving content as media data for document ID: {document_id}")
document_manager = DocumentManager() document_manager = DocumentManager()
return await document_manager.retrieve_document_as_http_media(document_id) result = await document_manager.retrieve_document_as_http_media(document_id)
await self.module_logger.log_info(f"Successfully retrieved media data for document ID: {document_id}")
return result

View File

@ -13,6 +13,7 @@ from webapi.providers import probes
from webapi.providers import metrics from webapi.providers import metrics
from .freeleaps_app import FreeleapsApp from .freeleaps_app import FreeleapsApp
from common.config.app_settings import app_settings from common.config.app_settings import app_settings
from common.log.module_logger import ModuleLogger
def create_app() -> FastAPI: def create_app() -> FastAPI:
@ -21,6 +22,10 @@ def create_app() -> FastAPI:
app = FreeleapsApp() app = FreeleapsApp()
register_logger() register_logger()
# Create application logger for startup logging
app_logger = ModuleLogger(sender_id="ApplicationBootstrap")
register(app, exception_handler) register(app, exception_handler)
register(app, database) register(app, database)
register(app, router) register(app, router)
@ -37,6 +42,15 @@ def create_app() -> FastAPI:
# Register metrics APIs if enabled # Register metrics APIs if enabled
if app_settings.METRICS_ENABLED: if app_settings.METRICS_ENABLED:
register(app, metrics) register(app, metrics)
# Log application startup completion
import asyncio
async def log_startup():
await app_logger.log_info("Content application initialized successfully")
# Run the async logging
asyncio.create_task(log_startup())
return app return app

View File

@ -15,7 +15,7 @@ RUN pip install --no-cache-dir -r requirements.txt
COPY . . COPY . .
# Set environment variables # Set environment variables
ENV LOG_BASE_PATH=/app/log/devsvc ENV LOG_BASE_PATH=/app/log/devops
# Create necessary directories # Create necessary directories
RUN mkdir -p /app/log/devops RUN mkdir -p /app/log/devops

View File

@ -11,6 +11,7 @@ from app.providers import probes
from app.providers import exception_handler from app.providers import exception_handler
from app.providers import message_queue from app.providers import message_queue
from app.common.config.app_settings import app_settings from app.common.config.app_settings import app_settings
from app.common.log.module_logger import ModuleLogger
def create_app() -> FastAPI: def create_app() -> FastAPI:
logging.info("App initializing") logging.info("App initializing")
@ -33,6 +34,16 @@ def create_app() -> FastAPI:
# Register metrics APIs if enabled # Register metrics APIs if enabled
if app_settings.METRICS_ENABLED: if app_settings.METRICS_ENABLED:
register(app, metrics) register(app, metrics)
# Add startup logging
@app.on_event("startup")
async def startup_logging():
module_logger = ModuleLogger(sender_id="ApplicationBootstrap")
await module_logger.log_info(
text=f"DevOps service started successfully in {app_settings.APP_ENV} environment",
data={"app_name": app_settings.APP_NAME, "environment": app_settings.APP_ENV}
)
return app return app

View File

@ -2,7 +2,7 @@ from pydantic_settings import BaseSettings
# NOTE: The values fall backs to your environment variables when not set here # NOTE: The values fall backs to your environment variables when not set here
class AppSettings(BaseSettings): class AppSettings(BaseSettings):
NAME: str = "YOUR_APP_NAME" NAME: str = "devops"
APP_NAME: str = NAME APP_NAME: str = NAME
APP_ENV: str = "alpha" APP_ENV: str = "alpha"
@ -17,8 +17,8 @@ class AppSettings(BaseSettings):
APP_MONGODB_NAME: str = "testdb" APP_MONGODB_NAME: str = "testdb"
LOG_BASE_PATH: str = "./log" LOG_BASE_PATH: str = "./log"
BACKEND_LOG_FILE_NAME: str = APP_NAME BACKEND_LOG_FILE_NAME: str = "devops"
APPLICATION_ACTIVITY_LOG: str = APP_NAME + "-application-activity"\ APPLICATION_ACTIVITY_LOG: str = "devops-application-activity"\
RABBITMQ_HOST: str = "localhost" RABBITMQ_HOST: str = "localhost"
RABBITMQ_PORT: int = 5672 RABBITMQ_PORT: int = 5672

View File

@ -1,4 +1,4 @@
FROM python:3.10-slim-buster FROM python:3.12-slim
# docker settings # docker settings
ARG CONTAINER_APP_ROOT=/app ARG CONTAINER_APP_ROOT=/app

View File

@ -14,6 +14,7 @@ from webapi.providers import metrics
from webapi.providers import middleware from webapi.providers import middleware
from .freeleaps_app import FreeleapsApp from .freeleaps_app import FreeleapsApp
from common.config.app_settings import app_settings from common.config.app_settings import app_settings
from common.log.module_logger import ModuleLogger
from prometheus_fastapi_instrumentator import Instrumentator from prometheus_fastapi_instrumentator import Instrumentator

View File

@ -3,6 +3,8 @@ from backend.infra.rabbitmq.async_subscriber import AsyncMQSubscriber
from backend.models.constants import NotificationChannel from backend.models.constants import NotificationChannel
from webapi.utils.email_consumer import EmailMQConsumer from webapi.utils.email_consumer import EmailMQConsumer
from webapi.utils.sms_consumer import SmsMQConsumer from webapi.utils.sms_consumer import SmsMQConsumer
from common.log.module_logger import ModuleLogger
from common.config.app_settings import app_settings
class FreeleapsApp(FastAPI): class FreeleapsApp(FastAPI):
@ -21,6 +23,14 @@ class FreeleapsApp(FastAPI):
@self.on_event("startup") @self.on_event("startup")
async def start_consumers(): async def start_consumers():
print("starting up!") print("starting up!")
# Add startup logging
module_logger = ModuleLogger(sender_id="ApplicationBootstrap")
await module_logger.log_info(
text=f"Notification service started successfully in {app_settings.APP_ENV} environment",
data={"app_name": app_settings.APP_NAME, "environment": app_settings.APP_ENV}
)
await self.sms_handler.register_consumer() await self.sms_handler.register_consumer()
await self.email_handler.register_consumer() await self.email_handler.register_consumer()

View File

@ -1,4 +1,4 @@
FROM python:3.10-slim-buster FROM python:3.12-slim
# docker settings # docker settings
ARG CONTAINER_APP_ROOT=/app ARG CONTAINER_APP_ROOT=/app

View File

@ -12,6 +12,7 @@ from webapi.providers import probes
from webapi.providers import exception_handler from webapi.providers import exception_handler
from .freeleaps_app import FreeleapsApp from .freeleaps_app import FreeleapsApp
from common.config.app_settings import app_settings from common.config.app_settings import app_settings
from common.log.module_logger import ModuleLogger
def create_app() -> FastAPI: def create_app() -> FastAPI:
logging.info("App initializing") logging.info("App initializing")

View File

@ -1,6 +1,18 @@
from fastapi import FastAPI from fastapi import FastAPI
from common.log.module_logger import ModuleLogger
from common.config.app_settings import app_settings
class FreeleapsApp(FastAPI): class FreeleapsApp(FastAPI):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.register_startup_event()
def register_startup_event(self):
@self.on_event("startup")
async def startup_logging():
module_logger = ModuleLogger(sender_id="ApplicationBootstrap")
await module_logger.log_info(
text=f"Payment service started successfully in {app_settings.APP_ENV} environment",
data={"app_name": app_settings.APP_NAME, "environment": app_settings.APP_ENV}
)