package com.netease.nim.uikit.common.util.log; import android.text.TextUtils; import android.util.Log; import com.netease.nim.uikit.common.util.storage.StorageUtil; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.concurrent.Executor; import java.util.concurrent.Executors; final class LogImpl { private static final String FILE_FORMAT = "yyyyMMdd"; private static final String MESSAGE_FORMAT = "MM-dd HH:mm:ss.ms"; private static final String SUFFIX = ".log"; private static final String SEPARATOR = "."; private static String logPath; private static int level = Log.DEBUG; private static final DateFormat messageFormat = new SimpleDateFormat(MESSAGE_FORMAT, Locale.getDefault()); private static final DateFormat fileNameFormat = new SimpleDateFormat(FILE_FORMAT, Locale.getDefault()); private static final Executor logger = Executors.newSingleThreadExecutor(); public static void init(String logPath, int level) { LogImpl.logPath = logPath; LogImpl.level = level; } public static void i(String tag, String msg) { i(tag, msg, null); } public static void i(String tag, String msg, Throwable tr) { o(Log.INFO, tag, msg, tr); } public static void v(String tag, String msg) { v(tag, msg, null); } public static void v(String tag, String msg, Throwable tr) { o(Log.VERBOSE, tag, msg, tr); } public static void e(String tag, String msg) { e(tag, msg, null); } public static void e(String tag, String msg, Throwable tr) { o(Log.ERROR, tag, msg, tr); } public static void d(String tag, String msg) { d(tag, msg, null); } public static void d(String tag, String msg, Throwable tr) { o(Log.DEBUG, tag, msg, tr); } public static void w(String tag, String msg) { w(tag, msg, null); } public static void w(String tag, String msg, Throwable tr) { o(Log.WARN, tag, msg, tr); } public static void o(int priority, String tag, String msg) { o(priority, tag, msg, null); } public static void o(final int priority, final String tag, final String msg, final Throwable tr) { final long time = System.currentTimeMillis(); final long threadId = Thread.currentThread().getId(); logger.execute(new Runnable() { @Override public void run() { String timeStr = messageFormat.format(new Date(time)); Log.println(priority, tag, threadId + "/" + msg + '\n' + Log.getStackTraceString(tr)); if (level <= priority) { outMessage(tag, timeStr, msg, tr); } } }); } public static void setLevel(int level) { LogImpl.level = level; } private static void outMessage(String tag, String time, String msg, Throwable tr) { outMessage("", tag, time, msg, tr); } private static void outMessage(String cat, String tag, String time, String msg, Throwable tr) { if (TextUtils.isEmpty(logPath)) { return; } outputToFile(formatMessage(tag, time, msg, tr), getLogFilePath(cat)); } private static String formatMessage(String tag, String time, String msg, Throwable tr) { StringBuilder sb = new StringBuilder(); // time sb.append(time); sb.append(": "); // tag sb.append(tag); sb.append(": "); // message sb.append(msg); sb.append("\n"); // Throwable if (tr != null) { sb.append(Log.getStackTraceString(tr)); sb.append("\n"); } return sb.toString(); } private static boolean outputToFile(String message, String path) { if (TextUtils.isEmpty(message)) { return false; } if (TextUtils.isEmpty(path)) { return false; } StorageUtil.checkValid(); boolean written = false; try { BufferedWriter fw = new BufferedWriter(new FileWriter(path, true)); fw.write(message); fw.flush(); fw.close(); written = true; } catch (Exception e) { e.printStackTrace(); } return written; } /*package*/ static String getLogFileName(String cat) { StringBuilder sb = new StringBuilder(); sb.append(fileNameFormat.format(new Date())); if (!TextUtils.isEmpty(cat)) { sb.append(SEPARATOR); sb.append(cat); } sb.append(SUFFIX); return sb.toString(); } private static String getLogFilePath(String cat) { File dir = new File(logPath); if (!dir.exists()) { dir.mkdirs(); } return logPath + "/" + getLogFileName(cat); } }