From a21d0758fd56a76d934a036a3bfeacea8984ee85 Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Sun, 18 Mar 2018 16:36:18 +0200 Subject: Implemented custom logging on Java ! --- .../com/twine/tango/logging/ExceptionLogItem.java | 41 ++++ .../java/com/twine/tango/logging/FileLogger.java | 99 ++++++++++ .../main/java/com/twine/tango/logging/ILogger.java | 9 + .../java/com/twine/tango/logging/LogCatLogger.java | 58 ++++++ .../java/com/twine/tango/logging/LogCategory.java | 5 + .../main/java/com/twine/tango/logging/LogItem.java | 64 ++++++- .../java/com/twine/tango/logging/LogManager.java | 206 +++++++++++++++++++++ .../com/twine/tango/logging/MessageLogItem.java | 24 +++ 8 files changed, 505 insertions(+), 1 deletion(-) (limited to 'Software/Android_Studio/Tango.Logging/src/main/java') diff --git a/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/ExceptionLogItem.java b/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/ExceptionLogItem.java index 86166ff95..49aa1b687 100644 --- a/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/ExceptionLogItem.java +++ b/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/ExceptionLogItem.java @@ -6,4 +6,45 @@ package com.twine.tango.logging; public class ExceptionLogItem extends LogItem { + private Exception exception; + private String description; + + public Exception getException() + { + return exception; + } + + public void setException(Exception exception) + { + this.exception = exception; + } + + public String getDescription() + { + return description; + } + + public void setDescription(String description) + { + this.description = description; + } + + @Override + public String getMessage() + { + return exception.getMessage(); + } + + @Override + public String toString() + { + return String.format("[%s] [%s] [%s] [%s] [Line %s]: %s\n%s", + getTimeStamp().toString("HH:mm:ss.SS"), + getCategory().toString(), + getCallerFile(), + getCallerMethodName(), + String.valueOf(getCallerLineNumber()), + getDescription(), + exception.toString()); + } } diff --git a/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/FileLogger.java b/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/FileLogger.java index db9da89a7..50b6b27b6 100644 --- a/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/FileLogger.java +++ b/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/FileLogger.java @@ -1,9 +1,108 @@ package com.twine.tango.logging; +import android.content.Context; + +import org.joda.time.DateTime; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + /** * Created by Roy on 3/18/2018. */ public class FileLogger implements ILogger { + private boolean enabled; + private boolean immediate; + private String fileName; + private String folder; + private Context context; + private FileOutputStream stream; + private boolean fileCreated; + + public FileLogger(Context context) + { + this.context = context; + folder = "logs"; + fileName = "log-" + DateTime.now().toString("dd-MM-yyyy_HH-mm-ss") + ".log"; + enabled = true; + } + + public FileLogger(Context context, String folder, String fileName) + { + this(context); + + this.folder = folder; + this.fileName = fileName; + this.context = context; + } + + @Override + public void setEnabled(boolean enabled) + { + this.enabled = enabled; + } + + @Override + public boolean getEnabled() + { + return this.enabled; + } + + @Override + public void setImmediate(boolean immediate) + { + this.immediate = immediate; + } + + @Override + public boolean getImmediate() + { + return this.immediate; + } + + public String getFileName() + { + return fileName; + } + + @Override + public void onLog(LogItem log) + { + try + { + ensureLogFile(); + stream.write((log.toString() + System.lineSeparator()).getBytes(StandardCharsets.UTF_8)); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + @Override + protected void finalize() throws Throwable + { + super.finalize(); + stream.close(); + } + + private void ensureLogFile() throws IOException + { + if (!fileCreated) + { + fileCreated = true; + File sdcard = context.getFilesDir(); + File dir = new File(sdcard.getAbsolutePath() + "/" + folder); + boolean b = dir.mkdirs(); + + File file = new File(dir.getAbsolutePath() + "/" + fileName); + b = file.createNewFile(); + + stream = new FileOutputStream(file, true); + } + } } diff --git a/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/ILogger.java b/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/ILogger.java index 4e550332b..a6ddf1dfc 100644 --- a/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/ILogger.java +++ b/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/ILogger.java @@ -6,4 +6,13 @@ package com.twine.tango.logging; public interface ILogger { + void onLog(LogItem log); + + void setEnabled(boolean enabled); + + boolean getEnabled(); + + void setImmediate(boolean immediate); + + boolean getImmediate(); } diff --git a/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/LogCatLogger.java b/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/LogCatLogger.java index 8dc14abad..e394503e1 100644 --- a/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/LogCatLogger.java +++ b/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/LogCatLogger.java @@ -1,9 +1,67 @@ package com.twine.tango.logging; +import android.util.Log; + /** * Created by Roy on 3/18/2018. */ public class LogCatLogger implements ILogger { + private boolean enabled; + private boolean immediate; + private static final String tag = "Tango"; + + public LogCatLogger() + { + enabled = true; + immediate = true; + } + + @Override + public void setEnabled(boolean enabled) + { + this.enabled = enabled; + } + + @Override + public boolean getEnabled() + { + return this.enabled; + } + + @Override + public void setImmediate(boolean immediate) + { + this.immediate = immediate; + } + + @Override + public boolean getImmediate() + { + return this.immediate; + } + + @Override + public void onLog(LogItem log) + { + switch (log.getCategory()) + { + case Info: + Log.i(tag,log.toString()); + break; + case Error: + Log.e(tag,log.toString()); + break; + case Warning: + Log.w(tag,log.toString()); + break; + case Critical: + Log.wtf(tag,log.toString()); + break; + case Debug: + Log.d(tag,log.toString()); + break; + } + } } diff --git a/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/LogCategory.java b/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/LogCategory.java index bf116f95a..5ce2c521e 100644 --- a/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/LogCategory.java +++ b/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/LogCategory.java @@ -6,4 +6,9 @@ package com.twine.tango.logging; public enum LogCategory { + Info, + Warning, + Error, + Critical, + Debug, } diff --git a/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/LogItem.java b/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/LogItem.java index 327858b15..deaeb3084 100644 --- a/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/LogItem.java +++ b/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/LogItem.java @@ -1,9 +1,71 @@ package com.twine.tango.logging; +import org.joda.time.DateTime; + /** * Created by Roy on 3/18/2018. */ -public class LogItem +public abstract class LogItem { + private String callerMethodName; + private String callerFile; + private int callerLineNumber; + private DateTime timeStamp; + private LogCategory category; + + public String getCallerMethodName() + { + return callerMethodName; + } + + public void setCallerMethodName(String callerMethodName) + { + this.callerMethodName = callerMethodName; + } + + public String getCallerFile() + { + return callerFile; + } + + public void setCallerFile(String callerFile) + { + this.callerFile = callerFile; + } + + public int getCallerLineNumber() + { + return callerLineNumber; + } + + public void setCallerLineNumber(int callerLineNumber) + { + this.callerLineNumber = callerLineNumber; + } + + public DateTime getTimeStamp() + { + return timeStamp; + } + + public void setTimeStamp(DateTime timeStamp) + { + this.timeStamp = timeStamp; + } + + public LogCategory getCategory() + { + return category; + } + + public void setCategory(LogCategory category) + { + this.category = category; + } + + public abstract String getMessage(); + + @Override + public abstract String toString(); } diff --git a/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/LogManager.java b/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/LogManager.java index f77e09274..b3b8041a2 100644 --- a/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/LogManager.java +++ b/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/LogManager.java @@ -1,9 +1,215 @@ package com.twine.tango.logging; +import org.joda.time.DateTime; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; + /** * Created by Roy on 3/18/2018. */ public class LogManager { + private static LogManager defaultLogger; + + private List loggers; + private ConcurrentLinkedQueue logs; + private Thread loggingThread; + private boolean isStarted; + private List categories; + + public static LogManager getDefault() + { + if (defaultLogger == null) + { + defaultLogger = new LogManager(); + } + + return defaultLogger; + } + + public LogManager() + { + loggers = new ArrayList<>(); + logs = new ConcurrentLinkedQueue<>(); + categories = new ArrayList<>(); + + categories.add(LogCategory.Info); + categories.add(LogCategory.Critical); + categories.add(LogCategory.Error); + categories.add(LogCategory.Warning); + } + + public List getCategories() + { + return categories; + } + + public void setCategories(List categories) + { + this.categories = categories; + } + + public boolean getHasLogsPending() + { + return logs.size() > 0; + } + + public void registerLogger(ILogger logger) + { + if (logger != null && !loggers.contains(logger)) + { + loggers.add(logger); + } + } + + public void unregisterLogger(ILogger logger) + { + if (logger != null && loggers.contains(logger)) + { + loggers.remove(logger); + } + } + + private void fillStackInfo(StackTraceElement[] stackTraceElements, LogItem log) + { + if (stackTraceElements.length > 0) + { + int counter = 0; + + StackTraceElement stack = stackTraceElements[counter]; + + while (!stack.getFileName().equals("LogManager.java")) + { + stack = stackTraceElements[counter++]; + } + + stack = stackTraceElements[counter]; + + log.setCallerFile(stack.getFileName()); + log.setCallerMethodName(stack.getMethodName()); + log.setCallerLineNumber(stack.getLineNumber()); + } + } + + public Exception log(Exception exception, LogCategory category, String description) + { + if (!categories.contains(category)) return exception; + + ExceptionLogItem log = new ExceptionLogItem(); + StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); + fillStackInfo(stackTraceElements, log); + log.setTimeStamp(DateTime.now()); + log.setCategory(category); + log.setDescription(description); + log.setException(exception); + + appendLog(log); + + return exception; + } + + public Exception log(Exception exception, String description) + { + ExceptionLogItem log = new ExceptionLogItem(); + StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); + fillStackInfo(stackTraceElements, log); + log.setTimeStamp(DateTime.now()); + log.setDescription(description); + log.setException(exception); + log.setCategory(LogCategory.Error); + + appendLog(log); + + return exception; + } + + public String log(String message, LogCategory category) + { + MessageLogItem log = new MessageLogItem(); + StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); + fillStackInfo(stackTraceElements, log); + log.setTimeStamp(DateTime.now()); + log.setMessage(message); + log.setCategory(category); + + appendLog(log); + + return message; + } + + public String log(String message) + { + MessageLogItem log = new MessageLogItem(); + StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); + fillStackInfo(stackTraceElements, log); + log.setTimeStamp(DateTime.now()); + log.setMessage(message); + log.setCategory(LogCategory.Info); + + appendLog(log); + + return message; + } + + private void appendLog(LogItem log) + { + if (log != null) + { + for (ILogger logger : loggers) + { + if (logger.getEnabled() && logger.getImmediate()) + { + logger.onLog(log); + } + } + + logs.add(log); + } + + startLoggingThread(); + } + + private void startLoggingThread() + { + if (!isStarted) + { + isStarted = true; + loggingThread = new Thread(this::loggingThreadMethod); + loggingThread.start(); + } + } + + private void loggingThreadMethod() + { + try + { + while (isStarted) + { + while (logs.size() > 0) + { + LogItem log = logs.poll(); + + if (log != null) + { + for (ILogger logger : loggers) + { + if (logger.getEnabled() && !logger.getImmediate()) + { + logger.onLog(log); + } + } + } + } + + Thread.sleep(10); + } + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } } diff --git a/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/MessageLogItem.java b/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/MessageLogItem.java index 90659cb7e..cf7c7ab48 100644 --- a/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/MessageLogItem.java +++ b/Software/Android_Studio/Tango.Logging/src/main/java/com/twine/tango/logging/MessageLogItem.java @@ -6,4 +6,28 @@ package com.twine.tango.logging; public class MessageLogItem extends LogItem { + private String message; + + @Override + public String getMessage() + { + return message; + } + + public void setMessage(String message) + { + this.message = message; + } + + @Override + public String toString() + { + return String.format("[%s] [%s] [%s] [%s] [Line %s]: %s", + getTimeStamp().toString("HH:mm:ss.SS"), + getCategory().toString(), + getCallerFile(), + getCallerMethodName(), + String.valueOf(getCallerLineNumber()), + getMessage()); + } } -- cgit v1.3.1