将boost日志消息作为参数传递给函数

将boost日志消息作为参数传递给函数

本文介绍了将boost日志消息作为参数传递给函数调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经编写了C ++代码来捕获消息的各种严重性级别.我为此使用了 https://github.com/gklingler/simpleLogger .

I have written C++ code for capturing the various severity levels of messages. I have used https://github.com/gklingler/simpleLogger for this.

  • 文件simpleLogger.cpp

#include "simpleLogger.h"

#include <boost/log/core/core.hpp>
#include <boost/log/expressions/formatters/date_time.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/trivial.hpp>
#include <boost/core/null_deleter.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <fstream>
#include <ostream>


namespace logging = boost::log;
namespace src = boost::log::sources;
namespace expr = boost::log::expressions;
namespace sinks = boost::log::sinks;
namespace attrs = boost::log::attributes;

BOOST_LOG_ATTRIBUTE_KEYWORD(line_id, "LineID", unsigned int)
BOOST_LOG_ATTRIBUTE_KEYWORD(timestamp, "TimeStamp", boost::posix_time::ptime)
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", logging::trivial::severity_level)

BOOST_LOG_GLOBAL_LOGGER_INIT(logger, src::severity_logger_mt) {
    src::severity_logger_mt<boost::log::trivial::severity_level> logger;

    // add attributes
    logger.add_attribute("LineID", attrs::counter<unsigned int>(1));     // lines are sequentially numbered
    logger.add_attribute("TimeStamp", attrs::local_clock());             // each log line gets a timestamp

    // add a text sink
    typedef sinks::synchronous_sink<sinks::text_ostream_backend> text_sink;
    boost::shared_ptr<text_sink> sink = boost::make_shared<text_sink>();

    // add a logfile stream to our sink
    sink->locked_backend()->add_stream(boost::make_shared<std::ofstream>(LOGFILE));

    // add "console" output stream to our sink
    sink->locked_backend()->add_stream(boost::shared_ptr<std::ostream>(&std::clog, boost::null_deleter()));

    // specify the format of the log message
    logging::formatter formatter = expr::stream
        << std::setw(7) << std::setfill('0') << line_id << std::setfill(' ') << " | "
        << expr::format_date_time(timestamp, "%Y-%m-%d, %H:%M:%S.%f") << " "
        << "[" << logging::trivial::severity << "]"
        << " - " << expr::smessage;
    sink->set_formatter(formatter);

    // only messages with severity >= SEVERITY_THRESHOLD are written
    sink->set_filter(severity >= SEVERITY_THRESHOLD);

    // "register" our sink
    logging::core::get()->add_sink(sink);

    return logger;
}

  • 文件simpleLogger.h

    #ifndef simpleLogger_h__
    #define simpleLogger_h__
    
    #define BOOST_LOG_DYN_LINK // necessary when linking the boost_log library dynamically
    
    #include <boost/log/trivial.hpp>
    #include <boost/log/sources/global_logger_storage.hpp>
    
    // the logs are also written to LOGFILE
    #define LOGFILE "logfile.log"
    
    // just log messages with severity >= SEVERITY_THRESHOLD are written
    #define SEVERITY_THRESHOLD logging::trivial::warning
    
    // register a global logger
    BOOST_LOG_GLOBAL_LOGGER(logger, boost::log::sources::severity_logger_mt<boost::log::trivial::severity_level>)
    
    // just a helper macro used by the macros below - don't use it in your code
    #define LOG(severity) BOOST_LOG_SEV(logger::get(),boost::log::trivial::severity)
    
    // ===== log macros =====
    #define LOG_TRACE   LOG(trace)
    #define LOG_DEBUG   LOG(debug)
    #define LOG_INFO    LOG(info)
    #define LOG_WARNING LOG(warning)
    #define LOG_ERROR   LOG(error)
    #define LOG_FATAL   LOG(fatal)
    
    #endif
    

  • 文件app.cpp

    #include "simpleLogger.h"
    
    int main() {
      LOG_TRACE << "this is a trace message";
      LOG_DEBUG << "this is a debug message";
      LOG_WARNING << "this is a warning message";
      LOG_ERROR << "this is an error message";
      LOG_FATAL << "this is a fatal error message";
      return 0;
    }
    

  • 所以我将以

    LOG_INFO << "This is info message"

    但是我需要将此日志消息发送给其他函数作为参数.在该功能中,我将对日志消息进行其他更改,即"This is info message".

    But this log message I need to send it to some other function as an argument. In that function I will be doing some other changes on the log message i.e "This is info message".

    如何将增强日志消息作为函数的参数发送?我找不到与此相关的来源.

    How to send the boost log message as an argument to function?I didn't find relevant source for this.

    预先感谢

    推荐答案

    您可以定义一个懒惰的参与者",您可以将其放入包装的格式化程序表达式中.这几乎是Boost Log的火箭科学,但是也许这个简单的示例可以为您提供帮助:

    You can define a "lazy actor" that you can put into a wrapped formatter expression. This is pretty much the rocket science of Boost Log, but perhaps this simple example will help you:

    auto reverse_expr = [](auto fmt) {
        return expr::wrap_formatter([fmt](logging::record_view const& rec, logging::formatting_ostream& strm) {
            logging::formatting_ostream tmp;
            std::string text;
            tmp.attach(text);
    
            fmt(rec, tmp);
    
            std::reverse(text.begin(), text.end());
            strm << text;
        });
    };
    
    // specify the format of the log message
    logging::formatter formatter = expr::stream
        << reverse_expr(expr::stream << std::setw(7) << std::setfill('0') << line_id)
        << " | "
        << expr::format_date_time(timestamp, "%Y-%m-%d, %H:%M:%S.%f") << " "
        << "[" << logging::trivial::severity << "]"
        << " - "
        << reverse_expr(expr::stream << expr::smessage);
    
    sink->set_formatter(formatter);
    

    结果:

    3000000 | 2020-04-28, 16:15:15.779204 [warning] - egassem gninraw a si siht
    4000000 | 2020-04-28, 16:15:15.779308 [error] - egassem rorre na si siht
    5000000 | 2020-04-28, 16:15:15.779324 [fatal] - egassem rorre lataf a si siht
    

    更新下面的改进方法(请参见"奖金"部分)

    UPDATE Improved method below (see section BONUS)

    稍微通用一些的实现可能看起来像这样:

    A slightly more generic implementation might look like:

    template <typename F> struct Xfrm {
        Xfrm(F f) : _f(f) {}
        F _f;
    
        template <typename E> auto operator[](E fmt) const {
            return expr::wrap_formatter(
                [f=_f,fmt](logging::record_view const& rec, logging::formatting_ostream& strm) {
                    logging::formatting_ostream tmp;
                    std::string text;
                    tmp.attach(text);
                    fmt(rec, tmp);
    
                    strm << f(text);
                });
        }
    };
    

    因此您实际上可以将其用于其他功能:

    So you can actually use it for other functions:

    std::string reversed(std::string v) {
        std::reverse(v.begin(), v.end());
        return v;
    }
    std::string to_uppercase(std::string v) {
        for (auto& ch : v) ch = std::toupper(ch);
        return v;
    }
    

    然后您可以像这样使用:

    Which you could then use like:

    logging::formatter formatter = expr::stream
        << Xfrm(reversed)[expr::stream << std::setw(7) << std::setfill('0') << line_id]
        << " | "
        << expr::format_date_time(timestamp, "%Y-%m-%d, %H:%M:%S.%f") << " "
        << "[" << logging::trivial::severity << "]"
        << " - "
        << Xfrm(to_uppercase)[ expr::stream << expr::smessage ];
    

    或将操纵器放在您的头文件中:

    Or put the manipulators in your header file:

    static inline constexpr Xfrm UC{to_uppercase};
    static inline constexpr Xfrm REV{reversed};
    

    因此您可以在预制设备上使用它:

    So you can use it pre-fab:

    logging::formatter formatter = expr::stream
        << REV[ expr::stream << std::setw(7) << std::setfill('0') << line_id ]
        << " | "
        << expr::format_date_time(timestamp, "%Y-%m-%d, %H:%M:%S.%f") << " "
        << "[" << logging::trivial::severity << "]"
        << " - "
        << UC[ expr::stream << expr::smessage ];
    

    输出

    3000000 | 2020-04-28, 16:36:46.184958 [warning] - THIS IS A WARNING MESSAGE
    4000000 | 2020-04-28, 16:36:46.185034 [error] - THIS IS AN ERROR MESSAGE
    5000000 | 2020-04-28, 16:36:46.185045 [fatal] - THIS IS A FATAL ERROR MESSAGE
    

    实时演示

    在魔盒上直播

    Live Demo

    Live On Wandbox

    • 文件simpleLogger.h

     #ifndef _HOME_SEHE_PROJECTS_STACKOVERFLOW_SIMPLELOGGER_H
     #define _HOME_SEHE_PROJECTS_STACKOVERFLOW_SIMPLELOGGER_H
    
     #pragma once
     #define BOOST_LOG_DYN_LINK \
         1 // necessary when linking the boost_log library dynamically
    
     #include <boost/log/sources/global_logger_storage.hpp>
     #include <boost/log/trivial.hpp>
    
     // the logs are also written to LOGFILE
     #define LOGFILE "logfile.log"
    
     // just log messages with severity >= SEVERITY_THRESHOLD are written
     #define SEVERITY_THRESHOLD logging::trivial::warning
    
     // register a global logger
     BOOST_LOG_GLOBAL_LOGGER(logger, boost::log::sources::severity_logger_mt<
                                         boost::log::trivial::severity_level>)
    
     // just a helper macro used by the macros below - don't use it in your code
     #define LOG(severity) \
         BOOST_LOG_SEV(logger::get(), boost::log::trivial::severity)
    
     // ===== log macros =====
     #define LOG_TRACE LOG(trace)
     #define LOG_DEBUG LOG(debug)
     #define LOG_INFO LOG(info)
     #define LOG_WARNING LOG(warning)
     #define LOG_ERROR LOG(error)
     #define LOG_FATAL LOG(fatal)
    
     #endif
    

  • 文件simpleLogger.cpp

     #include "simpleLogger.h"
    
     #include <boost/core/null_deleter.hpp>
     #include <boost/log/core/core.hpp>
     #include <boost/log/expressions.hpp>
     #include <boost/log/expressions/formatters/char_decorator.hpp>
     #include <boost/log/expressions/formatters/date_time.hpp>
     #include <boost/log/sinks/sync_frontend.hpp>
     #include <boost/log/sinks/text_ostream_backend.hpp>
     #include <boost/log/sources/severity_logger.hpp>
     #include <boost/log/support/date_time.hpp>
     #include <boost/log/trivial.hpp>
     #include <boost/log/utility/setup/common_attributes.hpp>
     #include <boost/make_shared.hpp>
     #include <boost/phoenix.hpp>
     #include <boost/phoenix/function.hpp>
     #include <boost/shared_ptr.hpp>
     #include <fstream>
     #include <ostream>
    
     namespace logging = boost::log;
     namespace src = boost::log::sources;
     namespace expr = boost::log::expressions;
     namespace sinks = boost::log::sinks;
     namespace attrs = boost::log::attributes;
    
     BOOST_LOG_ATTRIBUTE_KEYWORD(line_id, "LineID", unsigned int)
     BOOST_LOG_ATTRIBUTE_KEYWORD(timestamp, "TimeStamp", boost::posix_time::ptime)
     BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity",
                                 logging::trivial::severity_level)
    
     namespace /*extend locally*/ {
         template <typename F> struct Xfrm {
             constexpr Xfrm(F f) : _f(f) {}
             F _f;
    
             template <typename E> auto operator[](E fmt) const {
                 return expr::wrap_formatter(
                     [f = _f, fmt](logging::record_view const& rec,
                                   logging::formatting_ostream& strm) {
                         logging::formatting_ostream tmp;
                         std::string text;
                         tmp.attach(text);
                         fmt(rec, tmp);
    
                         strm << f(text);
                     });
             }
         };
    
         std::string reversed(std::string v) {
             std::reverse(v.begin(), v.end());
             return v;
         }
         std::string to_uppercase(std::string v) {
             for (auto& ch : v) {
                 ch = std::toupper(ch);
             }
             return v;
         }
    
         inline constexpr Xfrm UC{ to_uppercase };
         inline constexpr Xfrm REV{ reversed };
     } // namespace
    
     BOOST_LOG_GLOBAL_LOGGER_INIT(logger, src::severity_logger_mt) {
         src::severity_logger_mt<boost::log::trivial::severity_level> logger;
    
         // add attributes
         logger.add_attribute("LineID", attrs::counter<unsigned int>(
                                            1)); // lines are sequentially numbered
         logger.add_attribute(
             "TimeStamp", attrs::local_clock()); // each log line gets a timestamp
    
         // add a text sink
         using text_sink = sinks::synchronous_sink<sinks::text_ostream_backend>;
         boost::shared_ptr<text_sink> sink = boost::make_shared<text_sink>();
    
         // add a logfile stream to our sink
         sink->locked_backend()->add_stream(
             boost::make_shared<std::ofstream>(LOGFILE));
    
         // add "console" output stream to our sink
         sink->locked_backend()->add_stream(
             boost::shared_ptr<std::ostream>(&std::clog, boost::null_deleter()));
    
         // specify the format of the log message
         logging::formatter formatter =
             expr::stream
             << REV[expr::stream << std::setw(7) << std::setfill('0') << line_id]
             << " | "
             << expr::format_date_time(timestamp, "%Y-%m-%d, %H:%M:%S.%f") << " "
             << "[" << logging::trivial::severity << "]"
             << " - " << UC[expr::stream << expr::smessage];
    
         sink->set_formatter(formatter);
         // only messages with severity >= SEVERITY_THRESHOLD are written
         sink->set_filter(severity >= SEVERITY_THRESHOLD);
    
         // "register" our sink
         logging::core::get()->add_sink(sink);
    
         return logger;
     }
    

  • 文件test.cpp

     #include "simpleLogger.h"
    
     int main() {
         LOG_TRACE << "this is a trace message";
         LOG_DEBUG << "this is a debug message";
         LOG_WARNING << "this is a warning message";
         LOG_ERROR << "this is an error message";
         LOG_FATAL << "this is a fatal error message";
         return 0;
     }
    

  • 为避免双重缓冲,我们可以避免使用原始格式化程序.这对已知属性最有效:

    To avoid double-buffering, we can avoid using the original formatter. This works best for known attributes:

    struct OddEvenId {
        void operator()(logging::record_view const& rec, logging::formatting_ostream& strm) const {
            auto vr = line_id.or_throw()(rec);
            if (!vr.empty()) {
                strm << std::setw(4) << (vr.get<uint32_t>()%2? "Odd":"Even");
            }
        }
    };
    
    struct QuotedMessage {
        void operator()(logging::record_view const& rec, logging::formatting_ostream& strm) const {
            auto vr = expr::smessage.or_throw()(rec);
            if (!vr.empty())
                strm << std::quoted(vr.get<std::string>());
        }
    };
    
    static inline auto oddeven_id = expr::wrap_formatter(OddEvenId{});
    static inline auto qmessage = expr::wrap_formatter(QuotedMessage{});
    

    现在我们可以简单地说qmessage而不是expr::smessage来获取引用的消息值:

    Now we can simply say qmessage instead of expr::smessage to get the quoted message value:

    在魔盒上直播

    Live On Wandbox

    logging::formatter formatter = expr::stream
        << oddeven_id
        << " | "
        << expr::format_date_time(timestamp, "%Y-%m-%d, %H:%M:%S.%f") << " "
        << "[" << logging::trivial::severity << "]"
        << " - " << qmessage;
    

    打印

     Odd | 2020-04-28, 17:21:12.619565 [warning] - "this is a warning message"
    Even | 2020-04-28, 17:21:12.619666 [error] - "this is an error message"
     Odd | 2020-04-28, 17:21:12.619684 [fatal] - "this is a fatal error message"
    

    这篇关于将boost日志消息作为参数传递给函数调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    08-26 12:02