Androidログ保存ポリシー

21670 ワード

前言:
プロジェクトはログ統計の仕事ができていないので、問題があるたびにバックエンドを探してドッキングしなければなりません.仕事の効率に深刻な影響を及ぼします.最近わざわざプロジェクトにログ保存ポリシーを加えて、ここで共有して、必要な人が勉強します.
詳細なログ情報
ロゴをカスタマイズすることにした以上、スレッド情報:threadId、threadNameなど、より多くの情報を表示することができます.
private String getFunctionName() {
        StackTraceElement[] sts = Thread.currentThread().getStackTrace();
        if (sts == null) {
            return null;
        }

        for (StackTraceElement st : sts) {
            if (st.isNativeMethod()) {
                continue;
            }
            if (st.getClassName().equals(Thread.class.getName())) {
                continue;
            }
            if (st.getClassName().equals(this.getClass().getName())) {
                continue;
            }

            Thread t = Thread.currentThread();
            return "[T(id:" + t.getId() +
                    ", name:" + t.getName() +
                    ", priority:" + t.getPriority() +
                    ", groupName:" + t.getThreadGroup().getName() +
                    "): " + st.getFileName() + ":"
                    + st.getLineNumber() + " " + st.getMethodName() + " ]";
        }
        return "";
    }
StackTrace(スタックトラック)には、メソッド呼び出しスタックの情報が格納され、メソッドが実行するスレッドに関する情報や、実行するメソッド名などが取得される.これらの情報は、問題の所在をよりよく検索するのに役立ちます.
private void logPrint(int logLevel, Object msg) {
        if (isDebug) {
            String name = getFunctionName();
            customTag = TextUtils.isEmpty(customTag) ? defaultTag : customTag;
            Log.println(logLevel, customTag, name + " - " + msg);
        }
    }

