【问题标题】:Small logger class小型记录器类
【发布时间】:2011-02-17 11:25:31
【问题描述】:

我正在寻找一个用 c++ 编写的小型轻量级日志系统。我找到了一些现有的框架,但我现在不需要它们的所有功能。我主要是在寻找一个可以配置日志级别输出文件的小型系统。我正在寻找现有的解决方案,因为我不想重新发明轮子。

【问题讨论】:

  • 如果您不想重新发明轮子,为什么不使用现有的日志记录解决方案? log4cpp 看起来不错
  • 嗨 Herzl 你的环境是什么? Visual C++ 根本没有托管代码?在 .NET 中有跟踪/调试侦听器的概念,可以使用日志级别和不同的侦听器进行配置,例如文件、控制台、输出窗口等……不确定原始 C++ 中内置的内容可能什么都没有…… .
  • 我想你已经看过这个了吧? codeproject.com/KB/cpp/CPP_logging.aspx
  • thank davide 我忘了说的重要通知是:我的系统将在 linux 系统下工作。
  • @Nekresh:我认为 OP 意味着他不需要他见过的复杂框架。他想要一些简单的东西。

标签: c++ logging


【解决方案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*。因此,我们现在能够通过链接流来添加不错的功能,例如加密日志。

【讨论】:

  • ftp.drdobbs.com/sourcecode/ddj/2007/0710.zip。 “log.h”是最好的文件;另一种是不太灵活的无模板版本。我已经把它上传到这里,以防 Dobbs 博士再次对其进行洗牌:pastie.org/1574516
  • 不认为您愿意分享您对 ofstream 的更改吗?
  • @Pedrod'Aquino 很好的参考,但有一点是它不会将日志写入磁盘,直到程序终止,或者 LOG 对象被破坏。如果我想查看更新的日志文件,我该怎么办?
  • 我开始使用这个lib并放入bitbucket:bitbucket.org/volkanozyilmaz/logcpp
  • @pathygeek 他的意思是,如果你这样做FILE_LOG(logWarning) &lt;&lt; "before loop"; for (int i = 0; i &lt; 5; ++i) { FILE_LOG(logInfo) &lt;&lt; "loop count" &lt;&lt; i; } 将导致循环计数首先写入日志,因为它们写入析构函数,然后写入“循环前”语句。这是错误的顺序。如果您在程序开始时有一个“应用程序初始化”,则应在主循环中的任何内容之前编写它。我不得不修改这个库,让它写在每条语句之后。
【解决方案2】:

对于任何想要简单解决方案的人,我推荐: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 调试 [默认] [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++ 专家,所以这段代码在极端情况下可能会爆炸)。

【讨论】:

  • +1 用于最小版本。我必须将第一条配置行 structlog LOGCFG = {}; 放在全局范围内的 main 方法之外,以使其正常工作。
  • 更新:最新版本不仅仅是头文件 - 它确实有一个非头文件。旧版本只是标题。
  • 对 Windows 不太友好:wingdi.h 的头文件 #undefs ERROR 宏!!!除了 TRACE 和 DEBUG 宏,它们也是 ATL/MFC 高度标准的东西。不能推荐这种情况或准备一点黑客攻击。
  • @mgruber4 :是的,我同意。由于我不使用 Windows,因此我应该指定它仅在 Linux 中进行了测试。其他人可能有兴趣,所以如果你让它在 Windows 下工作,你能发布你的版本吗? (作为评论,作为此答案的补充或作为单独的答案)
  • @lepe &lt;&lt; 线程安全()吗?好像没有。
