首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用easylogging++在C++中进行多进程日志记录时丢失消息

使用easylogging++在C++中进行多进程日志记录时丢失消息
EN

Stack Overflow用户
提问于 2022-06-22 19:15:11
回答 1查看 83关注 0票数 0

我在我的应用程序中使用easylogging++来记录用于控制的消息,并且我注意到在生产中(在Linux下运行),一些消息正在从日志文件中消失或丢失。我在测试环境中(在Windows上)用一个简单的例子来模拟这个问题。我创建了一个无限线程,该线程一直在记录一个计数器,然后执行两个程序实例,下面是我的代码的一个恢复示例:

代码语言:javascript
复制
#include "Log/Log.h"
#include <chrono>
#include <thread>

INITIALIZE_EASYLOGGINGPP

void log_test() {
    long int count = 0;
    while (true) {
        log_info("Logando..." + std::to_string(count)); // this is defined in Log.h
        boost::this_thread::sleep(boost::posix_time::milliseconds(10));
        count++;
    }
}

int main(){
        std::thread t(log_test);

        t.detach();
        // rest of the code
}

Log.h/Log.cpp是:

代码语言:javascript
复制
#pragma once

#include "easylogging++.h"
#include <mutex>

static std::mutex mtx;

void log_info(std::string s);
void log_error(std::string s);

Log.cpp:

代码语言:javascript
复制
#include "Log.h"

void log_info(std::string s)
{
  mtx.lock();
  LOG(INFO, ELPP_THREAD_SAFE) << s;
  mtx.unlock();
}

void log_error(std::string s)
{
  mtx.lock();
  LOG(ERROR, ELPP_THREAD_SAFE) << s;
  mtx.unlock();
}

这两个可执行文件都使用相同的.conf文件,配置如下:

代码语言:javascript
复制
* GLOBAL:
   FORMAT               =  "%datetime %msg"
   FILENAME             =  "C:/logs/%datetime{%Y-%M-%d}/msgs.log"
   ENABLED              =  true
   TO_FILE              =  true
   TO_STANDARD_OUTPUT   =  false
   SUBSECOND_PRECISION  =  6
   PERFORMANCE_TRACKING =  true
   MAX_LOG_FILE_SIZE    =  2097152 ## 2MB - Comment starts with two hashes (##)

在msgs.log文件中,我注意到了以下示例:

代码语言:javascript
复制
2022-06-22 18:51:24,886631 Logando...288
2022-06-22 18:51:24,901856 Logando...289
2022-06-22 18:51:24,917820 Logando...5

2022-06-22 18:51:24,932827 Logando...291
2022-06-22 18:51:24,948248 Logando...292

在第一个进程中缺少log 290,而只有这个空行。我猜想可能只是对每个进程使用不同的日志文件,但是它不会发生在一个具有多个线程的进程中(像前面的代码示例一样,实例化线程t1、t2、t3 )。目前,我不能只将一个日志文件更改为生产中的每个进程,因为它将产生很大的影响,所以我如何解决它--我根本不丢失任何消息?提前感谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-22 19:44:36

我猜想一种解决方案可能只是对每个进程使用不同的日志文件,但是它不会发生在一个具有多个线程的进程中(如前面的代码示例所示,实例化线程t1、t2、t3 )。

嗯,单个进程中的线程共享std::mutex mtx的一个实例,因此它们是正确同步的。也许更重要的是,正确同步的是访问单个缓冲区,这是写入文件的唯一缓冲区。

两个进程将拥有完全独立的std::mutex mtx实例,如果它们是单线程的,这并不重要,因为只有一个线程正在写入每个进程的缓冲区。问题是,两个缓冲区在写入文件时并不同步,而且正如注释中提到的,这些写入显然不是原子附加的。

解决办法是:

  1. 只需使用线程,因为这已经起作用了。
  2. 使用共享互斥对象--这通常是特定于平台的,但是Boost.Interprocess是一个很好的起点。
  3. 使用两个文件--让其他一些进程尾随它们,如果需要的话,将它们合并成一个文件。
  4. 对输出文件使用两个FIFO,并让其他进程同时读取它们并将它们合并到一个文件中。它避免重复磁盘上的文件存储,但可能是*NIX特定的。
  5. 使用网络接收器(请参阅easyloggingc++文档),并让进程监听本地主机上的两个端口.并将它们合并成一个文件。比FIFO更便携,但编码也更多。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72720891

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档