I'm attempting to use Boost.Log (in v1.57) to write logs to multiple platforms, Android included. For the NDK code we have, I need to send log messages down to __android_log_print
.
After reading the documentation over and over (The whole system is pretty complex), it seems that I either need to write my own logging backend. Alternatively, it seems I could use their existing ostream backend and write my own stream (with Boost.Iostream).
The thing is, a stream isn't really appropriate for this if you think about it. I won't necessarily have a buffer that I'm storing the logs inside of. I'm just forwarding them along to the aforementioned Android NDK function.
What is the proper solution here? IO streams or custom backend for the logger?
I suggest creating a custom sink backend which forwards the log messages to the android logging function. The following example code implements this and uses the android log levels so that you can filter log messages based on the log level. You can of course define your own log levels and add a mapping between your log level and the android ones.
You need to call boost_android_logging::init()
once, then you can instantiate a boost_android_logging::Logger
wherever you need one and send log messages using BOOST_LOG_SEV
.
#include <iostream>
typedef enum android_LogPriority {
ANDROID_LOG_UNKNOWN = 0,
ANDROID_LOG_DEFAULT,
ANDROID_LOG_VERBOSE,
ANDROID_LOG_DEBUG,
ANDROID_LOG_INFO,
ANDROID_LOG_WARN,
ANDROID_LOG_ERROR,
ANDROID_LOG_FATAL,
ANDROID_LOG_SILENT,
} android_LogPriority;
int fake__android_log_print(int prio, const char *tag, const char *fmt, ...)
{
std::cout << prio << " " << tag << ": " << fmt << std::endl;
return 0;
}
#include <boost/log/attributes.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/sources/logger.hpp>
#include <boost/log/utility/setup.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/expressions/keyword.hpp>
namespace boost_android_logging
{
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", android_LogPriority)
BOOST_LOG_ATTRIBUTE_KEYWORD(module, "Module", std::string)
namespace logging = boost::log;
namespace sinks = boost::log::sinks;
namespace expr = boost::log::expressions;
struct android_sink_backend : public sinks::basic_sink_backend<logging::sinks::concurrent_feeding>
{
void consume(const logging::record_view& rec)
{
android_LogPriority log_sev = rec[severity].get();
const char* log_msg = rec[expr::smessage].get().c_str();
const char* log_module = "unknown";
if (rec[module])
{
log_module = rec[module].get().c_str();
}
// forward to actual logging function
fake__android_log_print(log_sev, log_module, log_msg);
}
};
typedef boost::log::sources::severity_logger<android_LogPriority> Logger;
void init()
{
logging::add_common_attributes();
typedef sinks::synchronous_sink<android_sink_backend> android_sink;
boost::shared_ptr<android_sink> sink = boost::make_shared<android_sink>();
sink->set_filter(severity >= ANDROID_LOG_INFO);
logging::core::get()->add_sink(sink);
}
void shutdown()
{
logging::core::get()->remove_all_sinks();
}
} // namespace boost_android_logging
#define SET_MODULE(logger,log_module) logger.add_attribute(boost_android_logging::module.get_name(), boost::log::attributes::constant<std::string>(#log_module));
struct Demo
{
Demo()
{
SET_MODULE(logger, Demo);
BOOST_LOG_SEV(logger, ANDROID_LOG_WARN) << "this is a warning";
}
void test()
{
BOOST_LOG_SEV(logger, ANDROID_LOG_FATAL) << "fatal error occured";
}
boost_android_logging::Logger logger;
};
int main()
{
boost_android_logging::init();
boost_android_logging::Logger logger;
SET_MODULE(logger, main);
BOOST_LOG_SEV(logger, ANDROID_LOG_WARN) << "this is a warning";
BOOST_LOG_SEV(logger, ANDROID_LOG_DEBUG) << "this will be filtered";
BOOST_LOG_SEV(logger, ANDROID_LOG_FATAL) << "fatal error occured";
Demo d;
d.test();
boost_android_logging::shutdown();
}
live on coliru
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With