diff --git a/backend/api/endpoints/command.py b/backend/api/endpoints/command.py index 583ea5a..1fab796 100644 --- a/backend/api/endpoints/command.py +++ b/backend/api/endpoints/command.py @@ -24,19 +24,24 @@ def get_commands(db: Session = Depends(get_db)): @command_router.post("/", response_model=CommandSingleResponse) -def create_command(payload: CommandRequest): +def create_command(payload: CommandRequest, db: Session = Depends(get_db)): """ Creates an item with the given payload in the database and returns this payload after pulling it from the database @param payload: The data used to create an item @return returns a json object with field of "data" under which there is the payload now pulled from the database """ - # TODO:(Member) Implement this endpoint - + command = Command(**payload.dict()) + db.add(command) + db.commit() + db.refresh(command) + return {"data": command} + + @command_router.delete("/{id}", response_model=CommandListResponse) -def delete_command(id: int): +def delete_command(id: int, db: Session = Depends(get_db)): """ Deletes the item with the given id if it exists. Otherwise raises a 404 error. @@ -44,3 +49,10 @@ def delete_command(id: int): @return returns the list of commands after deleting the item """ # TODO:(Member) Implement this endpoint + command = db.get(Command, id) + if command is None: + raise HTTPException(status_code=404, detail="Command not found") + db.delete(command) + db.commit() + items = db.exec(select(Command)).all() + return {"data": items} diff --git a/backend/api/middlewares/logger_middleware.py b/backend/api/middlewares/logger_middleware.py index 44daa5d..fc227c2 100644 --- a/backend/api/middlewares/logger_middleware.py +++ b/backend/api/middlewares/logger_middleware.py @@ -1,8 +1,13 @@ +from time import perf_counter +from datetime import datetime from collections.abc import Callable from typing import Any from fastapi import Request, Response from starlette.middleware.base import BaseHTTPMiddleware +from logging import getLogger +custom_logger = getLogger("my_logger") + class LoggerMiddleware(BaseHTTPMiddleware): async def dispatch( @@ -18,5 +23,23 @@ async def dispatch( @return Response from endpoint """ # TODO:(Member) Finish implementing this method + start_time = perf_counter() + + timestamp = datetime.utcnow().isoformat() + + # Log incoming request + custom_logger.info(f"[{timestamp}] Incoming request: {request.method} {request.url}") + custom_logger.info(f"Headers: {dict(request.headers)}") + if request.query_params: + custom_logger.info(f"Query Params: {dict(request.query_params)}") + + response = await call_next(request) + + # Measure execution time + duration = perf_counter() - start_time + custom_logger.info( + f"Response status: {response.status_code} | Duration: {duration:.4f} seconds" + ) + return response diff --git a/backend/data/data_models.py b/backend/data/data_models.py index 68adddb..c90303d 100644 --- a/backend/data/data_models.py +++ b/backend/data/data_models.py @@ -25,17 +25,29 @@ class MainCommand(BaseSQLModel, table=True): data_size: int total_size: int + @model_validator(mode="after") def validate_params_format(self): """ - Check that params and format are both None or that the params and format have the same number of comma seperated values. + Check that params and format are both None or that the params and format have the same number of comma separated values. In either of these cases return self. Otherwise raise a ValueError. - The format of the comma seperated values is "data1,data2" so no spaces between data and the commas. + The format of the comma separated values is "data1,data2" so no spaces between data and the commas. """ - # TODO: (Member) Implement this method + if self.params is None and self.format is None: + return self + if self.params is None or self.format is None: + raise ValueError("Both params and format should be None or both should be provided.") + + params_count = len(self.params.split(",")) + format_count = len(self.format.split(",")) + + if params_count != format_count: + raise ValueError(f"Mismatch: params has {params_count} values, but format has {format_count}.") + return self + class Command(BaseSQLModel, table=True): """ An instance of a MainCommand.