/
breton75
/
modus2
Обзор
Документация
Войти
/
breton75
/
modus2
Код
Запросы
0
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
framework/logger/master_logger.cpp
624 строки
20 KB
s.sviridov
Update master_logger.cpp
19 фев 2026, 13:08
19 фев 2026, 13:08
3a788cf
Код
Авторство
О чём код?
#include "master_logger.h" modus::MasterLogger::MasterLogger(QObject* parent): QObject(parent) { } modus::MasterLogger::~MasterLogger() { m_modus_entities->deleteLoggers(); foreach (auto logger, m_event_loggers.keys()) delete logger; foreach (auto logger, m_sys_loggers.keys()) delete logger; } bool modus::MasterLogger::init(const modus::AppConfig& cfg, modus::Entities* entities, modus::Configuration* configuration) // int default_level) { try { m_syslog_level = int(modus::event::stringToLevel(cfg.start_log_level)); //default_level; m_modus_entities = entities; m_modus_configiration = configuration; //! создаем логгер по умолчанию. на 18.07.2025 это dbus //! 30.07.2025 тотальная переделка //! информацию о всех логгерах берем из параметра P_LOGGERS //! логгеры делятся на: //! 1) sys loggers - логгеры, которые выводят сообщения переданные через qCritical (или qSystem). эти логгеры не фильтрую сообщения. //! 2) event loggers - логгеры событий. выводят сообщения переданные через qInfo (или qEvent). выводят только отфильтрованные сообщения. //! системные логгеры по-умолчанию читаем из параметра P_SYSLOG. Если он не определен, то это libterm.so - логируем в терминал if(m_modus_configiration->json().contains(P_LOGGERS) && m_modus_configiration->json().value(P_LOGGERS).isObject()) { QJsonObject loggersObj = m_modus_configiration->json().value(P_LOGGERS).toObject(); // оставляем возможность задать уровень сжатия данных if(loggersObj.contains(P_DATA_COMPRESS_LEVEL) && loggersObj.value(P_DATA_COMPRESS_LEVEL).isDouble()) modus::event::Message::compressLevel = loggersObj.value(P_DATA_COMPRESS_LEVEL).toInt(DEFAULT_DATA_COMPRESS_LEVEL); // и порог размер данных, которые не надо сжимать if(loggersObj.contains(P_DATA_COMPRESS_TRESHOLD) && loggersObj.value(P_DATA_COMPRESS_TRESHOLD).isDouble()) modus::event::Message::compressLevel = loggersObj.value(P_DATA_COMPRESS_TRESHOLD).toInt(DEFAULT_DATA_COMPRESS_THRESHOLD); //! SYSLOG { m_sys_loggers.clear(); if(loggersObj.contains(P_SYSLOG) && loggersObj.value(P_SYSLOG).isArray()) { QJsonArray sysLoggersArray = loggersObj.value(P_SYSLOG).toArray(); for(auto l : sysLoggersArray) { modus::LoggerInfo info = modus::LoggerInfo::fromJsonObject(l.toObject()); AbstractLogger* logger = loadLoggerPlugin(info); m_sys_loggers.insert(logger, info); } } //! если m_sys_loggers по какой-то причине пуст, создаем единственный системный логгер. по умолчанию - terminal if(m_sys_loggers.isEmpty()) { QString libpath = QFileInfo(QDir(qApp->applicationDirPath()), "./lib/log/libterm.so").absoluteFilePath(); QString name = QString("terminal"); modus::LoggerInfo info = modus::LoggerInfo(libpath, name); AbstractLogger* logger = loadLoggerPlugin(info); m_sys_loggers.insert(logger, info); } } //! EVENTLOG /*{ m_event_loggers.clear(); if(loggersObj.contains(P_EVENTLOG) && loggersObj.value(P_EVENTLOG).isArray()) { QJsonArray eventLoggersArray = loggersObj.value(P_EVENTLOG).toArray(); for(auto l : eventLoggersArray) { modus::LoggerInfo info = modus::LoggerInfo::fromJsonObject(l.toObject()); QString error = QString{}; if(!addEventLogger(info, error)) throw SvException(error); } } }*/ } else { //! если раздел LOGGERS отсутствует вообще, создаем единственный системный логгер. по умолчанию - terminal QString libpath = QFileInfo(QDir(qApp->applicationDirPath()), "./lib/log/libterm.so").absoluteFilePath(); QString name = QString("terminal"); modus::LoggerInfo info = modus::LoggerInfo(libpath, name); AbstractLogger* logger = loadLoggerPlugin(libpath, QString("terminal"), QJsonObject{}); m_sys_loggers.insert(logger, info); } return true; } catch(sv::SvException& e) { m_lastError = QString("Ошибка при инициализации системы журналирования: %1").arg(e.error); return false; } } bool modus::MasterLogger::setEventLog(const QByteArray& content, QString& result) { try { QJsonParseError je; modus::JsonParser jd = modus::JsonParser::fromJson(content, &je); if(je.error != QJsonParseError::NoError) throw sv::SvException(je.errorString()); return setEventLog(jd.object(), result); } catch(sv::SvException& e) { result = e.error; return false; } } bool modus::MasterLogger::setEventLog(const QJsonObject& content, QString& result) { try { QList<modus::LoggerInfo> infos; QJsonObject obj = content; if(content.contains(P_LOGGERS) && content.value(P_LOGGERS).isObject()) obj = content.value(P_LOGGERS).toObject(); if(obj.contains(P_EVENTLOG) && obj.value(P_EVENTLOG).isArray()) { for(auto l : obj.value(P_EVENTLOG).toArray()) { infos.append(modus::LoggerInfo::fromJsonObject(l.toObject())); } } return setEventLog(infos, result); } catch(sv::SvException& e) { result = e.error; return false; } } bool modus::MasterLogger::setEventLog(QList<modus::LoggerInfo>& infos, QString& result) { try { // удаляем все текущие логгеры if(!m_modus_entities) throw sv::SvException(QString("На сервере не найден ENTITIES : Обратитесь к разработчику")); m_modus_entities->deleteLoggers(); for(auto key:m_event_loggers.keys()) delete key; m_event_loggers.clear(); result.clear(); for(auto info: infos) if(!addEventLogger(info, result)) throw SvException(result); return true; } catch(sv::SvException& e) { result = QString("Ошибка во время выполнения setEventLog: '%1'").arg(e.error); return false; } } bool modus::MasterLogger::addEventLogger(const QByteArray& content, QString& result) { try { QJsonParseError je; modus::JsonParser jd = modus::JsonParser::fromJson(content, &je); if(je.error != QJsonParseError::NoError) throw sv::SvException(je.errorString()); modus::LoggerInfo info = modus::LoggerInfo::fromJsonObject(jd.object()); return addEventLogger(info, result); } catch(sv::SvException& e) { result = e.error; return false; } } bool modus::MasterLogger::addEventLogger(const modus::LoggerInfo& info, QString& result) { try { AbstractLogger* logger = loadLoggerPlugin(info); if(!logger) throw SvException(QString("Неопознанная ошибка при вызове addEventLogger->loadLoggerPlugin")); for(auto filter: info.events) { if(filter.sender().entity != modus::eControl) { if(!m_modus_entities->setLogger(filter.sender())) throw sv::SvException(m_modus_entities->lastError()); } else emit connectControl(); } // формируем список успешно добавленных логгеров result.append(result.isEmpty() ? "" : ",").append(logger->name()); m_event_loggers.insert(logger, info); return true; } catch(sv::SvException& e) { result = e.error; return false; } } bool modus::MasterLogger::delEventLogger(const QByteArray& content, QString& result) { try { QJsonParseError je; modus::JsonParser jd = modus::JsonParser::fromJson(content, &je); if(je.error != QJsonParseError::NoError) throw sv::SvException(je.errorString()); modus::LoggerInfo info = modus::LoggerInfo::fromJsonObject(jd.object()); return delEventLogger(info, result); } catch(sv::SvException& e) { result = e.error; return false; } } bool modus::MasterLogger::delEventLogger(const modus::LoggerInfo& info, QString& result) { try { for(auto logger: m_event_loggers.keys()) { modus::LoggerInfo _info = m_event_loggers.value(logger); if(_info == info) { for(auto filter: _info.events) { if(filter.sender().entity != modus::eControl) { if(!m_modus_entities->deleteLogger(filter.sender())) throw sv::SvException(m_modus_entities->lastError()); } else emit disconnectControl(); } // формируем список успешно удаленных логгеров result.append(result.isEmpty() ? "" : ",").append(logger->name()); m_event_loggers.remove(logger); delete logger; } } return true; } catch(sv::SvException& e) { result = e.error; return false; } } AbstractLogger* modus::MasterLogger::loadLoggerPlugin(const QString& libpath, const QString& name, const QJsonObject& params) { AbstractLogger* logger = nullptr; try { QPluginLoader pluginLoader(libpath); logger = qobject_cast<AbstractLogger*>(pluginLoader.instance()); if(!logger) throw sv::SvException(QString(pluginLoader.errorString())); else { QString n = name; if(n.trimmed().isEmpty()) n = QFileInfo(libpath).fileName().replace("lib", "").replace(".so", "#").append(QString::number(qHash(QUuid::createUuid().toString()), 16)); if(!logger->init(n, params)) throw sv::SvException(logger->lastError()); connect(logger, &AbstractLogger::error, this, &modus::MasterLogger::handleError); } return logger; } catch(SvException& e) { if(logger) delete logger; throw sv::SvException(QString("Ошибка загрузки библиотеки логера %1\n%2").arg(libpath).arg(e.error)); } } AbstractLogger* modus::MasterLogger::loadLoggerPlugin(const modus::LoggerInfo& info) { return loadLoggerPlugin(info.libpath, info.token.name, info.params); } void modus::MasterLogger::handleMessage(QtMsgType type, const QMessageLogContext& context, const QString& msg) { Q_UNUSED(context); switch (type) { case QtMsgType::QtDebugMsg: qDebug() << msg; break; case QtMsgType::QtCriticalMsg: { modus::event::Message message{}; message.restoreFromDebug(msg); for(auto logger : m_sys_loggers.keys()) { if(logger && (message.level() <= m_syslog_level)) logger->log(message.formatString()); } break; } default: { modus::event::Message message; message.restoreFromDebug(msg); if(message.level() == modus::event::llUndefined || message.type() == modus::event::mtUndefined) break; for(auto logger: m_event_loggers.keys()) { modus::LoggerInfo info = m_event_loggers.value(logger); for(auto event: info.events) { QString filterNamePattern = event.sender().name; QString messageName = message.sender().name; if (filterNamePattern != "*" && event.sender().entity != modus::eControl) { QRegExp rx(filterNamePattern, Qt::CaseSensitive); if (!rx.exactMatch(messageName)) continue; } if(event.sender().entity != message.sender().entity) continue; if((message.level() > event.level()) || ((event.type() != modus::event::mtAll) && (quint64(event.type()) != quint64(message.type())))) continue; logger->log(message.formatString(!event.format().isEmpty() ? event.format() : info.format)); } } break; } } } void modus::MasterLogger::handleError(const QString& error) { AbstractLogger* logger = qobject_cast<AbstractLogger*>(sender()); qDebug() << "Ошибка в логгере " << logger->name() << "\n" << error; } QList<modus::LoggerInfo> modus::MasterLogger::getAvailableLoggerPlugins(const QString& path) { QDir dir(path); QList<LoggerInfo> loggerInfos; foreach (QString fileName, dir.entryList(QStringList() << "*.so", QDir::Files)) { QString filePath = dir.absoluteFilePath(fileName); QPluginLoader loader(filePath); QObject *plugin = loader.instance(); if (!plugin) continue; // проверяем, что это AbstractLogger AbstractLogger *logger = qobject_cast<AbstractLogger*>(plugin); if (!logger) continue; LoggerInfo info; info.libpath = filePath; info.title = logger->getTitle(); info.params = logger->getDefaultParams(); // name и token здесь не назначаем. тут они не нужны loggerInfos.append(info); } return loggerInfos; } /*bool modus::MasterLogger::parseRequest(const QByteArray& content, QString& result, QList<modus::event::Filter>& filters) { try { QJsonParseError je; QJsonDocument jd = QJsonDocument::fromJson(content, &je); if(je.error != QJsonParseError::NoError) throw sv::SvException(je.errorString()); QJsonObject jo = jd.object(); if(!jo.contains(P_EVENTS) || !jo.value(P_EVENTS).isArray()) throw sv::SvException(QString("Для операции %1 данные должны содержать массив %2. Смотри руководство разработчика.") .arg("set_eventlog").arg(P_EVENTS)); QJsonArray events = jo.value(P_EVENTS).toArray(); for(int i = 0; i < events.count(); i++) { // QJsonValue v: events) { if(events.at(i).isObject()) { QJsonObject event = events.at(i).toObject(); bool enable = (event.contains(P_ENABLE) ? event.value(P_ENABLE).toBool() : true); if(!enable) continue; QSet<QString> loggersNames; if(event.contains(P_LOGGERS) && event.value(P_LOGGERS).isArray()) { // loggersNames.insert(P_DEFAULT_LOGGER_NAME); // throw sv::SvException(QString("Для операции %1 данные должны содержать массив %2. Смотри руководство разработчика.") // .arg("set_eventlog").arg(P_LOGGERS)); QJsonArray loggers = event.value(P_LOGGERS).toArray(); for(int j = 0; j < loggers.count(); j++){ if(loggers.at(j).toString("").isEmpty()) continue; if(loggers.at(j).toString("").trimmed() == "*") { loggersNames.clear(); for(auto name: m_event_loggers.keys()){ loggersNames.insert(name); } break; } loggersNames.insert(loggers.at(j).toString("")); } } if(loggersNames.isEmpty()) loggersNames.insert(P_DEFAULT_LOGGER_NAME); modus::event::Level level = (event.contains(P_LOG_LEVEL) ? modus::event::stringToLevel(event.value(P_LOG_LEVEL).toString()) : modus::event::llInfo); if(level == modus::event::llUndefined) throw sv::SvException(QString(IMPERMISSIBLE_VALUE).arg(P_LOG_LEVEL).arg(QString(QJsonDocument(event).toJson(QJsonDocument::Compact))) .arg("Допустимые значения: none, error, warning, info, debug, debug2, all")); modus::event::Type type = (event.contains(P_TYPE) ? modus::event::stringToType(event.value(P_TYPE).toString()) : modus::event::mtSimple); if(type == modus::event::mtSimple) throw sv::SvException(QString(IMPERMISSIBLE_VALUE).arg(P_TYPE).arg(QString(QJsonDocument(event).toJson(QJsonDocument::Compact))) .arg("Допустимые значения: all, success, info, event, action, duty, attention," " warning, fail, critical, error, new, change, reset, parse, data, receive," " send, request, reply, excange, connect, disconnect, login, logout, connection," " debug, debug2, debug3, debug4, debug, update")); QString entity = QString(); QVariant identifier = QVariant(); if(event.contains(P_ENTITY) && event.value(P_ENTITY).isString()) entity = event.value(P_ENTITY).toString(); else throw sv::SvException(QString(IMPERMISSIBLE_VALUE).arg(P_EVENTS).arg(QString(QJsonDocument(event).toJson(QJsonDocument::Compact))) .arg(QString("Отсутствует значение '%1'. Смотри руководство разработчика.").arg(P_ENTITY))); qDebug() << "MasterLogger::parseRequest" << "entity" << entity << event.contains(P_NAME) << event.value(P_NAME).toVariant(); // определяем идентифиатор сущности - id или name if(event.contains(P_ID)) { if(event.value(P_ID).isDouble()) identifier = event.value(P_ID).toVariant(); else throw sv::SvException(QString(IMPERMISSIBLE_VALUE).arg(P_ID).arg(QString(QJsonDocument(event).toJson(QJsonDocument::Compact))) .arg(QString("Идентификтор 'id' должен быть задан целым числом. Смотри руководство разработчика."))); } else if(event.contains(P_NAME)) { if(event.value(P_NAME).isString()) identifier = event.value(P_NAME).toVariant(); else throw sv::SvException(QString(IMPERMISSIBLE_VALUE).arg(P_NAME).arg(QString(QJsonDocument(event).toJson(QJsonDocument::Compact))) .arg(QString("Идентификтор 'name' должен быть задан как текст. Смотри руководство разработчика."))); } else throw sv::SvException(QString(IMPERMISSIBLE_VALUE).arg(P_EVENTS).arg(QString(QJsonDocument(event).toJson(QJsonDocument::Compact))) .arg(QString("Отсутствует идентификтор. Смотри руководство разработчика."))); modus::event::Filter filter = modus::event::Filter(entity, identifier, level, type); for(auto name: loggersNames){ filter.appendLogger(name); } filters.append(filter); } } return true; } catch(sv::SvException& e) { result = e.error; return false; } }*/ /*bool modus::MasterLogger::configure(modus::Entities* entities, modus::Configuration* configuration) { m_modus_configiration = configuration; m_modus_entities = entities; return parseConfig(); }*/ /*bool modus::MasterLogger::parseConfig() { if(m_modus_configiration->json().contains(P_LOGGERS)) { if(m_modus_configiration->json().value(P_LOGGERS).isArray()) { QJsonArray loggersArray = m_modus_configiration->json().value(P_LOGGERS).toArray(); for(auto logger : loggersArray) { QJsonObject obj = logger.toObject(); if(!loadLoggerPlugin(obj.value(P_PATH).toString(), obj.value(P_NAME).toString(), obj.value(P_PARAMS).toObject())) return false; } } } return true; }*/