当前位置: 首页 > 知识库问答 >
问题:

使用流[多线程]的记录器类

夏华藏
2023-03-14

我有一个C语言的日志类。它是一个支持多线程的单例。

我想要实现的(主要是做到的):

  • 拥有通用记录器类
  • 独生子女
  • 将其与流插入运算符一起使用,而不是作为函数调用

该类写入std::stringstream,在std::endl上刷新std::stringstream内容到文件。一个很大的缺点是,std::endl需要一次,每次调用一次,才能在多线程应用程序中正常工作。不确定这是否是一个好方法,但目前还可以,就我而言,我可以接受这个缺点

我的问题是,在日志记录时调用std::setfill()会死锁。这个调用似乎没有发送到我的Logger类,而是在其关键部分之外执行

我能做到这一点吗?一个完全支持manps的记录器类?

记录通话

LOGI << "Some message " << aVariable << std::endl;                // OK
LOGI << std::setw(20) << var << std::endl                         // OK
LOGI << std::setfill('-') << std::setw(50) << var << std::endl;   // NOT OK because of setfill() call !!!!

类示例代码

#define LOGFATAL Logger::GetLogger(LOGLEVEL_FATAL,      __FUNCTION__)
#define LOGE     Logger::GetLogger(LOGLEVEL_ERROR,      __FUNCTION__)
#define LOGW     Logger::GetLogger(LOGLEVEL_WARN,       __FUNCTION__)
#define LOGI     Logger::GetLogger(LOGLEVEL_INFO,       __FUNCTION__)
#define LOGD     Logger::GetLogger(LOGLEVEL_DEBUG,      __FUNCTION__)
#define LOGV     Logger::GetLogger(LOGLEVEL_VERBOSE,    __FUNCTION__)

class Logger
{
public:
    static void Initialize(const std::string& _logFile, const std::string& _logLevel)
    {
        isInitialized = true;
        logFileName = _logFile;
        logLevel = GetLogLevel(_logLevel);
    }
    static Logger& GetLogger(LogLevel l, const std::string& funcName)
    {
        if(isInitialized)
            csFile->lock();

        msgLogLevel = l;
        functionName = funcName;
        return GetLogger();
    }

    typedef std::ostream&  (*ManipFn)(std::ostream&);
    typedef std::ios_base& (*FlagsFn)(std::ios_base&);

    template<class T>
    Logger& operator<<(const T& output)
    {
        if (!isInitialized)
            return *this;

        m_stream << output;
        return *this;
    }

    Logger& operator<<(const ManipFn manip)
    {
        if (!isInitialized)
            return *this;

        manip(m_stream);

        if (manip == static_cast<ManipFn>(std::flush) ||
            manip == static_cast<ManipFn>(std::endl))
        {
            // flush the stream and unlock the mutex
            this->flush();
            csFile->unlock();
        }
        return *this;
    }

    Logger& operator<<(const FlagsFn manip) /// setiosflags, resetiosflags
    {
        manip(m_stream);
        return *this;
    }
...
    static Logger& GetLogger()
    {
        static Logger instance;
        return instance;
    }


如果需要更多信息,请告诉我

共有1个答案

章安宜
2023-03-14

我错过了我自己的话和我自己的代码问题和限制(当我发布问题时我就知道了)。我的错误是没有发布使我的进程陷入僵局的初始代码。这是代码:

LOGV << std::setfill('-') << std::setw(206) << '-' << std::endl;
LOGV << std::setfill(' ');

引用我自己的话“一个很大的缺点是,每次调用都需要std::endl一次,并且只有一次,才能在多线程应用程序中正常工作”。

所以我的问题的解决方法是LOGV

抱歉没有进一步检查,浪费了任何人的时间。

 类似资料:
  • 给定:我在Kafka中有两个主题,假设主题A和主题B。Kafka流从主题A中读取一条记录,对其进行处理,并产生与所消耗记录相对应的多条记录(假设recordA和recordB)。现在的问题是我如何使用Kafka流来实现这一点。 在这里,读取的记录是消息;处理之后,它返回一个消息列表。如何将此列表划分为两个生产者流?任何帮助都将不胜感激。

  • 虽然很清楚如何配置多线程jBehave run,但我不清楚如何处理日志记录混乱。 这里有哪些选项?

  • 我在List上使用并行流。我想它会使用WorkJoinPool生成多个工作线程,根据日志,不知何故一直只有一个线程: 以下是我的代码的简短版本: [编辑]我在本地机器上尝试了一些非常简单的代码,它确实产生了多个线程。不幸的是,我无法在本地或其他环境中运行生产代码。。 为什么我的并行流不使用WorkJoinPool生成多个线程? 非常感谢。

  • 先说背景,9本,二战失败,机试370。 机试 3/15 我大概做了150道leetcode题,80道简单,60道中等,10道困难吧大概。主要是滑动窗口,dfs,bfs,回溯,动态规划,贪心,二分查找,优先队列,并查集,单调栈之类的题目。当然一些简单的数据结构的题目也是要做的,像是字符串、线性表、队列、栈、哈希表,不过这些题往往比较简单,机试很少会考到这么简单,可以用作练手。树和图会考,但考的比较少

  • 问题内容: 我正在用log4j开发一个非常大的Java应用程序,我想知道是否有一种方法可以在运行时提取活动记录器的数量?或应用程序中现有的记录器是什么?我的最终目标是获取所有记录器的列表并更改它们在运行时的级别。谢谢。 问题答案: 您可以尝试类似: 然后遍历allLoggers。