# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['pybotx_smart_logger']

package_data = \
{'': ['*']}

install_requires = \
['fastapi>=0.70.1,<0.71.0', 'pybotx>=0.32.0,<0.33.0']

setup_kwargs = {
    'name': 'pybotx-smart-logger',
    'version': '0.6.2',
    'description': 'Shows logs when you need it',
    'long_description': '# pybotx-smart-logger\n\n_Shows logs when you need it_\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, log_item: Any = undefined)` логируете всю\nинформацию, которая поможет в диагностике ошибки. Если во время обработки сообщения\nбудет выброшено исключение, в логи попадёт:\n\n1. Текущее сообщение от пользователя,\n2. Вся залогированная с помощью `smart_log` информация,\n3. Выброшенное исключение.\n\nЕсли обработка сообщения завершится успешно, накопленные логи будут "выброшены".\n\nВ ботах часто используются фоновые задачи, исключения которых не могут быть перехвачены\nхендлером. Для них используется `smart_logger_decorator`, позволяющий получить\nаналогичное для обработки сообщений поведение.\n\nВы так же можете подлючить миддлварь для возможности логирования из FastAPI хендлеров. В таком случае, если во время обработки исключения будет выброшено ислючение, в логи попадет:\n\n1. Метод\n2. Урл запроса с query параметрами\n3. Заголовки запроса\n\nПри необходимости, тело запроса нужно логировать в самом хендлере:\n``` python\n`smart_log(await request.json())`\n```\n\n\n## Режим отладки\n\nПоявление необходимых логов при возникновении ошибки очень удобно. Однако есть\nситуации, когда необходимо понаблюдать за нормальной работой кода. Тем более, что вызовы\n`smart_log` уже расставлены. Поэтому для сообщений и фоновых задач предусмотрены функции\nотладки.\n\n`BotXSmartLoggerMiddleware` принимает пользовательскую функцию\n`debug_enabled_for_message(message: Message) -> bool`, позволяющую включить режим отладки в\nзависимости от входящего сообщения.\n\n`make_smart_logger_decorator` принимает пользовательскую функцию\n`debug_enabled_for_task(task_name: str) -> bool` позволяющую включить режим отладки в\nзависимости от имени функции. `smart_logger_decorator` знает имя функции, которую он\nоборачивает и передаёт его в `debug_enabled_for_task` в качестве аргумента.\n\nЭти функции можно использовать для включения отладки через переменные окружения, стейт\nбота, Redis, PostgreSQL и т.д. Рекомендую завести команды, которые позволят включать\nрежим отладки отправкой сообщения (см. пример ниже).\n\n`FastApiSmartLoggerMiddleware` принимает аргумент `debug_enabled: bool`.\n\n\n## Настройка\n\n1. Добавляем библиотеку в зависимости `poetry` и устанавливаем:\n\n```toml\npybotx-smart-logger = { git = "https://gitlab.ccsteam.ru/rnd/pybotx-smart-logger", rev = "0.6.0" }\n```\n\n```bash\n$ poetry lock && poetry install\n```\n\n2. Создаём хендлер исключений и подлючаем его к боту. Хендлер должен быть подключен к\n   типу Exception, т.е. заменяет подключенный в коробке `internal_error_handler`.\n\n```python\nfrom app.resources import strings\nfrom pybotx_smart_logger import make_smart_logger_exception_handler\n\nsmart_logger_exception_handler = make_smart_logger_exception_handler(\n    strings.BOT_INTERNAL_ERROR_TEXT\n)\n\nbot.add_exception_handler(Exception, smart_logger_exception_handler)\n```\n\n3. Подключаем миддлварь:\n\n```python\nfrom pybotx_smart_logger import BotXSmartLoggerMiddleware\n\nbot.add_middleware(\n    BotXSmartLoggerMiddleware, debug_enabled_for_message=lambda message: False\n)\n```\n\n4. [Опционально] Для фоновых задач создаём декоратор и запускаем фоновые задачи в при\n   старте бота:\n\n```python\nimport asyncio\nfrom pybotx_smart_logger import make_smart_logger_decorator\n\nsmart_logger_decorator = make_smart_logger_decorator(lambda task_name: False)\n\n\n@smart_logger_decorator\nasync def update_users_tasks() -> None:\n    pass\n\n\nasync def update_background_task() -> None:\n    while True:\n        await update_users_tasks()\n        await asyncio.sleep(60)\n\n# Внутри функции бота `start_app`:\nasyncio.create_task(update_background_task())\n```\n\n5. [Опционально] Возможность логирования из FastAPI хендлера:\nВ файле `app/main.py`\n5.1 Подлключаем миддлварь:\n``` python\nfrom pybotx_smart_logger import FastApiSmartLoggerMiddleware\n...\ndef get_application() -> FastAPI:\n    ...\n    application.middleware("http")(FastApiSmartLoggerMiddleware(debug_enabled=False))\n```\n5.2 Подключаем хендлер исключений:\n``` python\nfrom pybotx_smart_logger import FastApiSmartLoggerMiddleware, fastapi_exception_handler\n...\ndef get_application() -> FastAPI:\n    ...\n    application.middleware("http")(FastApiSmartLoggerMiddleware(debug_enabled=False))\n    application.add_exception_handler(Exception, fastapi_exception_handler)\n```\n\n## Пример команд для включения отладки\n\n```python\n@collector.hidden(command="/_debug:enable-for-huids")\nasync def enable_debug_for_users(message: Message, bot: Bot) -> None:\n    try:\n        huids = [UUID(huid) for huid in message.command.arguments]\n    except ValueError:\n        await bot.answer_message("Получен невалидный user_huid", message)\n        return\n\n    # TODO: Обновите список user_huid\n\n    await bot.answer_message("Список user_huid для отладки обновлён", message)\n```\n\n\n```python\n@collector.hidden(command="/_debug:enable-for-tasks")\nasync def enable_debug_for_tasks(message: Message, bot: Bot) -> None:\n    # TODO: Обновите список имён задач\n\n    await bot.answer_message("Список задач для отладки обновлён", message)\n```\n\n\n## Где применять\n\n1. Проверка роли:\n\n```python\nfrom pybotx_smart_logger import smart_log\n\nasync def subscribed_users_only(\n    message: Message,\n    bot: Bot,\n    user: User = user_dependency,\n) -> None:\n    if not user.is_subscribed:\n        await bot.send(only_subscribed_users_allowed_message(message))\n\n        raise DependencyFailure\n\n    smart_log("This user is subscribed")\n```\n\n2. Обращение в API:\n\n```python\nfrom pybotx_smart_logger import smart_log\n\nasync def _perform_request(\n    self,\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) -> ResponseSchema:\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=self._base_url) as client:\n            response = await client.request(\n                method, url, params=query_params, json=body_dict\n            )\n    except HTTPError as exc:\n        raise RequestToAwesomeAPIFailed 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 InvalidStatusCodeFromAwesomeAPI from exc\n\n    return response.text\n```\n\nА также любые моменты, где что-то может пойти не так. Логируйте -- не стестяйтесь.\n',
    'author': 'Alexander Samoylenko',
    'author_email': 'alexandr.samojlenko@ccsteam.ru',
    'maintainer': None,
    'maintainer_email': None,
    'url': None,
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '>=3.8,<3.10',
}


setup(**setup_kwargs)
