您的位置:首页 > 其它

log日志打印封装,并保存到本地文件

2016-06-21 19:33 447 查看
封装了本地日志,可以通过config

文件动态控制log的打印,方便上线前日志打印的检查,并且如果在测试环境下,日志等级为i以上的日志都会存文件,并且文件以日期命名,最大数量为5,可以配置。

代码如下所示:

public final class EBLog {
private static final String TAG = EBLog.class.getName();

/**
* Define the log priority.
*/
private static LogType logType;

private static HashMap<Integer, String> level = new HashMap<>();

static {
level.put(2, "verbose");
level.put(3, "debug");
level.put(4, "info");
level.put(5, "warn");
level.put(6, "error");
level.put(7, "asset");
if (Config.ISRELEASE) {
setLogType(LogType.asset);
} else {
setLogType(LogType.verbose);
}
}

private EBLog() {
}

/**
* Get the log level.
*
* @return log level
*/
public static LogType getLogType() {
return logType;
}

/**
* Set the log level for the application.
*
* @param logType the value to be set.
*/
public static void setLogType(LogType logType) {
EBLog.logType = logType;
i(TAG, "logType: " + logType);
}

/**
* Send a  log message.
*
* @param tag Used to identify the source of a log message. It usually
*            identifies the class or activity where the log call occurs.
* @param msg The message you would like logged.
*/
public static int v(String tag, String msg) {
StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[3];
return ElectronicBrandPrintln(LogType.verbose.value(), tag, msg,stackTraceElement);
}

/**
* Send a  log message and log the exception.
*
* @param tag Used to identify the source of a log message. It usually
*            identifies the class or activity where the log call occurs.
* @param msg The message you would like logged.
* @param tr  An exception to log
*/
public static int v(String tag, String msg, Throwable tr) {
StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[3];
return ElectronicBrandPrintln(LogType.verbose.value(), tag, msg + '\n' + getStackTraceString(tr),stackTraceElement);
}

/**
* Send a log message.
*
* @param tag Used to identify the source of a log message. It usually
*            identifies the class or activity where the log call occurs.
* @param msg The message you would like logged.
*/
public static int d(String tag, String msg) {
StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[3];
return ElectronicBrandPrintln(LogType.debug.value(), tag, msg,stackTraceElement);
}

/**
* Send a  log message and log the exception.
*
* @param tag Used to identify the source of a log message. It usually
*            identifies the class or activity where the log call occurs.
* @param msg The message you would like logged.
* @param tr  An exception to log
*/
public static int d(String tag, String msg, Throwable tr) {
StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[3];
return ElectronicBrandPrintln(LogType.debug.value(), tag, msg + '\n' + getStackTraceString(tr),stackTraceElement);
}

/**
* Send an log message.
*
* @param tag Used to identify the source of a log message. It usually
*            identifies the class or activity where the log call occurs.
* @param msg The message you would like logged.
*/
public static int i(String tag, String msg) {
StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[3];
return ElectronicBrandPrintln(LogType.info.value(), tag, msg,stackTraceElement);
}

/**
* Send a log message and log the exception.
*
* @param tag Used to identify the source of a log message. It usually
*            identifies the class or activity where the log call occurs.
* @param msg The message you would like logged.
* @param tr  An exception to log
*/
public static int i(String tag, String msg, Throwable tr) {
StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[3];
return ElectronicBrandPrintln(LogType.info.value(), tag, msg + '\n' + getStackTraceString(tr),stackTraceElement);
}

/**
* Send a log message.
*
* @param tag Used to identify the source of a log message. It usually
*            identifies the class or activity where the log call occurs.
* @param msg The message you would like logged.
*/
public static int w(String tag, String msg) {
StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[3];
return ElectronicBrandPrintln(LogType.warn.value(), tag, msg,stackTraceElement);
}

/**
* Send a log message and log the exception.
*
* @param tag Used to identify the source of a log message. It usually
*            identifies the class or activity where the log call occurs.
* @param msg The message you would like logged.
* @param tr  An exception to log
*/
public static int w(String tag, String msg, Throwable tr) {
StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[3];
return ElectronicBrandPrintln(LogType.warn.value(), tag, msg + '\n' + getStackTraceString(tr),stackTraceElement);
}

/**
* Checks to see whether or not a log for the specified tag is loggable at
* the specified level. The default level of any tag is set to INFO. This
* means that any level above and including INFO will be logged. Before you
* make any calls to a logging method you should check to see if your tag
* should be logged. You can change the default level by setting a system
* property: 'setprop log.tag.<YOUR_LOG_TAG> <LEVEL>' Where level is
* either value of LogType, or SUPPRESS. SUPRESS will turn off all logging
* for your tag. You can also create a local.prop file that with the
* following in it: 'log.tag.<YOUR_LOG_TAG>=<LEVEL>' and place that in
* /data/local.prop.
*
* @param tag   The tag to check.
* @param level The level to check, value of LogType.
* @return Whether or not that this is allowed to be logged.
* @throws IllegalArgumentException is thrown if the tag.length() > 23.
*/
public static native boolean isLoggable(String tag, int level);

/*
* Send a {@link #WARN} log message and log the exception.
*
* @param tag Used to identify the source of a log message. It usually
* identifies the class or activity where the log call occurs.
*
* @param tr An exception to log
*/
public static int w(String tag, Throwable tr) {
StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[3];
return ElectronicBrandPrintln(LogType.warn.value(), tag, getStackTraceString(tr),stackTraceElement);
}

/**
* Send an log message.
*
* @param tag Used to identify the source of a log message. It usually
*            identifies the class or activity where the log call occurs.
* @param msg The message you would like logged.
*/
public static int e(String tag, String msg) {
StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[3];
return ElectronicBrandPrintln(LogType.error.value(), tag, msg,stackTraceElement);
}

/**
* Send a log message and log the exception.
*
* @param tag Used to identify the source of a log message. It usually
*            identifies the class or activity where the log call occurs.
* @param msg The message you would like logged.
* @param tr  An exception to log
*/
public static int e(String tag, String msg, Throwable tr) {
StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[3];
return ElectronicBrandPrintln(LogType.error.value(), tag, msg + "\n" + getStackTraceString(tr),stackTraceElement);
}

/**
* Handy function to get a loggable stack trace from a Throwable
*
* @param tr An exception to log
*/
private static String getStackTraceString(Throwable tr) {
if (tr == null) {
return "";
}
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
tr.printStackTrace(pw);
return sw.toString();
}

private static int ElectronicBrandPrintln(int priority, String tag, String msg,StackTraceElement stackTraceElement) {
if (priority >= logType.value()) {
if (!Config.ISRELEASE && priority >= 4) {
ThreadPoolService.addTask(new LogSaveUtils(getLogInfo( priority, tag, msg,stackTraceElement)));
}
return android.util.Log.println(priority, tag, msg);
} else {
return -1;
}
}

/**
* May be verbose, debug, info, warn, error, asset.
*
* @author coleman
*/
public static enum LogType {
verbose(2), debug(3), info(4), warn(5), error(6), asset(7);

private final int type;

private LogType(int type) {
this.type = type;
}

public int value() {
return type;
}

public static LogType instanse(int i) {
LogType type = verbose;
switch (i) {
case 2:
type = verbose;
break;
case 3:
type = debug;
break;
case 4:
type = info;
break;
case 5:
type = warn;
break;
case 6:
type = error;
break;
case 7:
type = asset;
break;
default:
type = null;
break;
}
return type;
}
}

/**
* 保存日志所包含的信息
*
* @param tag
* @param priority
* @return
*/
private static String getLogInfo(int priority, String tag, String msg,StackTraceElement stackTraceElement) {
StringBuilder logInfoStringBuilder = new StringBuilder();
// 获取线程名
String threadName = Thread.currentThread().getName();
// 获取类名.即包名+类名
String className = stackTraceElement.getClassName();
// 获取方法名称
String methodName = stackTraceElement.getMethodName();
// 获取生日输出行数
int lineNumber = stackTraceElement.getLineNumber();
logInfoStringBuilder.append(GeneralUtils.getCurrentTime(Constants.YEAR_MONTH_DAY_HOUR_MINUTE_SECOND));
logInfoStringBuilder.append("  [");
logInfoStringBuilder.append(threadName).append("]   ");
logInfoStringBuilder.append(className).append("   ");
logInfoStringBuilder.append(level.get(priority)).append("/").append(tag);
logInfoStringBuilder.append("   [methodName=" + methodName).append("]   ");
logInfoStringBuilder.append("[lineNumber=" + lineNumber);
logInfoStringBuilder.append(" ]   ");
logInfoStringBuilder.append(msg);
return logInfoStringBuilder.toString();
}
}


