Вход на сайт

Просмотр новости

Найдите то, что Вас интересует

От сложности к простоте: как я переписал систему логирования Discord-серверов и сделал её в 10 раз проще

Дата публикации: 18-07-2026 03:10:41

История о том, как сервис логирования Discord-серверов прошёл путь от сложной связки MySQL + PHP + Python до простого решения на Python + SQLite в одном Docker-контейнере — и почему упрощение стека того стоило.

Основное содержимое страницы с новостью.

Всем привет! В апреле я создавал сервис для логирования серверов в Discord. Моя идея была максимально простой: бот отвечает за отслеживание событий и запись логов в базу данных, а веб-интерфейс отображает их.

Первоначально я задумывал делать это через связку MySQL c ботом на Python и сайтом на PHP. Такая задумка работала и вышла в свет 11 февраля 2025 года. Но все оказалось не так гладко как я думал. 4 апреля проект получил обновление 2.0 где были мелкие исправления и редизайн веб-интерфейса.

Однако поддержка такой задумки оказалось слишком сложной. Связка MySQL + PHP + Python породила несколько конкретных проблем. Во-первых, схему базы приходилось держать синхронной сразу в двух местах: бот на Python писал данные, сайт на PHP их читал. Любое изменение структуры таблицы означало правки в двух кодовых базах на двух языках, и рассинхрон ловился только в рантайме. Во-вторых, развёртывание превращалось в квест. Пользователю нужно было поднять MySQL, настроить веб-сервер под PHP, прописать доступы и связать всё между собой. Для инструмента, который люди разворачивают у себя на сервере, это слишком высокий порог входа. В-третьих, дублировалась логика: форматирование одних и тех же данных писалось отдельно на Python (для записи) и на PHP (для вывода). В итоге все это привело к тому, что проект закрылся и был помещен в архив.

Однако идея не давала мне покоя — уж слишком полезный инструмент может получиться. И спустя 5 месяцев проект переродился: 27 сентября 2025 года свет увидел Discord Log Hub — бот или же целая система для логирования Discord сервера.

Новая архитектура

Стек проекта был радикально упрощен и вместо MySQL + PHP + Python используются связка Python + SQLite3. Почему SQLite3 вместо MySQL? Основная причина - один писатель и короткие чтения. Логгер пишет данные в базу и даже на активном сервере, объем будет небольшим. Веб-интерфейс в свою же очередь, читает данные из базы и получает их только тогда, когда пользователь заходит на сайт. Для такого сценария отдельный сервер под базу данных показался мне избыточным. Почему Python вместо PHP? Потому что бот уже изначально был написан на Python и унификация веб-части устраняет главную проблему — рассинхрон схемы.

Первая версия проекта имела установщики (setup.exe и setup), которые создавали: файл конфига, файл зависимостей и файл конфигурации для деплоя на один из хостингов. Однако в обновлении 1.1.0, которое вышло 3 июня 2026 года, я отказался от такой задумки в пользу docker compose, дабы упростить деплой с установкой и окончательно привести все к единой точке входа.

services:
  discord-log-hub:
    build: .
    image: discord-log-hub:latest
    container_name: discord-log-hub
    restart: unless-stopped
    env_file:
      - .env
    ports:
      - "5000:5000"
    volumes:
      - ./data:/app/data

Отныне проект работает по гораздо более простой схеме:

[Discord] ↔ [Бот] ↔ [База данных] ↔ [Веб-интерфейс] ↔ [Пользователь]

А весь сервис может целиком запуститься одной командой:

python main.py

или

docker compose up -d

Что под капотом
  • Бот слушает события и обрабатывает их записывая в базу данных

  • Веб-интерфейс считывает записи с базы данных и отображает их в виде таблицы

Бот и веб-интерфейс — это два отдельных процесса, а не один. web.py на flask крутит свой event loop, bot.py на disnake — свой асинхронный, и держать их в одном процессе означало бы вручную сводить два цикла событий. Запуск двумя Popen разводит их по разным процессам: каждый живёт в своём цикле, а общаются они только через общий SQLite-файл:

