misc.cpp 4.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
#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>
14
#include <sys/system_properties.h>
15 16 17 18 19 20 21
#endif

using namespace lite;

namespace lite {
namespace log_detail {

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
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<LiteLogLevel>(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<LiteLogLevel>(atoi(buf));
    }
#endif

    return default_level;
}
LiteLogLevel current_log_level = config_default_log_level();
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113

template <class T, size_t N>
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, ...) {
114 115
    if (!format)
        return "";
116 117 118 119 120 121 122 123
    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, ...) {
124 125
    if (!format)
        return;
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
    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];
M
Megvii Engine Team 已提交
146 147 148
    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()));
149

M
Megvii Engine Team 已提交
150
    const char* prefix[] = {"LITE[DBG] ", "LITE[INF] ", "LITE[WRN] ", "LITE[ERR] "};
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
    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}}}