From db25329effc85d3af1dbf3f1427c6461589dce8b Mon Sep 17 00:00:00 2001 From: Morozov Artem <126605382+Temmmmmo@users.noreply.github.com> Date: Thu, 26 Dec 2024 20:57:32 +0300 Subject: [PATCH 01/24] Add sorting by create_ts --- rating_api/routes/comment.py | 1 + 1 file changed, 1 insertion(+) diff --git a/rating_api/routes/comment.py b/rating_api/routes/comment.py index 1dfa07c..3afbc74 100644 --- a/rating_api/routes/comment.py +++ b/rating_api/routes/comment.py @@ -182,6 +182,7 @@ async def get_comments( result.comments.sort(key=lambda comment: comment.create_ts, reverse=True) result.total = len(result.comments) result.comments = [CommentGet.model_validate(comment) for comment in result.comments] + result.comments.sort(key=lambda comment: comment.create_ts, reverse=True) return result From 635e7a4a17c14d6c8638f764d9e02242452dde73 Mon Sep 17 00:00:00 2001 From: Morozov Artem <126605382+Temmmmmo@users.noreply.github.com> Date: Thu, 26 Dec 2024 21:16:28 +0300 Subject: [PATCH 02/24] Update lecturer.py --- rating_api/routes/lecturer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rating_api/routes/lecturer.py b/rating_api/routes/lecturer.py index 1bdd563..ff805d2 100644 --- a/rating_api/routes/lecturer.py +++ b/rating_api/routes/lecturer.py @@ -135,7 +135,7 @@ async def get_lecturers( if comment.review_status is ReviewStatus.APPROVED ] if "comments" in info and approved_comments: - lecturer_to_result.comments = approved_comments + lecturer_to_result.comments = sorted(approved_comments, key=lambda comment: comment.create_ts, reverse=True) if "mark" in info and approved_comments: lecturer_to_result.mark_freebie = sum([comment.mark_freebie for comment in approved_comments]) / len( approved_comments From 42ed81eef83bf626d100980055103e7d3ca9084c Mon Sep 17 00:00:00 2001 From: Morozov Artem <126605382+Temmmmmo@users.noreply.github.com> Date: Thu, 26 Dec 2024 21:24:09 +0300 Subject: [PATCH 03/24] Update lecturer.py --- rating_api/routes/lecturer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rating_api/routes/lecturer.py b/rating_api/routes/lecturer.py index ff805d2..c81e165 100644 --- a/rating_api/routes/lecturer.py +++ b/rating_api/routes/lecturer.py @@ -59,7 +59,7 @@ async def get_lecturer(id: int, info: list[Literal["comments", "mark"]] = Query( if comment.review_status is ReviewStatus.APPROVED ] if "comments" in info and approved_comments: - result.comments = approved_comments + result.comments = sorted(approved_comments, key=lambda comment: comment.create_ts, reverse=True) if "mark" in info and approved_comments: result.mark_freebie = sum(comment.mark_freebie for comment in approved_comments) / len(approved_comments) result.mark_kindness = sum(comment.mark_kindness for comment in approved_comments) / len(approved_comments) From 60ba34e905c7c0ba77e4eaccfac5cea2a2c93a03 Mon Sep 17 00:00:00 2001 From: Timur Enikeev Date: Fri, 24 Jan 2025 17:07:54 -0500 Subject: [PATCH 04/24] Achievement for com --- rating_api/routes/comment.py | 24 ++++++++++++++++++++++++ rating_api/routes/lecturer.py | 4 +++- rating_api/settings.py | 6 ++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/rating_api/routes/comment.py b/rating_api/routes/comment.py index 3afbc74..ee58be5 100644 --- a/rating_api/routes/comment.py +++ b/rating_api/routes/comment.py @@ -2,6 +2,7 @@ from typing import Literal from uuid import UUID +import aiohttp from auth_lib.fastapi import UnionAuth from fastapi import APIRouter, Depends, Query from fastapi_sqlalchemy import db @@ -94,6 +95,29 @@ async def create_comment(lecturer_id: int, comment_info: CommentPost, user=Depen user_id=user_id, review_status=ReviewStatus.PENDING, ) + + # Выдача аччивки юзеру за первый комментарий + async with aiohttp.ClientSession() as session: + give_achievement = True + async with session.get( + settings.API_URL + f"achievement/user/{user.get('id'):}", + headers={"Accept": "application/json"}, + ) as response: + if response.status == 200: + user_achievements = await response.json() + for achievement in user_achievements.get("achievement", []): + if achievement.get("id") == settings.FIRST_COMMENT_ACHIEVEMENT_ID: + give_achievement = False + break + else: + give_achievement = False + if give_achievement: + session.post( + settings.API_URL + + f"achievement/achievement/{settings.FIRST_COMMENT_ACHIEVEMENT_ID}/reciever/{user.get('id'):}", + headers={"Accept": "application/json", "Authorization": settings.ACHIEVEMENT_GIVE_TOKEN}, + ) + return CommentGet.model_validate(new_comment) diff --git a/rating_api/routes/lecturer.py b/rating_api/routes/lecturer.py index c81e165..e7c0e4d 100644 --- a/rating_api/routes/lecturer.py +++ b/rating_api/routes/lecturer.py @@ -135,7 +135,9 @@ async def get_lecturers( if comment.review_status is ReviewStatus.APPROVED ] if "comments" in info and approved_comments: - lecturer_to_result.comments = sorted(approved_comments, key=lambda comment: comment.create_ts, reverse=True) + lecturer_to_result.comments = sorted( + approved_comments, key=lambda comment: comment.create_ts, reverse=True + ) if "mark" in info and approved_comments: lecturer_to_result.mark_freebie = sum([comment.mark_freebie for comment in approved_comments]) / len( approved_comments diff --git a/rating_api/settings.py b/rating_api/settings.py index 1f7612c..79d5670 100644 --- a/rating_api/settings.py +++ b/rating_api/settings.py @@ -19,6 +19,12 @@ class Settings(BaseSettings): CORS_ALLOW_METHODS: list[str] = ['*'] CORS_ALLOW_HEADERS: list[str] = ['*'] + '''Temp settings''' + + API_URL: str = "https://api.test.profcomff.com/" + FIRST_COMMENT_ACHIEVEMENT_ID: int = 1 + ACHIEVEMENT_GIVE_TOKEN: str = "" + model_config = ConfigDict(case_sensitive=True, env_file=".env", extra="ignore") From 748f8da3eef2744d86881f134edb0b6d1780ee4e Mon Sep 17 00:00:00 2001 From: Timur Enikeev Date: Fri, 24 Jan 2025 17:14:28 -0500 Subject: [PATCH 05/24] Add req --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 1b6d4e1..ed9f291 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ alembic auth-lib-profcomff[fastapi] +aiohttp fastapi fastapi-sqlalchemy gunicorn From 452a49d0cceba848232c5ba6efc9a7475962959b Mon Sep 17 00:00:00 2001 From: Timur Enikeev Date: Sat, 25 Jan 2025 12:44:39 -0500 Subject: [PATCH 06/24] Fix workflow --- .github/workflows/checks.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index adbafe2..d6ecea3 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -11,6 +11,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Set up docker + run: touch /etc/docker/daemon.json uses: docker-practice/actions-setup-docker@master - name: Run postgres run: | From e5aaa8123d2931feff140f053e477b9f9950e95d Mon Sep 17 00:00:00 2001 From: Timur Enikeev Date: Sat, 25 Jan 2025 12:48:51 -0500 Subject: [PATCH 07/24] Fix workflow --- .github/workflows/checks.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index d6ecea3..c6aba5b 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -10,8 +10,9 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - name: Set up docker + - name: Init daemon.json run: touch /etc/docker/daemon.json + - name: Set up docker uses: docker-practice/actions-setup-docker@master - name: Run postgres run: | From e9fbb062c39a5ca44b768e6534dd3ebd4ced36fd Mon Sep 17 00:00:00 2001 From: Timur Enikeev Date: Sat, 25 Jan 2025 12:49:34 -0500 Subject: [PATCH 08/24] Fix workflow --- .github/workflows/checks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index c6aba5b..233ac3c 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -11,7 +11,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Init daemon.json - run: touch /etc/docker/daemon.json + run: sudo touch /etc/docker/daemon.json - name: Set up docker uses: docker-practice/actions-setup-docker@master - name: Run postgres From 6d81f2d0e36117da73ad2a6c720f3bd8a7c2dc5d Mon Sep 17 00:00:00 2001 From: Mark Arzangulyan <15670678+Arzangulyan@users.noreply.github.com> Date: Sun, 26 Jan 2025 18:02:39 +0300 Subject: [PATCH 09/24] Update settings.py --- rating_api/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rating_api/settings.py b/rating_api/settings.py index 79d5670..89eade2 100644 --- a/rating_api/settings.py +++ b/rating_api/settings.py @@ -22,7 +22,7 @@ class Settings(BaseSettings): '''Temp settings''' API_URL: str = "https://api.test.profcomff.com/" - FIRST_COMMENT_ACHIEVEMENT_ID: int = 1 + FIRST_COMMENT_ACHIEVEMENT_ID: int = 12 ACHIEVEMENT_GIVE_TOKEN: str = "" model_config = ConfigDict(case_sensitive=True, env_file=".env", extra="ignore") From 0e9bb66d97b6a21d208311c06baa18b29ddc0699 Mon Sep 17 00:00:00 2001 From: DROPDATABASE Date: Tue, 11 Feb 2025 09:34:13 +0300 Subject: [PATCH 10/24] Add logging deliver to marketing_api As middleware for any request --- rating_api/routes/base.py | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/rating_api/routes/base.py b/rating_api/routes/base.py index d320a86..eebb5c7 100644 --- a/rating_api/routes/base.py +++ b/rating_api/routes/base.py @@ -1,4 +1,5 @@ -from fastapi import FastAPI +import httpx +from fastapi import FastAPI, Request, Response from fastapi.middleware.cors import CORSMiddleware from fastapi_sqlalchemy import DBSessionMiddleware @@ -18,6 +19,7 @@ docs_url=None if __version__ != 'dev' else '/docs', redoc_url=None, ) +print(app.root_path) app.add_middleware( @@ -36,3 +38,34 @@ app.include_router(lecturer) app.include_router(comment) + +LOGGING_URL = ( + settings.ROOT_PATH if __version__ != 'dev' else 'http://localhost:8080/v1/action' +) # Заменить на рабочие ссылки + + +@app.middleware("http") +async def add_process_time_header(request: Request, call_next): + try: + response: Response = await call_next(request) # Выполняем сам запрос + status_code = response.status_code + except Exception as e: + status_code = 500 # Если произошла ошибка, ставим 500 + response = Response(content="Internal server error", status_code=500) # Что делать с сообщением ошибки? + + log_data = { + "user_id": 0, + "action": "string", + "additional_data": " ".join(["method:", str(request.method), "status_code:", str(status_code)]), + "path_from": "string", + "path_to": app.root_path + request.url.path, + } + + # Отправляем лог на внешний сервис асинхронно + async with httpx.AsyncClient() as client: + try: + await client.post(LOGGING_URL, json=log_data) + except Exception as log_error: + print(f"Ошибка при отправке логов: {log_error}") # Можно заменить на `logger.error(...)` + + return response From 49b65fd752317ba10caf9fb1fd0df9fbdf4db0b1 Mon Sep 17 00:00:00 2001 From: DROPDATABASE Date: Tue, 11 Feb 2025 11:48:39 +0300 Subject: [PATCH 11/24] Make send log async --- rating_api/routes/base.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/rating_api/routes/base.py b/rating_api/routes/base.py index eebb5c7..c3fbcf5 100644 --- a/rating_api/routes/base.py +++ b/rating_api/routes/base.py @@ -1,8 +1,12 @@ +import asyncio +import time import httpx from fastapi import FastAPI, Request, Response from fastapi.middleware.cors import CORSMiddleware from fastapi_sqlalchemy import DBSessionMiddleware +# from auth_lib.fastapi import UnionAuth + from rating_api import __version__ from rating_api.routes.comment import comment from rating_api.routes.lecturer import lecturer @@ -19,8 +23,6 @@ docs_url=None if __version__ != 'dev' else '/docs', redoc_url=None, ) -print(app.root_path) - app.add_middleware( DBSessionMiddleware, @@ -43,6 +45,14 @@ settings.ROOT_PATH if __version__ != 'dev' else 'http://localhost:8080/v1/action' ) # Заменить на рабочие ссылки +async def send_log(log_data): + """Отправляем лог на внешний сервис асинхронно""" + async with httpx.AsyncClient(timeout=15) as client: + try: + await client.post(LOGGING_URL, json=log_data) + except Exception as log_error: + print(f"Ошибка при отправке логов: {log_error}") + @app.middleware("http") async def add_process_time_header(request: Request, call_next): @@ -54,18 +64,13 @@ async def add_process_time_header(request: Request, call_next): response = Response(content="Internal server error", status_code=500) # Что делать с сообщением ошибки? log_data = { - "user_id": 0, + "user_id": 0, # UnionAuth()(request).get('id') "action": "string", - "additional_data": " ".join(["method:", str(request.method), "status_code:", str(status_code)]), + "additional_data": f"method: {request.method}, status_code: {status_code}", "path_from": "string", "path_to": app.root_path + request.url.path, } - # Отправляем лог на внешний сервис асинхронно - async with httpx.AsyncClient() as client: - try: - await client.post(LOGGING_URL, json=log_data) - except Exception as log_error: - print(f"Ошибка при отправке логов: {log_error}") # Можно заменить на `logger.error(...)` + asyncio.create_task(send_log(log_data)) return response From cffa0ebef19026e41fad0637339dc620ac72171d Mon Sep 17 00:00:00 2001 From: DROPDATABASE Date: Wed, 12 Feb 2025 11:14:27 +0300 Subject: [PATCH 12/24] Fixups, separate funcs, make url global --- rating_api/__init__.py | 7 ++++++ rating_api/routes/base.py | 51 +++++++++++++++++++++++---------------- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/rating_api/__init__.py b/rating_api/__init__.py index fa9c098..d6ef3b8 100644 --- a/rating_api/__init__.py +++ b/rating_api/__init__.py @@ -2,3 +2,10 @@ __version__ = os.getenv('APP_VERSION', 'dev') + +LOGGING_MARKETING_URLS = { + "dev": f"http://localhost:{os.getenv('MARKETING_PORT', 8000)}/v1/action" if os.getenv('MARKETING_PORT', None) else "https://api.test.profcomff.com/marketing/v1/action", + "prod": "https://api.profcomff.com/marketing/v1/action", +} + +LOGGING_MARKETING_URL = LOGGING_MARKETING_URLS.get(__version__, LOGGING_MARKETING_URLS["prod"]) \ No newline at end of file diff --git a/rating_api/routes/base.py b/rating_api/routes/base.py index c3fbcf5..6cdeb73 100644 --- a/rating_api/routes/base.py +++ b/rating_api/routes/base.py @@ -1,5 +1,4 @@ import asyncio -import time import httpx from fastapi import FastAPI, Request, Response from fastapi.middleware.cors import CORSMiddleware @@ -7,7 +6,7 @@ # from auth_lib.fastapi import UnionAuth -from rating_api import __version__ +from rating_api import __version__, LOGGING_MARKETING_URL from rating_api.routes.comment import comment from rating_api.routes.lecturer import lecturer from rating_api.settings import get_settings @@ -41,36 +40,46 @@ app.include_router(lecturer) app.include_router(comment) -LOGGING_URL = ( - settings.ROOT_PATH if __version__ != 'dev' else 'http://localhost:8080/v1/action' -) # Заменить на рабочие ссылки - async def send_log(log_data): """Отправляем лог на внешний сервис асинхронно""" - async with httpx.AsyncClient(timeout=15) as client: + async with httpx.AsyncClient() as client: try: - await client.post(LOGGING_URL, json=log_data) + await client.post(LOGGING_MARKETING_URL, json=log_data) except Exception as log_error: print(f"Ошибка при отправке логов: {log_error}") +async def get_request_body(request: Request) -> tuple[Request, str]: + """Читает тело запроса и возвращает новый request и тело в виде JSON-строки.""" + body = await request.body() + json_body = body.decode("utf-8") if body else "{}" + + async def new_stream(): + yield body + + return Request(request.scope, receive=new_stream()), json_body + +async def log_request(request: Request, status_code: int, json_body: str): + """Формирует лог и отправляет его в асинхронную задачу.""" + log_data = { + "user_id": -2, # UnionAuth()(request).get('id') + "action": request.method, + "additional_data": f"status_code: {status_code}, auth_user_id: {2323423}, request: {json_body}", + "path_from": app.root_path, + "path_to": request.url.path, + } + asyncio.create_task(send_log(log_data)) @app.middleware("http") async def add_process_time_header(request: Request, call_next): + """Основной middleware, который логирует запрос и восстанавливает тело.""" try: - response: Response = await call_next(request) # Выполняем сам запрос + request, json_body = await get_request_body(request) # Получаем тело и восстанавливаем request + response: Response = await call_next(request) status_code = response.status_code - except Exception as e: - status_code = 500 # Если произошла ошибка, ставим 500 - response = Response(content="Internal server error", status_code=500) # Что делать с сообщением ошибки? + except Exception: + status_code = 500 + response = Response(content="Internal server error", status_code=500) - log_data = { - "user_id": 0, # UnionAuth()(request).get('id') - "action": "string", - "additional_data": f"method: {request.method}, status_code: {status_code}", - "path_from": "string", - "path_to": app.root_path + request.url.path, - } - - asyncio.create_task(send_log(log_data)) + await log_request(request, status_code, json_body) # Логируем запрос return response From 5b10447bfdf338261db2c29dadc804125b26f426 Mon Sep 17 00:00:00 2001 From: DROPDATABASE Date: Thu, 13 Feb 2025 14:57:40 +0300 Subject: [PATCH 13/24] Some fixup --- rating_api/routes/base.py | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/rating_api/routes/base.py b/rating_api/routes/base.py index 6cdeb73..a7ff2fa 100644 --- a/rating_api/routes/base.py +++ b/rating_api/routes/base.py @@ -40,13 +40,31 @@ app.include_router(lecturer) app.include_router(comment) +RETRY_DELAYS = [2, 4, 8] # Задержки перед повторными попытками (в секундах) + async def send_log(log_data): - """Отправляем лог на внешний сервис асинхронно""" + """Отправляем лог на внешний сервис асинхронно с обработкой ошибок и ретраями""" async with httpx.AsyncClient() as client: - try: - await client.post(LOGGING_MARKETING_URL, json=log_data) - except Exception as log_error: - print(f"Ошибка при отправке логов: {log_error}") + for attempt, sleep_time in enumerate(RETRY_DELAYS, start = 1): + try: + response = await client.post(LOGGING_MARKETING_URL, json=log_data) + + if response.status_code < 500: + break # Успешно или ошибки, которые не стоит повторять (например, неправильные данные) + + except httpx.HTTPStatusError as e: + print(f"HTTP ошибка ({e.response.status_code}): {e.response.text}") + print('\n\n', response.status_code, '\n\n') + + except httpx.RequestError as e: + print(f"Ошибка сети: {e}") + + except Exception as e: + print(f"Неизвестная ошибка: {e}") + + await asyncio.sleep(sleep_time) # Ожидание перед повторной попыткой + + print("Не удалось отправить лог после нескольких попыток.") # logging async def get_request_body(request: Request) -> tuple[Request, str]: """Читает тело запроса и возвращает новый request и тело в виде JSON-строки.""" @@ -63,7 +81,7 @@ async def log_request(request: Request, status_code: int, json_body: str): log_data = { "user_id": -2, # UnionAuth()(request).get('id') "action": request.method, - "additional_data": f"status_code: {status_code}, auth_user_id: {2323423}, request: {json_body}", + "additional_data": f"response_status_code: {status_code}, auth_user_id: {{}}, request: {json_body}", "path_from": app.root_path, "path_to": request.url.path, } From 816ccc193132e579281a4b177a3a61ac5ebcc6a8 Mon Sep 17 00:00:00 2001 From: DROPDATABASE Date: Thu, 13 Feb 2025 16:29:57 +0300 Subject: [PATCH 14/24] Format --- rating_api/__init__.py | 8 ++++++-- rating_api/routes/base.py | 22 ++++++++++++++-------- rating_api/routes/lecturer.py | 4 +++- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/rating_api/__init__.py b/rating_api/__init__.py index d6ef3b8..94d8063 100644 --- a/rating_api/__init__.py +++ b/rating_api/__init__.py @@ -4,8 +4,12 @@ __version__ = os.getenv('APP_VERSION', 'dev') LOGGING_MARKETING_URLS = { - "dev": f"http://localhost:{os.getenv('MARKETING_PORT', 8000)}/v1/action" if os.getenv('MARKETING_PORT', None) else "https://api.test.profcomff.com/marketing/v1/action", + "dev": ( + f"http://localhost:{os.getenv('MARKETING_PORT', 8000)}/v1/action" + if os.getenv('MARKETING_PORT', None) + else "https://api.test.profcomff.com/marketing/v1/action" + ), "prod": "https://api.profcomff.com/marketing/v1/action", } -LOGGING_MARKETING_URL = LOGGING_MARKETING_URLS.get(__version__, LOGGING_MARKETING_URLS["prod"]) \ No newline at end of file +LOGGING_MARKETING_URL = LOGGING_MARKETING_URLS.get(__version__, LOGGING_MARKETING_URLS["prod"]) diff --git a/rating_api/routes/base.py b/rating_api/routes/base.py index a7ff2fa..147a3b9 100644 --- a/rating_api/routes/base.py +++ b/rating_api/routes/base.py @@ -1,17 +1,19 @@ import asyncio + import httpx from fastapi import FastAPI, Request, Response from fastapi.middleware.cors import CORSMiddleware from fastapi_sqlalchemy import DBSessionMiddleware -# from auth_lib.fastapi import UnionAuth - -from rating_api import __version__, LOGGING_MARKETING_URL +from rating_api import LOGGING_MARKETING_URL, __version__ from rating_api.routes.comment import comment from rating_api.routes.lecturer import lecturer from rating_api.settings import get_settings +# from auth_lib.fastapi import UnionAuth + + settings = get_settings() app = FastAPI( title='Рейтинг преподавателей', @@ -42,23 +44,24 @@ RETRY_DELAYS = [2, 4, 8] # Задержки перед повторными попытками (в секундах) + async def send_log(log_data): """Отправляем лог на внешний сервис асинхронно с обработкой ошибок и ретраями""" async with httpx.AsyncClient() as client: - for attempt, sleep_time in enumerate(RETRY_DELAYS, start = 1): + for attempt, sleep_time in enumerate(RETRY_DELAYS, start=1): try: response = await client.post(LOGGING_MARKETING_URL, json=log_data) - + if response.status_code < 500: break # Успешно или ошибки, которые не стоит повторять (например, неправильные данные) - + except httpx.HTTPStatusError as e: print(f"HTTP ошибка ({e.response.status_code}): {e.response.text}") print('\n\n', response.status_code, '\n\n') - + except httpx.RequestError as e: print(f"Ошибка сети: {e}") - + except Exception as e: print(f"Неизвестная ошибка: {e}") @@ -66,6 +69,7 @@ async def send_log(log_data): print("Не удалось отправить лог после нескольких попыток.") # logging + async def get_request_body(request: Request) -> tuple[Request, str]: """Читает тело запроса и возвращает новый request и тело в виде JSON-строки.""" body = await request.body() @@ -76,6 +80,7 @@ async def new_stream(): return Request(request.scope, receive=new_stream()), json_body + async def log_request(request: Request, status_code: int, json_body: str): """Формирует лог и отправляет его в асинхронную задачу.""" log_data = { @@ -87,6 +92,7 @@ async def log_request(request: Request, status_code: int, json_body: str): } asyncio.create_task(send_log(log_data)) + @app.middleware("http") async def add_process_time_header(request: Request, call_next): """Основной middleware, который логирует запрос и восстанавливает тело.""" diff --git a/rating_api/routes/lecturer.py b/rating_api/routes/lecturer.py index c81e165..e7c0e4d 100644 --- a/rating_api/routes/lecturer.py +++ b/rating_api/routes/lecturer.py @@ -135,7 +135,9 @@ async def get_lecturers( if comment.review_status is ReviewStatus.APPROVED ] if "comments" in info and approved_comments: - lecturer_to_result.comments = sorted(approved_comments, key=lambda comment: comment.create_ts, reverse=True) + lecturer_to_result.comments = sorted( + approved_comments, key=lambda comment: comment.create_ts, reverse=True + ) if "mark" in info and approved_comments: lecturer_to_result.mark_freebie = sum([comment.mark_freebie for comment in approved_comments]) / len( approved_comments From be89d943925014a9aae55ef7baed6702dd7f09bd Mon Sep 17 00:00:00 2001 From: DROPDATABASE Date: Thu, 13 Feb 2025 22:59:30 +0300 Subject: [PATCH 15/24] fixups --- rating_api/__init__.py | 7 ++----- rating_api/routes/base.py | 16 ++++++++++------ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/rating_api/__init__.py b/rating_api/__init__.py index 94d8063..f7d610b 100644 --- a/rating_api/__init__.py +++ b/rating_api/__init__.py @@ -4,11 +4,8 @@ __version__ = os.getenv('APP_VERSION', 'dev') LOGGING_MARKETING_URLS = { - "dev": ( - f"http://localhost:{os.getenv('MARKETING_PORT', 8000)}/v1/action" - if os.getenv('MARKETING_PORT', None) - else "https://api.test.profcomff.com/marketing/v1/action" - ), + "dev": f"http://localhost:{os.getenv('MARKETING_PORT', 8000)}/v1/action", + "test": "https://api.test.profcomff.com/marketing/v1/action", "prod": "https://api.profcomff.com/marketing/v1/action", } diff --git a/rating_api/routes/base.py b/rating_api/routes/base.py index 147a3b9..84cf54f 100644 --- a/rating_api/routes/base.py +++ b/rating_api/routes/base.py @@ -1,4 +1,5 @@ import asyncio +import logging import httpx from fastapi import FastAPI, Request, Response @@ -42,6 +43,8 @@ app.include_router(lecturer) app.include_router(comment) +LOG = logging.getLogger(__name__) + RETRY_DELAYS = [2, 4, 8] # Задержки перед повторными попытками (в секундах) @@ -52,22 +55,23 @@ async def send_log(log_data): try: response = await client.post(LOGGING_MARKETING_URL, json=log_data) - if response.status_code < 500: + if response.status_code not in {408, 409, 429, 500, 502, 503, 504}: + LOG.info(f"Ответ записи логов от markting status_code: {response.status_code}") break # Успешно или ошибки, которые не стоит повторять (например, неправильные данные) except httpx.HTTPStatusError as e: - print(f"HTTP ошибка ({e.response.status_code}): {e.response.text}") - print('\n\n', response.status_code, '\n\n') + LOG.warning(f"HTTP ошибка ({e.response.status_code}): {e.response.text}") except httpx.RequestError as e: - print(f"Ошибка сети: {e}") + LOG.warning(f"Ошибка сети: {e}") except Exception as e: - print(f"Неизвестная ошибка: {e}") + LOG.warning(f"Неизвестная ошибка: {e}") await asyncio.sleep(sleep_time) # Ожидание перед повторной попыткой - print("Не удалось отправить лог после нескольких попыток.") # logging + else: + LOG.warning("Не удалось отправить лог после нескольких попыток.") async def get_request_body(request: Request) -> tuple[Request, str]: From 5e316d9b0551d94a416af26df440a0b177516020 Mon Sep 17 00:00:00 2001 From: DROPDATABASE Date: Sat, 15 Feb 2025 13:19:07 +0300 Subject: [PATCH 16/24] Move log_urls to settings.py --- rating_api/__init__.py | 10 +--------- rating_api/routes/base.py | 20 ++++++++++---------- rating_api/settings.py | 6 ++++++ 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/rating_api/__init__.py b/rating_api/__init__.py index f7d610b..10b3477 100644 --- a/rating_api/__init__.py +++ b/rating_api/__init__.py @@ -1,12 +1,4 @@ import os -__version__ = os.getenv('APP_VERSION', 'dev') - -LOGGING_MARKETING_URLS = { - "dev": f"http://localhost:{os.getenv('MARKETING_PORT', 8000)}/v1/action", - "test": "https://api.test.profcomff.com/marketing/v1/action", - "prod": "https://api.profcomff.com/marketing/v1/action", -} - -LOGGING_MARKETING_URL = LOGGING_MARKETING_URLS.get(__version__, LOGGING_MARKETING_URLS["prod"]) +__version__ = os.getenv('APP_VERSION', 'dev') \ No newline at end of file diff --git a/rating_api/routes/base.py b/rating_api/routes/base.py index 84cf54f..0a3250f 100644 --- a/rating_api/routes/base.py +++ b/rating_api/routes/base.py @@ -6,16 +6,16 @@ from fastapi.middleware.cors import CORSMiddleware from fastapi_sqlalchemy import DBSessionMiddleware -from rating_api import LOGGING_MARKETING_URL, __version__ +from rating_api import __version__ from rating_api.routes.comment import comment from rating_api.routes.lecturer import lecturer -from rating_api.settings import get_settings +from rating_api.settings import Settings, get_settings # from auth_lib.fastapi import UnionAuth -settings = get_settings() +settings: Settings = get_settings() app = FastAPI( title='Рейтинг преподавателей', description='Хранение и работа с рейтингом преподавателей и отзывами на них.', @@ -43,7 +43,7 @@ app.include_router(lecturer) app.include_router(comment) -LOG = logging.getLogger(__name__) +log = logging.getLogger(__name__) RETRY_DELAYS = [2, 4, 8] # Задержки перед повторными попытками (в секундах) @@ -53,25 +53,25 @@ async def send_log(log_data): async with httpx.AsyncClient() as client: for attempt, sleep_time in enumerate(RETRY_DELAYS, start=1): try: - response = await client.post(LOGGING_MARKETING_URL, json=log_data) + response = await client.post(settings.LOGGING_MARKETING_URL, json=log_data) if response.status_code not in {408, 409, 429, 500, 502, 503, 504}: - LOG.info(f"Ответ записи логов от markting status_code: {response.status_code}") + log.info(f"Ответ записи логов от markting status_code: {response.status_code}") break # Успешно или ошибки, которые не стоит повторять (например, неправильные данные) except httpx.HTTPStatusError as e: - LOG.warning(f"HTTP ошибка ({e.response.status_code}): {e.response.text}") + log.warning(f"HTTP ошибка ({e.response.status_code}): {e.response.text}") except httpx.RequestError as e: - LOG.warning(f"Ошибка сети: {e}") + log.warning(f"Ошибка сети: {e}") except Exception as e: - LOG.warning(f"Неизвестная ошибка: {e}") + log.warning(f"Неизвестная ошибка: {e}") await asyncio.sleep(sleep_time) # Ожидание перед повторной попыткой else: - LOG.warning("Не удалось отправить лог после нескольких попыток.") + log.warning("Не удалось отправить лог после нескольких попыток.") async def get_request_body(request: Request) -> tuple[Request, str]: diff --git a/rating_api/settings.py b/rating_api/settings.py index 1f7612c..41b83df 100644 --- a/rating_api/settings.py +++ b/rating_api/settings.py @@ -4,6 +4,11 @@ from pydantic import ConfigDict, PostgresDsn from pydantic_settings import BaseSettings +LOGGING_MARKETING_URLS = { + "dev": f"http://localhost:{os.getenv('MARKETING_PORT', 8000)}/v1/action", + "test": "https://api.test.profcomff.com/marketing/v1/action", + "prod": "https://api.profcomff.com/marketing/v1/action", +} class Settings(BaseSettings): """Application settings""" @@ -18,6 +23,7 @@ class Settings(BaseSettings): CORS_ALLOW_CREDENTIALS: bool = True CORS_ALLOW_METHODS: list[str] = ['*'] CORS_ALLOW_HEADERS: list[str] = ['*'] + LOGGING_MARKETING_URL: str = LOGGING_MARKETING_URLS.get(os.getenv("APP_VERSION", "dev"), LOGGING_MARKETING_URLS["test"]) model_config = ConfigDict(case_sensitive=True, env_file=".env", extra="ignore") From f007ff67d90ab6544dfbef2b02697e2d5855da29 Mon Sep 17 00:00:00 2001 From: DROPDATABASE Date: Sat, 15 Feb 2025 13:42:18 +0300 Subject: [PATCH 17/24] Make additional data as json string from json dict --- rating_api/routes/base.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/rating_api/routes/base.py b/rating_api/routes/base.py index 0a3250f..ebe0eab 100644 --- a/rating_api/routes/base.py +++ b/rating_api/routes/base.py @@ -1,4 +1,5 @@ import asyncio +import json import logging import httpx @@ -77,7 +78,7 @@ async def send_log(log_data): async def get_request_body(request: Request) -> tuple[Request, str]: """Читает тело запроса и возвращает новый request и тело в виде JSON-строки.""" body = await request.body() - json_body = body.decode("utf-8") if body else "{}" + json_body = json.loads(body) if body else {} # В json(dict) from byte string async def new_stream(): yield body @@ -85,12 +86,17 @@ async def new_stream(): return Request(request.scope, receive=new_stream()), json_body -async def log_request(request: Request, status_code: int, json_body: str): +async def log_request(request: Request, status_code: int, json_body: dict): """Формирует лог и отправляет его в асинхронную задачу.""" + + additional_data = {"response_status_code": status_code, + "auth_user_id": 0, + "request": json_body + } log_data = { "user_id": -2, # UnionAuth()(request).get('id') "action": request.method, - "additional_data": f"response_status_code: {status_code}, auth_user_id: {{}}, request: {json_body}", + "additional_data": json.dumps(additional_data), "path_from": app.root_path, "path_to": request.url.path, } From 83c1b0491648b9e6b57a1c43bdf15fd19c6d8513 Mon Sep 17 00:00:00 2001 From: DROPDATABASE Date: Sat, 15 Feb 2025 15:52:45 +0300 Subject: [PATCH 18/24] Get user_id, add query params to additional_data --- rating_api/routes/base.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/rating_api/routes/base.py b/rating_api/routes/base.py index ebe0eab..05f55cc 100644 --- a/rating_api/routes/base.py +++ b/rating_api/routes/base.py @@ -13,7 +13,7 @@ from rating_api.settings import Settings, get_settings -# from auth_lib.fastapi import UnionAuth +from auth_lib.fastapi import UnionAuth settings: Settings = get_settings() @@ -76,7 +76,7 @@ async def send_log(log_data): async def get_request_body(request: Request) -> tuple[Request, str]: - """Читает тело запроса и возвращает новый request и тело в виде JSON-строки.""" + """Читает тело запроса и возвращает новый request и тело в виде JSON.""" body = await request.body() json_body = json.loads(body) if body else {} # В json(dict) from byte string @@ -85,16 +85,26 @@ async def new_stream(): return Request(request.scope, receive=new_stream()), json_body +async def get_user_id(request: Request): + """Получает user_id из UnionAuth""" + try: + user_id = UnionAuth()(request).get('id') + except Exception as e: + user_id = "Not auth" # Или лучше -1? чтобы типизация :int была? + log.error(e) + + return user_id async def log_request(request: Request, status_code: int, json_body: dict): """Формирует лог и отправляет его в асинхронную задачу.""" additional_data = {"response_status_code": status_code, - "auth_user_id": 0, + "auth_user_id": await get_user_id(request), + "query": request.url.query, "request": json_body } log_data = { - "user_id": -2, # UnionAuth()(request).get('id') + "user_id": -2, "action": request.method, "additional_data": json.dumps(additional_data), "path_from": app.root_path, From 08ed3a4e8eb2459df8e20d69fb7a3028ba644af0 Mon Sep 17 00:00:00 2001 From: DROPDATABASE Date: Sat, 15 Feb 2025 15:54:06 +0300 Subject: [PATCH 19/24] Make format --- rating_api/__init__.py | 2 +- rating_api/routes/base.py | 19 ++++++++++--------- rating_api/settings.py | 6 +++++- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/rating_api/__init__.py b/rating_api/__init__.py index 10b3477..fa9c098 100644 --- a/rating_api/__init__.py +++ b/rating_api/__init__.py @@ -1,4 +1,4 @@ import os -__version__ = os.getenv('APP_VERSION', 'dev') \ No newline at end of file +__version__ = os.getenv('APP_VERSION', 'dev') diff --git a/rating_api/routes/base.py b/rating_api/routes/base.py index 05f55cc..62473cc 100644 --- a/rating_api/routes/base.py +++ b/rating_api/routes/base.py @@ -3,6 +3,7 @@ import logging import httpx +from auth_lib.fastapi import UnionAuth from fastapi import FastAPI, Request, Response from fastapi.middleware.cors import CORSMiddleware from fastapi_sqlalchemy import DBSessionMiddleware @@ -13,9 +14,6 @@ from rating_api.settings import Settings, get_settings -from auth_lib.fastapi import UnionAuth - - settings: Settings = get_settings() app = FastAPI( title='Рейтинг преподавателей', @@ -85,6 +83,7 @@ async def new_stream(): return Request(request.scope, receive=new_stream()), json_body + async def get_user_id(request: Request): """Получает user_id из UnionAuth""" try: @@ -92,17 +91,19 @@ async def get_user_id(request: Request): except Exception as e: user_id = "Not auth" # Или лучше -1? чтобы типизация :int была? log.error(e) - + return user_id + async def log_request(request: Request, status_code: int, json_body: dict): """Формирует лог и отправляет его в асинхронную задачу.""" - additional_data = {"response_status_code": status_code, - "auth_user_id": await get_user_id(request), - "query": request.url.query, - "request": json_body - } + additional_data = { + "response_status_code": status_code, + "auth_user_id": await get_user_id(request), + "query": request.url.query, + "request": json_body, + } log_data = { "user_id": -2, "action": request.method, diff --git a/rating_api/settings.py b/rating_api/settings.py index 41b83df..637e68d 100644 --- a/rating_api/settings.py +++ b/rating_api/settings.py @@ -4,12 +4,14 @@ from pydantic import ConfigDict, PostgresDsn from pydantic_settings import BaseSettings + LOGGING_MARKETING_URLS = { "dev": f"http://localhost:{os.getenv('MARKETING_PORT', 8000)}/v1/action", "test": "https://api.test.profcomff.com/marketing/v1/action", "prod": "https://api.profcomff.com/marketing/v1/action", } + class Settings(BaseSettings): """Application settings""" @@ -23,7 +25,9 @@ class Settings(BaseSettings): CORS_ALLOW_CREDENTIALS: bool = True CORS_ALLOW_METHODS: list[str] = ['*'] CORS_ALLOW_HEADERS: list[str] = ['*'] - LOGGING_MARKETING_URL: str = LOGGING_MARKETING_URLS.get(os.getenv("APP_VERSION", "dev"), LOGGING_MARKETING_URLS["test"]) + LOGGING_MARKETING_URL: str = LOGGING_MARKETING_URLS.get( + os.getenv("APP_VERSION", "dev"), LOGGING_MARKETING_URLS["test"] + ) model_config = ConfigDict(case_sensitive=True, env_file=".env", extra="ignore") From 5073848f2c61801b76afd2ec17decf53eca2e04d Mon Sep 17 00:00:00 2001 From: DROPDATABASE Date: Sat, 15 Feb 2025 15:57:56 +0300 Subject: [PATCH 20/24] Fixup --- rating_api/routes/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rating_api/routes/base.py b/rating_api/routes/base.py index 62473cc..1fe6ce1 100644 --- a/rating_api/routes/base.py +++ b/rating_api/routes/base.py @@ -90,7 +90,7 @@ async def get_user_id(request: Request): user_id = UnionAuth()(request).get('id') except Exception as e: user_id = "Not auth" # Или лучше -1? чтобы типизация :int была? - log.error(e) + log.error(f"USER_AUTH: {e}") return user_id From 33c0eaa0e928abd19ea2217bfe13842b0c88e99a Mon Sep 17 00:00:00 2001 From: DROPDATABASE Date: Sat, 15 Feb 2025 17:28:46 +0300 Subject: [PATCH 21/24] Move middleware log funcs to utils --- rating_api/routes/base.py | 79 +---------------------------- rating_api/utils/logging_utils.py | 82 +++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 78 deletions(-) create mode 100644 rating_api/utils/logging_utils.py diff --git a/rating_api/routes/base.py b/rating_api/routes/base.py index 1fe6ce1..1008618 100644 --- a/rating_api/routes/base.py +++ b/rating_api/routes/base.py @@ -1,9 +1,3 @@ -import asyncio -import json -import logging - -import httpx -from auth_lib.fastapi import UnionAuth from fastapi import FastAPI, Request, Response from fastapi.middleware.cors import CORSMiddleware from fastapi_sqlalchemy import DBSessionMiddleware @@ -12,6 +6,7 @@ from rating_api.routes.comment import comment from rating_api.routes.lecturer import lecturer from rating_api.settings import Settings, get_settings +from rating_api.utils.logging_utils import get_request_body, log_request settings: Settings = get_settings() @@ -42,78 +37,6 @@ app.include_router(lecturer) app.include_router(comment) -log = logging.getLogger(__name__) - -RETRY_DELAYS = [2, 4, 8] # Задержки перед повторными попытками (в секундах) - - -async def send_log(log_data): - """Отправляем лог на внешний сервис асинхронно с обработкой ошибок и ретраями""" - async with httpx.AsyncClient() as client: - for attempt, sleep_time in enumerate(RETRY_DELAYS, start=1): - try: - response = await client.post(settings.LOGGING_MARKETING_URL, json=log_data) - - if response.status_code not in {408, 409, 429, 500, 502, 503, 504}: - log.info(f"Ответ записи логов от markting status_code: {response.status_code}") - break # Успешно или ошибки, которые не стоит повторять (например, неправильные данные) - - except httpx.HTTPStatusError as e: - log.warning(f"HTTP ошибка ({e.response.status_code}): {e.response.text}") - - except httpx.RequestError as e: - log.warning(f"Ошибка сети: {e}") - - except Exception as e: - log.warning(f"Неизвестная ошибка: {e}") - - await asyncio.sleep(sleep_time) # Ожидание перед повторной попыткой - - else: - log.warning("Не удалось отправить лог после нескольких попыток.") - - -async def get_request_body(request: Request) -> tuple[Request, str]: - """Читает тело запроса и возвращает новый request и тело в виде JSON.""" - body = await request.body() - json_body = json.loads(body) if body else {} # В json(dict) from byte string - - async def new_stream(): - yield body - - return Request(request.scope, receive=new_stream()), json_body - - -async def get_user_id(request: Request): - """Получает user_id из UnionAuth""" - try: - user_id = UnionAuth()(request).get('id') - except Exception as e: - user_id = "Not auth" # Или лучше -1? чтобы типизация :int была? - log.error(f"USER_AUTH: {e}") - - return user_id - - -async def log_request(request: Request, status_code: int, json_body: dict): - """Формирует лог и отправляет его в асинхронную задачу.""" - - additional_data = { - "response_status_code": status_code, - "auth_user_id": await get_user_id(request), - "query": request.url.query, - "request": json_body, - } - log_data = { - "user_id": -2, - "action": request.method, - "additional_data": json.dumps(additional_data), - "path_from": app.root_path, - "path_to": request.url.path, - } - asyncio.create_task(send_log(log_data)) - - @app.middleware("http") async def add_process_time_header(request: Request, call_next): """Основной middleware, который логирует запрос и восстанавливает тело.""" diff --git a/rating_api/utils/logging_utils.py b/rating_api/utils/logging_utils.py new file mode 100644 index 0000000..830d1f8 --- /dev/null +++ b/rating_api/utils/logging_utils.py @@ -0,0 +1,82 @@ +import asyncio +import json +import logging +from fastapi import Request +import httpx + +from auth_lib.fastapi import UnionAuth +from rating_api.settings import Settings, get_settings + + +settings: Settings = get_settings() + +log = logging.getLogger(__name__) + +RETRY_DELAYS = [2, 4, 8] # Задержки перед повторными попытками (в секундах) + + +async def send_log(log_data): + """Отправляем лог на внешний сервис асинхронно с обработкой ошибок и ретраями""" + async with httpx.AsyncClient() as client: + for attempt, sleep_time in enumerate(RETRY_DELAYS, start=1): + try: + response = await client.post(settings.LOGGING_MARKETING_URL, json=log_data) + + if response.status_code not in {408, 409, 429, 500, 502, 503, 504}: + log.info(f"Ответ записи логов от markting status_code: {response.status_code}") + break # Успешно или ошибки, которые не стоит повторять (например, неправильные данные) + + except httpx.HTTPStatusError as e: + log.warning(f"HTTP ошибка ({e.response.status_code}): {e.response.text}") + + except httpx.RequestError as e: + log.warning(f"Ошибка сети: {e}") + + except Exception as e: + log.warning(f"Неизвестная ошибка: {e}") + + await asyncio.sleep(sleep_time) # Ожидание перед повторной попыткой + + else: + log.warning("Не удалось отправить лог после нескольких попыток.") + + +async def get_request_body(request: Request) -> tuple[Request, str]: + """Читает тело запроса и возвращает новый request и тело в виде JSON.""" + body = await request.body() + json_body = json.loads(body) if body else {} # В json(dict) from byte string + + async def new_stream(): + yield body + + return Request(request.scope, receive=new_stream()), json_body + + +async def get_user_id(request: Request): + """Получает user_id из UnionAuth""" + try: + user_id = UnionAuth()(request).get('id') + except Exception as e: + user_id = "Not auth" # Или лучше -1? чтобы типизация :int была? + log.error(f"USER_AUTH: {e}") + + return user_id + + +async def log_request(request: Request, status_code: int, json_body: dict): + """Формирует лог и отправляет его в асинхронную задачу.""" + + additional_data = { + "response_status_code": status_code, + "auth_user_id": await get_user_id(request), + "query": request.url.path+"?"+request.url.query, + "request": json_body, + } + log_data = { + "user_id": -2, + "action": request.method, + "additional_data": json.dumps(additional_data), + "path_from": '', # app.root_path + "path_to": request.url.path, + } + asyncio.create_task(send_log(log_data)) \ No newline at end of file From a547199ee0130f62a06e9a522c197d7649918e23 Mon Sep 17 00:00:00 2001 From: DROPDATABASE Date: Sat, 15 Feb 2025 17:30:17 +0300 Subject: [PATCH 22/24] make format --- rating_api/routes/base.py | 1 + rating_api/utils/logging_utils.py | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/rating_api/routes/base.py b/rating_api/routes/base.py index 1008618..30f0099 100644 --- a/rating_api/routes/base.py +++ b/rating_api/routes/base.py @@ -37,6 +37,7 @@ app.include_router(lecturer) app.include_router(comment) + @app.middleware("http") async def add_process_time_header(request: Request, call_next): """Основной middleware, который логирует запрос и восстанавливает тело.""" diff --git a/rating_api/utils/logging_utils.py b/rating_api/utils/logging_utils.py index 830d1f8..52bc800 100644 --- a/rating_api/utils/logging_utils.py +++ b/rating_api/utils/logging_utils.py @@ -1,10 +1,11 @@ import asyncio import json import logging -from fastapi import Request -import httpx +import httpx from auth_lib.fastapi import UnionAuth +from fastapi import Request + from rating_api.settings import Settings, get_settings @@ -69,7 +70,7 @@ async def log_request(request: Request, status_code: int, json_body: dict): additional_data = { "response_status_code": status_code, "auth_user_id": await get_user_id(request), - "query": request.url.path+"?"+request.url.query, + "query": request.url.path + "?" + request.url.query, "request": json_body, } log_data = { @@ -79,4 +80,4 @@ async def log_request(request: Request, status_code: int, json_body: dict): "path_from": '', # app.root_path "path_to": request.url.path, } - asyncio.create_task(send_log(log_data)) \ No newline at end of file + asyncio.create_task(send_log(log_data)) From 70d871913a149ed7ff88df4a5dd28a2015969ab3 Mon Sep 17 00:00:00 2001 From: Mikhail Date: Sun, 16 Feb 2025 12:26:58 +0300 Subject: [PATCH 23/24] change user_id for marketing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -2 уже занято событиями из ботов --- rating_api/utils/logging_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rating_api/utils/logging_utils.py b/rating_api/utils/logging_utils.py index 52bc800..18c4a10 100644 --- a/rating_api/utils/logging_utils.py +++ b/rating_api/utils/logging_utils.py @@ -74,7 +74,7 @@ async def log_request(request: Request, status_code: int, json_body: dict): "request": json_body, } log_data = { - "user_id": -2, + "user_id": -3, "action": request.method, "additional_data": json.dumps(additional_data), "path_from": '', # app.root_path From 8f89ba9e3259736cb4504363eacaeb44a104a1a2 Mon Sep 17 00:00:00 2001 From: parfenovma Date: Sun, 16 Feb 2025 16:44:08 +0000 Subject: [PATCH 24/24] fix dev logs --- rating_api/routes/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rating_api/routes/base.py b/rating_api/routes/base.py index 30f0099..3d725d7 100644 --- a/rating_api/routes/base.py +++ b/rating_api/routes/base.py @@ -48,7 +48,7 @@ async def add_process_time_header(request: Request, call_next): except Exception: status_code = 500 response = Response(content="Internal server error", status_code=500) - - await log_request(request, status_code, json_body) # Логируем запрос + if __version__ != "dev": # Локально не отправляем логи в маркетинг + await log_request(request, status_code, json_body) # Логируем запрос return response