Класс малого регистратора - PullRequest
27 голосов
/ 17 февраля 2011

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

Ответы [ 8 ]

39 голосов
/ 17 февраля 2011

Я настоятельно рекомендую эту простую систему регистрации: http://www.drdobbs.com/cpp/201804215. Она состоит из одного заголовочного файла. Я успешно использовал его в Linux, Windows и Mac OS X.

Вы пишете в журнал так:

FILE_LOG(logWARNING) << "Ops, variable x should be " << expectedX << "; is " << realX;

Мне очень нравится синтаксис потока. Это ненавязчиво, небезопасно и выразительно. Инфраструктура ведения журнала автоматически добавляет \n в конце строки, плюс дату, время и отступ.

Настройка журналов довольно проста:

FILELog::ReportingLevel() = logDEBUG3;
FILE* log_fd = fopen( "mylogfile.txt", "w" );
Output2FILE::Stream() = log_fd;

Эта структура также легко расширяется. На работе мы недавно внесли некоторые изменения, чтобы теперь он использовал std::ofstream вместо FILE*. В результате теперь мы можем добавлять полезные функции, такие как шифрование журналов, путем объединения потоков.

17 голосов
/ 28 августа 2015

Для тех, кому нужно простое решение, я рекомендую: easylogging ++

Только библиотека с одним заголовком C ++.Он чрезвычайно легкий, прочный, быстродействующий, безопасный для резьбы и типа и состоит из множества встроенных функций.Это дает возможность писать логи в своем собственном настроенном формате.Он также обеспечивает поддержку регистрации ваших классов, сторонних библиотек, STL и сторонних контейнеров и т. Д.

В этой библиотеке есть все встроенные средства для предотвращения использования внешних библиотек.

Простой пример: (более сложные примеры доступны по ссылке выше).

#include "easylogging++.h"

INITIALIZE_EASYLOGGINGPP

int main(int argv, char* argc[]) {
   LOG(INFO) << "My first info log using default logger";
   return 0;
}

Пример вывода внутри класса:

2015-08-28 10: 38: 45 900 DEBUG[по умолчанию] [user @ localhost] [Config :: Config (const string)] [src / Config.cpp: 7] Чтение конфигурационного файла: 'config.json'

Я пробовал log4cpp и boost:: log, но они не так просты, как этот.

ДОПОЛНИТЕЛЬНОЕ СОДЕРЖАНИЕ: минимальная версия - заголовок LOG

Я создал небольшой код для еще более простых приложений, основанный на easylogging, но не требует инициализациизнать, что это, вероятно, не потокобезопасно).Вот код:

/* 
 * File:   Log.h
 * Author: Alberto Lepe <dev@alepe.com>
 *
 * Created on December 1, 2015, 6:00 PM
 */

#ifndef LOG_H
#define LOG_H

#include <iostream>

using namespace std;

enum typelog {
    DEBUG,
    INFO,
    WARN,
    ERROR
};

struct structlog {
    bool headers = false;
    typelog level = WARN;
};

extern structlog LOGCFG;

class LOG {
public:
    LOG() {}
    LOG(typelog type) {
        msglevel = type;
        if(LOGCFG.headers) {
            operator << ("["+getLabel(type)+"]");
        }
    }
    ~LOG() {
        if(opened) {
            cout << endl;
        }
        opened = false;
    }
    template<class T>
    LOG &operator<<(const T &msg) {
        if(msglevel >= LOGCFG.level) {
            cout << msg;
            opened = true;
        }
        return *this;
    }
private:
    bool opened = false;
    typelog msglevel = DEBUG;
    inline string getLabel(typelog type) {
        string label;
        switch(type) {
            case DEBUG: label = "DEBUG"; break;
            case INFO:  label = "INFO "; break;
            case WARN:  label = "WARN "; break;
            case ERROR: label = "ERROR"; break;
        }
        return label;
    }
};

#endif  /* LOG_H */

Использование:

#include "Log.h"

int main(int argc, char** argv) {
    //Config: -----(optional)----
    structlog LOGCFG = {};
    LOGCFG.headers = false; 
    LOGCFG.level = DEBUG;
    //---------------------------
    LOG(INFO) << "Main executed with " << (argc - 1) << " arguments";
}

