#include "./misc.h"
#include "lite/global.h"
#include <time.h>
#include <chrono>
#include <cstdarg>
#if LITE_BUILD_WITH_MGE
#include "megbrain/common.h"
#endif
#ifdef __ANDROID__
#include <android/log.h>
#endif
using namespace lite;
namespace lite {
namespace log_detail {
LiteLogLevel current_log_level = LiteLogLevel::ERROR;
template <class T, size_t N>
constexpr size_t countof(T (&)[N]) {
return N;
}
} }
namespace {
std::string svsprintf(const char* fmt, va_list ap_orig) {
int size = 100;
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;
}
}
}
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<uint32_t>(level) < static_cast<uint32_t>(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<microseconds>(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
}