0
votes

I have a program which make use of boost logging and most of the time this program writes logs either to a local file or when deployed to /var/log/messages via rsyslog. Most of the time we are just interested in seeing Error (boost::log::trivial::error) but when in development we want to log at higher levels. Everything seeems great with this method of logging, we also have several python scripts that also make use of rsyslog, they also put normally into /va/log/messages without issue.

My recent task as a developer is to move logging from /va/log/messages into postgres database table to allow an external client to get notification of when an error might happen. Anyway I've manages to get my logging into said database with a few tweaks to the /etc/rsyslog.conf file and adding files to our postgres database.

During my debugging process I have noticed with my C++ application every time I write a LOG ERROR to the syslog, the priority (column in database table) is set to level 6(info) and not level 3(error) (from rsyslog web pages). The python code always logs priority leve 3. This make it very difficult to now filter on. My boost config is as:

   if (syslog)
   {
       // Create a backend
       m_syslogSink = boost::make_shared<syslog_sink>(
            boost::log::keywords::facility = boost::log::sinks::syslog::user,
            boost::log::keywords::use_impl = boost::log::sinks::syslog::native
        );

        // Set the straightforward level translator for the "Severity" attribute of type int
        m_syslogSink->locked_backend()->set_severity_mapper(
            boost::log::sinks::syslog::direct_severity_mapping<int>("Severity"));
        
        m_syslogSink->set_formatter(
            boost::log::expressions::stream
                << boost::log::expressions::if_(boost::log::expressions::has_attr(unitName))[
                        boost::log::expressions::stream << '[' << unitName << "] "
                    ]
                << boost::log::expressions::smessage
            );

        // Share the filter level with the file log level but don't allow trace
        m_syslogSink->set_filter(boost::bind(
            &LogFilter, &m_fileLogLevel,
            boost::log::trivial::debug, boost::log::trivial::fatal,
            LogSource::LogType::FILE_OR_SYSLOG, ::_1));

        // Register the syslog sink with the logging core
        core->add_sink(m_syslogSink);
    }

our LOG_ERROR breaks down into BOOST_LOG_SEV(LogControl::getLog()->log, boost::log::trivial::error) << "A Error message";

Anyone know why this might be is it a known bug? in the boost library or have I done something stupid or is it not possible. I am using the boost::log::trivial::error level.

the /etc/rsyslog.conf contains the line *.info;mail.none;authpriv.none;cron.none :ompgsql:127.0.0.1,syslog,rsyslog,secret to place it into the database.

and raising a syslog log error using python code which does what I want syslog.syslog(syslog.LOG_ERROR, "ERROR message")

Thanks in advance.

1

1 Answers

0
votes

The problem is twofold, and comes from this line:

m_syslogSink->locked_backend()->set_severity_mapper(
    boost::log::sinks::syslog::direct_severity_mapping<int>("Severity"));

First, you're specifying the "Severity" attribute value type to be int, but given that you're providing boost::log::trivial::error in the logging statement, I'm assuming the value type is actually boost::log::trivial::severity_level. This mismatch means that the attribute value cannot be extracted from the log record, and a default value, which happens to be boost::log::sinks::syslog::info, is used.

Second, you're using direct_severity_mapping, which effectively performs no conversion from the attribute value to the syslog level, which is represented by boost::log::sinks::syslog::level enum. This mapping can only be used when the severity level attribute is boost::log::sinks::syslog::level or has values equivalent to that enum. boost::log::trivial::severity_level has different values, so it must be explicitly mapped to boost::log::sinks::syslog::level. For that you can use custom_severity_mapping.

boost::log::sinks::syslog::custom_severity_mapping< boost::log::trivial::severity_level > mapping;

mapping[boost::log::trivial::info] = boost::log::sinks::syslog::info;
mapping[boost::log::trivial::warning] = boost::log::sinks::syslog::warning;
mapping[boost::log::trivial::error] = boost::log::sinks::syslog::error;
// etc.

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