Enhance Log

This commit is contained in:
seven332 committed 2015-04-03 23:11:52 +08:00
1 parent 6c200bfbf5
commit f2588cc71a
4 files changed
+219 -21

No files matched your search

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2015 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.util;
import android.os.Environment;
import android.support.annotation.Nullable;
import java.io.File;
/**
* Something about this app
*/
public final class AppConfig {
private static final String APP_FOLDER_NAME = "EhViewer";
public static @Nullable File getAppFolder() {
if (Environment.getExternalStorageState()
.equals(android.os.Environment.MEDIA_MOUNTED)) {
return new File(Environment.getExternalStorageDirectory(), APP_FOLDER_NAME);
} else {
return null;
}
}
public static @Nullable File getFileInAppFolder(String filename) {
File appFolder = getAppFolder();
if (appFolder != null) {
return new File(appFolder, filename);
} else {
return null;
}
}
}
@@ -15,5 +15,23 @@
package com.hippo.util;
public final class Storage {
import java.io.File;
public final class FileUtils {
public static boolean ensureFile(File file) {
return file != null && (!file.exists() || file.isFile());
}
public static boolean ensureDirectory(File file) {
if (file != null) {
if (file.exists()) {
return file.isDirectory();
} else {
return file.mkdirs();
}
} else {
return false;
}
}
}
+29 -20
View File
@@ -15,7 +15,6 @@
package com.hippo.util;
import android.os.Looper;
import android.os.Process;
import com.hippo.ehviewer.BuildConfig;
@@ -23,8 +22,11 @@ import com.hippo.ehviewer.BuildConfig;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Log {
@@ -33,14 +35,20 @@ public class Log {
private static final String NO_MESSAGE = "No Message";
private static final SaveLogThreadPool mSaveLogThreadPool;
private static final Pool<SaveMsgTask> mSaveLogTaskPool;
private static final SaveLogThreadExecutor sSaveLogThreadPool;
private static final Pool<SaveMsgTask> sSaveLogTaskPool;
private static final File sLogFile = new File("/sdcard/EhViewer/log.log"); // TODO
private static final DateFormat sDataFormat;
private static final File sLogFile;
private static final boolean sSupportSaveLog;
static {
mSaveLogThreadPool = new SaveLogThreadPool();
mSaveLogTaskPool = new Pool<>(10);
sSaveLogThreadPool = new SaveLogThreadExecutor();
sSaveLogTaskPool = new Pool<>(10);
sDataFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);
sLogFile = AppConfig.getFileInAppFolder("ehviewer.log");
sSupportSaveLog = FileUtils.ensureFile(sLogFile);
}
private static String avoidNull(String str) {
@@ -56,24 +64,27 @@ public class Log {
}
private static void appendSaveLogTask(long time, String msg, Throwable tr) {
SaveMsgTask task = mSaveLogTaskPool.obtain();
if (!sSupportSaveLog) {
return;
}
SaveMsgTask task = sSaveLogTaskPool.obtain();
if (task == null) {
task = new SaveMsgTask();
}
task.setParams(time, msg, tr);
try {
mSaveLogThreadPool.execute(task);
sSaveLogThreadPool.execute(task);
} catch (Throwable t) {
Log.e("Get error when save message to file", t);
}
}
// TODO Need a better serial thread executor
private static class SaveLogThreadPool extends ThreadPoolExecutor {
private static class SaveLogThreadExecutor extends SerialThreadExecutor {
public SaveLogThreadPool() {
super(0, 1, 10L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(),
public SaveLogThreadExecutor() {
super(10L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(),
new PriorityThreadFactory("SaveLog", Process.THREAD_PRIORITY_BACKGROUND));
}
@@ -81,7 +92,7 @@ public class Log {
if (r instanceof SaveMsgTask) {
SaveMsgTask task = (SaveMsgTask) r;
task.clear();
mSaveLogTaskPool.recycle(task);
sSaveLogTaskPool.recycle(task);
}
}
}
@@ -104,15 +115,13 @@ public class Log {
@Override
public void run() {
Log.d("MainLooper thread is " + Looper.getMainLooper().getThread().toString());
Log.d("This thread is " + Thread.currentThread().toString());
FileWriter fw = null;
try {
fw = new FileWriter(sLogFile, true);
fw.append(Long.toString(mTime)).append(" : ").append(mMsg).append("\n")
.append(Log.getStackTraceString(mTr));
fw.append(sDataFormat.format(new Date(mTime))).append(" ").append(mMsg).append("\n");
if (mTr != null) {
fw.append(Log.getStackTraceString(mTr)).append("\n");
}
fw.flush(); // TODO Only do flush when the thread is about to close
} catch (IOException e) {
Log.e("Get error when save message to file", e);
@@ -0,0 +1,124 @@
/*
* Copyright (C) 2015 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.util;
import android.support.annotation.NonNull;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SerialThreadExecutor implements Executor, Runnable {
private long mKeepAliveTime;
private BlockingQueue<Runnable> mWorkQueue;
private ThreadFactory mThreadFactory;
private transient Thread mThread;
private final Lock mThreadLock = new ReentrantLock();
private final Object mWaitLock = new Object();
public SerialThreadExecutor(long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
mKeepAliveTime = unit.toMillis(keepAliveTime);
mWorkQueue = workQueue;
mThreadFactory = threadFactory;
}
@Override
public void execute(@NonNull Runnable command) {
try {
mWorkQueue.put(command);
ensureThread();
} catch (Exception e) {
putFailed(command, e);
}
}
private void ensureThread() {
mThreadLock.lock();
if (mThread == null) {
mThread = mThreadFactory.newThread(this);
mThread.start();
} else {
synchronized (mWaitLock) {
mWaitLock.notifyAll();
}
}
mThreadLock.unlock();
}
protected void putFailed(@NonNull Runnable command, @NonNull Exception e) {
}
protected void beforeExecute(Thread t, Runnable r) {
}
protected void afterExecute(Runnable r, Throwable t) {
}
protected void beforeExcute() {
}
@Override
public void run() {
boolean hasWait = false;
for (;;) {
mThreadLock.lock();
if (mWorkQueue.isEmpty()) {
if (hasWait) {
mThread = null;
mThreadLock.unlock();
// Have waitted enough time
break;
} else {
hasWait = true;
synchronized (mWaitLock) {
mThreadLock.unlock();
try {
mWaitLock.wait(mKeepAliveTime);
} catch (InterruptedException e) {
// Empty
}
continue;
}
}
} else {
mThreadLock.unlock();
}
hasWait = false;
Runnable runnable = mWorkQueue.poll();
if (runnable != null) {
beforeExecute(mThread, runnable);
Throwable throwable = null;
try {
runnable.run();
} catch (Throwable tr) {
throwable = tr;
}
afterExecute(runnable, throwable);
}
}
}
}