线程池类代码如下:

/**
* <线程池管理>
*
* @author caoyinfei
* @version [版本号, 2016/6/21]
* @see [相关类/方法]
* @since [V1]
*/
public class ThreadPoolService {
private static ExecutorService executor = Executors.newCachedThreadPool();
public static void addTask(LogSaveUtils logSaveUtils){
executor.execute(logSaveUtils);
}
}


文件保存类代码如下:

/**
* <日志文件处理类>
*
* @author caoyinfei
* @version [版本号, 2016/6/21]
* @see [相关类/方法]
* @since [V1]
*/
public class LogSaveUtils implements Runnable {

private String content;

public LogSaveUtils(String content) {
this.content = content;
}

/**
* 文件最大个数
*/
private static final int MAX_SIZE = 5;

/**
* 文件名后缀
*/
private static String FILE_NAME = ".log";

/**
* 文件
*/
private File file;

/**
* 输出流
*/
private RandomAccessFile randomAccessFile;

private SimpleDateFormat dataFormat = new SimpleDateFormat("yyyy-MM-dd");// 日志名称格式

@Override
public void run() {
saveToFile();
}

/**
* 保存到本地文件
*/
private synchronized void saveToFile() {
try {
deleteFile();
LocalFileStorageManager localFileStorageManager = BridgeFactory.getBridge(Bridges.LOCAL_FILE_STORAGE);
String fileName = localFileStorageManager.getVersionLogPath() + Config.LOG_FILE_NAME + GeneralUtils.getCurrentTime(Constants.YEAR_MONTH_DAY) + FILE_NAME;
file = new File(fileName);
randomAccessFile = new RandomAccessFile(file, "rw");
randomAccessFile.seek(file.length());
randomAccessFile.write(content.getBytes("utf-8"));
randomAccessFile.write("\r\n".getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
randomAccessFile.close();
} catch (Exception e) {

}
}
}

/**
* 文件超过最大个数则删除最旧的文件
*/
private void deleteFile() {
LocalFileStorageManager localFileStorageManager = BridgeFactory.getBridge(Bridges.LOCAL_FILE_STORAGE);
File root = new File(localFileStorageManager.getVersionLogPath());
if (root.isDirectory()) {
File[] listFiles = root.listFiles();
if (listFiles != null && listFiles.length >= MAX_SIZE) {
Arrays.sort(listFiles, new FileComparator());
listFiles[0].delete();
}
}
}

class FileComparator implements Comparator<File> {
public int compare(File file1, File file2) {
String createInfo1 = getFileNameWithoutExtension(file1.getName());
String createInfo2 = getFileNameWithoutExtension(file2.getName());

try {
Date create1 = dataFormat.parse(createInfo1);
Date create2 = dataFormat.parse(createInfo2);
if (create1.before(create2)) {
return -1;
} else {
return 1;
}
} catch (ParseException e) {
return 0;
}
}
}

/**
* 去除文件的扩展类型(.log)
*
* @param fileName
* @return
*/
private String getFileNameWithoutExtension(String fileName) {
try {
return fileName.substring(fileName.indexOf(".")+1, fileName.lastIndexOf("."));
} catch (Exception e) {
return "";
}
}

}