Этот код печатает сообщение, используя «cout», но вы можете изменить его на «cerr» или добавить файл,и т.д. Я надеюсь, что это полезно для кого-то.(Примечание: я ни в коем случае не эксперт по C ++, поэтому этот код может взорваться в крайних случаях).

8 голосов
/ 17 июля 2016

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

https://github.com/gabime/spdlog - это то, что мне нравится. Чистый синтаксис, обрабатывает все типичные использования. Быстро и мало. например для файлового регистратора это:

auto my_logger = spd::basic_logger_mt("basic_logger", "logs/basic.txt");
my_logger->info("Some log message");
7 голосов
/ 23 мая 2015

Рекомендую попробовать библиотеку plog (я автор).Это около 1000 строк кода, только заголовок и прост в использовании:

#include <plog/Log.h>

int main()
{
    plog::init(plog::debug, "Sample.log");

    LOGD << "Hello log!";
    LOGD_IF(true) << "conditional logging";
    return 0;
}
2 голосов
/ 17 февраля 2011

Если у вас нет ограничений по размеру проекта, и вы ожидаете, что он будет жить долго, я бы посоветовал взглянуть на Apache Log4cxx . Это не маленькая библиотека, но она поддерживает практически все, что вы когда-либо хотели (включая некоторые вещи, о которых вы даже не подозревали) в журналировании, и она переносима.

В любом более крупном проекте рано или поздно вы захотите, чтобы ваше решение для ведения журналов делало больше, чем «класс малого регистратора», поэтому, действительно, зачем изобретать велосипед.

1 голос
/ 17 февраля 2011

В этом вопросе есть моя попытка с какой-то фантазией. Это полностью стандартный C ++ и не делает никаких предположений о платформе. В основном он состоит из временного объекта, используемого так:

Debug(5) << "This is level 5 debug info.\n";

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

Имейте в виду: если вы будете указывать имя файла каждый раз, когда создаете его, открываете файл и закрываете его снова, производительность снижается. В случае нескольких выходных файлов, безусловно, было бы лучше иметь несколько статических элементов данных, которые открывают разные файлы при запуске программы или если они открываются в первый раз.

0 голосов
/ 12 февраля 2019

Я, как и многие другие, также ответил на этот вопрос некоторым кодом.

Это не совсем «готово» во всех отношениях, но его можно легко изменить:

https://gist.github.com/earonesty/977b14c93358fe9b9ee674baac5d42d7

Особенности:

  • запись в журнал не блокируется при вводе / выводе
  • макросы, аналогичные другим решениям (LOGE(blah << stream))
  • предпочитает отбрасывать записи в журнале замедлению
  • ленивая промывка
  • только заголовок, очень маленький, только классы stl
  • протестировано на osx / win / nix
  • формат времени настраивается

Пропавшие вещи:

  • простое, гибкое форматирование журнала (предопределение макроса было бы хорошо)
  • триггеры имеют интерфейс, но пока не работают
  • микросекунды еще не работают

Если кому-то действительно нравится это решение, lmk, и я сделаю из него реальное репо с тестами и т. Д. Это довольно быстро. Вероятно, не так быстро, как спидлоггер (более полная библиотека функций), но не уверен.

0 голосов
/ 15 марта 2018

Обновление Доктора Добба "Легкий регистратор для C ++": На самом деле есть пара регистраторов, упомянутых в докторе Доббе. Первый Logging In C ++ , который указан в одном из ответов. Я пытался использовать этот, но источник больше не доступен на сайте доктора Добба.

Второй, который мне подходит и который я рекомендую, это Легковесный регистратор для C ++ Филипа Янишевского, работающего в Nokia Siemens Networks. Сначала у меня были некоторые проблемы с запуском этого кода, поэтому, когда я искал решения, я наткнулся на обновление оригинального автора по адресу: GitHub: fjanisze / logger . Я обнаружил, что этот код легко понять, изменить и использовать. Это потокобезопасный и работает с Visual Studio с Windows.

Другой регистратор, упомянутый выше, - easylogging ++ . Когда я впервые попробовал это, это выглядело многообещающе. Но когда я добавил потоки и сокеты2 под Windows, он вылетел. У меня был набор определений для многопоточности и Sock2, но я все еще не мог заставить его работать, поэтому я не могу рекомендовать это. Исходный код также очень сложный, поэтому у меня не было возможности изменить и исправить его в течение разумного периода времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...