草庐IT

c++ - boost 日志记录类属性

coder 2024-02-08 原文

我正在尝试为我的应用程序做一个日志。我想添加一个属性,这样我就可以知道日志属于哪个类。我已经开始测试它是否有效:

#include <boost/log/expressions.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/common.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/syslog_backend.hpp>

enum severity_levels
{
    debug,
    info,
    warning,
    error
};

typedef boost::log::sinks::synchronous_sink< boost::log::sinks::syslog_backend > SinkSysLogBackEnd;
typedef boost::log::sources::severity_logger< severity_levels > BoostLogger;

std::ostream& operator<< (std::ostream& strm, severity_levels level)
{
    static const char* strings[] =
    {
        "debug",
        "info",
        "warning",
        "error"
    };

    if (static_cast< std::size_t >(level) < sizeof(strings) / sizeof(*strings))
        strm << strings[level];
    else
        strm << static_cast< int >(level);

    return strm;
}

BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_levels)
BOOST_LOG_ATTRIBUTE_KEYWORD(executable, "Executable", std::string)
BOOST_LOG_ATTRIBUTE_KEYWORD(className, "Class name", std::string)

void init_syslog()
{
    // Create a backend
    boost::shared_ptr< SinkSysLogBackEnd > sink(new SinkSysLogBackEnd());

    // We'll have to map our custom levels to the syslog levels
    boost::log::sinks::syslog::custom_severity_mapping< severity_levels > mapping("Severity");
    mapping[info] = boost::log::sinks::syslog::info;
    mapping[warning] = boost::log::sinks::syslog::warning;
    mapping[error] = boost::log::sinks::syslog::error;

    sink->set_formatter(
        boost::log::expressions::stream
        // line id will be written in hex, 8-digits, zero-filled
        << executable << " <" << severity
        << "> : " << boost::log::expressions::smessage);

    sink->locked_backend()->set_severity_mapper(mapping);

    // Set the remote address to sent syslog messages to
    sink->locked_backend()->set_target_address("localhost");

    // Wrap it into the frontend and register in the core.
    // The backend requires synchronization in the frontend.
    boost::log::core::get()->add_sink(sink);
}

class Cls1
{
    BoostLogger m_lg;
public:
    Cls1()
    {
        // set the class name to Cls1
    }

    void foo()
    {
        // print log that has "Class Name" attribute set to "Cls1"
    }
};

class Cls2
{
    BoostLogger m_lg;
public:
    Cls2()
    {
        // set the class name to Cls2
    }


    void foo()
    {
        // print log that has "Class Name" attribute set to "Cls2"
    }
};

int main(int argc, char** argv)
{
    init_syslog();

    Cls1 o1;
    o1.foo();
    Cls2 o2;
    o2.foo();

    return 0;
}

现在我卡住了...

  1. 怎么做比较好?
  2. 如何将属性设置为想要的值?
  3. 我应该将 BoostLogger 成员设为静态吗?

感谢您的任何建议。我看过 boost 日志属性教程( link1link2link3 ),但我还没有找到有用的东西...

最佳答案

下面是我编写的示例:

记录器.hpp :

#ifndef LOGGER_HPP
#define LOGGER_HPP

#include <ostream>
#include <fstream>

#include <boost/shared_ptr.hpp>
#include <boost/log/common.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/sources/logger.hpp>
#include <boost/log/sinks/async_frontend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/utility/empty_deleter.hpp>

class Logger
{
public:

    typedef boost::log::sinks::asynchronous_sink<boost::log::sinks::text_ostream_backend> text_sink;

    Logger();

    ~Logger();

    void    Initialize();

    void    Finalize();

    void    addStream(boost::shared_ptr<std::ostream>& stream);

    template< typename T >
    Logger& operator<<(const T& value)
    {
        BOOST_LOG(my_logger::get()) << value;
        return *this;
    }

    typedef Logger& (*LoggerManipulator)(Logger&);

    Logger& operator<<(LoggerManipulator manip)
    {
        return manip(*this);
    }

    static Logger& endl(Logger& stream)
    {
        std::cout << std::endl;
        return stream;
    }


    typedef std::basic_ostream<char, std::char_traits<char>> CoutType;

    typedef CoutType& (*StandardEndLine)(CoutType&);

    Logger& operator<<(StandardEndLine manip)
    {
        manip(std::cout);
        return *this;
    }

private:

    boost::log::sources::logger_mt m_lg;

    boost::shared_ptr<text_sink> m_sink;

};

#endif LOGGER_HPP

记录器.cpp:

    #include <boost/date_time/posix_time/posix_time.hpp>

    #include "Logger.hpp"

    Logger::Logger()
        :
        m_sink(new text_sink),
        m_lg()
    {
    }

    Logger::~Logger()
    {
    }

    void    Logger::Initialize()
    {
        m_sink->locked_backend()->auto_flush(true);

    m_sink->set_formatter
        (
        boost::log::expressions::format("[%1%] - %2%")
        % boost::log::expressions::attr< boost::posix_time::ptime >("TimeStamp")
        % boost::log::expressions::smessage
        );

    boost::log::core::get()->add_sink(m_sink);

    boost::log::core::get()->add_global_attribute("TimeStamp",boost::log::attributes::local_clock());
}

void    Logger::Finalize()
{
}

void    Logger::addStream(boost::shared_ptr<std::ostream>& stream)
{
    m_sink->locked_backend()->add_stream(stream);
}

主要.cpp:

int main
{
    boost::shared_ptr<std::ostream> stream_out(&std::clog, boost::empty_deleter());
    boost::shared_ptr<std::ostream> stream_file(new std::ofstream(ProgramName + ".log", std::ostream::app));

    Logger logger;

    logger.addStream(stream_out);
    logger.addStream(stream_file);
    logger.Initialize();

    logger << "Sample";

return 0;
}

关于c++ - boost 日志记录类属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25041577/

有关c++ - boost 日志记录类属性的更多相关文章

  1. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  2. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

  5. ruby - Sinatra:运行 rspec 测试时记录噪音 - 2

    Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/

  6. ruby - Nokogiri 剥离所有属性 - 2

    我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog

  7. ruby-on-rails - Rails 模型——非持久类成员或属性? - 2

    对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs

  8. ruby-on-rails - Rails 5 Active Record 记录无效错误 - 2

    我有两个Rails模型,即Invoice和Invoice_details。一个Invoice_details属于Invoice,一个Invoice有多个Invoice_details。我无法使用accepts_nested_attributes_forinInvoice通过Invoice模型保存Invoice_details。我收到以下错误:(0.2ms)BEGIN(0.2ms)ROLLBACKCompleted422UnprocessableEntityin25ms(ActiveRecord:4.0ms)ActiveRecord::RecordInvalid(Validationfa

  9. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  10. ruby-on-rails - 事件记录 : Select max of limit - 2

    我正在尝试将以下SQL查询转换为ActiveRecord,它正在融化我的大脑。deletefromtablewhereid有什么想法吗?我想做的是限制表中的行数。所以,我想删除少于最近10个条目的所有内容。编辑:通过结合以下几个答案找到了解决方案。Temperature.where('id这给我留下了最新的10个条目。 最佳答案 从您的SQL来看,您似乎想要从表中删除前10条记录。我相信到目前为止的大多数答案都会如此。这里有两个额外的选择:基于MurifoX的版本:Table.where(:id=>Table.order(:id).

随机推荐