/**
* <上线前需要更改的配置文件>
*
* @author caoyinfei
* @version [版本号, 2016/6/21]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public class Config {
/**
* 是否为release版本
*/
public static final boolean ISRELEASE = false;

/**
* 日志文件前缀
*/
public static final String LOG_FILE_NAME = "eb-p.";

}


文件目录的创建代码:

/**
* <日志目录>
* <功能详细描述>
* @return
*/
public static String getVersionLogPath() {
return FileUtil.createNewFile(getCacheFilePath() + FOLDER_NAME_LOG + File.separator);
}


public static String createNewFile(String path) {
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
return path;
}


保存的文件如下所示:

eb-p.2016-06-23.log
eb-p.2016-06-28.log


文件中的日志如下所示:

2016-06-23 16:43:17  [main]   com.test.electronicbrand.capabilities.log.EBLog   info/com.test.electronicbrand.capabilities.log.EBLog   [methodName=setLogType]   [lineNumber=90 ]   logType: verbose
2016-06-23 16:43:17  [main]   com.test.electronicbrand.ui.personcenter.LoginActivity   info/sdsd   [methodName=initData]   [lineNumber=57 ]   ssdsd
2016-06-23 16:43:17  [main]   com.test.electronicbrand.ui.personcenter.LoginActivity   info/aaa   [methodName=setHeader]   [lineNumber=64 ]   dfdf
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息