/* * The contents of this file are subject to the OpenMRS Public License * Version 1.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://license.openmrs.org * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * Copyright (C) OpenMRS, LLC. All Rights Reserved. */ package org.openmrs.mobile.application; import android.util.Log; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.io.PrintWriter; public class OpenMRSLogger { private static String mTAG = "OpenMRS"; private static final boolean IS_DEBUGGING_ON = true; private static final String LOG_FILENAME = "OpenMRS.log"; private static final int MAX_SIZE = 64 * 1024; // 64kB; private static File mLogFile = null; private static File mFolder = null; private static boolean mSaveToFileEnable = true; private static int mErrorCountSaveToFile = 2; private static boolean mIsRotating; private static OpenMRS mOpenMRS = OpenMRS.getInstance(); private static OpenMRSLogger logger = null; private Thread.UncaughtExceptionHandler androidDefaultUEH; public OpenMRSLogger() { logger = this; androidDefaultUEH = Thread.getDefaultUncaughtExceptionHandler(); Thread.UncaughtExceptionHandler handler = new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread thread, Throwable ex) { logger.e("Uncaught exception is: ", ex); androidDefaultUEH.uncaughtException(thread, ex); } }; Thread.setDefaultUncaughtExceptionHandler(handler); mFolder = new File(mOpenMRS.getOpenMRSDir()); try { if (isFolderExist()) { mLogFile = new File(mOpenMRS.getOpenMRSDir() + File.separator + LOG_FILENAME); if (!mLogFile.createNewFile()) { rotateLogFile(); } mLogFile.createNewFile(); } logger.d("Start logging to file"); } catch (IOException e) { logger.e("Error during create file", e); } } private static boolean isFolderExist() { boolean success = true; if (!mFolder.exists()) { success = mFolder.mkdir(); } return success; } private static boolean isSaveToFileEnable() { return mSaveToFileEnable && mErrorCountSaveToFile > 0; } private static void setErrorCount() { mErrorCountSaveToFile--; if (mErrorCountSaveToFile <= 0) { mSaveToFileEnable = false; logger.e("logging to file disabled because of to much error during save"); } } private static void saveToFile() { if (isFolderExist() && isSaveToFileEnable()) { String command = "logcat -d -v time -s " + mTAG; try { Process mLoggerProcess = Runtime.getRuntime().exec(command); BufferedReader in = new BufferedReader(new InputStreamReader(mLoggerProcess.getInputStream())); String line; FileWriter writer = new FileWriter(mLogFile, true); while ((line = in.readLine()) != null) { if (!line.startsWith("---------")) { writer.write(line + "\n"); } } writer.flush(); writer.close(); mLoggerProcess = Runtime.getRuntime().exec("logcat -c"); mLoggerProcess.waitFor(); } catch (IOException e) { setErrorCount(); if (isSaveToFileEnable()) { logger.e("Error during save log to file", e); } } catch (InterruptedException e) { setErrorCount(); if (isSaveToFileEnable()) { logger.e("Error during waitng for \"logcat -c\" process", e); } } rotateLogFile(); } } public void v(final String msg) { Log.v(mTAG, getMessage(msg)); saveToFile(); } public void v(final String msg, Throwable tr) { Log.v(mTAG, getMessage(msg), tr); saveToFile(); } public void d(final String msg) { if (IS_DEBUGGING_ON) { Log.d(mTAG, getMessage(msg)); saveToFile(); } } public void d(final String msg, Throwable tr) { if (IS_DEBUGGING_ON) { Log.d(mTAG, getMessage(msg), tr); saveToFile(); } } public void i(final String msg) { Log.i(mTAG, getMessage(msg)); saveToFile(); } public void i(final String msg, Throwable tr) { Log.i(mTAG, getMessage(msg), tr); saveToFile(); } public void w(final String msg) { Log.w(mTAG, getMessage(msg)); saveToFile(); } public void w(final String msg, Throwable tr) { Log.w(mTAG, getMessage(msg), tr); saveToFile(); } public void e(final String msg) { Log.e(mTAG, getMessage(msg)); saveToFile(); } public void e(final String msg, Throwable tr) { Log.e(mTAG, getMessage(msg), tr); saveToFile(); } private static String getMessage(String msg) { final String fullClassName = Thread.currentThread().getStackTrace()[4].getClassName(); final String className = fullClassName.substring(fullClassName.lastIndexOf('.') + 1); final String methodName = Thread.currentThread().getStackTrace()[4].getMethodName(); final int lineNumber = Thread.currentThread().getStackTrace()[4].getLineNumber(); return "#" + lineNumber + " " + className + "." + methodName + "() : " + msg; } public String getLogFilename() { return LOG_FILENAME; } private static void rotateLogFile() { if (mLogFile.length() > MAX_SIZE && !mIsRotating) { mIsRotating = true; logger.i("Log file size is too big. Start rotating log file"); new Thread() { @Override public void run() { try { LineNumberReader r = new LineNumberReader(new FileReader(mLogFile)); while (r.readLine() != null) { continue; } r.close(); int remove = Math.round(r.getLineNumber() * 0.3f); if (remove > 0) { r = new LineNumberReader(new FileReader(mLogFile)); while (r.readLine() != null && r.getLineNumber() < remove) { continue; } File newFile = new File(mLogFile.getAbsolutePath() + ".new"); PrintWriter pw = new PrintWriter(new FileWriter(newFile)); String line; while ((line = r.readLine()) != null) { pw.println(line); } pw.close(); r.close(); if (newFile.renameTo(mLogFile)) { logger.i("Log file rotated"); } mIsRotating = false; } } catch (IOException e) { logger.e("Error rotating log file. Rotating disable. ", e); } } } .start(); } } }