{"id":26090522,"url":"https://github.com/gri-gus/alchemica","last_synced_at":"2026-02-18T05:01:09.908Z","repository":{"id":280913389,"uuid":"943547121","full_name":"gri-gus/alchemica","owner":"gri-gus","description":"Alchemica — SQLAlchemy Logger with logging magic. Sync, async, multithreaded","archived":false,"fork":false,"pushed_at":"2025-03-09T08:16:25.000Z","size":1721,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-27T08:51:24.675Z","etag":null,"topics":["alchemica","asyncio","debugging","fastapi","logging","python","sql-explain","sqlalchemy","sqlalchemy-python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gri-gus.png","metadata":{"files":{"readme":"README-PYPI.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":"2025-03-05T22:08:50.000Z","updated_at":"2025-03-06T00:58:15.000Z","dependencies_parsed_at":"2025-03-06T01:32:35.031Z","dependency_job_id":"c70d0984-7f3c-4dfd-bcaf-3efedc48b59a","html_url":"https://github.com/gri-gus/alchemica","commit_stats":null,"previous_names":["gri-gus/alchemica"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gri-gus/alchemica","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gri-gus%2Falchemica","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gri-gus%2Falchemica/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gri-gus%2Falchemica/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gri-gus%2Falchemica/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gri-gus","download_url":"https://codeload.github.com/gri-gus/alchemica/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gri-gus%2Falchemica/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29569853,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-18T04:18:28.490Z","status":"ssl_error","status_checked_at":"2026-02-18T04:13:49.018Z","response_time":162,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["alchemica","asyncio","debugging","fastapi","logging","python","sql-explain","sqlalchemy","sqlalchemy-python"],"created_at":"2025-03-09T09:34:27.135Z","updated_at":"2026-02-18T05:01:09.863Z","avatar_url":"https://github.com/gri-gus.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003ca\u003e\n        \u003cimg src=\"https://raw.githubusercontent.com/gri-gus/alchemica/main/assets/cover.jpg\" alt=\"alchemica\"\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://pypi.org/project/alchemica\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://img.shields.io/pypi/v/alchemica\" alt=\"PyPI\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://pypi.org/project/alchemica\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://static.pepy.tech/badge/alchemica\" alt=\"PyPI\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://opensource.org/licenses/Apache-2.0\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/License-Apache_2.0-blue.svg\" alt=\"Apache\"\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n      \u003ca href=\"https://github.com/gri-gus/alchemica\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge\u0026logo=github\u0026logoColor=white\" alt=\"GitHub\"\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n# Alchemica - SQLAlchemy Logger\n\n**Alchemica** — это мощный и гибкий инструмент для логирования SQL-запросов в Python-приложениях, работающих с\nSQLAlchemy.\nОн поддерживает как синхронный, так и асинхронный режимы работы, а также корректно функционирует в многопоточных и\nмногопроцессорных средах. Alchemica позволяет легко отслеживать выполнение SQL-запросов, анализировать их\nпроизводительность и выявлять потенциальные проблемы.\n\n---\n\n## Основные возможности\n\n1. **Логирование SQL-запросов**\n    * Логирует все SQL-запросы, выполняемые через SQLAlchemy, в контексте задекорированных функций.\n\n    * Поддерживает логирование как параметризованных запросов, так и запросов с подставленными значениями (через\n      `compile_sql=True`).\n\n    * Каждый запрос сопровождается уникальным идентификатором (query_uuid), что упрощает отслеживание.\n\n2. **Поддержка синхронного и асинхронного режимов**\n    * Работает как с синхронными, так и с асинхронными приложениями.\n\n    * Для синхронного режима используется декоратор `sync_sql_logger`.\n\n    * Для асинхронного режима используется декоратор `async_sql_logger`.\n\n3. **Многопоточная и многопроцессорная поддержка**\n    * Корректно работает в многопоточных и многопроцессорных средах.\n\n    * Каждый поток или процесс имеет изолированный контекст выполнения, что исключает пересечение данных.\n\n4. **Логирование времени выполнения**\n    * Замеряет время выполнения каждого SQL-запроса.\n\n    * Предупреждает, если время выполнения превышает заданный порог (`critical_time`).\n\n5. **План выполнения запросов** (`EXPLAIN`)\n    * Поддерживает логирование плана выполнения запросов для анализа производительности.\n\n    * Полезно для оптимизации сложных запросов.\n\n6. **Гибкая настройка**\n    * Позволяет настраивать уровень логирования (`log_level`), формат сообщений и другие параметры.\n\n    * Поддерживает логирование дополнительной информации о выполнении (`log_execution_info`), такой как имя функции и\n      UUID запроса.\n\n7. **Изоляция контекста**\n    * Логирует только те SQL-запросы, которые выполняются в контексте задекорированной функции.\n\n    * Если внутри функции вызывается другая задекорированная функция, для нее создается новый контекст логирования.\n\n## Установка\n\nДля установки Alchemica выполните следующую команду:\n\n```shell\npip install alchemica\n```\n\n## Быстрый старт\n\n### Синхронный режим\n\n```python\nfrom alchemica import sync_sql_logger\nfrom sqlalchemy import create_engine, text\n\n# Создаем подключение к базе данных\nengine = create_engine(\"sqlite:///:memory:\")\n\n\n# Декорируем функцию для логирования SQL-запросов\n@sync_sql_logger(explain_plan=True)\ndef execute_query():\n    with engine.connect() as conn:\n        conn.execute(text(\"SELECT 1\"))\n\n\nif __name__ == '__main__':\n    # Выполняем запрос\n    execute_query()\n\n```\n\nВывод в консоль:\n\n```text\n2025-03-06 02:39:53,565 - INFO - 🚀 [FUNC](func_name: execute_query; func_uuid: 318df3) запущена\n2025-03-06 02:39:53,566 - INFO - 🟢 [SQL](func_name: execute_query; func_uuid: 318df3; query_uuid: 353cfd) SELECT 1\n2025-03-06 02:39:53,566 - INFO - 📝 [SQL PLAN](func_name: execute_query; func_uuid: 318df3; query_uuid: 353cfd) \n0 Init 0 1 0 None 0 None\n1 Integer 1 1 0 None 0 None\n2 ResultRow 1 1 0 None 0 None\n3 Halt 0 0 0 None 0 None\n2025-03-06 02:39:53,566 - INFO - 🕑️ [SQL](func_name: execute_query; func_uuid: 318df3; query_uuid: 353cfd) Выполнено за 0.0001 сек\n2025-03-06 02:39:53,566 - INFO - ✅ [FUNC](func_name: execute_query; func_uuid: 318df3) выполнена за 0.0009 сек\n```\n\n### Асинхронный режим\n\nДля примера потребуется установить библиотеку `aiosqlite`:\n\n```shell\npip install aiosqlite\n```\n\n```python\nimport asyncio\n\nfrom alchemica import async_sql_logger\nfrom sqlalchemy import text\nfrom sqlalchemy.ext.asyncio import create_async_engine, AsyncSession\n\n# Создаем асинхронное подключение к базе данных\nasync_engine = create_async_engine(\"sqlite+aiosqlite:///:memory:\")\n\n\n# Декорируем асинхронную функцию для логирования SQL-запросов\n@async_sql_logger()\nasync def execute_async_query():\n    async with AsyncSession(async_engine) as session:\n        await session.execute(text(\"SELECT 1\"))\n\n\nif __name__ == '__main__':\n    # Выполняем асинхронный запрос\n    asyncio.run(execute_async_query())\n\n```\n\nВывод в консоль:\n\n```text\n2025-03-06 02:41:03,244 - INFO - 🚀 [FUNC](func_name: execute_async_query; func_uuid: f01219) запущена\n2025-03-06 02:41:03,251 - INFO - 🟢 [SQL](func_name: execute_async_query; func_uuid: f01219; query_uuid: 2080d4) SELECT 1\n2025-03-06 02:41:03,251 - INFO - 🕑️ [SQL](func_name: execute_async_query; func_uuid: f01219; query_uuid: 2080d4) Выполнено за 0.0005 сек\n2025-03-06 02:41:03,252 - INFO - ✅ [FUNC](func_name: execute_async_query; func_uuid: f01219) выполнена за 0.0072 сек\n```\n\n## Общие параметры для sync_sql_logger и async_sql_logger\n\n| Параметр          | Тип               | По умолчанию      | Описание                                                        |\n|-------------------|-------------------|-------------------|-----------------------------------------------------------------|\n| logger            | logging.Logger    | None              | Логгер для записи сообщений. Если не указан, используется стандартный логгер. |\n| log_level         | int               | logging.INFO      | Уровень логирования (например, logging.INFO, logging.DEBUG).     |\n| log_execution_info| bool              | True              | Логировать ли информацию о выполнении (имя функции, UUID запроса и т.д.). |\n| compile_sql       | bool              | False             | Компилировать ли SQL-запросы перед логированием.                |\n| critical_time     | float             | 1.0               | Время в секундах, после которого запрос считается медленным.    |\n| explain_plan      | bool              | False             | Логировать ли план выполнения запроса (EXPLAIN).                |\n| uuid_len          | int               | 6                 | Длина UUID для идентификации запросов.                          |\n\n### Примеры использования\n\n#### Логирование с компиляцией SQL\n\n```python\n@sync_sql_logger(compile_sql=True)\ndef execute_query():\n    with engine.connect() as conn:\n        conn.execute(text(\"SELECT * FROM users WHERE id = :id\"), {\"id\": 1})\n```\n\n#### Логирование с планом выполнения\n\n```python\n\n@sync_sql_logger(explain_plan=True)\ndef execute_query():\n    with engine.connect() as conn:\n        conn.execute(text(\"SELECT * FROM users WHERE id = :id\"), {\"id\": 1})\n```\n\n#### Логирование с критическим временем выполнения\n\n```python\n@sync_sql_logger(critical_time=0.5)\ndef execute_query():\n    with engine.connect() as conn:\n        conn.execute(text(\"SELECT * FROM users WHERE id = :id\"), {\"id\": 1})\n```\n\n## Многопоточная поддержка\n\nAlchemica корректно работает в многопоточных и многопроцессорных средах. Каждый поток или процесс имеет изолированный\nконтекст выполнения, что исключает пересечение данных между ними.\n\n### Пример многопоточного использования\n\n```python\nimport threading\n\nfrom alchemica import sync_sql_logger\nfrom sqlalchemy import create_engine, text\n\nengine = create_engine(\"sqlite:///:memory:\")\n\n\n@sync_sql_logger()\ndef execute_query():\n    with engine.connect() as conn:\n        conn.execute(text(\"SELECT 1\"))\n\n\ndef main():\n    # Запускаем несколько потоков\n    threads = []\n    for _ in range(3):\n        thread = threading.Thread(target=execute_query)\n        threads.append(thread)\n        thread.start()\n\n    for thread in threads:\n        thread.join()\n\n\nif __name__ == '__main__':\n    main()\n\n```\n\nВывод в консоль:\n\n```text\n2025-03-06 02:51:15,422 - INFO - 🚀 [FUNC](func_name: execute_query; func_uuid: fa1278) запущена\n2025-03-06 02:51:15,422 - INFO - 🚀 [FUNC](func_name: execute_query; func_uuid: 0a4fea) запущена\n2025-03-06 02:51:15,422 - INFO - 🚀 [FUNC](func_name: execute_query; func_uuid: 4f27a3) запущена\n2025-03-06 02:51:15,423 - INFO - 🟢 [SQL](func_name: execute_query; func_uuid: 4f27a3; query_uuid: 505aac) SELECT 1\n2025-03-06 02:51:15,423 - INFO - 🕑️ [SQL](func_name: execute_query; func_uuid: 4f27a3; query_uuid: 505aac) Выполнено за 0.0003 сек\n2025-03-06 02:51:15,424 - INFO - ✅ [FUNC](func_name: execute_query; func_uuid: 4f27a3) выполнена за 0.0013 сек\n2025-03-06 02:51:15,424 - INFO - 🟢 [SQL](func_name: execute_query; func_uuid: 0a4fea; query_uuid: 16e6c1) SELECT 1\n2025-03-06 02:51:15,424 - INFO - 🟢 [SQL](func_name: execute_query; func_uuid: fa1278; query_uuid: 571638) SELECT 1\n2025-03-06 02:51:15,424 - INFO - 🕑️ [SQL](func_name: execute_query; func_uuid: fa1278; query_uuid: 571638) Выполнено за 0.0001 сек\n2025-03-06 02:51:15,424 - INFO - ✅ [FUNC](func_name: execute_query; func_uuid: fa1278) выполнена за 0.0023 сек\n2025-03-06 02:51:15,424 - INFO - 🕑️ [SQL](func_name: execute_query; func_uuid: 0a4fea; query_uuid: 16e6c1) Выполнено за 0.0005 сек\n2025-03-06 02:51:15,424 - INFO - ✅ [FUNC](func_name: execute_query; func_uuid: 0a4fea) выполнена за 0.0022 сек\n```\n\n## Логирование в асинхронном режиме\n\nAlchemica поддерживает асинхронные приложения, работающие с SQLAlchemy и asyncio.\n\n### Пример асинхронного использования\n\n```python\nimport asyncio\n\nfrom alchemica import async_sql_logger\nfrom sqlalchemy import Table, Column, Integer, String, MetaData\nfrom sqlalchemy import insert\nfrom sqlalchemy.ext.asyncio import create_async_engine, AsyncSession\n\n# Создаем асинхронное подключение к базе данных\nasync_engine = create_async_engine(\"sqlite+aiosqlite:///:memory:\")\n\n# Определяем метаданные и таблицу\nmetadata = MetaData()\nusers_table = Table(\n    \"users\",\n    metadata,\n    Column(\"id\", Integer, primary_key=True),\n    Column(\"name\", String),\n)\n\n\n@async_sql_logger(compile_sql=True, explain_plan=True)\nasync def create_user(name: str):\n    \"\"\"\n    Функция для создания нового пользователя.\n    \"\"\"\n    async with AsyncSession(async_engine) as session:\n        # Используем SQLAlchemy Core для создания запроса\n        stmt = insert(users_table).values(name=name)\n        await session.execute(stmt)\n        await session.commit()\n\n\n# Основная асинхронная функция\n@async_sql_logger(compile_sql=True)\nasync def main():\n    # Создаем таблицу users\n    async with async_engine.begin() as conn:\n        await conn.run_sync(metadata.create_all)\n\n    # Создаем пользователя\n    await create_user(\"Alice\")\n\n\n# Запускаем асинхронный код\nif __name__ == '__main__':\n    asyncio.run(main())\n\n\n```\n\nВывод в консоль:\n\n```text\n2025-03-06 03:11:34,493 - INFO - 🚀 [FUNC](func_name: main; func_uuid: 6c1054) запущена\n2025-03-06 03:11:34,495 - INFO - 🟢 [SQL](func_name: main; func_uuid: 6c1054; query_uuid: 155ef2) \nCREATE TABLE users (\n\tid INTEGER NOT NULL, \n\tname VARCHAR, \n\tPRIMARY KEY (id)\n)\n\n\n2025-03-06 03:11:34,495 - INFO - 🕑️ [SQL](func_name: main; func_uuid: 6c1054; query_uuid: 155ef2) Выполнено за 0.0003 сек\n2025-03-06 03:11:34,496 - INFO - 🚀 [FUNC](func_name: create_user; func_uuid: ddb888) запущена\n2025-03-06 03:11:34,496 - INFO - 🟢 [SQL](func_name: create_user; func_uuid: ddb888; query_uuid: fb157e) INSERT INTO users (name) VALUES ('Alice')\n2025-03-06 03:11:34,496 - INFO - 📝 [SQL PLAN](func_name: create_user; func_uuid: ddb888; query_uuid: fb157e) \n0 Init 0 8 0 None 0 None\n1 OpenWrite 0 2 0 2 0 None\n2 SoftNull 2 0 0 None 0 None\n3 String8 0 3 0 Alice 0 None\n4 NewRowid 0 1 0 None 0 None\n5 MakeRecord 2 2 4 DB 0 None\n6 Insert 0 4 1 users 57 None\n7 Halt 0 0 0 None 0 None\n8 Transaction 0 1 1 0 1 None\n9 Goto 0 1 0 None 0 None\n2025-03-06 03:11:34,497 - INFO - 🕑️ [SQL](func_name: create_user; func_uuid: ddb888; query_uuid: fb157e) Выполнено за 0.0005 сек\n2025-03-06 03:11:34,497 - INFO - ✅ [FUNC](func_name: create_user; func_uuid: ddb888) выполнена за 0.0015 сек\n2025-03-06 03:11:34,497 - INFO - ✅ [FUNC](func_name: main; func_uuid: 6c1054) выполнена за 0.0039 сек\n```\n\n## Логирование контекста в Alchemica\n\nОдной из ключевых особенностей Alchemica является изоляция контекста выполнения. Это означает, что декоратор\nsync_sql_logger или async_sql_logger логирует только те SQL-запросы, которые выполняются в контексте функции, к которой\nон применен. Если внутри этой функции вызывается другая функция, также декорированная sync_sql_logger или\nasync_sql_logger, то логироваться будут только запросы в контексте этой вложенной функции, а не в контексте родительской\nфункции.\n\n### Как это работает\n\n1. **Контекст выполнения:**\n    * Каждый вызов декорированной функции создает уникальный контекст выполнения, который идентифицируется с помощью\n      UUID.\n\n    * Логируются только те SQL-запросы, которые выполняются в этом контексте.\n\n2. **Вложенные функции:**\n    * Если внутри декорированной функции вызывается другая функция, также декорированная `sync_sql_logger` или\n      `async_sql_logger`, то для нее создается новый контекст выполнения.\n\n    * Запросы внутри вложенной функции логируются в ее контексте, а не в контексте родительской функции.\n\n### Пример\n\nРассмотрим пример, где есть две функции: `outer_function` и `inner_function`.\nОбе функции декорированы `sync_sql_logger`.\n\n```python\nfrom sqlalchemy import create_engine, text\nfrom alchemica import sync_sql_logger\n\n# Создаем подключение к базе данных\nengine = create_engine(\"sqlite:///:memory:\")\n\n\n@sync_sql_logger()\ndef outer_function():\n    \"\"\"\n    Внешняя функция, которая вызывает внутреннюю функцию.\n    \"\"\"\n    with engine.connect() as conn:\n        conn.execute(text(\"SELECT 1\"))  # Запрос 1\n        inner_function()  # Вызов внутренней функции\n        conn.execute(text(\"SELECT 2\"))  # Запрос 2\n\n\n@sync_sql_logger()\ndef inner_function():\n    \"\"\"\n    Внутренняя функция, которая выполняет свой SQL-запрос.\n    \"\"\"\n    with engine.connect() as conn:\n        conn.execute(text(\"SELECT 3\"))  # Запрос 3\n\n\n# Вызов внешней функции\nouter_function()\n```\n\nВывод в консоль:\n\n```text\n2025-03-06 03:18:04,659 - INFO - 🚀 [FUNC](func_name: outer_function; func_uuid: 77afc9) запущена\n2025-03-06 03:18:04,660 - INFO - 🟢 [SQL](func_name: outer_function; func_uuid: 77afc9; query_uuid: 07d89d) SELECT 1\n2025-03-06 03:18:04,660 - INFO - 🕑️ [SQL](func_name: outer_function; func_uuid: 77afc9; query_uuid: 07d89d) Выполнено за 0.0002 сек\n2025-03-06 03:18:04,660 - INFO - 🚀 [FUNC](func_name: inner_function; func_uuid: ef9eed) запущена\n2025-03-06 03:18:04,660 - INFO - 🟢 [SQL](func_name: inner_function; func_uuid: ef9eed; query_uuid: 86e750) SELECT 3\n2025-03-06 03:18:04,660 - INFO - 🕑️ [SQL](func_name: inner_function; func_uuid: ef9eed; query_uuid: 86e750) Выполнено за 0.0001 сек\n2025-03-06 03:18:04,660 - INFO - ✅ [FUNC](func_name: inner_function; func_uuid: ef9eed) выполнена за 0.0002 сек\n2025-03-06 03:18:04,660 - INFO - 🟢 [SQL](func_name: outer_function; func_uuid: 77afc9; query_uuid: db39e7) SELECT 2\n2025-03-06 03:18:04,660 - INFO - 🕑️ [SQL](func_name: outer_function; func_uuid: 77afc9; query_uuid: db39e7) Выполнено за 0.0001 сек\n2025-03-06 03:18:04,660 - INFO - ✅ [FUNC](func_name: outer_function; func_uuid: 77afc9) выполнена за 0.0014 сек\n```\n\n### Ключевые моменты\n\n1. **Изоляция контекста:**\n\n    * Каждая функция (outer_function и inner_function) имеет свой уникальный контекст выполнения, который\n      идентифицируется с помощью func_uuid.\n\n    * Логируются только те SQL-запросы, которые выполняются в контексте текущей функции.\n\n2. **Уникальные идентификаторы:**\n\n    * Каждый SQL-запрос имеет свой уникальный идентификатор (query_uuid), что позволяет отслеживать выполнение отдельных\n      запросов.\n\n3. **Время выполнения:**\n\n    * Для каждого SQL-запроса и функции логируется время выполнения, что помогает анализировать производительность.\n\n4. **Иерархия вызовов:**\n\n    * Логи четко показывают, какая функция вызывает другую, и какие запросы выполняются в каждом контексте.\n\n\u003e Важно отметить, что если оставить декоратор только на `outer_function`, то все запросы будут добавлены в лог в\n\u003e контексте этой функции. А если оставить декоратор только на `inner_function`, то запросы из `outer_function` не\n\u003e будут добавлены в лог.\n\n### Визуализация\n\nДля наглядности можно представить выполнение программы в виде дерева:\n\n```text\nouter_function (func_uuid: 77afc9)\n├── SQL: SELECT 1 (query_uuid: 07d89d)\n├── inner_function (func_uuid: ef9eed)\n│   └── SQL: SELECT 3 (query_uuid: 86e750)\n└── SQL: SELECT 2 (query_uuid: db39e7)\n```\n\n## Логируемые сообщения\n\nAlchemica логирует следующие события:\n\nЗапуск функции:\n\n```text\n🚀 [FUNC](func_name: execute_query; func_uuid: abc123) запущена\n```\n\nВыполнение SQL-запроса:\n\n```text\n🟢 [SQL](func_name: execute_query; func_uuid: abc123; query_uuid: def456) SELECT * FROM users WHERE id = :id\n```\n\nЗавершение функции:\n\n```text\n✅ [FUNC](func_name: execute_query; func_uuid: abc123) выполнена за 0.1234 сек\n```\n\nМедленный запрос:\n\n```text\n⚠️ [SQL](func_name: execute_query; func_uuid: abc123) Запрос выполнялся дольше 1 секунд: 1.2345 сек\n```\n\nПлан выполнения (EXPLAIN):\n\n```text\n📝 [SQL PLAN](func_name: execute_query; func_uuid: abc123)\nSCAN TABLE users\n```\n\nОшибки:\n\n```text\n❌ [SQL ERROR](func_name: execute_query; func_uuid: abc123) Ошибка при выполнении запроса: ...\n```\n\n---\n\nAlchemica — ваш надежный помощник в логировании SQL-запросов! 🚀\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgri-gus%2Falchemica","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgri-gus%2Falchemica","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgri-gus%2Falchemica/lists"}