#include "./misc.h" #include "lite/global.h" #include #include #include #if LITE_BUILD_WITH_MGE #include "megbrain/common.h" #endif #ifdef __ANDROID__ #include #include #endif using namespace lite; namespace lite { namespace log_detail { LiteLogLevel config_default_log_level() { auto default_level = LiteLogLevel::ERROR; //! env to config LogLevel //! DEBUG = 0, INFO = 1, WARN = 2, ERROR = 3, NO_LOG = 4 //! for example , export RUNTIME_OVERRIDE_LOG_LEVEL=0, means set LogLevel to //! DEBUG if (auto env = ::std::getenv("RUNTIME_OVERRIDE_LOG_LEVEL")) default_level = static_cast(std::stoi(env)); #ifdef __ANDROID__ //! special for Android prop, attention: getprop may need permission char buf[PROP_VALUE_MAX]; if (__system_property_get("RUNTIME_OVERRIDE_LOG_LEVEL", buf) > 0) { default_level = static_cast(atoi(buf)); } #endif return default_level; } LiteLogLevel current_log_level = config_default_log_level(); template constexpr size_t countof(T (&)[N]) { return N; } } // namespace log_detail } // namespace lite namespace { std::string svsprintf(const char* fmt, va_list ap_orig) { int size = 100; /* Guess we need no more than 100 bytes */ char* p; if ((p = (char*)malloc(size)) == nullptr) return "svsprintf: malloc failed"; for (;;) { va_list ap; va_copy(ap, ap_orig); int n = vsnprintf(p, size, fmt, ap); va_end(ap); if (n < 0) return "svsprintf: vsnprintf failed"; if (n < size) { std::string rst(p); free(p); return rst; } size = n + 1; char* np = (char*)realloc(p, size); if (!np) { free(p); return "svsprintf: realloc failed"; } else p = np; } } } // namespace void lite::set_log_level(LiteLogLevel l) { log_detail::current_log_level = l; #if LITE_BUILD_WITH_MGE mgb::LogLevel lite_log_level = mgb::LogLevel::DEBUG; switch (l) { case LiteLogLevel::DEBUG: lite_log_level = mgb::LogLevel::DEBUG; break; case LiteLogLevel::INFO: lite_log_level = mgb::LogLevel::INFO; break; case LiteLogLevel::WARN: lite_log_level = mgb::LogLevel::WARN; break; case LiteLogLevel::ERROR: lite_log_level = mgb::LogLevel::ERROR; break; default: LITE_THROW("unkonw loglevel"); } mgb::set_log_level(lite_log_level); #endif } LiteLogLevel lite::get_log_level() { return log_detail::current_log_level; } std::string lite::ssprintf(const char* format, ...) { if (!format) return ""; va_list ap; va_start(ap, format); auto ret = svsprintf(format, ap); va_end(ap); return ret; } void lite::print_log(LiteLogLevel level, const char* format, ...) { if (!format) return; if (static_cast(level) < static_cast(get_log_level())) { return; } using namespace std::chrono; auto now = system_clock::now(); auto now_time_t = system_clock::to_time_t(now); tm now_tm; #if _WIN32 localtime_s(&now_tm, &now_time_t); #else localtime_r(&now_time_t, &now_tm); #endif auto now_trunc_to_sec = system_clock::from_time_t(mktime(&now_tm)); auto microsec = duration_cast(now - now_trunc_to_sec); char time_buffer[100]; snprintf( time_buffer, log_detail::countof(time_buffer), "%02d:%02d:%02d.%06ld ", now_tm.tm_hour, now_tm.tm_min, now_tm.tm_sec, long(microsec.count())); const char* prefix[] = {"LITE[DBG] ", "LITE[INF] ", "LITE[WRN] ", "LITE[ERR] "}; std::string out; out += prefix[int(level)]; out += time_buffer; va_list ap; va_start(ap, format); auto ret = svsprintf(format, ap); va_end(ap); out += ret; #ifdef __ANDROID__ __android_log_print(ANDROID_LOG_INFO, "lite", "%s", out.c_str()); #else fprintf(stderr, "%s\n", out.c_str()); #endif } // vim: syntax=cpp.doxygen foldmethod=marker foldmarker=f{{{,f}}}