commit 33d6b44a202bac8c540b8c7dbdd03bc70b28291c Author: Klemek Date: Thu Aug 30 12:16:50 2018 +0100 simple-logger v1.0 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 0000000..8557fec Binary files /dev/null and b/download/simple-logger-1.0.jar differ 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