0

I'm using Boost.Log V2 1.75.0 and setting up my environment from configuration file by using boost::log::init_from_stream(config);

Is it possible to declare colored console sink trough configuration file or is there any way add colored output to the console?

Now, I add as many Console sink as many log level available in Boost Trivial Logger and filter them by distinct level, but I don't think, that this is the right way. Example:

[Sinks.ConsoleSinkTrace]
Destination=Console
Filter="%Severity% = trace"
Format="\033[0;35m[%TimeStamp%] [%ProcessId%] [%ThreadId%] [%Severity%] - %Message%\033[0m"
Asynchronous=false
AutoFlush=true

[Sinks.ConsoleSinkDebug]
Destination=Console
Filter="%Severity% = debug"
Format="\033[0;34m[%TimeStamp%] [%ProcessId%] [%ThreadId%] [%Severity%] - %Message%\033[0m"
Asynchronous=false
AutoFlush=true

... and so on...

Update

I have found the SO post suggested by @AndreySemashev, but I don't really understand, how can I accommodate it into my project: My key expectation is that I want to configure Boost.Log via file, so:

  1. if I delete console sink from config file at all, how to set the formatter to the sink? (I guess sink is a Console type sink that won't be instantiated if there is no such section in the config file)

sink->set_formatter(&coloring_formatter);

  1. if I provide a new formatter method, I assume, that handling the entire format string given in the config file is my responsible. I would like to avoid this too

Are these observations correct, or do I miss something?

Thank you

Moravas
  • 79
  • 6

1 Answers1

0

Creating a formatter with coloring support is described in another answer, here I will focus on how to incorporate that formatter into a settings file.

Boost.Log supports extending its settings file parser by registering sink factories, which you can leverage in your case. Since you can reuse the text_ostream_backend for output, you don't have to implement a new sink, but you do need to customize its configuration.

class colored_console_factory :
    public logging::sink_factory< char >
{
public:
    // Creates the sink with the provided parameters
    boost::shared_ptr< sinks::sink > create_sink(settings_section const& settings)
    {
        typedef sinks::text_ostream_backend backend_t;
        auto backend = boost::make_shared< backend_t >();

        backend->add_stream(
            boost::shared_ptr< std::ostream >(&std::clog, boost::null_deleter()));

        // Read settings and configure the backend accordingly
        if (auto auto_flush = settings["AutoFlush"])
            backend->auto_flush(*auto_flush == "1" || *auto_flush == "true");

        auto sink =
            boost::make_shared< sinks::synchronous_sink< backend_t > >(backend);

        // You can reuse filter and formatter parsers provided by Boost.Log
        if (auto filter = settings["Filter"])
            sink->set_filter(logging::parse_filter(*filter));

        if (auto format = settings["Format"])
        {
            logging::formatter fmt = logging::parse_formatter(*format);
            // Wrap the parsed formatter with coloring
            sink->set_formatter(coloring_formatter(std::move(fmt)));
        }

        return sink;
    }
};

In the above, coloring_formatter is a function object that wraps the parsed formatter with coloring prefix and suffix in the output. The function object must have the standard signature of the formatter.

class coloring_formatter
{
public:
    typedef void result_type;
    typedef basic_formatting_ostream< char > stream_type;

public:
    explicit coloring_formatter(logging::formatter&& fmt) :
        m_fmt(std::move(fmt))
    {}

    result_type operator() (
        logging::record_view const& rec, stream_type& strm) const
    {
        // Output coloring prefix
        auto severity = rec[logging::trivial::severity];
        if (severity)
        {
            switch (severity.get())
            {
                ...
            }
        }

        // Let the wrapped formatter produce its output
        m_fmt(rec, strm);

        // Output coloring suffix
        if (severity)
        {
            ...
        }
    }

private:
    logging::formatter m_fmt;
};

Refer to the answer I mentioned earlier for details on coloring_formatter implementation.

Andrey Semashev
  • 10,046
  • 1
  • 17
  • 27
  • Thank you @AndreySemashev. I think, adding this sink support to the library would be a welcome. – Moravas Mar 16 '21 at 06:43