{"id":29925492,"url":"https://github.com/expressapp/pybotx-smart-logger","last_synced_at":"2026-03-16T03:33:30.599Z","repository":{"id":38300871,"uuid":"473604708","full_name":"ExpressApp/pybotx-smart-logger","owner":"ExpressApp","description":null,"archived":false,"fork":false,"pushed_at":"2025-07-31T09:50:41.000Z","size":131,"stargazers_count":2,"open_issues_count":11,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-07-31T13:18:48.069Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ExpressApp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-03-24T12:52:14.000Z","updated_at":"2025-05-16T10:35:43.000Z","dependencies_parsed_at":"2023-10-23T23:21:55.985Z","dependency_job_id":"8d6fd83a-2063-4d80-8730-50df5e63908c","html_url":"https://github.com/ExpressApp/pybotx-smart-logger","commit_stats":null,"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/ExpressApp/pybotx-smart-logger","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ExpressApp%2Fpybotx-smart-logger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ExpressApp%2Fpybotx-smart-logger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ExpressApp%2Fpybotx-smart-logger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ExpressApp%2Fpybotx-smart-logger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ExpressApp","download_url":"https://codeload.github.com/ExpressApp/pybotx-smart-logger/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ExpressApp%2Fpybotx-smart-logger/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268379997,"owners_count":24241163,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-02T02:00:12.353Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-08-02T11:37:15.045Z","updated_at":"2026-03-16T03:33:30.585Z","avatar_url":"https://github.com/ExpressApp.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pybotx-smart-logger\n\n_Shows logs when you need it_\n\n## Requirements\n\n- Python 3.10+\n\n\n## Проблема/решение\n\nВ основном наши боты работают в закрытых контурах. Там невозможно использовать Sentry,\nпоэтому наш главный помощник в диагностике неполадок - логи контейнера.\n\nОднако, если сделать логи слишком подробными, то действительно важную информацию будет\nочень сложно найти. Также мы получим проблемы избыточного использования постоянной\nпамяти или слишком быструю ротацию логов. Но сделав логи слишком сжатыми, мы рискуем\nстолкнуться с ситуацией, когда их недостаточно для диагностики ошибки.\n\nТо есть хочется видеть как можно больше информации во время возникновения ошибок, и как\nможно меньше - когда всё хорошо.\n\n\n## Использование\n\nИспользуя функцию `smart_log(log_message: str, *args: Any, **kwargs: Any)` логируете всю\nинформацию, которая поможет в диагностике ошибки. Если во время обработки сообщения\nбудет выброшено исключение, в логи попадёт:\n\n1. Текущее сообщение от пользователя,\n2. Вся залогированная с помощью `smart_log` информация,\n3. Выброшенное исключение.\n\nЕсли обработка сообщения завершится успешно, накопленные логи будут \"выброшены\".\n\n## Настройка\n\n1. Устанавливаем библиотеку:  \n```bash\npoetry add pybotx-smart-logger\n```\n\n2. Подключим мидлварь для логирования входящих сообщений:\n\n**middlewares/smart_logger.py**\n```python #logger_init_middleware\nasync def smart_logger_middleware(\n    message: IncomingMessage,\n    bot: Bot,\n    call_next: IncomingMessageHandlerFunc,\n) -\u003e None:\n    async with wrap_smart_logger(\n        log_source=\"Incoming message\",\n        context_func=lambda: format_raw_command(message.raw_command),\n        debug=True,\n    ):\n        await call_next(message, bot)\n```\n\n**bot.py**\n```python #logger_init_bot\nBot(\n    collectors=[collector],\n    bot_accounts=[BOT_CREDENTIALS],\n    middlewares=[\n        smart_logger_middleware,\n    ],\n)\n```\n3. Для того чтобы логировать какие-то другие части приложения, необходимо обернуть в контекстный менеджер:\n```python #logger_common_use\nasync def handler() -\u003e None:\n    async with wrap_smart_logger(\n        log_source=\"Request to Server\",\n        context_func=lambda: str(kwargs),\n        debug=False,\n    ):\n        await make_request(**kwargs)\n```\n\n4.  Также можно использовать smart_logger для логирования запросов к FastAPI приложению:\n```python #logger_fastapi_use\napp = FastAPI()\n\n\n@app.middleware(\"http\")\nasync def smart_logger_middleware(request: Request, call_next: Callable) -\u003e None:\n    async with wrap_smart_logger(\n        log_source=\"Incoming request\",\n        context_func=lambda: pformat_str_request(request),\n        debug=DEBUG,\n    ):\n        return await call_next(request)\n```\n`log_source` определяет источник логов. `context_func` - пользовательская функция для форматирования логов.\n\n## Пример команд для включения отладки\n\n```python #logger_debug_enable\n@collector.command(\"/_debug:enable-for-huids\", visible=False)\nasync def enable_debug_for_users(message: IncomingMessage, bot: Bot) -\u003e None:\n    try:\n        huids = [UUID(huid) for huid in message.arguments]\n    except ValueError:\n        await bot.answer_message(\"Получен невалидный user_huid\")\n        return\n\n    # TODO: Обновите список user_huid\n\n    await bot.answer_message(f\"Список user_huid для отладки обновлён {huids}\")\n```\n\n\n```python #logger_debug_enable_command\n@collector.command(\"/_debug:enable-for-tasks\", visible=False)\nasync def enable_debug_for_tasks(message: IncomingMessage, bot: Bot) -\u003e None:\n    # TODO: Обновите список имён задач\n\n    await bot.answer_message(\"Список задач для отладки обновлён\")\n```\n\n## Группировка сообщений логера\nДля того, чтобы логи из разных хендлеров не перемешивались между собой \nи можно было удобно отследить весь порядок действия пользователя, можно \nвключить группировку логов.\n\n```python #logger_group\nasync def smart_logger_middleware(\n    message: IncomingMessage,\n    bot: Bot,\n    call_next: IncomingMessageHandlerFunc,\n) -\u003e None:\n    async with wrap_smart_logger(\n        log_source=\"Incoming message\",\n        context_func=lambda: format_raw_command(message.raw_command),\n        debug=True,\n        group=True,  # Enable grouping\n    ):\n        await call_next(message, bot)\n```\n\nТеперь всё, что было залогировано через функцию `smart_log` будет \"выброшено\" только\nпосле обработки сообщения и не будет перемешано с логами других сообщений.\n\n**Работает только с включенным `DEBUG`**\n\n## Где применять\n\n1. Проверка роли:\n\n```python #logger_check_role\n# TODO: Мидлварь для заполнения message.state.user\n\n\nasync def subscribed_users_only_middleware(\n    message: IncomingMessage,\n    bot: Bot,\n    call_next: IncomingMessageHandlerFunc,\n) -\u003e None:\n    if not message.state.user.is_subscribed:\n        await bot.send(message=only_subscribed_users_allowed_message(message))\n\n        return\n\n    smart_log(\"This user is subscribed\")\n\n    await call_next(message, bot)\n```\n\n2. Обращение в API:\n\n```python #logger_api_call\nasync def _perform_request(\n    method: Literal[\"GET\", \"POST\"],\n    url: str,\n    query_params: Optional[Dict[str, Any]] = None,\n    body_dict: Optional[Dict[str, Any]] = None,\n) -\u003e str:\n    smart_log(\"Performing request to YourAwesomeAPI\")\n    smart_log(\"Method:\", method)\n    smart_log(\"URL:\", url)\n    smart_log(\"Query parameters:\", query_params)\n    smart_log(\"Body dict:\", body_dict)\n\n    try:\n        async with AsyncClient(base_url=base_url) as client:\n            response = await client.request(\n                method,\n                url,\n                params=query_params,\n                json=body_dict,\n            )\n    except HTTPError as exc:\n        raise RequestToAwesomeAPIError from exc\n\n    smart_log(\"Response text:\", response.text)\n\n    try:\n        response.raise_for_status()\n    except HTTPStatusError as exc:  # noqa: WPS440\n        raise InvalidStatusCodeFromAwesomeAPIError from exc\n\n    return response.text\n```\n\nА также любые моменты, где что-то может пойти не так. Логируйте - не стестяйтесь.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexpressapp%2Fpybotx-smart-logger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fexpressapp%2Fpybotx-smart-logger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexpressapp%2Fpybotx-smart-logger/lists"}