#include "DebugLog.h" #include #include #include #include #include #include #include #include namespace { std::mutex g_mtx; FILE* g_fp = nullptr; std::string g_path; constexpr size_t kMaxSize = 2 * 1024 * 1024; // 2 MB before rotation pid_t currentTid() { return static_cast(syscall(SYS_gettid)); } } // namespace namespace DebugLog { void init(const char* internalDataPath) { std::lock_guard lk(g_mtx); if (g_fp) { return; // already initialized } const char* base = (internalDataPath && *internalDataPath) ? internalDataPath : "/data/local/tmp"; g_path = std::string(base) + "/face_sdk_debug.log"; // Rotate once if current file is too large. struct stat st{}; if (stat(g_path.c_str(), &st) == 0 && static_cast(st.st_size) > kMaxSize) { std::string backup = g_path + ".old"; std::remove(backup.c_str()); std::rename(g_path.c_str(), backup.c_str()); } g_fp = std::fopen(g_path.c_str(), "a"); if (g_fp) { time_t now = time(nullptr); struct tm tm_info{}; localtime_r(&now, &tm_info); char tbuf[64]; strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M:%S", &tm_info); std::fprintf(g_fp, "\n========== DebugLog opened @ %s (pid=%d) ==========\n", tbuf, getpid()); std::fflush(g_fp); } __android_log_print(ANDROID_LOG_INFO, "FACE_DBG", "DebugLog file path: %s", g_path.c_str()); } void log(const char* fmt, ...) { char buf[1024]; va_list ap; va_start(ap, fmt); int n = std::vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); if (n < 0) return; pid_t tid = currentTid(); timespec ts{}; clock_gettime(CLOCK_REALTIME, &ts); struct tm tm_info{}; localtime_r(&ts.tv_sec, &tm_info); char timebuf[32]; strftime(timebuf, sizeof(timebuf), "%H:%M:%S", &tm_info); std::lock_guard lk(g_mtx); if (g_fp) { std::fprintf(g_fp, "[%s.%03ld][tid=%d] %s\n", timebuf, ts.tv_nsec / 1000000, tid, buf); std::fflush(g_fp); } __android_log_print(ANDROID_LOG_INFO, "FACE_DBG", "[tid=%d] %s", tid, buf); } void flush() { std::lock_guard lk(g_mtx); if (g_fp) std::fflush(g_fp); } std::string getLogPath() { std::lock_guard lk(g_mtx); return g_path; } } // namespace DebugLog