if __name__ == "__main__":
    try:
        flask_proc = subprocess.Popen(["python", "web.py"])
        bot_proc = subprocess.Popen(["python", "bot.py"])
        flask_proc.wait()
        bot_proc.wait()
    except KeyboardInterrupt:
        pass
Функционал логирования (каналы)

Имеется 5 направлений (или категорий) логирования:

  • Сообщения, редактирование и удаление

  • Участники, входы и выходы, баны и разбаны и смены никнеймов

  • Сервер, изменение ролей, редактирование каналов, голосовая активность и приглашения

  • Прочее, использование команд (бота), изменение эмодзи и стикеров.

Пример записи события с редактированием сообщения:

@commands.Cog.listener()
async def on_message_edit(self, before: disnake.Message, after: disnake.Message):
    if not self.is_enabled(before.guild.id) or (before.author.bot and self.should_ignore_bots(before.guild.id)):
        return

    cursor.execute("SELECT log_message_edit FROM settings WHERE guild_id = ?", (before.guild.id,))
    if cursor.fetchone() is None or False:
        return

    if before.content == after.content:
        return
    cursor.execute("INSERT INTO logs_messages (message_id, channel_id, guild_id, user_id, username, action_type, old_content, new_content) VALUES (?, ?, ?, ?, ?, 'EDIT', ?, ?)", (before.id, before.channel.id, before.guild.id, before.author.id, f"{before.author.name}#{before.author.discriminator}", before.content, after.content))
    connection.commit()

Остальные записи сделаны аналогичным образом.

Каждая категория имеет свои каналы, всего их 13.

Также, каждый канал логирования можно включить или отключить, изменить режим отображения сообщений: embed или обычные и настроить цвет embed сообщений.

Многопользовательский режим

Новая система также получила функцию мультиаккаунтности. Через бота можно создать или удалить пользователей, а также получить их список. При создании пользователя, ему в личное сообщение отправляется пароль, хеш которого хранится в базе данных.

Управление пользователями в боте

Управление пользователями в боте

У пользователей есть 2 уровня прав доступа:

  • 1 уровень — обычный пользователь, который может просматривать веб-интерфейс

  • 2 уровень — администратор, может создавать пользователей (через бота), удалять их (через бота и веб) и сбрасывать им пароль (через веб)

Внешний видГлавная страница

Главная страница

Основная страница логов

Основная страница логов

Отображение настроек

Отображение настроек

Логи сервера

Логи сервера

Заключение

Упрощение стека полностью оправдало ожидания. Проект из сложного в поддержке монстра превратился в элегантное и при этом довольно простое решение. Вместо двух кодовых баз, я смог прийти к одной кодовой базе. Деплой стал возможен через одну команду, вместо настройки целых MySQL и веб серверов.

Проект полностью открыт: GitHub

Если проект получит популярность, я буду готов обновлять и улучшать его.


P.S. Если тема интересна — пишите в комментариях, о каких технических деталях хотели бы узнать подробнее

Схожие новости

#Наименование новостиТональностьИнформативностьДата публикации
1Хватит засовывать всё в контейнеры: возвращаем комфорт в локальную разработку08.8427-06-2026
2Как мы оптимизировали логику Битрикс на Python/Flask и уложили ее в 1 МБ09.0719-02-2026
3Оптимизация сборки Python Docker образа: размер меньше на -43% (-57%)07.4827-03-2026
4Сервисы — место, где живет бизнес-логика010.3902-01-2026
5Пошаговые диалоги в Python без боли: описываем визарды в JSON, а не в if-ах010.6521-04-2026
6Как я собрал OmniBot: Discord Activity, локальный ruBERT и модерация без чёрного ящика09.4419-07-2026
7Надоел Celery? Не нужен K8s? Как мы сделали легковесный оркестратор на Python07.622-02-2026
8PostgreSQL + VectorChord = Гибридный поиск. Часть 1. Инфраструктура08.1421-04-2026
9Между tail и ELK: пытаюсь собрать логи с нескольких серверов одной командой06.5611-03-2026
10Чтобы ваши тесты работали быстрее, нужен простой советский… xdist. Я измерил. Часть 2013.0719-06-2026

Классификация: . Схожих патентов: 0. Схожих новостей: 10. Тональность: 0. Информативность: 12.86. Источник: pythondigest.ru.