0

We have a log management system that prints out on a file the logcat while the app is running. Each day there’s a new file, and the log file of the day before is deleted. The problem is that if the user uses the app for an extended period of time, the log file gets quite large in size and it can reach GBs.

We need a log management system that avoids this, in order to always have updated logs in a reasonable size, ideally less than 150 - 200 mb. The log file a simple text file where the logcat is saved. From the moment that every line in that file corresponds to a specific time, I was thinking that when the file reaches 150 mb the first x lines are deleted, in order to diminish the file size keeping the latest logs, the important ones we need to hold only the file for the day. We don't need the yesterday files

The logic could be:

if today 20201128 delete 20201127
   create a directory with the datum "20201128"
   create file 20201128_11_52 in it

create a control system

while file < 200 mb do nothing
then
open new file logs in it
close old file
zip old file
if 20201128 > 2 GB sent mail to us,
somethis is going worong

Below is the current code we are working with

    public class startLogging {
​
    static String globalLogName = "logcat-" + getCurrentDate() + "-.txt";
​
    public static void startLog(){
​
        if (isExternalStorageWritable()) {
            //Delete old logs
            deleteOldLogs();
​
            File logDirectory      = new File(Environment.getExternalStorageDirectory().getPath() +"/ElenaLogs/");
            File logFile           = new File(logDirectory, globalLogName );
​
​
            // create log folder
            if (!logDirectory.exists()) {
                logDirectory.mkdir();
            }
​
            // clear the previous logcat and then write the new one to the file
            try {
                Process process     = Runtime.getRuntime().exec("logcat -c");
                process             = Runtime.getRuntime().exec("logcat -f " + logFile);
            } catch ( IOException e ) {
                e.printStackTrace();
            }
​
        }
    }
​
    private static boolean isExternalStorageWritable() {
        String state = Environment.getExternalStorageState();
        return Environment.MEDIA_MOUNTED.equals(state);
    }
​
    private static String getCurrentDate(){
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
        Date date = new Date();
        //Return the date in this format: 20200515, that is a larger number every day, more easy to delete old logs
        return formatter.format(date).replace("/", "");
    }
​
    public static String getCurrentLogPath(){
        return Environment.getExternalStorageDirectory().getPath() +"/ElenaLogs/" + globalLogName;
    }
​
    private static String[] getFilesInDir(){
        //Get all the files in the ElenaLogs dir
        String[] fileNames;
        File f = new File(Environment.getExternalStorageDirectory().getPath()+"/ElenaLogs");
        fileNames = f.list();
        return fileNames;
    }
​
    private static boolean deleteFile(String dateToDelete){
​
        String globalPath           = Environment.getExternalStorageDirectory().getPath() +"/ElenaLogs/";
​
        String fileToDelete         = "logcat-"+dateToDelete+"-.txt";
        String pathFile             = globalPath + fileToDelete;
​
        String zipToDelete          = "logcat-"+dateToDelete+"-.zip";
        String pathZip             = globalPath + zipToDelete;
​
        File filetoDelete               = new File(pathFile);
        File ziptoDelete                = new File(pathZip);
​
        ziptoDelete.delete();
​
        return filetoDelete.delete();
    }
​
    private static void deleteOldLogs(){
​
        String          date                    = getCurrentDate();
        int             dateNumber              = Integer.parseInt(date);
        String[]        allLogs                 = getFilesInDir();
​
        try{
            for (String logFileName : allLogs) {
​
                int logDate = Integer.parseInt(logFileName.split("-")[1]);
​
                if (logDate < dateNumber) {
                    //Old file, delete
                    deleteFile(String.valueOf(logDate));
                }
​
            }
        }catch (NullPointerException e){
            e.printStackTrace();
        }
​
​
    }
​
    public static String getPathForEmail(){
​
        String zippedFilename   =   globalLogName.replace(".txt", ".zip");
        String zippedFilePath   =   Environment.getExternalStorageDirectory().getPath() + "/ElenaLogs/" + zippedFilename;
​
        //Zip the current log file
        if (zipFileAtPath(getCurrentLogPath(), zippedFilePath)){
            return zippedFilePath;
        }else {
            return getCurrentLogPath();
        }
​
    }
​
    /** Zips the logs**/
​
    public static boolean zipFileAtPath(String sourcePath, String toLocation) {
        final int BUFFER = 2048;
​
        File sourceFile = new File(sourcePath);
        try {
            BufferedInputStream origin = null;
            FileOutputStream dest = new FileOutputStream(toLocation);
            ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
                    dest));
            if (sourceFile.isDirectory()) {
                zipSubFolder(out, sourceFile, sourceFile.getParent().length());
            } else {
                byte data[] = new byte[BUFFER];
                FileInputStream fi = new FileInputStream(sourcePath);
                origin = new BufferedInputStream(fi, BUFFER);
                ZipEntry entry = new ZipEntry(getLastPathComponent(sourcePath));
                entry.setTime(sourceFile.lastModified()); // to keep modification time after unzipping
                out.putNextEntry(entry);
                int count;
                while ((count = origin.read(data, 0, BUFFER)) != -1) {
                    out.write(data, 0, count);
                }
            }
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
​
​
    private static void zipSubFolder(ZipOutputStream out, File folder,
                              int basePathLength) throws IOException {
​
        final int BUFFER = 2048;
​
        File[] fileList = folder.listFiles();
        BufferedInputStream origin = null;
        for (File file : fileList) {
            if (file.isDirectory()) {
                zipSubFolder(out, file, basePathLength);
            } else {
                byte data[] = new byte[BUFFER];
                String unmodifiedFilePath = file.getPath();
                String relativePath = unmodifiedFilePath
                        .substring(basePathLength);
                FileInputStream fi = new FileInputStream(unmodifiedFilePath);
                origin = new BufferedInputStream(fi, BUFFER);
                ZipEntry entry = new ZipEntry(relativePath);
                entry.setTime(file.lastModified()); // to keep modification time after unzipping
                out.putNextEntry(entry);
                int count;
                while ((count = origin.read(data, 0, BUFFER)) != -1) {
                    out.write(data, 0, count);
                }
                origin.close();
            }
        }
    }
​
    /*
     * gets the last path component
     *
     * Example: getLastPathComponent("downloads/example/fileToZip");
     * Result: "fileToZip"
     */
    private static String getLastPathComponent(String filePath) {
        String[] segments = filePath.split("/");
        if (segments.length == 0)
            return "";
        String lastPathComponent = segments[segments.length - 1];
        return lastPathComponent;
    }
​
}

