add 500 alert
This commit is contained in:
parent
6bd69cd7fb
commit
0d0db1209e
@ -1,6 +1,8 @@
|
|||||||
import os
|
import os
|
||||||
import uuid
|
import uuid
|
||||||
import logging
|
import logging
|
||||||
|
import asyncio
|
||||||
|
import traceback
|
||||||
from fastapi import FastAPI, Request, HTTPException
|
from fastapi import FastAPI, Request, HTTPException
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
from fastapi.exceptions import RequestValidationError
|
from fastapi.exceptions import RequestValidationError
|
||||||
@ -16,11 +18,101 @@ from starlette.status import (
|
|||||||
)
|
)
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from config import settings
|
from config import settings
|
||||||
|
from common_lib.utils.http_client import client
|
||||||
|
|
||||||
# Настраиваем логирование
|
# Настраиваем логирование
|
||||||
logging.basicConfig(level=logging.ERROR)
|
logging.basicConfig(level=logging.ERROR)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
FEEDBACK_SERVICE_URL = "http://yobble-feedback-service:8000"
|
||||||
|
ERROR_LOG_ENVIRONMENT = "beta"
|
||||||
|
ERROR_LOG_METHODS = {"GET", "POST", "PUT", "PATCH", "DELETE"}
|
||||||
|
|
||||||
|
|
||||||
|
def _get_service_name() -> str:
|
||||||
|
return (
|
||||||
|
getattr(settings, "SERVICE_NAME", None)
|
||||||
|
or os.getenv("SERVICE_NAME")
|
||||||
|
or "unknown"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_uuid(value: str | None) -> str | None:
|
||||||
|
if not value:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
return str(uuid.UUID(str(value)))
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
async def _read_request_body(request: Request):
|
||||||
|
try:
|
||||||
|
body = await request.body()
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if not body:
|
||||||
|
return None
|
||||||
|
|
||||||
|
content_type = request.headers.get("content-type", "")
|
||||||
|
if "application/json" in content_type:
|
||||||
|
try:
|
||||||
|
return await request.json()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return {
|
||||||
|
"raw": body.decode("utf-8", errors="replace")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def _send_internal_error_log(request: Request, exc: Exception, error_id: str) -> None:
|
||||||
|
service_name = _get_service_name()
|
||||||
|
if service_name == "feedback_service":
|
||||||
|
return
|
||||||
|
|
||||||
|
method = request.method.upper()
|
||||||
|
if method not in ERROR_LOG_METHODS:
|
||||||
|
method = "GET"
|
||||||
|
|
||||||
|
current_user = getattr(request.state, "current_user", None)
|
||||||
|
user_id = getattr(current_user, "user_id", None)
|
||||||
|
session_id = getattr(current_user, "session_id", None)
|
||||||
|
|
||||||
|
payload = {
|
||||||
|
"user_id": str(user_id) if user_id else None,
|
||||||
|
"service_name": service_name,
|
||||||
|
"source": "api",
|
||||||
|
"endpoint": request.url.path,
|
||||||
|
"method": method,
|
||||||
|
"http_status": 500,
|
||||||
|
"request_headers": dict(request.headers),
|
||||||
|
"request_body": await _read_request_body(request),
|
||||||
|
"request_query_params": dict(request.query_params),
|
||||||
|
"response_body": {
|
||||||
|
"status": "error",
|
||||||
|
"errors": [{"field": "server", "message": "Internal Server Error"}],
|
||||||
|
},
|
||||||
|
"ip_address": request.client.host if request.client else None,
|
||||||
|
"user_agent": request.headers.get("user-agent"),
|
||||||
|
"session_id": str(session_id) if session_id else _parse_uuid(request.headers.get("x-session-id")),
|
||||||
|
"error_message": str(exc),
|
||||||
|
"error_stack": "".join(traceback.format_exception(type(exc), exc, exc.__traceback__)),
|
||||||
|
"error_code": error_id,
|
||||||
|
"severity": "high",
|
||||||
|
"environment": ERROR_LOG_ENVIRONMENT,
|
||||||
|
"correlation_id": _parse_uuid(request.headers.get("x-request-id")),
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
await client.post(
|
||||||
|
f"{FEEDBACK_SERVICE_URL}/internal/error-log",
|
||||||
|
json=payload,
|
||||||
|
)
|
||||||
|
except Exception as log_exc:
|
||||||
|
print("error auto log failed:", log_exc)
|
||||||
|
|
||||||
|
|
||||||
def register_error_handlers(app: FastAPI):
|
def register_error_handlers(app: FastAPI):
|
||||||
|
|
||||||
@ -156,6 +248,7 @@ def register_error_handlers(app: FastAPI):
|
|||||||
)
|
)
|
||||||
|
|
||||||
print("500 critical error:", full_log_message)
|
print("500 critical error:", full_log_message)
|
||||||
|
asyncio.create_task(_send_internal_error_log(request, exc, error_id))
|
||||||
# with open(log_filename, "w", encoding="utf-8") as log_file:
|
# with open(log_filename, "w", encoding="utf-8") as log_file:
|
||||||
# log_file.write(full_log_message)
|
# log_file.write(full_log_message)
|
||||||
|
|
||||||
|
|||||||
@ -183,7 +183,9 @@ async def get_current_user(
|
|||||||
detail="Not authenticated"
|
detail="Not authenticated"
|
||||||
)
|
)
|
||||||
|
|
||||||
return await _fetch_current_user(request, token, require_permissions=False, is_web=is_web)
|
current_user = await _fetch_current_user(request, token, require_permissions=False, is_web=is_web)
|
||||||
|
request.state.current_user = current_user
|
||||||
|
return current_user
|
||||||
|
|
||||||
|
|
||||||
async def get_current_user_with_permissions(
|
async def get_current_user_with_permissions(
|
||||||
@ -205,7 +207,9 @@ async def get_current_user_with_permissions(
|
|||||||
detail="Not authenticated"
|
detail="Not authenticated"
|
||||||
)
|
)
|
||||||
|
|
||||||
return await _fetch_current_user(request, token, require_permissions=True, is_web=is_web)
|
current_user = await _fetch_current_user(request, token, require_permissions=True, is_web=is_web)
|
||||||
|
request.state.current_user = current_user
|
||||||
|
return current_user
|
||||||
|
|
||||||
|
|
||||||
async def get_current_user_or_bot(
|
async def get_current_user_or_bot(
|
||||||
@ -229,7 +233,9 @@ async def get_current_user_or_bot(
|
|||||||
)
|
)
|
||||||
|
|
||||||
is_bot_flag = str(is_bot).lower() in ("true", "1", "yes") if is_bot else False
|
is_bot_flag = str(is_bot).lower() in ("true", "1", "yes") if is_bot else False
|
||||||
return await _fetch_current_user(request, token, require_permissions=False, is_bot=is_bot_flag, is_web=is_web)
|
current_user = await _fetch_current_user(request, token, require_permissions=False, is_bot=is_bot_flag, is_web=is_web)
|
||||||
|
request.state.current_user = current_user
|
||||||
|
return current_user
|
||||||
|
|
||||||
|
|
||||||
def validate_username(value: str,
|
def validate_username(value: str,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "common-lib"
|
name = "common-lib"
|
||||||
version = "0.0.57"
|
version = "0.0.58"
|
||||||
description = "Библиотека общих компонентов для микросервисов yobble"
|
description = "Библиотека общих компонентов для микросервисов yobble"
|
||||||
authors = [{ name = "cheykrym", email = "you@example.com" }]
|
authors = [{ name = "cheykrym", email = "you@example.com" }]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user