com.momock.util.Logger.java Source code

Java tutorial

Introduction

Here is the source code for com.momock.util.Logger.java

Source

/*******************************************************************************
 * Copyright 2012 momock.com
 * 
 * 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
 * distributed under the License is distributed on an "AS IS" BASIS,
 * 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.momock.util;

import static android.os.Environment.getExternalStorageState;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import org.json.JSONObject;

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Environment;

import com.momock.event.Event;
import com.momock.event.EventArgs;
import com.momock.event.IEvent;
import com.momock.event.IEventHandler;

public class Logger {
    public static final int LEVEL_ALL = 0;

    public static final int LEVEL_DEBUG = 3;

    public static final int LEVEL_INFO = 4;

    public static final int LEVEL_WARN = 5;

    public static final int LEVEL_ERROR = 6;

    public static final int LEVEL_NONE = 7;

    static PrintStream logStream = System.out;
    static String logName = "app";
    static String logFileName = "log.txt";
    static int logLevel = LEVEL_DEBUG;
    static boolean enabled = true;
    static String appName;
    static RemoteLoggerThread remoteLogger = null;

    public static class LogEventArgs extends EventArgs {
        String message;
        Throwable error;

        public LogEventArgs(String message, Throwable error) {
            this.message = message;
            this.error = error;
        }

        public String getMessage() {
            return message;
        }

        public Throwable getError() {
            return error;
        }
    }

    static IEvent<LogEventArgs> event = new Event<LogEventArgs>();

    public static void addErrorLogHandler(IEventHandler<LogEventArgs> handler) {
        event.addEventHandler(handler);
    }

    static class RemoteLoggerThread extends Thread {
        class LogItem {
            public String level;
            public String content;
            public Date time;
            public String source;

            public LogItem(String level, String content, String source) {
                this.level = level;
                this.content = content;
                this.source = source;
                this.time = new Date();
            }
        }

        public String url = null;
        public String deviceId = null;
        boolean forceStop = false;
        ArrayList<LogItem> logs = new ArrayList<LogItem>();

        public RemoteLoggerThread(String url, String deviceId) {
            this.url = url;
            this.deviceId = deviceId;
        }

        public void log(String level, String content, String source) {
            logs.add(new LogItem(level, content, source));
        }

        @Override
        public void run() {
            while (!forceStop) {
                try {
                    if (logs.size() == 0) {
                        sleep(1000);
                    } else {
                        HttpURLConnection connection = null;
                        while (logs.size() > 0) {
                            LogItem item = logs.get(0);
                            logs.remove(0);

                            try {
                                URL httpURL = new URL(url);
                                connection = (HttpURLConnection) httpURL.openConnection();
                                connection.setConnectTimeout(15000);
                                connection.setReadTimeout(30000);
                                connection.setRequestMethod("POST");
                                connection.setRequestProperty("Content-Type", "application/json");
                                JSONObject jo = new JSONObject();
                                jo.put("did", deviceId);
                                jo.put("app", appName);
                                jo.put("level", item.level);
                                jo.put("content", item.content);
                                jo.put("source", item.source);
                                jo.put("time", item.time.getTime());
                                String body = jo.toString();
                                if (body != null) {
                                    OutputStream os = connection.getOutputStream();
                                    OutputStreamWriter osw = new OutputStreamWriter(os);
                                    osw.write(body);
                                    osw.flush();
                                    osw.close();
                                }
                                connection.getResponseCode();
                                connection = null;
                            } catch (Exception e) {
                            }
                        }
                    }
                } catch (Exception e) {
                }
            }
        }

        public void destroy() {
            forceStop = true;
        }
    }

    @TargetApi(Build.VERSION_CODES.FROYO)
    static File getExternalCacheDir(final Context context) {
        return context.getExternalCacheDir();
    }

    public static void setRemoteLoggerServer(String url, String deviceId) {
        if (remoteLogger != null && url != null) {
            remoteLogger.url = url;
            remoteLogger.deviceId = deviceId;
            return;
        }
        if (remoteLogger != null) {
            remoteLogger.destroy();
            remoteLogger = null;
        }
        if (url != null) {
            remoteLogger = new RemoteLoggerThread(url, deviceId);
            remoteLogger.start();
        }
    }

    public static void open(Context context, final String name, int maxLogFiles, int level) {
        if (!enabled)
            return;
        appName = context.getPackageName();
        logName = name;
        logFileName = logName + "[" + new SimpleDateFormat("yyyyMMddHHmmss", Locale.US).format(new Date())
                + "].log";
        if (logStream == System.out) {
            File logDir = null;
            try {
                if (getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                    logDir = Environment.getExternalStorageDirectory();
                } else if (context != null) {
                    logDir = context.getCacheDir();
                }
                if (logDir != null) {
                    android.util.Log.d("Logger", logDir.getAbsolutePath());
                    String[] fs = logDir.list(new FilenameFilter() {

                        @Override
                        public boolean accept(File dir, String filename) {
                            return filename.startsWith(logName + "[") && filename.endsWith("].log");
                        }

                    });
                    List<String> allLogs = new ArrayList<String>();
                    for (int i = 0; fs != null && i < fs.length; i++)
                        allLogs.add(fs[i]);
                    Collections.sort(allLogs);
                    for (int i = 0; i < allLogs.size() - maxLogFiles + 1; i++)
                        new File(logDir, allLogs.get(i)).delete();
                    logStream = new PrintStream(new FileOutputStream(new File(logDir, logFileName), false));
                }
            } catch (IOException e) {
                android.util.Log.e("Logger", "Fails to create log file!", e);
            }
        }
        logLevel = level;

        logStream.println("========== Logger Begin ==========");
        logStream.flush();
    }

    public static void open(Context context, String logfilename, int level) {
        if (!enabled)
            return;
        logFileName = logfilename;
        if (logStream == null) {
            logStream = System.out;
            File logDir = null;
            try {
                if (getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                    logDir = Environment.getExternalStorageDirectory();
                } else if (context != null) {
                    logDir = context.getCacheDir();
                }
                if (logDir != null) {
                    android.util.Log.d("Logger", logDir.getAbsolutePath());
                    logStream = new PrintStream(new FileOutputStream(new File(logDir, logFileName), false));
                }
            } catch (IOException e) {
                android.util.Log.e("Logger", "Fails to create log file!", e);
            }
        }
        logLevel = level;

        logStream.println("========== Logger Begin ==========");
        logStream.flush();
    }

    public static void close() {
        if (!enabled)
            return;
        if (logStream == null)
            return;
        logStream.println("========== Logger End   ==========");
        logStream.close();
        logStream = null;
    }

    static void checkLogFile() {
    }

    static String getLog(String level, String msg) {
        Throwable t = new Throwable();
        StackTraceElement trace = t.getStackTrace()[2];
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);
        if (remoteLogger != null) {
            remoteLogger.log(level, msg, trace.getFileName() + "(" + trace.getLineNumber() + ")");
        }
        return "[" + level + "] " + sdf.format(new Date()) + " in " + trace.getFileName() + "("
                + trace.getLineNumber() + ") >" + msg;
    }

    static String getSourceInfo(StackTraceElement trace) {
        return trace.getFileName() + "(" + trace.getLineNumber() + ")";
    }

    public static void debug(String msg) {
        if (!enabled || logLevel > LEVEL_DEBUG)
            return;
        if (msg == null)
            msg = "";
        Throwable t = new Throwable();
        StackTraceElement trace = t.getStackTrace()[1];
        android.util.Log.d(logName, msg + " @ " + getSourceInfo(trace));
        checkLogFile();
        logStream.println(getLog("DEBUG", msg));
        logStream.flush();
    }

    public static void info(String msg) {
        if (!enabled || logLevel > LEVEL_INFO)
            return;
        if (msg == null)
            msg = "";
        Throwable t = new Throwable();
        StackTraceElement trace = t.getStackTrace()[1];
        android.util.Log.i(logName, msg + " @ " + getSourceInfo(trace));
        checkLogFile();
        logStream.println(getLog("INFO", msg));
        logStream.flush();
    }

    public static void warn(String msg) {
        if (!enabled || logLevel > LEVEL_WARN)
            return;
        if (msg == null)
            msg = "";
        Throwable t = new Throwable();
        StackTraceElement trace = t.getStackTrace()[1];
        android.util.Log.w(logName, msg + " @ " + getSourceInfo(trace));
        checkLogFile();
        logStream.println(getLog("WARN", msg));
        logStream.flush();
    }

    public static void error(String msg) {
        if (!enabled || logLevel > LEVEL_ERROR)
            return;
        if (msg == null)
            msg = "";
        Throwable t = new Throwable();
        StackTraceElement trace = t.getStackTrace()[1];
        android.util.Log.e(logName, msg + " @ " + getSourceInfo(trace));
        checkLogFile();
        logStream.println(getLog("ERROR", msg));
        logStream.flush();
        event.fireEvent(null, new LogEventArgs(msg, null));
    }

    public static String getStackTrace(Throwable e) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(baos);
        e.printStackTrace(ps);
        return new String(baos.toByteArray());
    }

    public static void error(Throwable e) {
        if (!enabled || logLevel > LEVEL_ERROR)
            return;
        String msg = e.getMessage() + " : " + getStackTrace(e);
        Throwable t = new Throwable();
        StackTraceElement trace = t.getStackTrace()[1];
        android.util.Log.e(logName, msg + " @ " + getSourceInfo(trace));
        checkLogFile();
        logStream.println(getLog("ERROR", msg));
        logStream.flush();
        event.fireEvent(null, new LogEventArgs(null, e));
    }

    public static void check(boolean condition, String msg) {
        if (!condition) {
            if (!enabled || logLevel > LEVEL_ERROR)
                return;
            if (msg == null)
                msg = "";
            Throwable t = new Throwable();
            StackTraceElement trace = t.getStackTrace()[1];
            android.util.Log.e(logName, msg + " @ " + getSourceInfo(trace));
            checkLogFile();
            logStream.println(getLog("ASSERT", msg));
            logStream.flush();

            throw new RuntimeException(msg);
        }
    }

    public static boolean isEnabled() {
        return enabled;
    }

    public static void setEnabled(boolean enabled) {
        Logger.enabled = enabled;
    }
}