Russian Qt Forum

Qt => Дополнительные компоненты => Тема начата: asvil от Апрель 19, 2010, 20:14



Название: 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
Далее:
*NIX
Код:
cd 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

После выше перечисленных манипуляций в зависимости от системы сборки необходимо добавить в файл Вашего проекта следующие строки:
qmake
Код:
CONFIG += log4qt 
cmake
Код:
find_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 пространство имен:
Код:
using namespace 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, где в зависимости от количество строк в таблице, будут удаляться более ранние по дате/времени сообщения.

    Цитата: SABROG
    Длинновато
    Не могу не согласиться. Для того, чтобы сохранить возможности перегруженных операторов "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.