Название: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: asvil от Апрель 19, 2010, 20:14
Авторство портирования данного проекта из log4j (http://logging.apache.org/log4j/ (http://logging.apache.org/log4j/)) принадлежит человеку по имени Martin Heinrich. Подробнее о данном проекте http://log4qt.sourceforge.net (http://log4qt.sourceforge.net). Я в свою очередь перевел проект на CMake систему сборки, а также добавил несколько функций. Кратко о возможностях: - Ведение нескольких журналов.
- Форматирование сообщений.
- Один и более методов вывода журнала:
- файл
- консоль
- отладочный вывод
- sql база данных
- Перехват qDebug, qWarning, qCritical, QFatal
Направления вывода сообщений: Быстрый старт требует от Вас наличия git'а и системы сборки cmake версии не ниже, чем 2.6. Скачиваем архив главной ветки проекта: http://gitorious.org/log4qt/log4qt/archive-tarball/master Или клонируем репозиторий: git clone git://gitorious.org/log4qt/log4qt.git Далее: *NIXcd log4qt cmake -DQT_USE_QTSQL=TRUE -DCMAKE_BUILD_TYPE=Release . make make install
WIN*cd log4qt cmake -DQT_USE_QTSQL=TRUE -DCMAKE_BUILD_TYPE=Release -G "MinGW Makefiles" . mingw32-make mingw32-make install
После выше перечисленных манипуляций в зависимости от системы сборки необходимо добавить в файл Вашего проекта следующие строки: qmakecmakefind_package(log4qt PATHS ${QT_MKSPECS_DIR}/cmake NO_DEFAULT_PATH) include_directories(${LOG4QT_INCLUDE_DIRS}) target_link_libraries(main ${QT_LIBRARIES} log4qt) Использование в проекте: Подключение заголовочных файлов: #include <Log4Qt/logmanager.h> #include <Log4Qt/simplelayout.h> #include <Log4Qt/consoleappender.h> #include <Log4Qt/databaselayout.h> #include <Log4Qt/databaseappender.h> #include <Log4Qt/ttcclayout.h> #include <Log4Qt/consoleappender.h>
Весь ниже перечисленный код использует Log4Qt пространство имен:
[/b] Загружаем файл перевода для библиотеки: QTranslator trans; trans.load("log4qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath)); app.installTranslator(&trans); Инициализация главного журнала: LogManager::rootLogger(); Перехват qDebug, qWarning... LogManager::setHandleQtMessages(true); Создание объекта, форматирующего сообщения в простом виде (тип, имя журнала, сообщение): simpleLayout = new SimpleLayout(); simpleLayout->setName(QLatin1String("SimpleLayout")); Каждый объект должен быть активирован.simpleLayout->activateOptions();
Данный объект форматирует сообщение в строку содержащую все данные (дата/время, тип, имя журнала, поток, сообщение). В конструкторе задается формат вывода даты/времени. TTCCLayout *ttccLayout = new TTCCLayout(TTCCLayout::ISO8601); ttccLayout->setName(QLatin1String("TtccLayout")); ttccLayout->activateOptions();
Создание объекта выводящего сообщения в консоль. Данному объекту в конструкторе назначается объект форматирующий сообщения. ConsoleAppender *consoleAppender = new ConsoleAppender(simpleLayout, ConsoleAppender::STDOUT_TARGET); consoleAppender->setName(QLatin1String("ConsoleAppender")); consoleAppender->activateOptions(); Создание объекта генерирующего сигнал при возникновении сообщения. SignalAppender *signalAppeder = new SignalAppender(); signalAppeder->setName("SignalAppender"); Назначение объекта форматирующего сообщения. signalAppeder->setLayout(ttccLayout); signalAppeder->activateOptions(); Назначаем корневому журналу сообщений выводящие объекты: LogManager::rootLogger()->addAppender(d->signalAppeder); LogManager::rootLogger()->addAppender(d->consoleAppender); В системе есть один корневой журнал в которые приходят все сгенерированные сообщения и любое число дочерних журналов, в которые приходят только те сообщения, которые туда и отправлялись:) Объект журнала создавать не нужно, он создается автоматически при первом к нему обращении, например: LogManager::logger("SimpleLogger"); Создание системы ведения журнала сообщений в базе данных: Где-то в дебрях исходных текстов: QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL"); db.setDatabaseName("postgres"); db.open("postgres", "postgres")); db.exec("CREATE TABLE log_table ( time_stamp timestamp without time zone, logger text, thread text, _level text, message text ) WITH ( OIDS=FALSE );");
Инициализация форматирования и вывода сообщений в sql базу данных: DatabaseLayout *dbLayout = new DatabaseLayout(); Назначаем соответсвтия между структурой сообщения и sql таблицей: dbLayout->setTimeStampColumn("time_stamp"); dbLayout->setLoggerNameColumn("logger"); dbLayout->setThreadNameColumn("thread"); dbLayout->setLevelColumn("_level"); dbLayout->setMessageColumn("message"); Создаем объект вывода сообщений в базу данных. В конструкторе указывает имя таблицы, имя qt sql соединения. DatabaseAppender *dbAppender = new DatabaseAppender(dbLayout, "log_table", db.connectionName()); dbAppender->setName(QLatin1String("DatabaseAppender")); dbAppender->activateOptions(); Выводим журнал сообщений именуемый "Database" в базу данных, а также на консоль. LogManager::logger("Database")->addAppender(dbAppender); LogManager::logger("Database")->addAppender(consoleAppender); Теперь где угодно в *.cpp, подключив Log4Qt/logmanager.h, оставляем о себе знать: LogManager::logger("Database")->info("Message from " + Q_FUNC_INFO); Данное сообщение попадет в журнал Database и в корневой журнал. Журнал Database выводиться в sql базу данных, а также в консоль. Корневой журнал выводится в консоль, а также генерируется сигнал, оповещающий о получении сообщения. Создание вывода в файл. При достижении файлом определенного размера, будет выполняться его резервное копирование. RollingFileAppender *dbFileAppender = new RollingFileAppender(ttccLayout,"myapp.log", true); d->dbFileAppender->setName("FileAppender"); d->dbFileAppender->activateOptions(); d->dbFileAppender->setMaximumFileSize(1024*1024*10); // max file size 10 mb LogManager::logger("FileLogger")->addAppender(dbFileAppender); Кроме всеговышеперечисленного данные проект содержит возможность диамического создания журналов, объектов форматирования и вывода сообщений на основе QSettings. Но заглянув туда я увидел схему преобразования QSettings, грубо говоря, в log4j settings. Потом это log4j settings анализируется и с помощью фабрики классов создаются новые объекты. Q_INVOKABLE конструкторы не используются, что не очень удобно при создании новый классов вывода, форматирования сообщений. Вообщем на данную возможность ставку делать, на мой взгляд, не стоит. А также я не затрагивал систему фильтрации сообщений. P.S. Возможно я обманул Вас, в заголовке сообщения форума.
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: fland от Апрель 20, 2010, 19:23
как я понял основоной плюс по сравнению с qDebug/qError/etc - более удобная работа с БД?
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: asvil от Апрель 20, 2010, 22:56
Да вы правильно поняли. Смею поправить - скорее работа с БД просто есть. А используя без Log4Qt qDebug()... эту работу необходимо реализовывать. К основным плюсам также можно отнести: детализированность сообщения (время, поток, журнал, уровень (info, warning, debug), наличие неограниченного числа журналов, которые могут выводиться каждый в своем "направлении" (БД, консоль, файл). Работа с журналом сообщений сводится к нескольким действиям: - Открыть qt sql подключение
- Создать Log4Qt::DatabaseLayout
- Назначить соответствия имен столбцов с полями сообщения
Log4Qt::DatabaseLayout::set*Column(columnName); - Создать Log4Qt::DatabaseAppender
- Назначить qt sql подключение и имя таблицы
Log4Qt::DatabaseAppender::setConnection(connectionName); Log4Qt::DatabaseAppender::setTable(tableName);
- Применить созданный объект вывода (Log4Qt::DatabaseAppender) к любому журналу, получаемому вызовом:
Log4Qt::LogManager::logger(loggerName)::addAppender() или же корневому журналу, куда попадают все сообщения генерируемые в приложении: Log4Qt::LogManager::rootLogger()::addAppender() После чего все qDebug() заменить на Log4Qt::LogManager::logger("Имя подпроекта")->debug(QString("%1 - %2").arg(Q_FUNC_INFO,"исходное сообщение")) все qWarning() на Log4Qt::LogManager::logger("Имя подпроекта")->warn(QString("%1 - %2").arg(Q_FUNC_INFO,"исходное сообщение")) И т.д.
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: lit-uriy от Апрель 20, 2010, 23:35
а при задании размер журнала библиотека будет заниматься урезанием наиболее старых сообщений, а не всех?
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: SABROG от Апрель 20, 2010, 23:50
C++ (Qt) Log4Qt::LogManager::logger("Имя подпроекта")->debug(QString("%1 - %2").arg(Q_FUNC_INFO,"исходное сообщение"))
Длинновато :) Судя по всему вся прелесть перегруженности оператора << теряется и придется всё писать самому. Например вывод имен установленных флагов, названий перечислений, содержимое контейнеров...
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: asvil от Апрель 21, 2010, 09:19
а при задании размер журнала библиотека будет заниматься урезанием наиболее старых сообщений, а не всех?
По логике проекта данной функцией должен заниматься выводящий объект (Log4Qt::*Appender). *RollingFileAppender реализовывают резервное копирование более ранних сообщений в отдельный файл. В DatabaseAppender я не реализовал данную функцию. Проблема заключается в том, что по усмотрению программиста, DatabaseLayout может не соотносить дату/время сообщения с колонкой таблицы, и соответственно дата/время сохраняться не будет. Поэтому удалить ранее внесенные записи в таблице я не могу. Так как я пользуюсь postgresql, то при необходимости, скорее реализую данную функцию в триггере. Если sql-путь решения проблемы не удобен, я могу назначить "обязательное" соотнесение столбца для даты и поля сообщения журнала, а также создать RollingDatabaseAppender, где в зависимости от количество строк в таблице, будут удаляться более ранние по дате/времени сообщения. Длинновато Не могу не согласиться. Для того, чтобы сохранить возможности перегруженных операторов "QDebug() <<", библиотекой регистрируется "перехватчик" данных сообщений. Для этого в инициализационной части Вашего проекта необходимо вызвать: Log4Qt::LogManager::setHandleQtMessages(true); В результате qDebug() и др. будут перенаправляться в журнал с именем Qt. Доступ к этому журналу можно получить данной строкой: Log4Qt::LogManager::qtLogger() Данный журнал как и любой другой можно направить в интересующем из доступных направлений. На будущее скажу что реализация класса, выводящего сообщения сводится к переопределению одного метода. В библиотеке имеется TextAppender, который выводит сообщения в QTextStream, что позволяет назначить свой поток вывода, унаследованный от вышеназванного класса. Я умалчиваю о классе форматирующем сообщения в зависимости от строки-шаблона Log4Qt::PatternLayout. У меня не дошли до него руки. А если быть точнее, что-то в нем не заработало с первого раза, и я перенес свое внимание на другие проблемы.
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: SABROG от Апрель 21, 2010, 09:53
А это уже интересно. Планируется ли в Log4Qt добавить "цветной" вывод логов в консоль (как в CMake)? Где-то уже на этом форуме поднималась тема как это реализовать для Windows и Linux.
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: kuzulis от Апрель 21, 2010, 11:02
А это уже интересно. Планируется ли в Log4Qt добавить "цветной" вывод логов в консоль (как в CMake)? Где-то уже на этом форуме поднималась тема как это реализовать для Windows и Linux. дадада, и чтобы можно выло устанавливать любой цвет на любые типы сообщений!
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: asvil от Апрель 21, 2010, 15:56
Я не нуждаюсь в цветном выводе в консоль, так как я пользуюсь выводом "в сигнал", и в последствии вывожу в QPlainTextEdit. При выводе в QPlainTextEdit я задаю цвет. Я читал "цветной вывод", и на основе некоторых сообщений сделал выводящий класс, унаследованный от Log4Qt::ConsoleAppender. Не придумав ничего лучше, я реализовал цветной вывод в зависимости от регулярного выражения сравниваемого с уже отформатированным сообщением. Я решил, что если сделаю что-то с более сложным интерфейсом, где для каждого составляющей сообщения будет назначаться свой цвет, то мощность и сложность использования такого решения будет излишней для цели. Проблема, с которой я столкнулся, заключается в том, что в Ubuntu 9.10, я не смог назначить background color. А также я прошу заинтересовавшихся протестировать класс в win среде. Использование цветного вывода сводится к нескольким шагам. - Создать объект форматирующий сообщения
- Создать объект выводящий сообщения в цвете
- Создать карту цветов. Карта цветов - это: QHash<QString, QPair<int, int> >. Где QString используется в качество шаблона для QRegExp, QPair::first является цветом шрифта, QPair::second - background color.Например:
ColorConsoleAppender::ColorMap colorMap; colorMap[".*Qt.*"] = QPair<int,int>(ColorConsoleAppender::ForegroundLightGreen, ColorConsoleAppender::BackgroundBlue); colorMap[".*INFO.*Logger - .*"] = QPair<int,int>(ColorConsoleAppender::ForegroundLightGreen, ColorConsoleAppender::BackgroundBlue); colorMap[".*WARN.*Logger.*"] = QPair<int,int>(ColorConsoleAppender::ForegroundLightRed, ColorConsoleAppender::BackgroundBlue);
- Назначить объекту выводящему сообщения карту цветов. Для этого служит функция:
Log4Qt::ColorConsoleAppender::setColorMap() - Назначить получившийся объект вывода, любому понравившемуся журналу с помощью:
Log4Qt::LogManager::logger()::addAppender() Заголовочный файл colorconsoleappender.h /****************************************************************************** * * package: log4qt * file: colorconsoleappender.h * created: March 2010 * author: Filonenko Michael * * * Copyright 2010 Filonenko Michael * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/
#ifndef _COLORCONSOLEAPPENDER_H #define _COLORCONSOLEAPPENDER_H
/****************************************************************************** * Dependencies ******************************************************************************/
#include "consoleappender.h"
#include <QtCore/QHash> #include <QtCore/QPair> #include <QtCore/QRegExp>
/****************************************************************************** * Declarations ******************************************************************************/
class QFile; class QTextStream;
namespace Log4Qt {
/*! * \brief The class ConsoleAppender appends to stdout or stderr. * * \note All the functions declared in this class are thread-safe. * * \note The ownership and lifetime of objects of this class are managed. * See \ref Ownership "Object ownership" for more details. */ class LOG4QT_EXPORT ColorConsoleAppender : public ConsoleAppender { Q_OBJECT
Q_ENUMS(ForegroundColor BackgroundColor Colors)
public: typedef QHash<QString, QPair<int, int> > ColorMap; #if defined(linux) || defined(__linux) || defined(__linux__) || defined(Q_OS_UNIX) enum ForegroundColor { ForegroundLightBlack = 30 , ForegroundLightRed = 31 , ForegroundLightGreen = 32 , ForegroundLightYellow = 33 , ForegroundLightBlue = 34 , ForegroundLightPurple = 35 , ForegroundLightCyan = 36 , ForegroundLightWhite = 37 };
enum BackgroundColor { BackgroundBlack = 40 , BackgroundRed = 41 , BackgroundGreen = 42 , BackgroundYellow = 43 , BackgroundBlue = 44 , BackgroundPurple = 45 , BackgroundCyan = 46 , BackgroundWhite = 47 };
enum Colors { Default = 0 , Bright = 1 , Blink = 5 }; #endif
#if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32) enum ForegroundColor { ForegroundLightBlack = 0 , ForegroundLightRed = 4 , ForegroundLightGreen = 2 , ForegroundLightYellow = 14 , ForegroundLightBlue = 1 , ForegroundLightPurple = 5 , ForegroundLightCyan = 11 , ForegroundLightWhite = 15 };
enum BackgroundColor { BackgroundBlack = 0 , BackgroundRed = 4 , BackgroundGreen = 2 , BackgroundYellow = 14 , BackgroundBlue = 1 , BackgroundPurple = 5 , BackgroundCyan = 11 , BackgroundWhite = 15 };
enum Colors { Default = 0 , Bright = +8 , Blink = 6 }; #endif ColorConsoleAppender(QObject *pParent = 0); ColorConsoleAppender(Layout *pLayout, QObject *pParent = 0); ColorConsoleAppender(Layout *pLayout, const QString &rTarget, QObject *pParent = 0);
/*! * Creates a ConsoleAppender with the layout \a pLayout, the target * value specified by the \a target constant and the parent * \a pParent. */ ColorConsoleAppender(Layout *pLayout, Target target, QObject *pParent = 0);
void setColorMap(const ColorMap& map);
protected: virtual void append(const LoggingEvent& rEvent);
private: ColorMap colorMap; };
/************************************************************************** * Operators, Helper **************************************************************************/
/************************************************************************** * Inline **************************************************************************/
} // namespace Log4Qt
// Q_DECLARE_TYPEINFO(::ConsoleAppender, Q_COMPLEX_TYPE); // Use default
#endif // _COLORCONSOLEAPPENDER_H
Файл с реализацией класса colorconsoleappender.cpp: /****************************************************************************** * * package: log4qt * file: colorconsoleappender.cpp * created: March 2010 * author: Filonenko Michael * * * Copyright 2010 Filonenko Michael * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/
/****************************************************************************** * Dependencies ******************************************************************************/
#include "colorconsoleappender.h"
#include <QtCore/QTextStream>
#include <Log4Qt/loggingevent.h> #include <Log4Qt/layout.h> #include <Log4Qt/helpers/datetime.h>
#if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32) #include <windows.h> #endif
namespace Log4Qt {
/************************************************************************** * Declarations **************************************************************************/
/************************************************************************** * C helper functions **************************************************************************/
/************************************************************************** * Class implementation: ColorConsoleAppender **************************************************************************/
ColorConsoleAppender::ColorConsoleAppender(QObject *pParent) : ConsoleAppender(pParent) { }
ColorConsoleAppender::ColorConsoleAppender(Layout *pLayout, QObject *pParent) : ConsoleAppender(pLayout, pParent) { }
ColorConsoleAppender::ColorConsoleAppender(Layout *pLayout, const QString &rTarget, QObject *pParent) : ConsoleAppender(pLayout, rTarget, pParent) {}
ColorConsoleAppender::ColorConsoleAppender(Layout *pLayout, Target target, QObject *pParent) : ConsoleAppender(pLayout, target, pParent) { }
void ColorConsoleAppender::append(const LoggingEvent &rEvent) {
// форматируем собщение QString message = layout()->format(rEvent);
QRegExp rexp;
// if we are in win* #if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32) // Getting pointer to console HANDLE hConsole; if (target() == "STDOUT_TARGET") hConsole = GetStdHandle(STD_OUTPUT_HANDLE); else if (target() == "STDERR_TARGET") hConsole = GetStdHandle(STD_ERROR_HANDLE);
// save colors CONSOLE_SCREEN_BUFFER_INFO cbi = {sizeof(cbi)}; GetConsoleScreenBufferInfo(hConsole,&cbi);
ColorMap::ConstIterator colorMapIt = colorMap.constBegin(); ColorMap::ConstIterator colorMapEnd = colorMap.constEnd();
for(;colorMapIt != colorMapEnd; ++colorMapIt) { rexp.setPattern(colorMapIt.key()); if (rexp.exactMatch(message)) { // load colors SetConsoleTextAttribute(hConsole, colorMapIt.value().second*16 + colorMapIt.value().first); break; } }
// print message to output console writer()->operator <<(message);
// load old colors SetConsoleTextAttribute(hConsole, cbi.wAttributes); #endif // #if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32)
// if we are in *nix #if defined(linux) || defined(__linux) || defined(__linux__) || defined(Q_OS_UNIX)
ColorMap::ConstIterator colorMapIt = colorMap.constBegin(); ColorMap::ConstIterator colorMapEnd = colorMap.constEnd();
for(;colorMapIt != colorMapEnd; ++colorMapIt) { rexp.setPattern(colorMapIt.key()); if (rexp.exactMatch(message)) { message.prepend(QString("\e[%1m").arg(QString::number(colorMapIt.value().first))); message.append("\e[0m"); break; } }
writer()->operator <<(message);
#endif //#if defined(linux) || defined(__linux) || defined(__linux__) || defined(Q_OS_UNIX)
// обрабатываем ошибки, по умолчанию метод не реализован if (handleIoErrors()) return;
if (immediateFlush()) { writer()->flush(); if (handleIoErrors()) return; } }
void ColorConsoleAppender::setColorMap(const ColorMap& map) { colorMap = map; }
/****************************************************************************** * Implementation: Operators, Helper ******************************************************************************/
} // namespace Log4Qt
Использование в проекте: #include "colorconsoleappender.h" .............................
SimpleTimeLayout *timeLayout = new SimpleTimeLayout(); timeLayout->setName("TimeLayout"); timeLayout->activateOptions();
ColorConsoleAppender *colorAppender = new ColorConsoleAppender(timeLayout, ColorConsoleAppender::STDOUT_TARGET); colorAppender->setName("ColorAppender"); colorAppender->activateOptions();
ColorConsoleAppender::ColorMap colorMap; colorMap[".*Qt.*"] = QPair<int,int>(ColorConsoleAppender::ForegroundLightGreen, ColorConsoleAppender::BackgroundBlue); colorMap[".*INFO.*Logger - .*"] = QPair<int,int>(ColorConsoleAppender::ForegroundLightGreen, ColorConsoleAppender::BackgroundBlue); colorMap[".*WARN.*Logger.*"] = QPair<int,int>(ColorConsoleAppender::ForegroundLightRed, ColorConsoleAppender::BackgroundBlue); colorAppender->setColorMap(colorMap);
LogManager::rootLogger()->addAppender(colorAppender); LogManager::rootLogger(); qDebug() << "From qDebug() ";
LogManager::logger("Logger")->info("First message");
LogManager::logger("Logger")->warn("Warn message");
LogManager::logger("SecondLogger")->warn("Second message");
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: asvil от Апрель 21, 2010, 15:58
Проект ColorConsoleAppender, использующий CMake >= 2.6.
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: SABROG от Апрель 21, 2010, 16:41
Чего-то не могу собрать: [ 75%] Building CXX object CMakeFiles/main.dir/colorconsoleappender.cpp.obj c:\mingw\bin\g++.exe -DQT_DLL -DQT_GUI_LIB -DQT_SQL_LIB -DQT_CORE_LIB -DQT_DEBUG -g -IC:\SABROG\colorappender -IC:\SABROG\qt-everywhere-opensource-src-4.6.2\include -IC:\SABROG\qt-everywhere-opensource-src-4.6.2\include\QtGui -IC:\SABROG\ qt-everywhere-opensource-src-4.6.2\include\QtSql -IC:\SABROG\qt-everywhere-opensource-src-4.6.2\include\QtCore -IC:\SABROG\qt-everywhere-opensource-src-4.6.2\include\Log4Qt -o CMakeFiles\main.dir\colorconsoleappender.cpp.obj -c C:\SABROG\colorappender\colorconsoleappender.cpp C:\SABROG\colorappender\colorconsoleappender.cpp:63: warning: 'Log4Qt::ColorConsoleAppender::ColorConsoleAppender(QObject*)' redeclared without dllimport attribute: previous dllimport ignored C:\SABROG\colorappender\colorconsoleappender.cpp:69: warning: 'Log4Qt::ColorConsoleAppender::ColorConsoleAppender(Log4Qt::Layout*, QObject*)' redeclared without dllimport attribute: previous dllimport ignored C:\SABROG\colorappender\colorconsoleappender.cpp:76: warning: 'Log4Qt::ColorConsoleAppender::ColorConsoleAppender(Log4Qt::Layout*, const QString&, QObject*)' redeclared without dllimport attribute: previous dllimport ignored C:\SABROG\colorappender\colorconsoleappender.cpp:83: warning: 'Log4Qt::ColorConsoleAppender::ColorConsoleAppender(Log4Qt::Layout*, Log4Qt::ConsoleAppender::Target, QObject*)' redeclared without dllimport attribute: previous dllimport ignored C:\SABROG\colorappender\colorconsoleappender.cpp:91: warning: 'virtual void Log4Qt::ColorConsoleAppender::append(const Log4Qt::LoggingEvent&)' redeclared without dllimport attribute: previous dllimport ignored C:\SABROG\colorappender\colorconsoleappender.cpp:163: warning: 'void Log4Qt::ColorConsoleAppender::setColorMap(const QHash<QString, QPair<int, int> >&)' redeclared without dllimport attribute: previous dllimport ignored C:\CMake\bin\cmake.exe -E cmake_progress_report C:\SABROG\colorappender\CMakeFiles 3 [100%] Building CXX object CMakeFiles/main.dir/moc_colorconsoleappender.cxx.obj c:\mingw\bin\g++.exe -DQT_DLL -DQT_GUI_LIB -DQT_SQL_LIB -DQT_CORE_LIB -DQT_DEBUG -g -IC:\SABROG\colorappender -IC:\SABROG\qt-everywhere-opensource-src-4.6.2\include -IC:\SABROG\qt-everywhere-opensource-src-4.6.2\include\QtGui -IC:\SABROG\ qt-everywhere-opensource-src-4.6.2\include\QtSql -IC:\SABROG\qt-everywhere-opensource-src-4.6.2\include\QtCore -IC:\SABROG\qt-everywhere-opensource-src-4.6.2\include\Log4Qt -o CMakeFiles\main.dir\moc_colorconsoleappender.cxx.obj -c C:\SABROG\colorappender\moc_colorconsoleappender.cxx C:\SABROG\colorappender\moc_colorconsoleappender.cxx:76: warning: 'Log4Qt::ColorConsoleAppender::staticMetaObject' redeclared without dllimport attribute afterbeing referenced with dll linkage C:\SABROG\colorappender\moc_colorconsoleappender.cxx:85: warning: 'virtual const QMetaObject* Log4Qt::ColorConsoleAppender::metaObject() const' redeclared without dllimport attribute: previous dllimport ignored C:\SABROG\colorappender\moc_colorconsoleappender.cxx:90: warning: 'virtual void* Log4Qt::ColorConsoleAppender::qt_metacast(const char*)' redeclared without dllimport attribute: previous dllimport ignored C:\SABROG\colorappender\moc_colorconsoleappender.cxx:98: warning: 'virtual int Log4Qt::ColorConsoleAppender::qt_metacall(QMetaObject::Call, int, void**)' redeclared without dllimport attribute: previous dllimport ignored Linking CXX executable main.exe C:\CMake\bin\cmake.exe -E cmake_link_script CMakeFiles\main.dir\link.txt --verbose=1 c:\mingw\bin\g++.exe -g CMakeFiles\main.dir\main.cpp.obj CMakeFiles\main.dir\colorconsoleappender.cpp.obj CMakeFiles\main.dir\moc_colorconsoleappender.cxx.obj -o main.exe -Wl,--out-implib,libmain.dll.a -Wl,--major-image-version,0,--minor-image-version,0 C:\SABROG\qt-everywhere-opensource-src-4.6.2\lib\libQtGuid4.a C:\SABROG\qt-everywhere-opensource-src-4.6.2\lib\libQtSqld4.a C:\SABROG\qt-everywhere-opensource-src-4.6.2\lib\libQtCored4.a C:\SABROG\qt-everywhere-opensource-src-4.6.2\lib\liblog4qt.dll.a C:\SABROG\qt-everywhere-opensource-src-4.6.2\lib\libQtGui4.a C:\SABROG\qt-everywhere-opensource-src-4.6.2\lib\libQtSql4.a C:\SABROG\qt-everywhere-opensource-src-4.6.2\lib\libQtCore4.a -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 CMakeFiles\main.dir\main.cpp.obj: In function `main': C:/SABROG/colorappender/main.cpp:42: undefined reference to `_imp___ZN6Log4Qt20ColorConsoleAppenderC1EPNS_6LayoutENS_15ConsoleAppender6TargetEP7QObject' C:/SABROG/colorappender/main.cpp:53: undefined reference to `_imp___ZN6Log4Qt20ColorConsoleAppender11setColorMapERK5QHashI7QString5QPairIiiEE' CMakeFiles\main.dir\colorconsoleappender.cpp.obj: In function `ColorConsoleAppender': C:/SABROG/colorappender/colorconsoleappender.cpp:64: undefined reference to `_imp___ZTVN6Log4Qt20ColorConsoleAppenderE' C:/SABROG/colorappender/colorconsoleappender.cpp:64: undefined reference to `_imp___ZTVN6Log4Qt20ColorConsoleAppenderE' C:/SABROG/colorappender/colorconsoleappender.cpp:71: undefined reference to `_imp___ZTVN6Log4Qt20ColorConsoleAppenderE' C:/SABROG/colorappender/colorconsoleappender.cpp:71: undefined reference to `_imp___ZTVN6Log4Qt20ColorConsoleAppenderE' C:/SABROG/colorappender/colorconsoleappender.cpp:79: undefined reference to `_imp___ZTVN6Log4Qt20ColorConsoleAppenderE' CMakeFiles\main.dir\colorconsoleappender.cpp.obj:C:/SABROG/colorappender/colorconsoleappender.cpp:79: more undefined references to `_imp___ZTVN6Log4Qt20ColorConsoleAppenderE' follow CMakeFiles\main.dir\moc_colorconsoleappender.cxx.obj:C:/SABROG/colorappender/moc_colorconsoleappender.cxx:87: undefined reference to `_imp___ZN6Log4Qt20ColorConsoleAppender16staticMetaObjectE' CMakeFiles\main.dir\moc_colorconsoleappender.cxx.obj: In function `_static_initialization_and_destruction_0': C:/SABROG/colorappender/moc_colorconsoleappender.cxx:79: undefined reference to`_imp___ZN6Log4Qt20ColorConsoleAppender16staticMetaObjectE' collect2: ld returned 1 exit status mingw32-make[2]: *** [main.exe] Error 1 mingw32-make[2]: Leaving directory `C:/SABROG/colorappender' mingw32-make[1]: *** [CMakeFiles/main.dir/all] Error 2 mingw32-make[1]: Leaving directory `C:/SABROG/colorappender' mingw32-make: *** [all] Error 2
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: asvil от Апрель 21, 2010, 19:52
Прошу прощения, ориентировался на включение класса в "коробку". Необходимо удалить LOG4QT_EXPORT в определении класса: class LOG4QT_EXPORT ColorConsoleAppender : public ConsoleAppender
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: Prm от Апрель 22, 2010, 08:00
Еще было бы неплохо добавить уровни отладки(журналирования). Т.е. настроить систему журналов так, чтобы в нее попадали сообщения с уровнем <= требуемый.
Например, пусть имеется 3 уровня отладки: 0 - высший приоритет (для критических сообщений) 1 - средний приоритет (обычные сообщения) 2 - низший приоритет
Пример использования: Пусть имеется объект работы с последовательным (ну или любым другим) портом. Информацию о событиях типа порт открыт/закрыт можно добавлять в журнал со средним приоритетом, распечатку принятых/отправляемых данных добавлять с низшим приоритетом. В процессе разработки объекта систему журналирования настраиваем на низший уровень приорита, видим полную картину работы объекта. Отладили программу - выставляем средний уровень и контролируем лишь основные события.
Кроме того, может быть полезен TCP лог (часто им пользуюсь), т.к. не всегда удобно в реал-тайме осуществлять работу с программой и контролировать ее текущее состояние (модальные окна могут перекрывать отладочный лог). А так прога работает, отладочные сообщения через сокеты отправляются в другую прогу, которая их отображает.
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: asvil от Апрель 22, 2010, 10:16
Уровни отладки сообщений уже имеются, просто не были освещены мной. Первый путь использования: Порядок уровней сообщений: enum Value { /*! NULL_INT is used for no level has been specified */ NULL_INT = 0, ALL_INT = 32, TRACE_INT = 64, DEBUG_INT = 96, // qDebug() INFO_INT = 128, WARN_INT = 150, // qWarning() ERROR_INT = 182, // qCritical() FATAL_INT = 214, // qFatal() OFF_INT = 255 };
LogManager::logger("Logger")->setLevel(Level(Level::INFO_INT));
После данной строки в журнал "Logger" будут попадать только сообщения НИЖЕ (или большие по значению) данного включительно, т.е. INFO, WARN, ERROR, FATAL. Второй путь использования более глобальный, применяется для всех журналов: Log4Qt::LogManager::setTreshold(Level); Действие данной функции аналогично действию вышеназванной. В журналах будут регистрироваться только сообщения НИЖЕ (или большие по значению) установленного уровня включительно. Третий путь самый локальный: установка уровня сообщений для выводящего объекта: Log4Qt::*Appender::setThreshold(Level) Prm, я надеюсь, что Вам подходят данные функции. Еще один путь взаимодействия с уровнями сообщений: - Создание объекта фильтрующего сообщения по уровню
- Настройка объекта
- Установка данного объекта в качестве фильтра в объект выводящий сообщения
В выбранном направлении будут выводиться отфильтрованные сообщения. На данный момент существует два класса фильтрующих по уровню: LevelMatchFilter и LevelRangeFilter. Названия говорят сами за себя. Допустим есть задача не выводить сообщения отладочного типа: // фильтр LevelMatchFilter *filter = new LevelMatchFilter(); // не принимать сообщения filter->setAcceptOnMatch(false); // с данным уровнем filter->setLevelToMatch(Level(Level::DEBUG_INT)); //filter->activateOptions(); // не требуется
// добавляем фильтр объекту colorAppender->addFilter(filter);
После данных манипуляций сообщения отладочного уровня выводиться с помощью colorAppender не будут.
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: SABROG от Апрель 22, 2010, 11:46
Чего-то я понять не могу этот CMake. Даю команду: cmake -DQT_USE_QTSQL=TRUE -DCMAKE_BUILD_TYPE=Release -G"MinGW Makefiles" mingw32-make
На выходе получается .exe'шник требующий debug версии Qt'шных библиотек, в то время как liblog4qt.dll требует релизных. --- Понял, кое-кто жестко задал тип билда, так что он даже не переопределяется... set(CMAKE_BUILD_TYPE Debug)
--- Не работают цвета в виндовой консоли: (http://img541.imageshack.us/img541/3639/colorconsole.png) Ни когда запускаешь командой, ни когда двойным кликом на .exe'шник.
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: asvil от Апрель 22, 2010, 12:39
Предлагаемая архитектура передачи сообщений, использую сетевую подсистему QT Framework не является единственной возможной. Исходные алгоритмы не претендуют на оптимальность.Для того чтобы передать сообщение "по сети" необходимо выполнить следующие действия: - Создать приложение-сервер принимающее сообщения
- В главном приложении создать Log4Qt::WriterAppender, выводящий сообщения в QTcpSocket
Приложение сервер запускается, бесконечно долго ждет подключения, после установки подключения выводит все данные пришедшие по подключению в qDebug(), после разрыва соединения завершает работу. Исходный код состоит из одного файла main.cpp: #include <QtCore>
#include <QtNetwork>
int main(int argc, char** argv) { QCoreApplication app(argc, argv);
QTcpServer *server = new QTcpServer; // слушаем на всех интерфейсах порт, 10600 - log00 server->listen(QHostAddress::Any, 10600);
QTcpSocket *connection; // ждем подключения if (server->waitForNewConnection(-1)) { // получаем соект connection = server->nextPendingConnection();
// пока не поизойдет разрыва соединения while(true) { // ждем данных одну секунду if (connection->waitForReadyRead(1000)) // направляем все пришедшие данные в qDebug() qDebug() << connection->readAll(); // Если произошел разрыв, выходим из цикла if (connection->state() == QAbstractSocket::UnconnectedState) break; } }
// вычурно, но удобно QTimer::singleShot(1000, &app, SLOT(quit())); return app.exec(); }
Исходный код главного приложения, подвергаемого журналированию, также состоит из одного файла main.cpp: #include <QtCore>
#include <QtNetwork>
#include <Log4Qt/logmanager.h>
#include <Log4Qt/simpletimelayout.h>
#include <Log4Qt/consoleappender.h>
int main(int argc, char** argv) { using namespace Log4Qt; QCoreApplication app(argc, argv);
QTranslator trans; trans.load("log4qt_" + QLocale::system().name() , QLibraryInfo::location(QLibraryInfo::TranslationsPath));
qDebug() << "transl empty" << trans.isEmpty();
app.installTranslator(&trans);
LogManager::rootLogger();
LogManager::setHandleQtMessages(true);
// создаем объект форматирующий сообщения SimpleTimeLayout *timeLayout = new SimpleTimeLayout(); timeLayout->setName("TimeLayout"); timeLayout->activateOptions();
// выводим в консоль ConsoleAppender *console = new ConsoleAppender(timeLayout, ConsoleAppender::STDOUT_TARGET); console->setName("Console"); console->activateOptions();
LogManager::rootLogger()->addAppender(console);
// сокет для подключения QTcpSocket *socket = new QTcpSocket();
// подключаемся socket->connectToHost("localhost", 10600);
// Ждем 5 секунд if (socket->waitForConnected(50000)) { qDebug() << "Connected";
// Создаем текстовый поток, но основе сокета QTextStream *textStream = new QTextStream(socket);
// Создаем объект выводящий сообщения на основе текстового потока WriterAppender *socketAppender = new WriterAppender(timeLayout, textStream); socketAppender->setName("SocketAppender"); // обязательно активируем socketAppender->activateOptions();
// Добавляем вывод к журналу LogManager::rootLogger()->addAppender(socketAppender); } else qDebug() << "Not connected";
LogManager::rootLogger();
qDebug() << "From qDebug() ";
LogManager::startup();
LogManager::logger("Logger")->info("First message");
LogManager::logger("Logger")->warn("Warn message");
// ждем отправки данных 5 секунд socket->waitForBytesWritten(5000);
QTimer::singleShot(1000, &app, SLOT(quit()));
app.exec(); }
Создание выводящего объекта сводилось к следующим строкам: QTcpSocket *socket = new QTcpSocket(); socket->connectToHost("localhost", 10600); if (socket->waitForConnected(50000)) { QTextStream *textStream = new QTextStream(socket); WriterAppender *socketAppender = new WriterAppender(timeLayout, textStream); socketAppender->setName("SocketAppender"); socketAppender->activateOptions(); LogManager::rootLogger()->addAppender(socketAppender); }
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: asvil от Апрель 22, 2010, 13:57
В win* среде SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 1) не влияет на stdout. В colorconsoleappender.cpp необходимо изменить (выделено жирным): #if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32) .....
writer()->operator <<(messsage);..... #endif // #if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32)
на следующие строки: // print message to output console //writer()->operator <<(message); // MINI HACK in win stdout not friend with setConsoleTextAttribute DWORD res; WriteConsole(hConsole, message.toLatin1().data(), message.toLatin1().size(), &res, 0);
Совпадение констант цветов между win* и *nix лежит на совести французов.
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: SABROG от Апрель 22, 2010, 15:00
Во, теперь работает. Правда тускловато :) (http://img191.imageshack.us/img191/2068/colorconsole3.png) Заметил, что строка "красится" целиком. Возможно ли частичное "раскрашивание", как на некоторых строках CMake? Было бы здорово добавить некий аналог HTML тегов для цвета (правда для вывода в файл эти теги не нужны). Закомментировав эту строчку: C++ (Qt) writer()->operator <<(messsage);
Мы сводим на нет возможность перегрузки оператора <<?
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: asvil от Апрель 23, 2010, 21:32
Во, теперь работает. Правда тускловато :)
Небольшой "обходной путь": в win среде устновка 4 бита цвета увеличивает яркость. Например зеленый цвет с большей яркостью: (ColorConsoleAppender::ForegroundLightGreen | 8 ) Но в CMake не все цвета осветленные. Я еще не успел полностью сравнить палитру. Возможно ли частичное "раскрашивание", как на некоторых строках CMake
Используя класс ColorConsoleAppender невозможно. Я еще не придумал простую и удобною реализацию интерфеса класса для частичного раскрашивания. Реализация системы тегов порождает, как уже сказано, проблему вывода сообщений в других направлениях. Исходя из архитектуры проекта форматированием сообщений должен заниматься класс типа Log4Qt::*Layout, а выводом Log4Qt::*Appender. Для *nix такая логика подходит, так как Layout может вставить в некоторых местах QString "\e[ddm", а Appender впоследствии выведет это в консоль. В win* системах цвет выводимого сообщения необходимо менять вызовом функции и это создает небольшие трудности. Но лучше я поставлю вопрос по другому. Подойдет ли такой интерфейс? - Создаем объект форматирующий сообщения.
- Назначаем ему шаблон вывода. Шаблон вывода в свою очередь состоит из следующих возможных placeholders.
Параметры тегов в квадратных скобках необязательны.
- %t[time_format_str] - время, time_format_str шаблон вывода времени, применяемый QDateTime::toString()
- %l - уровень сообщения (Debug, Warn, Info и т.д.)
- %f - поток, в котором было сгенерировано сообщение
- %s - название журнала
- %m - текст сообщение
- %e[FG_COLOR[,BG_COLOR]][/rexp] - форматирование следующих символов цветом. Форматирование отменяется следующим тегом %e. Если тег %e вставлен без параметров устанавливается цвет по умолчанию. Если установлена строка rexp, то фоматирование строки цветом будет только в случае совпадения с регулярным выражением.
- Создаем объект осущесвтляющий цветной вывод в консоль.
- Назначаем выводящему объекту форматирующий объект
- Устанавливаем выводящий объект журналу
Мы сводим на нет возможность перегрузки оператора <<?
Нет, не сводим. Функция writer возвращает указатель на QTextStream и поэтому я использую явный вызов функции-оператора. Функциональность оператора в сочетании с qDebug() не нарушается.[/list]
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: SABROG от Апрель 23, 2010, 22:36
Подойдет ли такой интерфейс?
Думаю это сильно бы упростило работу с логами и укоротило код. Было бы полезным заготовить стандартные распространенные шаблоны, которые бы можно было использовать из "коробки".
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: asvil от Апрель 25, 2010, 11:07
Исходные коды log4qt были обновлены в репозитории. Все заинтересовавшиеся скачайте обновленную версию версию в виде тарбола master-ветки (http://gitorious.org/log4qt/log4qt/archive-tarball/master) или выполнив git pull в папке клонированного репозитория. Note:Интерфейс класса Log4Qt::ColorConsoleAppender был полностью изменен. Кроссплатформенный цветной вывод в консоль.Для того изменить цвет выводимой строки в *nix системах применяются esc-последовательности. Для win* я сделал небольшой парсер, меняющий цвета вывода в зависимости от встретившейся последовательности. Для того чтобы данной возможностью воспользоваться в log4qt необходимо: - Создать Log4Qt::PatternLayout.
- Задать шаблон форматирования сообщения.
- Создать Log4Qt::ColorConsoleAppender
- Назначить ему созданный PatternLayout
- "Активировать" ColorConsoleAppender
- Назначить какому-либо журналу созданный ColorConsoleAppender
Самое интересное здесь это шаблон форматирования. Итак, он может состоять из следующих тэгов обозначенных симоволом %, параметры тегов заключаются в фигурные скобки: - m - текст сообщения
- p - название уровня сообщения (WARN, DEBUG, INFO и т.д.)
- е - имя потока, в котором было сгенерировано сообщение.
- x - ndc name (не знаю)
- X - mdc name (не знаю)
- c{digit} - имя журнала сообщений, параметр digit должен быть представлен целым числов и является необязательным. Данный параметр указывает количество выводимых секций названия журнала начиная с конца названия. Секции в названии журнала разделяются знаком :: (два двоеточия).
- d{format} - дата/время, параметр format должен быть представлен строкой, используемой для форматирования времени методом QDateTime::toString(). Если данный параметр опущен, используется ISO8601.
- r - выводится время отсчитываемое с момента запуска программы.
- n - перевод строки (*nix - \n, win* - \r\n)
ESC-последовательность в C-строках начинается с символов: \e[ или \033[ и завершается симоволом m. Между данными символами перечисляются параметры, представленные цылыми числами, разделенными знаком ; (точка с запятой). Данные параметры назначают форматирование следующим символам строки, до тех пор пока следующая ESC-последовательность не изменит данное форматирование. Возможные параметры ESC-последовательности: - 0 - отменяет все форматирование
- 1 - увеличивает яркость цвета. А для *nix также делает шрифт жирным.
- 30-37 - назначает цвет шрифта
- 40-47 - назначает цвет фона
Палитра для *nix систем: (http://4.bp.blogspot.com/_133IIjOOGoE/S9L41D9LWKI/AAAAAAAAAAM/jyfFU-co5Us/s1600/colortable16.png) Палитра для win* систем: (http://2.bp.blogspot.com/_133IIjOOGoE/S9PnGLv4xzI/AAAAAAAAAAc/5y4sCtYwCac/s1600/winpalette_small.png) Пример использования всего вышеперечисленного: #include <QtCore/QCoreApplication>
#include <QtCore/QTimer>
#include <Log4Qt/patternlayout.h> #include <Log4Qt/colorconsoleappender.h> #include <Log4Qt/logmanager.h>
int main(int argc, char *argv[]) { QCoreApplication a(argc, argv);
using namespace Log4Qt;
PatternLayout *layout = new PatternLayout("\e[1;32m%d{dd.MM.yyyy hh:mm} \e[1;33m %p \e[44m%c [%t] - \e[47;1;31m%m\e[0m%n");
ColorConsoleAppender *appender = new ColorConsoleAppender(layout, ColorConsoleAppender::STDOUT_TARGET); appender->activateOptions();
LogManager::logger("Logger")->addAppender(appender);
LogManager::logger("Logger")->info("Colored info message");
QTimer::singleShot(1000, &a, SLOT(quit())); return a.exec(); }
Строка форматирования сообщения, используемая в программе: "\e[1;32m%d{dd.MM.yyyy hh:mm} \e[1;33m %p \e[44m%c [%t] - \e[47;1;31m%m\e[0m%n"Проект и скриншот работы программы прикреплен к сообщению. Использованные источники: http://www.frexx.de/xterm-256-notes/ (http://www.frexx.de/xterm-256-notes/) http://msdn.microsoft.com/en-us/library/ms682088(v=VS.85).aspx#_win32_character_attributes (http://msdn.microsoft.com/en-us/library/ms682088(v=VS.85).aspx#_win32_character_attributes)
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: SABROG от Апрель 25, 2010, 18:50
PatternLayout добавляется ко всему журналу. Можно ли как-то задать разные шаблоны для разных уровней сообщений одного журнала? LogManager::logger("Logger")->info("Colored info message"); // info - белый цвет например (шаблон 1) LogManager::logger("Logger")->warn("Colored warning message"); // warn - желтый цвет (шаблон 2)
и т.п. для всех этих методов разные цвета (fatal красный к примеру): debug() error() fatal() info() log() trace() warn()
Сделать что-то типа частичного наследования шаблона. Например не хотелось бы дублировать целиком шаблон, чтобы подкрасить только текст (%m) другим цветом или какую-либо другую часть при другом уровне сообщения: "\e[1;32m%d{dd.MM.yyyy hh:mm} \e[1;33m %p \e[44m%c [%t] - \e[47;1;31m%m\e[0m%n" То есть как это сделано в Style Sheet's Qt: CSS ClassName { color: red; border: 1px; } ClassName::sub-control { color: green; background: black; }
Соответственно срабатывают сразу 2 правила - общее и частное. CSS Logger { color: white; background: black; } Logger::level::info { color: white; } Logger::level::warn { color: yellow; }
Название: Re: Log4Qt - система ведения журналов сообщений за несколько минут
Отправлено: asvil от Апрель 25, 2010, 21:57
Пока можно задать разные шаблоны для разных уровней только создав n-ое количество PatternLayout, ColorConsoleAppender, LevelMatchFilter. На данный момент для того, чтобы выполнить форматирование в зависимости от полей сообщения, я могу предложить только наследование класса Log4Qt::Layout с последующим переопределением метода QString format(const LoggingEvent& rEvent). Пример класса (colorlayout.h): #include <QtCore/QHash> #include <Log4Qt/layout.h>
namespace Log4Qt { class ColorLayout : public Layout { Q_OBJECT public: ColorLayout(QObject* parent = 0);
virtual QString format(const LoggingEvent &rEvent);
protected: virtual QDebug debug(QDebug &rDebug) const; };
}
Пример класса (colorlayout.cpp): #include "colorlayout.h" #include <QtCore/QDebug>
#include <Log4Qt/loggingevent.h> #include <Log4Qt/loggingevent.h> #include <Log4Qt/helpers/datetime.h>
namespace Log4Qt { ColorLayout::ColorLayout(QObject *parent) :Layout(parent) {}
QString ColorLayout::format(const LoggingEvent &rEvent) { QString message; message += DateTime::fromMilliSeconds(rEvent.timeStamp()).toString("dd.MM.yyyy hh:mm"); message += " "; if (rEvent.level().toInt() == Level::FATAL_INT) message += "\e[1;31m"; message += rEvent.level().toString(); message += " "; message += rEvent.loggerName(); message += " ["; message += rEvent.threadName(); message += "] - "; message += rEvent.message(); message += "\e[0m"; message += endOfLine(); return message; }
QDebug ColorLayout::debug(QDebug &rDebug) const { rDebug.nospace() << "ColorLayout(" << "name:" << objectName() << ")"; return rDebug.space(); } }
Назначать объект данного класса необходимо объекту ColorConsoleAppender. Данный способ является наиболее универсальным и быстрым, так как алгоритм форматирования может быть сколь угодно сложным и создание класса не занимает много времени. Единственным минусом является невозможность динамического преобразования формата вывода. Но это проблема может быть решена с помощью QtScriptBindingsGenerator.
|