From 33d6b44a202bac8c540b8c7dbdd03bc70b28291c Mon Sep 17 00:00:00 2001 From: Klemek Date: Thu, 30 Aug 2018 12:16:50 +0100 Subject: [PATCH] simple-logger v1.0 --- .gitignore | 4 + README.md | 89 +++++++++++ download/simple-logger-1.0.jar | Bin 0 -> 5391 bytes pom.xml | 73 +++++++++ src/main/java/fr/klemek/logger/Logger.java | 172 +++++++++++++++++++++ src/main/java/fr/klemek/logger/Utils.java | 53 +++++++ src/test/resources/logging.properties | 12 ++ 7 files changed, 403 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 download/simple-logger-1.0.jar create mode 100644 pom.xml create mode 100644 src/main/java/fr/klemek/logger/Logger.java create mode 100644 src/main/java/fr/klemek/logger/Utils.java create mode 100644 src/test/resources/logging.properties diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9c333a9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/target/ +/maven-repo.bat +/.idea/ +*.iml diff --git a/README.md b/README.md new file mode 100644 index 0000000..a6ab634 --- /dev/null +++ b/README.md @@ -0,0 +1,89 @@ +# Simple Logger +A simple but useful Java logger to use everywhere. + +Current version v1.0 + +## Download + +* [simple-logger-1.0.jar](../../raw/master/download/simple-logger-1.0.jar) + +## How to use + +Initialization : +```Java +Logger.init("logging.properties", Level.WARNING); +// or +Logger.init("logging.properties"); +Logger.setLevel(Level.WARNING); +``` + +Configuration file as follow (example) : +``` +#Parameters for good behavior +handlers=java.util.logging.ConsoleHandler +.level=WARNING +java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter + +#Customize date/time shown with this line +java.util.logging.SimpleFormatter.format=[%1$tF %1$tT][%4$s]%5$s %n + +#Specify your app name here +app_name=YourApp +# (Optional, specify your app package) +default_package=com.your.app +``` + +The default package works as follow : When logging stack trace of an error, it will stop when the package doesnt't match your app anymore. It helps having small and relevant stack trace in logs. + +Usage : +```Java +//general logging +Logger.log("my message"); //INFO log +Logger.log("my message : {0}", 123); //INFO log with parameters +Logger.log(Level.WARNING, "my message"); //custom level log +Logger.log(Level.SEVERE, "my message : {0}-{1}", 123, 456); //custom level log with parameters +//exception logging +Logger.log(exception1); //SEVERE logging with stack trace +Logger.log(exception2, "exception when doing task"); //SEVERE logging with stack trace and message +Logger.log(Level.WARNING, exception3); //custom level logging without stack trace +Logger.log(Level.INFO, exception4, "exception when doing task"); //custom level logging with message +``` +This will show the following : +``` +[INFO][MyApp-CallingClass] my message +[INFO][MyApp-CallingClass] my message : 123 +[WARNING][MyApp-CallingClass] my message +[SEVERE][MyApp-CallingClass] my message : 123-456 +[SEVERE][MyApp-CallingClass] (exception1.toString) +[SEVERE][MyApp-CallingClass] (exception1.stackTrace) +[SEVERE][MyApp-CallingClass] (exception1.stackTrace) +[SEVERE][MyApp-CallingClass] ... +[SEVERE][MyApp-CallingClass] exception when doing task : (exception2.toString) +[SEVERE][MyApp-CallingClass] (exception2.stackTrace) +[SEVERE][MyApp-CallingClass] (exception2.stackTrace) +[SEVERE][MyApp-CallingClass] ... +[WARNING][MyApp-CallingClass] (exception3.toString) +[INFO][MyApp-CallingClass] exception when doing task : (exception4.toString) +``` + +## Maven + +You can use this project as a maven dependency with this : +```XML + + ... + + fr.klemek + https://github.com/klemek/mvn-repo/raw/master + + +... + + ... + + fr.klemek + simple-logger + 1.0 + + +``` diff --git a/download/simple-logger-1.0.jar b/download/simple-logger-1.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..8557fec4df8460ad9fe6cf9964c03ef1de026f04 GIT binary patch literal 5391 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 literal 0 HcmV?d00001 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..ce6cb2e --- /dev/null +++ b/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + + fr.klemek + simple-logger + 1.0 + + SimpleLogger + + + UTF-8 + + + + target/${project.artifactId}/WEB-INF/classes + src/main/java + src/test/java + + + src/test/resources + + **/*.java + + + + + + + org.codehaus.mojo + versions-maven-plugin + 2.5 + + + validate + + display-dependency-updates + display-plugin-updates + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.7.0 + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.0 + + download + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.0 + + + + + \ No newline at end of file diff --git a/src/main/java/fr/klemek/logger/Logger.java b/src/main/java/fr/klemek/logger/Logger.java new file mode 100644 index 0000000..cde186d --- /dev/null +++ b/src/main/java/fr/klemek/logger/Logger.java @@ -0,0 +1,172 @@ +package fr.klemek.logger; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Locale; +import java.util.logging.Level; +import java.util.logging.LogManager; + +/** + * Simple logger for this application. + * + * @author Clement Gouin + */ +public final class Logger { + + private static java.util.logging.Logger appLogger = java.util.logging.Logger.getLogger(Utils.getString("app_name","Unkown")); + private static final String APP_NAME = Utils.getString("app_name","Unkown"); + private static final String BASE_PACKAGE = Utils.getString("default_package",null); + private static final int DEFAULT_DEPTH = 4; + + private static boolean initialized = false; + + private Logger() { + } + + /** + * @return the current logger level; + */ + public static Level getLevel() { + return appLogger.getLevel(); + } + + /** + * Change the log level of this logger. + * + * @param newLevel the level of log to show + */ + public static void setLevel(Level newLevel) { + appLogger.setLevel(newLevel); + } + + /** + * Load a config file for the logger and set locale to english. + * + * @param relativePath the path in resources of the config file + */ + public static void init(String relativePath) { + init(relativePath, Level.INFO); + } + + /** + * Load a config file for the logger and set locale to english. + * + * @param relativePath the path in resources of the config file + * @param level the level to set the logger to + */ + public static void init(String relativePath, Level level) { + Locale.setDefault(Locale.ENGLISH); + loadConfigFromFile(relativePath); + Logger.setLevel(level); + Logger.initialized = true; + } + + /** + * Load a config file for the logger. + * + * @param relativePath the path in resources of the config file + */ + private static void loadConfigFromFile(String relativePath) { + try { + InputStream is = Logger.class.getClassLoader().getResourceAsStream(relativePath); + if (is == null) { + Logger.log(Level.SEVERE, "Logger config file not found at path {0}", relativePath); + return; + } + LogManager.getLogManager().readConfiguration(is); + appLogger = java.util.logging.Logger.getLogger(APP_NAME); + } catch (IOException e) { + Logger.log(e); + } + } + + /** + * Log an exception. + * + * @param e the exception to log + */ + public static void log(Exception e) { + Logger.log(Logger.DEFAULT_DEPTH, Level.SEVERE, e.toString(), e); + } + + /** + * Log an exception. + * + * @param lvl the level of logging + * @param e the exception to log + */ + public static void log(Level lvl, Exception e) { + Logger.log(Logger.DEFAULT_DEPTH, lvl, e.toString(), e); + } + + /** + * Log an exception. + * + * @param e the exception to log + * @param msg the exception msg + */ + public static void log(Exception e, String msg) { + Logger.log(Logger.DEFAULT_DEPTH, Level.SEVERE, msg + " : {0}", e); + } + + /** + * Log an exception. + * + * @param lvl the level of logging + * @param e the exception to log + * @param msg the exception msg + */ + public static void log(Level lvl, Exception e, String msg) { + Logger.log(Logger.DEFAULT_DEPTH, lvl, msg + " : {0}", e); + } + + /** + * Log an INFO message. + * + * @param message the message + * @param objects the object for the message formatting + */ + public static void log(String message, Object... objects) { + Logger.log(Logger.DEFAULT_DEPTH, Level.INFO, message, objects); + } + + /** + * Log a message. + * + * @param lvl the level of logging + * @param message the message + * @param objects the object for the message formatting + */ + public static void log(Level lvl, String message, Object... objects) { + Logger.log(Logger.DEFAULT_DEPTH, lvl, message, objects); + } + + /** + * Log a message. + * + * @param depth the source depth in stack + * @param lvl the level of logging + * @param message the message + * @param objects the object for the message formatting + */ + private static void log(int depth, Level lvl, String message, Object... objects) { + if(!initialized) { + Logger.log(Level.WARNING, "Logger was not initialized please do so before using."); + initialized = true; + } + message = String.format("[%s-%s] %s", APP_NAME, Utils.getCallingClassName(depth), message); + appLogger.log(lvl, message, objects); + if (lvl == Level.SEVERE && objects.length > 0 && objects[0] instanceof Exception) { + boolean inPackage = false; + for (StackTraceElement ste : ((Exception) objects[0]).getStackTrace()) { + Logger.log(depth + 1, Level.SEVERE, "\t {0}", ste); + if(Logger.BASE_PACKAGE != null){ + if (!inPackage && ste.getClassName().startsWith(Logger.BASE_PACKAGE)) + inPackage = true; + else if (inPackage && !ste.getClassName().startsWith(Logger.BASE_PACKAGE)) + break; + } + } + } + } +} diff --git a/src/main/java/fr/klemek/logger/Utils.java b/src/main/java/fr/klemek/logger/Utils.java new file mode 100644 index 0000000..2465722 --- /dev/null +++ b/src/main/java/fr/klemek/logger/Utils.java @@ -0,0 +1,53 @@ +package fr.klemek.logger; + +import java.util.Arrays; +import java.util.List; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.util.logging.Level; + +/** + * Utility class that store useful misc functions. + * + * @author Clement Gouin + */ +final class Utils { + + private static final ResourceBundle CONFIGURATION_BUNDLE = ResourceBundle.getBundle("logging"); + + private Utils() { + } + + /* + * Configuration utils + */ + + /** + * Get a configuration string by its key. + * + * @param key the key in the config file + * @param defaultValue the default value to use if not found + * @return the string or default value if not found + */ + static String getString(String key, String defaultValue) { + try { + return CONFIGURATION_BUNDLE.getString(key); + } catch (MissingResourceException e) { + return defaultValue; + } + } + + /** + * Return the class name from the calling class in th stack trace. + * + * @param stackLevel the level in the stack trace + * @return the classname of th calling class + */ + static String getCallingClassName(int stackLevel) { + StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); + if (stackLevel >= stackTrace.length) + return null; + String[] source = stackTrace[stackLevel].getClassName().split("\\."); + return source[source.length - 1]; + } +} diff --git a/src/test/resources/logging.properties b/src/test/resources/logging.properties new file mode 100644 index 0000000..8ea7c3f --- /dev/null +++ b/src/test/resources/logging.properties @@ -0,0 +1,12 @@ +#Parameters for good behavior +handlers=java.util.logging.ConsoleHandler +.level=WARNING +java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter + +#Customize date/time shown with this line +java.util.logging.SimpleFormatter.format=[%1$tF %1$tT][%4$s]%5$s %n + +#Specify your app name here +app_name=Test +#(Optional, specify your app package) +default_package=fr.klemek.logger \ No newline at end of file