ログの使用printlnメソッドは関連情報を印刷すればよい.
ログ保存ポリシー
バックエンドの人はテスト中にBUGに遭遇し、フロントエンドが問題なのかバックエンドが問題なのか分からないことがあります.より迅速な位置決めのために、バックエンドはフロントエンドのログがどこに保存されているかを知るべきです.これには、ログ保存ポリシーを作成する必要があります.(ログをアップロードする場合でも、ファイルとして保存してからファイルをアップロードする必要があります.そうしないと、ログごとにインタフェースを呼び出すと、インタフェースの圧力が大きくなり、合理的ではありません)
ログを保存するプロセスは時間がかかるため、スレッドを開いて保存する必要があります.しかし、ログの発生頻度が高い可能性があり、一般的なスレッドでは処理できないため、多くのスレッドでもパフォーマンスが損なわれます.キューの形式でログを保存し、1つずつ保存することを考慮する必要があります.
    public void initSaveStrategy(Context context) {
        if (saveLogStrategy != null || !isDebug) {
            return;
        }
        final int MAX_BYTES = 1024 * 1024;
        String diskPath = Environment.getExternalStorageDirectory().getAbsolutePath();
        File cacheFile = context.getCacheDir();
        if (cacheFile != null) {
            diskPath = cacheFile.getAbsolutePath();
        }
        String folder = diskPath + File.separatorChar + "log";
        HandlerThread ht = new HandlerThread("SohuLiveLogger." + folder);
        ht.start();
        Handler handler = new SaveLogStrategy.WriteHandler(ht.getLooper(), folder, MAX_BYTES);
        saveLogStrategy = new SaveLogStrategy(handler);
    }
   public static class WriteHandler extends Handler {

        private final String folder;
        private final int maxFileSize;

        WriteHandler(@NonNull Looper looper, @NonNull String folder, int maxFileSize) {
            super(checkNotNull(looper));
            this.folder = checkNotNull(folder);
            this.maxFileSize = maxFileSize;
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            String content = (String) msg.obj;
            FileWriter fileWriter = null;
            File logFile = getLogFile(folder, "logs");
            try {
                fileWriter = new FileWriter(logFile, true);
                writeLog(fileWriter, content);
                fileWriter.flush();
                fileWriter.close();
            } catch (IOException e) {
                if (fileWriter != null) {
                    try {
                        fileWriter.flush();
                        fileWriter.close();
                    } catch (IOException e1) {

                    }
                }
            }
        }

私たちはHandlerThreadを使用してこのタスクを処理します.HandlerThreadはhandlerを使用できるThreadです.メッセージをメッセージキューに保存すると、スレッドで処理され、多くのスレッドが生成されないことが保証されます.実はここでもinstentserviceを使って実現することができて、このサービスは量が大きくて時間のかからない任務に適しています.
最後に、印刷と保存を1つの方法で統一します.
    private void logPrint(int logLevel, Object msg) {
        if (isDebug) {
            String name = getFunctionName();
            if (saveLogStrategy != null) {
                saveLogStrategy.log(Log.ERROR, customTag, name + " - " + msg);
            }
            Log.println(logLevel, customTag, name + " - " + msg);
        }
    }

カスタマイズされたlogポリシーは簡単ですが、主にこの考えです.ログ情報の詳細を印刷し、キューの形式で保存します.次はすべてのコードです.
public class Logger {
    public final static String tag = "";
    private static SaveLogStrategy saveLogStrategy;
    private final static boolean logFlag = true;
    private static Logger logger;
    private int logLevel = Log.VERBOSE;
    private static boolean isDebug = BuildConfig.DEBUG;
    private String customTag = null;

    private Logger(String customTag) {
        this.customTag = customTag;
    }

    public void initSaveStrategy(Context context) {
        if (saveLogStrategy != null || !isDebug) {
            return;
        }
        final int MAX_BYTES = 1024 * 1024;
        String diskPath = Environment.getExternalStorageDirectory().getAbsolutePath();
        File cacheFile = context.getCacheDir();
        if (cacheFile != null) {
            diskPath = cacheFile.getAbsolutePath();
        }
        String folder = diskPath + File.separatorChar + "log";
        HandlerThread ht = new HandlerThread("Logger." + folder);
        ht.start();
        Handler handler = new SaveLogStrategy.WriteHandler(ht.getLooper(), folder, MAX_BYTES);
        saveLogStrategy = new SaveLogStrategy(handler);
    }

    public static Logger getLogger(String tag) {
        if (logger == null) {
            logger = new Logger(tag);
        }
        return logger;
    }

    public static Logger getLogger() {
        if (logger == null) {
            logger = new Logger(tag);
        }
        return logger;
    }

    /**
     * Verbose(2)     
     *
     * @param str String
     */
    public void v(Object str) {
        logLevel = Log.VERBOSE;
        logPrint(logLevel, str);
    }

    /**
     * Debug(3)     
     *
     * @param str String
     */
    public void d(Object str) {
        logLevel = Log.DEBUG;
        logPrint(logLevel, str);
    }

    /**
     * Info(4)     
     *
     * @param str String
     */
    public void i(Object str) {
        logLevel = Log.INFO;
        logPrint(logLevel, str);
    }

    /**
     * Warn(5)     
     *
     * @param str String
     */
    public void w(Object str) {
        logLevel = Log.WARN;
        logPrint(logLevel, str);
    }

    /**
     * Error(6)     
     *
     * @param str String
     */
    public void e(Object str) {
        logLevel = Log.ERROR;
        logPrint(logLevel, str);
    }

    private void logPrint(int logLevel, Object msg) {
        if (isDebug) {
            String name = getFunctionName();
            if (saveLogStrategy != null) {
                saveLogStrategy.log(Log.ERROR, customTag, name + " - " + msg);
            }
            Log.println(logLevel, customTag, name + " - " + msg);
        }
    }

    /**
     *        
     *
     * @return    
     */
    private String getFunctionName() {
        StackTraceElement[] sts = Thread.currentThread().getStackTrace();
        if (sts == null) {
            return null;
        }

        for (StackTraceElement st : sts) {
            if (st.isNativeMethod()) {
                continue;
            }
            if (st.getClassName().equals(Thread.class.getName())) {
                continue;
            }
            if (st.getClassName().equals(this.getClass().getName())) {
                continue;
            }

            Thread t = Thread.currentThread();
            return "[Thread(id:" + t.getId() +
                    ", name:" + t.getName() +
                    ", priority:" + t.getPriority() +
                    ", groupName:" + t.getThreadGroup().getName() +
                    "): " + st.getFileName() + ":"
                    + st.getLineNumber() + " " + st.getMethodName() + " ]";
        }
        return "";
    }
}
public class SaveLogStrategy {

    @NonNull
    private final Handler handler;

    public SaveLogStrategy(@NonNull Handler handler) {
        this.handler = checkNotNull(handler);
    }

    public void log(int level, @Nullable String tag, @NonNull String message) {
        checkNotNull(message);
        handler.sendMessage(handler.obtainMessage(level, message));
    }

    static class WriteHandler extends Handler {

        private final String folder;
        private final int maxFileSize;

        WriteHandler(@NonNull Looper looper, @NonNull String folder, int maxFileSize) {
            super(checkNotNull(looper));
            this.folder = checkNotNull(folder);
            this.maxFileSize = maxFileSize;
        }

        @SuppressWarnings("checkstyle:emptyblock")
        @Override
        public void handleMessage(@NonNull Message msg) {
            String content = (String) msg.obj;
            FileWriter fileWriter = null;
            File logFile = getLogFile(folder, "logs");

            try {
                fileWriter = new FileWriter(logFile, true);

                writeLog(fileWriter, content);

                fileWriter.flush();
                fileWriter.close();
            } catch (IOException e) {
                if (fileWriter != null) {
                    try {
                        fileWriter.flush();
                        fileWriter.close();
                    } catch (IOException e1) {

                    }
                }
            }
        }

        private void writeLog(@NonNull FileWriter fileWriter, @NonNull String content) throws IOException {
            checkNotNull(fileWriter);
            checkNotNull(content);
            fileWriter.append("
"
).append(content); } private File getLogFile(@NonNull String folderName, @NonNull String fileName) { checkNotNull(folderName); checkNotNull(fileName); File folder = new File(folderName); if (!folder.exists()) { if (!folder.mkdirs()) { Log.println(Log.ERROR, "saveLog", " , "); } } int newFileCount = 0; File newFile; File existingFile = null; newFile = new File(folder, String.format("%s_%s.txt", fileName, newFileCount)); while (newFile.exists()) { existingFile = newFile; newFileCount++; newFile = new File(folder, String.format("%s_%s.txt", fileName, newFileCount)); } if (existingFile != null) { if (existingFile.length() >= maxFileSize) { return newFile; } return existingFile; } return newFile; } } }

以上がすべてですが、皆さんのお役に立てばと思います