Подтвердить что ты не робот

Класс малого регистратора

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

4b9b3361

Ответ 1

Я настоятельно рекомендую эту простую систему регистрации: 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*. В результате мы теперь можем добавлять приятные функции, такие как шифрование журналов, путем объединения потоков.

Ответ 2

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

Только один заголовок только для библиотеки протоколов С++. Это очень легкий вес, надежный, быстродействующий, поточный и безопасный тип и состоит из многих встроенные функции. Это позволяет записывать журналы самостоятельно настраиваемый формат. Он также обеспечивает поддержку для регистрации ваших классов, сторонних библиотек, 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 [по умолчанию] [пользователь @localhost] [Config:: Config (const string)] [src/Config.cpp: 7] Чтение файла конфигурации: 'Config.json'

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

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

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

/* 
 * File:   Log.h
 * Author: Alberto Lepe <[email protected]>
 *
 * 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" или добавить файл и т.д. Я надеюсь, что это полезно кому-то. (Примечание: я не специалист по С++, так что этот код может взорваться в крайних случаях).

Ответ 3

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

#include <plog/Log.h>

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

    LOGD << "Hello log!";
    LOGD_IF(true) << "conditional logging";
    return 0;
}

Ответ 4

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

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

auto my_logger = spd::basic_logger_mt("basic_logger", "logs/basic.txt");
my_logger->info("Some log message");

Ответ 5

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

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

Ответ 6

Этот вопрос имеет мою попытку с некоторой причудливостью. Он полностью Standard С++ и не делает никаких предположений платформы. Он в основном состоит из временного объекта, используемого следующим образом:

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

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

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