通过轮换增强 2 个文件中的日志记录

Boost logging in 2 files with rotation

本文关键字:文件 日志 记录 增强      更新时间:2023-10-16

我正在使用Boost将日志存储在文件中。一切都很好,轮换有效,但是是否可以只在两个文件中轮换日志?我只想有两个最大 250 MB 大小的文件,如果一个被填满,那么它会将日志存储在另一个文件广告中,如果第二个被填满,那么第一个将被清理,新日志将存储在那里......等等。可以通过提升吗?


我看到有一个sink->locked_backend()->set_close_handler(&foo);,是不是可以使用该功能删除旧的日志文件?(直到现在我还没有设法找到它)

有趣的问题。

看起来 boost 开发人员已经决定这更容易实现为单独的垃圾收集,如果您愿意的话

rm -v $(ls -t mylog_*.log | tail -n -2)

我实现了一种在创建第三个文件时删除最旧文件的方法。

我创建了以下类:

class Tutorial
{
public:
    enum SeverityLevels
    {
        debugs,
        infos,
        warnings,
        errors
    };
    static void initFilesList()
    {
        fs::path path("../logs/");
        fs::directory_iterator endDir;
        if (!fs::exists(path))
        {
            return;
        }
        if (!fs::is_directory(path))
        {
            return;
        }
        for (fs::directory_iterator it(path); it != endDir; it++)
        {
            if (fs::is_regular_file(it->status()))
            {
                if (fs::extension(*it) == ".log")
                {
                    std::string fileToPush = it->path().string();
                    if (std::find(sm_queue.begin(), sm_queue.end(), fileToPush) == sm_queue.end())
                    {
                        sm_queue.push_back(fileToPush);
                        while (sm_queue.size() > 2)
                        {
                            std::string fileToDelete = sm_queue.front();
                            if (fs::exists(fs::path(fileToDelete)))
                            {
                                fs::remove(fs::path(fileToDelete));
                                sm_queue.pop_front();
                            }
                            else
                            {
                                throw NoSuchFileException(fileToDelete);
                            }
                        }
                    }
                }
                else
                {
                    throw BadExtensionLogException(it->path().string());
                }
            }
        }
    }
private:
    static std::list< std::string > sm_queue;
    std::size_t m_cntr;
    src::severity_logger< SeverityLevels > m_slg;
    /** The function initializes the logging to mentioned file  and with specific format and rotation
     * 
     * @param fileNameIn : input file name string
     */
    void initZZ()
    {
        boost::shared_ptr< sinks::synchronous_sink< sinks::text_file_backend > > sink = logging::add_file_log(
            "../logs/" + m_logFileName + "_%N.log",
            keywords::format = expr::stream
                << expr::attr< attrs::current_process_name::value_type >("Executable") << "(" 
                << expr::attr< attrs::current_process_id::value_type >("ExeUID") << ") CID(" << line_id << ") " << severity
                << "[" << expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S.%f") << "] ["
                << expr::attr< attrs::current_thread_id::value_type >("ThreadID") << "] " << scope << " - " << expr::smessage,
            keywords::open_mode = (std::ios::out | std::ios::app),
            keywords::rotation_size = 25 * 1024
        );
        sink->locked_backend()->set_open_handler(&Tutorial::openingHandler);
        logging::core::get()->set_filter(severity >= SeverityLevels::infos);
        logging::core::get()->add_sink(sink);
    }
    static void openingHandler(sinks::text_file_backend::stream_type& file)
    {
        initFilesList()
    }
public:
    Tutorial(const std::string& fileNameIn) : m_cntr(0), m_logFileName(fileNameIn)
    {
        initZZ();
    }
    /** The function writes logs on the mentioned file and with the mentioned format with rotating on size
     * 
     * @param fileNameIn : input filen name string
     */
    void zzLoggingFormattedToFile()
    {
        BOOST_LOG_SEV(m_slg, SeverityLevels::debugs) << "Debug message " << m_cntr;
        BOOST_LOG_SEV(m_slg, SeverityLevels::errors) << "Error message " << m_cntr;
        BOOST_LOG_SEV(m_slg, SeverityLevels::infos) << "Info message " << m_cntr;
        BOOST_LOG_SEV(m_slg, SeverityLevels::warnings) << "Warning message " << m_cntr;
        ++m_cntr;
    }
};

以及以下operator<<重载:

/** The operator used for SeverityLevels */
std::ostream& operator<< (std::ostream& strmIn, Tutorial::SeverityLevels levelIn)
{
    static const char* stringsLevels[] = 
    {
        "DEBG",
        "INFO",
        "WARN",
        "ERRR"
    };
    if (static_cast< std::size_t >(levelIn) < sizeof(stringsLevels) / sizeof(*stringsLevels))
    {
        strmIn << stringsLevels[levelIn];
    }
    else
    {
        strmIn << static_cast< int >(levelIn);
    }
    return strmIn;
}

因此,每次创建新的日志文件时,都会对日志文件进行扫描,如果日志文件超过 2 个,则会删除最旧的日志文件。文件的名称保存在列表中,每次删除插入的第一个文件。

我想要任何评论;对此,你怎么看?


我知道可能存在不删除最后一个日志文件的错误,如果应用程序在之前多次运行并且 logs 文件夹中有文件:情况是当有log_0.log - 从上次运行 - 和log_X.log - 来自上次运行之前; 这样,列表中的第一个插入将被log_0.log, 但这可以通过添加日期和时间而不是计数器来解决。