Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Показано с 1 по 8 из 8
  1. #1
    Аватар для PawnoNoob
    Пользователь

    Статус
    Оффлайн
    Регистрация
    31.03.2016
    Сообщений
    257
    Репутация:
    3 ±

    Система логов

    Приветствую! Спрошу кратко: как лучше реализовать систему логов? На MySQL или на файлах?
    P.S.: планируется вести лог почти каждого действия.

  2. #2
    Аватар для ziggi
    Проверенный

    Статус
    Оффлайн
    Регистрация
    14.05.2015
    Сообщений
    1,181
    Репутация:
    790 ±
    Я бы сделал на MySQL, потому что можно реализовать логи с категориями, сделать удобный поиск и просмотр через веб-интерфейс с различными фильтрами.

  3. Пользователь сказал cпасибо:
    PawnoNoob (13.05.2018)
  4. #3
    Аватар для PawnoNoob
    Пользователь

    Статус
    Оффлайн
    Регистрация
    31.03.2016
    Сообщений
    257
    Репутация:
    3 ±
    Цитата Сообщение от ziggi Посмотреть сообщение
    Я бы сделал на MySQL, потому что можно реализовать логи с категориями, сделать удобный поиск и просмотр через веб-интерфейс с различными фильтрами.
    Хм, я тоже хотел бы сделать именно в базе данных, но не будет ли никаких "лагов" при большом количестве игроков?
    И ещё вопрос: как бы Вы порекомендовали сделать саму структуру базы данных для логирования действий администрации и игроков в целом?

  5. #4
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Цитата Сообщение от PawnoNoob Посмотреть сообщение
    Хм, я тоже хотел бы сделать именно в базе данных, но не будет ли никаких "лагов" при большом количестве игроков?
    Если запрос асинхронный, основной поток сервера не блокируется.

    Цитата Сообщение от PawnoNoob Посмотреть сообщение
    И ещё вопрос: как бы Вы порекомендовали сделать саму структуру базы данных для логирования действий администрации и игроков в целом?
    В общих чертах всё должно выглядеть примерно так:
      Открыть/закрыть

    1. CREATE TABLE `adm_actions`(
    2. `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    3. `datetime` DATETIME NOT NULL,
    4. `accid` INT UNSIGNED NOT NULL,
    5. `action` INT UNSIGNED NOT NULL,
    6. `extra` TEXT NOT NULL,
    7. PRIMARY KEY (`id`)
    8. );


    1. enum eAdminAction
    2. {
    3. ADMIN_ACTION_LOGIN,
    4. ADMIN_ACTION_LOGOUT,
    5. ADMIN_ACTION_KICK,
    6. ADMIN_ACTION_BAN
    7. };
    8.  
    9. LogAdminAction(playerid, eAdminAction:action, const extra[] = "")
    10. {
    11. new str[256];
    12. static const fmt[] =
    13. "INSERT INTO `adm_actions` (`datetime`,`accid`,`action`,`extra`) VALUES (NOW(),'%d','%d','%e')";
    14. mysql_format(mysql_connection, str, sizeof(str), fmt, player_info[playerid][pAccoundID], _:action, extra);
    15. return mysql_tquery(mysql_connection, str);
    16. }
    17.  
    18. CMD:kick(playerid, params[])
    19. {
    20. new targetname[MAX_PLAYER_NAME + 1];
    21. // ...
    22. LogAdminAction(playerid, ADMIN_ACTION_KICK, targetname);
    23. return SendClientMessage(/* ... */);
    24. }


    Или можно просто дампить строки, но это слишком "топорный" метод: мало того, что строки будут занимать больше пространства в БД, так ещё и не получится сделать вывод всех действий от конкретного админа или за конкретную дату (разве что юзать строковые функции, но это будет уже не так просто, да и не факт, что надёжно).
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  6. 2 пользователя(ей) сказали cпасибо:
    PawnoNoob (13.05.2018) Web (13.05.2018)
  7. #5
    Аватар для StevenH
    Пользователь

    Статус
    Оффлайн
    Регистрация
    13.10.2015
    Сообщений
    516
    Репутация:
    21 ±
    Цитата Сообщение от PawnoNoob Посмотреть сообщение
    Хм, я тоже хотел бы сделать именно в базе данных, но не будет ли никаких "лагов" при большом количестве игроков?
    И ещё вопрос: как бы Вы порекомендовали сделать саму структуру базы данных для логирования действий администрации и игроков в целом?
    Лагов не будет, на всех крупных проектах именно так и сделано (на адвансе например это отчеты, на аризоне почти каждое действие логируется в БД)

  8. Пользователь сказал cпасибо:
    PawnoNoob (13.05.2018)
  9. #6
    Аватар для PawnoNoob
    Пользователь

    Статус
    Оффлайн
    Регистрация
    31.03.2016
    Сообщений
    257
    Репутация:
    3 ±
    Цитата Сообщение от Daniel_Cortez Посмотреть сообщение
    Если запрос асинхронный, основной поток сервера не блокируется.


    В общих чертах всё должно выглядеть примерно так:
      Открыть/закрыть

    1. CREATE TABLE `adm_actions`(
    2. `id` INT UNSIGNED NOT NULL,
    3. `datetime` DATETIME NOT NULL,
    4. `accid` INT UNSIGNED NOT NULL,
    5. `action` INT UNSIGNED NOT NULL,
    6. `extra` TEXT NOT NULL,
    7. INDEX `id_index` (`id`)
    8. );


    1. enum eAdminAction
    2. {
    3. ADMIN_ACTION_LOGIN,
    4. ADMIN_ACTION_LOGOUT,
    5. ADMIN_ACTION_KICK,
    6. ADMIN_ACTION_BAN
    7. };
    8.  
    9. LogAdminAction(playerid, eAdminAction:action, const extra[] = "")
    10. {
    11. new str[256];
    12. static const fmt[] =
    13. "INSERT INTO `adm_actions` (`datetime`,`accid`,`action`,`extra`) VALUES (NOW(),'%d','%d','%e')";
    14. mysql_format(mysql_connection, str, sizeof(str), fmt, player_info[playerid][pAccoundID], _:action, extra);
    15. return mysql_tquery(mysql_connection, str);
    16. }
    17.  
    18. CMD:kick(playerid, params[])
    19. {
    20. new targetname[MAX_PLAYER_NAME + 1];
    21. // ...
    22. LogAdminAction(playerid, ADMIN_ACTION_KICK, targetname);
    23. return SendClientMessage(/* ... */);
    24. }


    Или можно просто дампить строки, но это слишком "топорный" метод: мало того, что строки будут занимать больше пространства в БД, так ещё и не получится сделать вывод всех действий от конкретного админа или за конкретную дату (разве что юзать строковые функции, но это будет уже не так просто, да и не факт, что надёжно).
    Хм, появилось ещё несколько вопросов:
    1. Почему именно "_:action"? (я про нижнее подчёркивание и двоеточние ) Что это даёт?
    2. Параметр "eAdminAction:action" возвращает порядковый номер из enum?
    3. В каких случаях используется mysql_format и mysql_tquery? Просто читал в одной из статей, что mysql_format защищает от инъекций и т.д.
    4. Что за "асинхронные" запросы?

  10. #7
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Цитата Сообщение от PawnoNoob Посмотреть сообщение
    Почему именно "_:action"? (я про нижнее подчёркивание и двоеточние ) Что это даёт?
    Потому что функция mysql_format ожидает только аргументы, имеющие теги "_" или "Float" (см. теги перед "..." ниже).
    1. native mysql_format(MySQL:handle, output[], max_len, const format[], {Float,_}:...);

    Если не понимаете о чём я - просто удалите "_:" из того кода и попробуйте скомпилировать - словите варнинг о несоответствии тегов.

    Цитата Сообщение от PawnoNoob Посмотреть сообщение
    Параметр "eAdminAction:action" возвращает порядковый номер из enum?
    Это не функция, чтобы что-то возвращать. Если вы про тег в аргументе "action", то да, он означает, что его значением должна быть одна из констант из enum eAdminAction.

    Цитата Сообщение от PawnoNoob Посмотреть сообщение
    В каких случаях используется mysql_format и mysql_tquery? Просто читал в одной из статей, что mysql_format защищает от инъекций и т.д.
    mysql_tquery() - отправляет асинхронные запросы к БД.
    mysql_format(), как можно понять из примера выше, отвечает за форматирование строки с запросом. Основная причина её использования вместо format() - защита от инъекций. И хотя польза такой защиты есть только тогда, когда в форматной строке есть спецификатор "%s" (или "%e" в случае с mysql_format()), ИМХО, проще по привычке всегда использовать для запросов именно эту функцию. Кроме того, в последних версиях SA-MP в format() тоже появился аналогичный спецификатор "%q", но он больше специфичен для SQLite и по идее может неправильно работать с запросами для MySQL.

    Цитата Сообщение от PawnoNoob Посмотреть сообщение
    Что за "асинхронные" запросы?
    Запросы, выполняемые в отдельном потоке и не блокирующие главный поток, в котором выполняются скрипты и обрабатываются серверные данные.
    Если запрос не асинхронный, он выполняется в главном потоке, в котором всё зависает, пока не выполнится запрос.


    И да, я немного обновил создание БД в предыдущем посте, в первоначальном варианте не работало автозаполнение поля "id".
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  11. 2 пользователя(ей) сказали cпасибо:
    geneff (15.05.2018) PawnoNoob (13.05.2018)
  12. #8
    Аватар для PawnoNoob
    Пользователь

    Статус
    Оффлайн
    Регистрация
    31.03.2016
    Сообщений
    257
    Репутация:
    3 ±
    Цитата Сообщение от Daniel_Cortez Посмотреть сообщение
    Потому что функция mysql_format ожидает только аргументы, имеющие теги "_" или "Float" (см. теги перед "..." ниже).
    1. native mysql_format(MySQL:handle, output[], max_len, const format[], {Float,_}:...);

    Если не понимаете о чём я - просто удалите "_:" из того кода и попробуйте скомпилировать - словите варнинг о несоответствии тегов.


    Это не функция, чтобы что-то возвращать. Если вы про тег в аргументе "action", то да, он означает, что его значением должна быть одна из констант из enum eAdminAction.


    mysql_tquery() - отправляет асинхронные запросы к БД.
    mysql_format(), как можно понять из примера выше, отвечает за форматирование строки с запросом. Основная причина её использования вместо format() - защита от инъекций. И хотя польза такой защиты есть только тогда, когда в форматной строке есть спецификатор "%s" (или "%e" в случае с mysql_format()), ИМХО, проще по привычке всегда использовать для запросов именно эту функцию. Кроме того, в последних версиях SA-MP в format() тоже появился аналогичный спецификатор "%q", но он больше специфичен для SQLite и по идее может неправильно работать с запросами для MySQL.


    Запросы, выполняемые в отдельном потоке и не блокирующие главный поток, в котором выполняются скрипты и обрабатываются серверные данные.
    Если запрос не асинхронный, он выполняется в главном потоке, в котором всё зависает, пока не выполнится запрос.


    И да, я немного обновил создание БД в предыдущем посте, в первоначальном варианте не работало автозаполнение поля "id".
    О как. Вот теперь всё встало на свои места. Огромное спасибо за понятное объяснение

 

 

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •