将boost日志消息作为参数传递给函数调用 [英] Passing boost log message as an argument to function call

查看:96
本文介绍了将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                       
    

    注意:由于涉及到双重缓冲"处理,因此不会过分有效.带有一个临时流,但是您可以看到它具有很高的灵活性.

    Notes: it will not be overly efficient because it involves "double buffering" with a temporary stream, but it is highly flexible, as you can see.

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

    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日志消息作为参数传递给函数调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