Доработка логирования
This commit is contained in:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "config_manager"
|
name = "config_manager"
|
||||||
version = "2.2.1"
|
version = "2.2.2"
|
||||||
description = "Большой рефакторинг, логирование"
|
description = "Большой рефакторинг, логирование"
|
||||||
authors = [
|
authors = [
|
||||||
{ name = "Aleksei Zosimov", email = "lesha.spb@gmail.com" }
|
{ name = "Aleksei Zosimov", email = "lesha.spb@gmail.com" }
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ class HttpControlChannel(ControlChannel):
|
|||||||
started = time.monotonic()
|
started = time.monotonic()
|
||||||
response = await call_next(request)
|
response = await call_next(request)
|
||||||
duration_ms = int((time.monotonic() - started) * 1000)
|
duration_ms = int((time.monotonic() - started) * 1000)
|
||||||
logger.info(
|
logger.debug(
|
||||||
"API call: method=%s path=%s status=%s duration_ms=%s",
|
"API call: method=%s path=%s status=%s duration_ms=%s",
|
||||||
request.method,
|
request.method,
|
||||||
request.url.path,
|
request.url.path,
|
||||||
@@ -230,6 +230,7 @@ class HttpControlChannel(ControlChannel):
|
|||||||
"HttpControlChannel._action_response result: action=%s status_code=404 detail=handler not configured",
|
"HttpControlChannel._action_response result: action=%s status_code=404 detail=handler not configured",
|
||||||
action,
|
action,
|
||||||
)
|
)
|
||||||
|
logger.warning("control command: action=%s status=handler_not_configured", action)
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
content={"status": "error", "detail": f"{action} handler is not configured"},
|
content={"status": "error", "detail": f"{action} handler is not configured"},
|
||||||
status_code=404,
|
status_code=404,
|
||||||
@@ -243,15 +244,18 @@ class HttpControlChannel(ControlChannel):
|
|||||||
action,
|
action,
|
||||||
detail,
|
detail,
|
||||||
)
|
)
|
||||||
|
logger.warning("control command: action=%s status=ok", action)
|
||||||
return JSONResponse(content={"status": "ok", "detail": detail}, status_code=200)
|
return JSONResponse(content={"status": "ok", "detail": detail}, status_code=200)
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
logger.warning("HttpControlChannel._action_response timeout: action=%s timeout=%s", action, self._timeout)
|
logger.debug("HttpControlChannel._action_response timeout: action=%s timeout=%s", action, self._timeout)
|
||||||
|
logger.warning("control command: action=%s status=timeout", action)
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
content={"status": "error", "detail": f"{action} handler did not respond within {self._timeout}s"},
|
content={"status": "error", "detail": f"{action} handler did not respond within {self._timeout}s"},
|
||||||
status_code=504,
|
status_code=504,
|
||||||
)
|
)
|
||||||
except Exception as exc: # noqa: BLE001
|
except Exception as exc: # noqa: BLE001
|
||||||
logger.exception("HttpControlChannel._action_response error: action=%s", action)
|
logger.debug("HttpControlChannel._action_response error: action=%s", action, exc_info=True)
|
||||||
|
logger.warning("control command: action=%s status=error", action)
|
||||||
return JSONResponse(content={"status": "error", "detail": str(exc)}, status_code=500)
|
return JSONResponse(content={"status": "error", "detail": str(exc)}, status_code=500)
|
||||||
|
|
||||||
async def start(
|
async def start(
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ class TelegramControlChannel(ControlChannel):
|
|||||||
for update in updates:
|
for update in updates:
|
||||||
await self._process_update(update)
|
await self._process_update(update)
|
||||||
except Exception as exc: # noqa: BLE001
|
except Exception as exc: # noqa: BLE001
|
||||||
self._logger.warning("Telegram polling error: %s", exc)
|
self._logger.debug("Telegram polling error: %s", exc, exc_info=True)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await asyncio.wait_for(self._stop_event.wait(), timeout=max(self._poll_interval, 0.1))
|
await asyncio.wait_for(self._stop_event.wait(), timeout=max(self._poll_interval, 0.1))
|
||||||
@@ -94,16 +94,32 @@ class TelegramControlChannel(ControlChannel):
|
|||||||
if chat_id != self._chat_id:
|
if chat_id != self._chat_id:
|
||||||
return
|
return
|
||||||
|
|
||||||
if text in {"/start", "/run"} and self._on_start is not None:
|
action: Optional[str]
|
||||||
reply = await self._on_start()
|
callback: Optional[StartHandler | StopHandler | StatusHandler]
|
||||||
elif text in {"/stop", "/halt"} and self._on_stop is not None:
|
if text in {"/start", "/run"}:
|
||||||
reply = await self._on_stop()
|
action = "start"
|
||||||
elif text in {"/status", "/health"} and self._on_status is not None:
|
callback = self._on_start
|
||||||
reply = await self._on_status()
|
elif text in {"/stop", "/halt"}:
|
||||||
|
action = "stop"
|
||||||
|
callback = self._on_stop
|
||||||
|
elif text in {"/status", "/health"}:
|
||||||
|
action = "status"
|
||||||
|
callback = self._on_status
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if callback is None:
|
||||||
|
self._logger.warning("control command: action=%s status=handler_not_configured", action)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
reply = await callback()
|
||||||
await asyncio.to_thread(self._send_message, reply)
|
await asyncio.to_thread(self._send_message, reply)
|
||||||
|
self._logger.warning("control command: action=%s status=ok", action)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
self._logger.warning("control command: action=%s status=timeout", action)
|
||||||
|
except Exception:
|
||||||
|
self._logger.debug("Telegram control command error: action=%s", action, exc_info=True)
|
||||||
|
self._logger.warning("control command: action=%s status=error", action)
|
||||||
|
|
||||||
def _send_message(self, text: str) -> None:
|
def _send_message(self, text: str) -> None:
|
||||||
"""Отправить текстовый ответ в настроенный чат Telegram."""
|
"""Отправить текстовый ответ в настроенный чат Telegram."""
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ class _RuntimeController:
|
|||||||
|
|
||||||
def _on_worker_degraded_change(self, degraded: bool) -> None:
|
def _on_worker_degraded_change(self, degraded: bool) -> None:
|
||||||
self._worker_degraded = degraded
|
self._worker_degraded = degraded
|
||||||
self.logger.warning("ConfigManagerV2._on_worker_degraded_change result: degraded=%s", degraded)
|
self.logger.debug("ConfigManagerV2._on_worker_degraded_change result: degraded=%s", degraded)
|
||||||
|
|
||||||
def _on_worker_metrics_change(self, inflight_count: int, timed_out_count: int) -> None:
|
def _on_worker_metrics_change(self, inflight_count: int, timed_out_count: int) -> None:
|
||||||
self._worker_inflight_count = inflight_count
|
self._worker_inflight_count = inflight_count
|
||||||
@@ -131,7 +131,7 @@ class _RuntimeController:
|
|||||||
self.logger.warning("ConfigManagerV2._worker_loop result: stopped")
|
self.logger.warning("ConfigManagerV2._worker_loop result: stopped")
|
||||||
|
|
||||||
async def _periodic_update_loop(self) -> None:
|
async def _periodic_update_loop(self) -> None:
|
||||||
self.logger.warning(
|
self.logger.debug(
|
||||||
"ConfigManagerV2._periodic_update_loop result: started update_interval=%s",
|
"ConfigManagerV2._periodic_update_loop result: started update_interval=%s",
|
||||||
self.update_interval,
|
self.update_interval,
|
||||||
)
|
)
|
||||||
@@ -144,7 +144,7 @@ class _RuntimeController:
|
|||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
continue
|
continue
|
||||||
finally:
|
finally:
|
||||||
self.logger.warning("ConfigManagerV2._periodic_update_loop result: stopped")
|
self.logger.debug("ConfigManagerV2._periodic_update_loop result: stopped")
|
||||||
|
|
||||||
async def _status_text(self) -> str:
|
async def _status_text(self) -> str:
|
||||||
health = await self._health_aggregator.collect()
|
health = await self._health_aggregator.collect()
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class WorkerLoop:
|
|||||||
self._degraded = value
|
self._degraded = value
|
||||||
if self._on_degraded_change is not None:
|
if self._on_degraded_change is not None:
|
||||||
self._on_degraded_change(value)
|
self._on_degraded_change(value)
|
||||||
logger.warning("WorkerLoop.run degraded state changed: degraded=%s", value)
|
logger.debug("WorkerLoop.run degraded state changed: degraded=%s", value)
|
||||||
|
|
||||||
def _start_execute(self) -> None:
|
def _start_execute(self) -> None:
|
||||||
execute_id = next(self._id_seq)
|
execute_id = next(self._id_seq)
|
||||||
@@ -107,7 +107,7 @@ class WorkerLoop:
|
|||||||
continue
|
continue
|
||||||
execution.timeout_reported = True
|
execution.timeout_reported = True
|
||||||
self._notify_error(TimeoutError(f"execute() did not finish within {self._execute_timeout}s"))
|
self._notify_error(TimeoutError(f"execute() did not finish within {self._execute_timeout}s"))
|
||||||
logger.warning(
|
logger.debug(
|
||||||
"WorkerLoop.run execute timeout: id=%s elapsed=%.3fs timeout=%ss",
|
"WorkerLoop.run execute timeout: id=%s elapsed=%.3fs timeout=%ss",
|
||||||
execution.id,
|
execution.id,
|
||||||
elapsed,
|
elapsed,
|
||||||
@@ -154,7 +154,7 @@ class WorkerLoop:
|
|||||||
|
|
||||||
if self._inflight:
|
if self._inflight:
|
||||||
if self._has_timed_out_inflight():
|
if self._has_timed_out_inflight():
|
||||||
logger.warning("WorkerLoop.run stop: timed-out execute still running; exiting without waiting")
|
logger.debug("WorkerLoop.run stop: timed-out execute still running; exiting without waiting")
|
||||||
else:
|
else:
|
||||||
await asyncio.gather(*(item.task for item in self._inflight), return_exceptions=True)
|
await asyncio.gather(*(item.task for item in self._inflight), return_exceptions=True)
|
||||||
self._collect_finished()
|
self._collect_finished()
|
||||||
|
|||||||
Reference in New Issue
Block a user