Setting up custom format and filter for Boost.Log: nothing happens

Viewed 203

I have issues configuring Boost.Log. I want a single, global logger to print to std::cout all messages with severity debug or higher. The format of the message is a simple "foobar: " prefix.

What I expect to be printed: foobar: foobar.

What is printed: nothing.

Sample code:

main.c:

#include "logger.hh"

int main() {
    init_logger();
    using namespace boost::log::trivial;
    BOOST_LOG_SEV(my_logger::get(), debug) << "foobar";
}

logger.hh:

#include <boost/log/sources/global_logger_storage.hpp>
#include <boost/log/sources/severity_feature.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/trivial.hpp>

BOOST_LOG_GLOBAL_LOGGER(my_logger, boost::log::sources::severity_logger_mt<>)
void init_logger();

logger.cc:

#include "logger.hh"

#include <boost/core/null_deleter.hpp>
#include <boost/log/core.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/logger.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>

#include <iostream>

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

BOOST_LOG_GLOBAL_LOGGER_INIT(my_logger, src::severity_logger_mt) {
    src::severity_logger_mt<> lg;
    return lg;
}

void init_logger() {
    // Construct the sink
    auto sink = boost::make_shared<sinks::synchronous_sink<sinks::text_ostream_backend>>();
    boost::shared_ptr<std::ostream> stream(&std::cout, boost::null_deleter{});
    sink->locked_backend()->add_stream(stream);
    sink->set_formatter(expr::stream << "foobar: " << expr::smessage);       // ???
    sink->set_filter(logging::trivial::severity >= logging::trivial::debug); // ???
    // Register the sink in the logging core
    logging::core::get()->add_sink(sink);
}

I do not understand what I'm doing wrong.

1 Answers

While browsing other answers and experimenting, I have realized a few things that are not stated clearly in the Boost.Log documentation and tutorial.

severity_logger_mt must be instantiated with a concrete type that represents a severity struct, with default being just an int (perhaps to eat any user-provided enums). An example of a severity struct is a severity_level struct from boost::log::trivial::severity_level.

The code below is a full working example:

main.cc: no changes.

logger.hh:

#pragma once

#include <boost/log/sources/global_logger_storage.hpp>
#include <boost/log/sources/severity_feature.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/trivial.hpp>

BOOST_LOG_GLOBAL_LOGGER(
    my_logger, boost::log::sources::severity_logger_mt<boost::log::trivial::severity_level>)

void init_logger();

logger.cc:

#include "logger.hh"

#include <boost/core/null_deleter.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/trivial.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>

#include <iostream>

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

BOOST_LOG_GLOBAL_LOGGER_INIT(my_logger, src::severity_logger_mt<logging::trivial::severity_level>) {
    src::severity_logger_mt<logging::trivial::severity_level> lg;
    return lg;
}

void init_logger() {
    // Construct the sink
    auto sink = boost::make_shared<sinks::synchronous_sink<sinks::text_ostream_backend>>();
    boost::shared_ptr<std::ostream> stream(&std::cout, boost::null_deleter{});
    sink->locked_backend()->add_stream(stream);
    sink->set_formatter(expr::stream << "foobar: " << expr::smessage);
    sink->set_filter(logging::trivial::severity >= logging::trivial::debug);
    // Register the sink in the logging core
    logging::core::get()->add_sink(sink);
}

An alternative way to adding a new sink explicitly is to use a helper function, such as add_console_log().

#include <boost/log/utility/setup/console.hpp>
namespace keywords = boost::log::keywords;
BOOST_LOG_GLOBAL_LOGGER_INIT(my_logger, src::severity_logger_mt<logging::trivial::severity_level>) {
    src::severity_logger_mt<logging::trivial::severity_level> lg;
    logging::add_console_log(std::cout,
                             keywords::format = (expr::stream << "foobar: " << expr::smessage));
    logging::core::get()->set_filter(logging::trivial::severity >= logging::trivial::debug);
    return lg;
}
Related