I have tried to implement the below logic after a lot of searching in the very first method i.e. startlog() in the above code. But it's not working.

if(logFile.length()/1024*1024>150){
    Log.d(globalLogName,"greaterFileSize"+logFile.length());
    process=Runtime.getRuntime().exec("tail -n +500"+logFile.getName());
}

Implemented the above logic in startlog() as below-

public static void startLog() {
        if (isExternalStorageWritable()) {
            //Delete old logs
            deleteOldLogs();
            File logDirectory = new File(Environment.getExternalStorageDirectory().getPath() + "/ElenaLogs/");
            File logFile = new File(logDirectory, globalLogName);
            // create log folder
            if (!logDirectory.exists()) {
                logDirectory.mkdir();
            }
            // clear the previous logcat and then write the new one to the file
            try {
                Log.d(globalLogName,"greaterFileSize"+logFile.length());
                Process process = Runtime.getRuntime().exec("logcat -c");
                process = Runtime.getRuntime().exec("logcat -f " + logFile);
                if(logFile.length()/1024*1024>150){
                    Log.d(globalLogName,"greaterFileSize"+logFile.length());
                    process=Runtime.getRuntime().exec("tail -n +500"+logFile.getName());
                }
            } catch (IOException e) {
                Log.d(globalLogName,"greaterFileSize"+logFile.length());
                e.printStackTrace();
            }
        }
    }
  • I'm missing the code where a part of you application wants to log someting and calls your logger for adding a line. Please show. – blackapps Nov 30 '20 at 13:31
  • `logDirectory.mkdir();` Check the return value as it might fail to create a directory. Handle accordingly. – blackapps Nov 30 '20 at 13:32
  • `isExternalStorageWritable()` That does not check for writability. No Android 10 device ? – blackapps Nov 30 '20 at 13:42
  • @blackapps logDirectory.mkdir(); is working fine and no other issue in the code. The main thing I want to implement is the logic I mentioned above – sidThunderbolt Nov 30 '20 at 17:27

0 Answers0