在 Android 上使用 Boost.Log 进行 logcat
Using Boost.Log on Android for logcats
我正在尝试使用 Boost.Log(在 v1.57 中)将日志写入多个平台,包括 Android。对于我们拥有的 NDK 代码,我需要将日志消息发送到 __android_log_print
.
看了一遍又一遍的文档(整个系统很复杂),看来我要么需要自己写一个日志后端。或者,我似乎可以使用他们现有的 ostream 后端并编写我自己的流(使用 Boost.Iostream)。
问题是,如果您考虑一下,流并不真正适合这个。我不一定有一个缓冲区来存储日志。我只是将它们转发给前面提到的 Android NDK 函数。
这里的正确解决方案是什么?记录器的 IO 流或自定义后端?
我建议创建一个自定义接收器后端,将日志消息转发到 android 日志记录功能。
以下示例代码实现了这一点并使用 android 日志级别,以便您可以根据日志级别过滤日志消息。您当然可以定义自己的日志级别,并在您的日志级别和 android 之间添加一个映射。
您需要调用 boost_android_logging::init()
一次,然后您可以在任何需要的地方实例化一个 boost_android_logging::Logger
并使用 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();
}
我正在尝试使用 Boost.Log(在 v1.57 中)将日志写入多个平台,包括 Android。对于我们拥有的 NDK 代码,我需要将日志消息发送到 __android_log_print
.
看了一遍又一遍的文档(整个系统很复杂),看来我要么需要自己写一个日志后端。或者,我似乎可以使用他们现有的 ostream 后端并编写我自己的流(使用 Boost.Iostream)。
问题是,如果您考虑一下,流并不真正适合这个。我不一定有一个缓冲区来存储日志。我只是将它们转发给前面提到的 Android NDK 函数。
这里的正确解决方案是什么?记录器的 IO 流或自定义后端?
我建议创建一个自定义接收器后端,将日志消息转发到 android 日志记录功能。 以下示例代码实现了这一点并使用 android 日志级别,以便您可以根据日志级别过滤日志消息。您当然可以定义自己的日志级别,并在您的日志级别和 android 之间添加一个映射。
您需要调用 boost_android_logging::init()
一次,然后您可以在任何需要的地方实例化一个 boost_android_logging::Logger
并使用 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();
}