【解决方案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】:

      This question 有我的一些幻想。它是完全标准的 C++ 并且不做任何平台假设。它基本上由一个像这样使用的临时对象组成:

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

      我相信当您拥有基本布局时,您可以弄清楚如何指定不同的文件和其他内容。我试图保持类的结构,以便在发布版本中,尽可能好地删除每种形式的 Debug 输出。

      请注意:如果每次构造文件时都指定一个文件名,然后打开文件并再次关闭它,性能会受到影响。在有多个输出文件的情况下,最好有几个静态数据成员,以便在程序运行或首次打开时打开不同的文件。

      【讨论】:

        【解决方案6】:

        如果您对项目没有大小限制,并且希望它能够持续很长时间,我建议您查看Apache Log4cxx。它不是一个小型库,但它几乎支持您在日志记录中想要的所有内容(包括一些您甚至不知道自己想要的东西),而且它是可移植的。

        在任何较大的项目中,您迟早会希望您的日志记录解决方案不仅仅是“小型记录器类”,那么为什么要重新发明轮子。

        【讨论】:

          【解决方案7】:

          Dobb 博士的“A Lightweight Logger for C++”的更新: 在 Dobb 博士的文章中实际上提到了几个记录器。第一个Logging In C++ 列在其中一个答案中。我尝试使用这个,但 Dobb 博士的网站上不再提供源代码。

          我推荐的第二个对我有用的方法是 A Lightweight Logger for C++,作者是在诺基亚西门子通信公司工作的 Filip Janiszewski。起初我在运行这段代码时遇到了一些问题,所以在我寻找解决方案时,我遇到了原作者的更新:GitHub: fjanisze/logger。我发现此代码易于理解、修改和使用。它是线程安全的,可与带有 Windows 的 Visual Studio 一起使用。

          上面提到的另一个记录器是easylogging++。当我第一次尝试这个时,它看起来很有希望。但是当我在 Windows 下添加 threading 和 sockets2 时,它就崩溃了。我确实为线程和 Sock2 设置了定义,但我仍然无法让它工作,所以我不能推荐这个。源代码也很复杂,所以我没有机会在合理的时间内修改和修复它。

          【讨论】:

            【解决方案8】:

            我和其他许多人也用一些代码回答了这个问题。

            这并不是真正“准备好”,但可以轻松修改:

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

            特点:

            • 写入日志不会在 i/o 上阻塞
            • 与其他解决方案类似的宏 (LOGE(blah &lt;&lt; stream))
            • 宁愿放弃日志条目也不愿放慢速度
            • 懒惰的冲洗
            • 仅标题,非常小,仅 stl 类
            • 在 osx/win/nix 上测试
            • 时间格式可配置

            缺少的东西:

            • 简单、灵活的日志格式(预定义宏就可以了)
            • 触发器有接口但还不能工作
            • 微秒还不行

            如果有人真的以任何方式喜欢这个解决方案,lmk 和我会用测试等方式制作一个真正的 repo。它非常快。可能不如 speedlogger(功能更强大的完整库)快,但不确定。

            【讨论】:

            • 我喜欢这个——它很小而且只有标题。
            【解决方案9】:

            以上答案都很棒。

            怀疑任何人都会看到这个答案,但这是我使用的 https://github.com/asn10038/Cpp_Logger

            在.h文件中配置4-5个变量名后易于设置,实现无非标准依赖。

            不仅是标题,而且很容易。

            也许这对某人有帮助。

            【讨论】:

              【解决方案10】:

              我创建了一个小型日志记录类,因为我在编译时遇到了在 VSCode 中包含其他示例的问题,这里是一个文件头:

              #include <iostream>
              #include <fstream>
              #include <string>
              #include <iomanip>
              #include <ctime>
              #include <sstream>
              
              using namespace std;
              
              class logging
              {
                  private: 
                      ofstream myfile;
                      std::string get_time()
                      {
                          auto t = std::time(nullptr);
                          auto tm = *std::localtime(&t);
              
                          std::ostringstream oss;
                          //2047-03-11 20:18:26
                          oss << std::put_time(&tm, "%Y-%m-%d-%H:%M:%S");
                          auto str = oss.str();
                          return str;
                      }
              
                  public: 
                      logging(string filepath)
                      {
                          myfile.open (filepath);
                      }
                      ~logging()
                      {
                          myfile.close();
                      }
                      void write(string line)
                      {
                          myfile << get_time() << " " << line <<std::endl;
                      }
              };
              

              【讨论】:

              • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
              猜你喜欢
              • 2021-12-30
              • 1970-01-01
              • 2020-02-05
              • 2021-11-12
              • 2022-08-10
              • 2013-07-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多