server.py: Добавлено детальное логирование

This commit is contained in:
2025-12-25 15:01:29 +05:00
parent a1bb30fb72
commit 02a003fdef

View File

@@ -1,11 +1,13 @@
from __future__ import annotations from __future__ import annotations
import json import json
from types import SimpleNamespace
import loguru
import asyncio import asyncio
from types import SimpleNamespace
from weakref import WeakValueDictionary, WeakSet, finalize from weakref import WeakValueDictionary, WeakSet, finalize
from collections import UserDict from collections import UserDict
from uuid import uuid4 from uuid import uuid4
from loguru import logger
from fastapi import WebSocket, FastAPI, WebSocketDisconnect, WebSocketException from fastapi import WebSocket, FastAPI, WebSocketDisconnect, WebSocketException
from .event import call_event from .event import call_event
@@ -19,7 +21,6 @@ class TopicWeakDict(UserDict):
super().__setitem__(key, value) super().__setitem__(key, value)
class Server: class Server:
_logger: loguru.Logger = loguru.logger
_static_tokens: list[str] = [] _static_tokens: list[str] = []
_temp_tokens: list[str] = [] _temp_tokens: list[str] = []
_server_connection: WebSocket | None = None _server_connection: WebSocket | None = None
@@ -60,6 +61,16 @@ class Server:
data = json.dumps(data) data = json.dumps(data)
# Меняем синтаксис под Squirrel # Меняем синтаксис под Squirrel
data = data.replace("'", '\\"').replace('True', 'true').replace('False', 'false') data = data.replace("'", '\\"').replace('True', 'true').replace('False', 'false')
logs_connection_list = [f"{item.client.host}:{item.client.port}" for item in connection_list]
logger.info(
'Отправлено новое сообщение по каналу WebSocket',
log_type = 'PyG2O',
receivers = logs_connection_list,
message_uuid = data[uuid],
message_data = data,
)
asyncio.create_task(cls._async_send(connection_list, data)) asyncio.create_task(cls._async_send(connection_list, data))
return request return request
@@ -118,7 +129,11 @@ class Server:
await connection.accept() await connection.accept()
await cls._subscribe(['all'], connection) await cls._subscribe(['all'], connection)
cls._logger.info('WebSocket клиент подключился') logger.info(
'WebSocket клиент подключился',
log_type = 'PyG2O',
connection = f"{connection.client.host}:{connection.client.port}",
)
try: try:
while True: while True:
@@ -127,16 +142,37 @@ class Server:
message_data = json.loads(data) message_data = json.loads(data)
asyncio.create_task(cls._process_message(connection, message_data)) asyncio.create_task(cls._process_message(connection, message_data))
except json.JSONDecodeError as e: except json.JSONDecodeError as e:
cls._logger.exception(f'Ошибка декодирования JSON: {e}') logger.info(
'Ошибка декодирования JSON сообщения',
log_type = 'PyG2O',
description = e,
message_data = data,
connection = f"{connection.client.host}:{connection.client.port}",
)
except WebSocketDisconnect: except WebSocketDisconnect:
cls._logger.info('WebSocket клиент отключился')
if connection == cls._server_connection: if connection == cls._server_connection:
cls._server_connection = None cls._server_connection = None
logger.info(
'WebSocket G2O сервер отключился',
log_type = 'PyG2O',
connection = f"{connection.client.host}:{connection.client.port}",
)
else: else:
playerid = next((key for key, values in cls._registered_clients.items() if connection in values), None) playerid = next((key for key, values in cls._registered_clients.items() if connection in values), None)
if playerid is not None: cls._registered_clients[playerid].remove(connection) if playerid is not None: cls._registered_clients[playerid].remove(connection)
logger.info(
'WebSocket клиент отключился',
log_type = 'PyG2O',
connection = f"{connection.client.host}:{connection.client.port}",
playerid = playerid,
)
except WebSocketException as e: except WebSocketException as e:
cls._logger.exception(f'Ошибка WebSocket подключения: {e}') logger.exception(
'Ошибка при обработке WebSocket сообщения',
log_type = 'PyG2O',
connection = f"{connection.client.host}:{connection.client.port}",
description = e,
)
@classmethod @classmethod
async def _process_message(cls, connection: WebSocket, message: dict): async def _process_message(cls, connection: WebSocket, message: dict):
@@ -163,25 +199,74 @@ class Server:
except KeyError: except KeyError:
cls._registered_clients[playerid] = [connection] cls._registered_clients[playerid] = [connection]
logs_connection_list = [f"{item.client.host}:{item.client.port}" for item in cls._registered_clients[playerid]]
logger.info(
'Зарегистрирован новый WebSocket клиент',
log_type = 'PyG2O',
connection = f"{connection.client.host}:{connection.client.port}",
playerid = playerid,
total_playerid_connections = logs_connection_list,
)
case {'event': 'register_server'}: case {'event': 'register_server'}:
if cls._server_connection is None: if cls._server_connection is None:
cls._server_connection = connection cls._server_connection = connection
logger.info(
'Зарегистрирован новый WebSocket G2O сервер',
log_type = 'PyG2O',
connection = f"{connection.client.host}:{connection.client.port}",
)
case {'event': 'sq_response', 'uuid': uuid, 'data': data}: case {'event': 'sq_response', 'uuid': uuid, 'data': data}:
try: try:
cls._requests[uuid].set_result(data) cls._requests[uuid].set_result(data)
logger.info(
'Получен ответ от G2O сервера (sq_response)',
log_type = 'PyG2O',
connection = f"{connection.client.host}:{connection.client.port}",
message_uuid = uuid,
message_data = data,
)
except KeyError: except KeyError:
... logger.warning(
'Получен неожиданный ответ от G2O сервера',
log_type = 'PyG2O',
connection = f"{connection.client.host}:{connection.client.port}",
message_uuid = uuid,
message_data = data,
)
case {'event': event, 'uuid': uuid, **kwargs}: case {'event': event, 'uuid': uuid, **kwargs}:
try: try:
cls._requests[uuid].set_result(SimpleNamespace(**kwargs)) cls._requests[uuid].set_result(SimpleNamespace(**kwargs))
logger.info(
'Получен ответ от клиента',
log_type = 'PyG2O',
connection = f"{connection.client.host}:{connection.client.port}",
message_event = event,
message_uuid = uuid,
message_data = kwargs,
)
except KeyError: except KeyError:
kwargs['uuid'] = uuid kwargs['uuid'] = uuid
kwargs['connection'] = connection kwargs['connection'] = connection
playerid = next((key for key, values in cls._registered_clients.items() if connection in values), None) playerid = next((key for key, values in cls._registered_clients.items() if connection in values), None)
if playerid is not None: kwargs['playerid'] = playerid if playerid is not None: kwargs['playerid'] = playerid
asyncio.create_task(call_event(event, **kwargs)) asyncio.create_task(call_event(event, **kwargs))
logger.info(
'Получено сообщение от сервера' if connection == cls._server_connection else 'Получено сообщение от клиента',
log_type = 'PyG2O',
connection = f"{connection.client.host}:{connection.client.port}",
message_event = event,
message_uuid = uuid,
message_data = kwargs,
)
case _: case _:
logger.error(
'Получено неподдерживаемое сообщение от сервера' if connection == cls._server_connection else 'Получено неподдерживаемое сообщение от клиента',
log_type = 'PyG2O',
connection = f"{connection.client.host}:{connection.client.port}",
message_data = message,
)
raise ValueError(f'Неподдерживаемый тип PyG2O сообщения: {message}') raise ValueError(f'Неподдерживаемый тип PyG2O сообщения: {message}')