From 053a98b2a0ea6a847f92b3895ef147bf07f2dcbf Mon Sep 17 00:00:00 2001 From: Ceki Gulcu Date: Sat, 2 Aug 2008 19:24:58 +0000 Subject: [PATCH] - decoupling slf4j version numbers from slf4j-ext version - moved the NOPLoger class from slf4j-nop module to slf4j-api. An NOPLogger came in handy in slf4j-ext - ongoing work on XLogger.java - other minor improvements in the docs --- pom.xml | 5 +- .../java/org/slf4j/helpers/NOPLogger.java | 238 ++++++++++++++++++ slf4j-ext/pom.xml | 4 +- .../src/main/java/org/slf4j/LoggerX.java | 61 ----- .../src/main/java/org/slf4j/XLogger.java | 140 +++++++++++ .../src/test/java/org/slf4j/LoggerXTest.java | 3 +- slf4j-site/src/site/pages/faq.html | 11 +- slf4j-site/src/site/pages/news.html | 12 +- 8 files changed, 401 insertions(+), 73 deletions(-) create mode 100644 slf4j-api/src/main/java/org/slf4j/helpers/NOPLogger.java delete mode 100644 slf4j-ext/src/main/java/org/slf4j/LoggerX.java create mode 100644 slf4j-ext/src/main/java/org/slf4j/XLogger.java diff --git a/pom.xml b/pom.xml index 27b10bb4..aa7d286f 100644 --- a/pom.xml +++ b/pom.xml @@ -19,8 +19,7 @@ 2005 - - 1.4.3 + 1.0-alpha0 @@ -53,7 +52,7 @@ - ${project.groupId} + org.slf4j slf4j-api ${project.version} diff --git a/slf4j-api/src/main/java/org/slf4j/helpers/NOPLogger.java b/slf4j-api/src/main/java/org/slf4j/helpers/NOPLogger.java new file mode 100644 index 00000000..251a7361 --- /dev/null +++ b/slf4j-api/src/main/java/org/slf4j/helpers/NOPLogger.java @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2004-2005 SLF4J.ORG + * Copyright (c) 2004-2005 QOS.ch + * + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons + * to whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY + * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * of the copyright holder. + * + */ + +package org.slf4j.helpers; + +import org.slf4j.Logger; +import org.slf4j.helpers.MarkerIgnoringBase; + + +/** + * A direct NOP (no operation) implementation of {@link Logger}. + * + * @author Ceki Gülcü + */ +public class NOPLogger extends MarkerIgnoringBase { + + private static final long serialVersionUID = -517220405410904473L; + + /** + * The unique instance of NOPLogger. + */ + public static final NOPLogger NOP_LOGGER = new NOPLogger(); + + /** + * There is no point in creating multiple instances of NOPLOgger, + * except by derived classes, hence the protected access for the constructor. + */ + protected NOPLogger() { + } + + /** + * Always returns the string value "NOP". + */ + public String getName() { + return "NOP"; + } + + /** + * Always returns false. + * @return always false + */ + final public boolean isTraceEnabled() { + return false; + } + + /** A NOP implementation. */ + final public void trace(String msg) { + // NOP + } + + /** A NOP implementation. */ + final public void trace(String format, Object arg) { + // NOP + } + + /** A NOP implementation. */ + public final void trace(String format, Object arg1, Object arg2) { + // NOP + } + + /** A NOP implementation. */ + public final void trace(String format, Object[] argArray) { + // NOP + } + + /** A NOP implementation. */ + final public void trace(String msg, Throwable t) { + // NOP + } + + /** + * Always returns false. + * @return always false + */ + final public boolean isDebugEnabled() { + return false; + } + + /** A NOP implementation. */ + final public void debug(String msg) { + // NOP + } + + /** A NOP implementation. */ + final public void debug(String format, Object arg) { + // NOP + } + + /** A NOP implementation. */ + public final void debug(String format, Object arg1, Object arg2) { + // NOP + } + + /** A NOP implementation. */ + public final void debug(String format, Object[] argArray) { + // NOP + } + + + + /** A NOP implementation. */ + final public void debug(String msg, Throwable t) { + // NOP + } + + /** + * Always returns false. + * @return always false + */ + final public boolean isInfoEnabled() { + // NOP + return false; + } + + + /** A NOP implementation. */ + final public void info(String msg) { + // NOP + } + + /** A NOP implementation. */ + final public void info(String format, Object arg1) { + // NOP + } + + /** A NOP implementation. */ + final public void info(String format, Object arg1, Object arg2) { + // NOP + } + + /** A NOP implementation. */ + public final void info(String format, Object[] argArray) { + // NOP + } + + + /** A NOP implementation. */ + final public void info(String msg, Throwable t) { + // NOP + } + + + /** + * Always returns false. + * @return always false + */ + final public boolean isWarnEnabled() { + return false; + } + + /** A NOP implementation. */ + final public void warn(String msg) { + // NOP + } + + /** A NOP implementation. */ + final public void warn(String format, Object arg1) { + // NOP + } + + /** A NOP implementation. */ + final public void warn(String format, Object arg1, Object arg2) { + // NOP + } + + /** A NOP implementation. */ + public final void warn(String format, Object[] argArray) { + // NOP + } + + + /** A NOP implementation. */ + final public void warn(String msg, Throwable t) { + // NOP + } + + + /** A NOP implementation. */ + final public boolean isErrorEnabled() { + return false; + } + + /** A NOP implementation. */ + final public void error(String msg) { + // NOP + } + + /** A NOP implementation. */ + final public void error(String format, Object arg1) { + // NOP + } + + /** A NOP implementation. */ + final public void error(String format, Object arg1, Object arg2) { + // NOP + } + + /** A NOP implementation. */ + public final void error(String format, Object[] argArray) { + // NOP + } + + + /** A NOP implementation. */ + final public void error(String msg, Throwable t) { + // NOP + } +} diff --git a/slf4j-ext/pom.xml b/slf4j-ext/pom.xml index 853a5eee..35fba362 100644 --- a/slf4j-ext/pom.xml +++ b/slf4j-ext/pom.xml @@ -12,6 +12,7 @@ org.slf4j slf4j-ext + ${slf4j-ext-version} jar SLF4J Extensions Module @@ -22,11 +23,12 @@ org.slf4j slf4j-api + ${parent.version} org.slf4j slf4j-log4j12 - ${project.version} + ${parent.version} test diff --git a/slf4j-ext/src/main/java/org/slf4j/LoggerX.java b/slf4j-ext/src/main/java/org/slf4j/LoggerX.java deleted file mode 100644 index c3f4cc3c..00000000 --- a/slf4j-ext/src/main/java/org/slf4j/LoggerX.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.slf4j; - -import org.slf4j.helpers.MessageFormatter; -import org.slf4j.spi.LocationAwareLogger; - -/** - * A utility that provides standard mechanisms for logging certain kinds of - * activities. - * - * @author Ralph Goers - * @author Ceki Gulcu - */ -public class LoggerX { - - private static final String FQCN = LoggerX.class.getName(); - static Marker FLOW_MARKER = MarkerFactory.getMarker("FLOW"); - static Marker ENTRY_MARKER = MarkerFactory.getMarker("ENTER"); - static Marker EXIT_MARKER = MarkerFactory.getMarker("EXIT"); - - static Marker EXCEPTION_MARKER = MarkerFactory.getMarker("EXCEPTION"); - static Marker DIAG_MARKER = MarkerFactory.getMarker("DIAG"); - - static String ENTRY_MESSAGE_0 = "entry"; - static String ENTRY_MESSAGE_1 = "entry with params ({})"; - static String ENTRY_MESSAGE_2 = "entry with params ({}, {})"; - static String ENTRY_MESSAGE_3 = "entry with params ({}, {}, {})"; - static String ENTRY_MESSAGE_4 = "entry with params ({}, {}, {}, {})"; - static int ENTRY_MESSAGE_ARRAY_LEN = 5; - static String[] ENTRY_MESSAGE_ARRAY = new String[ENTRY_MESSAGE_ARRAY_LEN]; - static { - ENTRY_MARKER.add(FLOW_MARKER); - EXIT_MARKER.add(FLOW_MARKER); - ENTRY_MESSAGE_ARRAY[0] = ENTRY_MESSAGE_0; - ENTRY_MESSAGE_ARRAY[1] = ENTRY_MESSAGE_1; - ENTRY_MESSAGE_ARRAY[2] = ENTRY_MESSAGE_2; - ENTRY_MESSAGE_ARRAY[3] = ENTRY_MESSAGE_3; - ENTRY_MESSAGE_ARRAY[4] = ENTRY_MESSAGE_4; - } - - /** - * Log entry to a method - * - * @param logger - * the Logger to log with. - */ - public static void entering(Logger logger, Object... argArray) { - if (logger.isDebugEnabled(ENTRY_MARKER) - && logger instanceof LocationAwareLogger) { - String messagePattern = ""; - if(argArray.length <= ENTRY_MESSAGE_ARRAY_LEN) { - messagePattern = ENTRY_MESSAGE_ARRAY[argArray.length]; - } - - String msg = MessageFormatter.arrayFormat(messagePattern, argArray); - - ((LocationAwareLogger) logger).log(ENTRY_MARKER, FQCN, - LocationAwareLogger.ERROR_INT, msg, null); - } - } - -} diff --git a/slf4j-ext/src/main/java/org/slf4j/XLogger.java b/slf4j-ext/src/main/java/org/slf4j/XLogger.java new file mode 100644 index 00000000..21d3be25 --- /dev/null +++ b/slf4j-ext/src/main/java/org/slf4j/XLogger.java @@ -0,0 +1,140 @@ +package org.slf4j; + +import org.slf4j.helpers.MessageFormatter; +import org.slf4j.helpers.NOPLogger; +import org.slf4j.spi.LocationAwareLogger; + +/** + * A utility that provides standard mechanisms for logging certain kinds of + * activities. + * + * @author Ralph Goers + * @author Ceki Gulcu + */ +public class XLogger { + + private static final String FQCN = XLogger.class.getName(); + static Marker FLOW_MARKER = MarkerFactory.getMarker("FLOW"); + static Marker ENTRY_MARKER = MarkerFactory.getMarker("ENTER"); + static Marker EXIT_MARKER = MarkerFactory.getMarker("EXIT"); + + static Marker EXCEPTION_MARKER = MarkerFactory.getMarker("EXCEPTION"); + static Marker THROWING_MARKER = MarkerFactory.getMarker("EXCEPTION"); + static Marker CATCHING_MARKER = MarkerFactory.getMarker("EXCEPTION"); + + static String EXIT_MESSAGE_0 = "exit"; + static String EXIT_MESSAGE_1 = "exit with {}"; + + static String ENTRY_MESSAGE_0 = "entry"; + static String ENTRY_MESSAGE_1 = "entry with ({})"; + static String ENTRY_MESSAGE_2 = "entry with ({}, {})"; + static String ENTRY_MESSAGE_3 = "entry with ({}, {}, {})"; + static String ENTRY_MESSAGE_4 = "entry with ({}, {}, {}, {})"; + static int ENTRY_MESSAGE_ARRAY_LEN = 5; + static String[] ENTRY_MESSAGE_ARRAY = new String[ENTRY_MESSAGE_ARRAY_LEN]; + static { + ENTRY_MARKER.add(FLOW_MARKER); + EXIT_MARKER.add(FLOW_MARKER); + THROWING_MARKER.add(EXCEPTION_MARKER); + CATCHING_MARKER.add(EXCEPTION_MARKER); + + ENTRY_MESSAGE_ARRAY[0] = ENTRY_MESSAGE_0; + ENTRY_MESSAGE_ARRAY[1] = ENTRY_MESSAGE_1; + ENTRY_MESSAGE_ARRAY[2] = ENTRY_MESSAGE_2; + ENTRY_MESSAGE_ARRAY[3] = ENTRY_MESSAGE_3; + ENTRY_MESSAGE_ARRAY[4] = ENTRY_MESSAGE_4; + } + + final Logger logger; + + public XLogger(Logger logger) { + + if (logger instanceof LocationAwareLogger) { + this.logger = logger; + } else { + // if the logger is not location aware, assume that + // there is no point in further effort + this.logger = NOPLogger.NOP_LOGGER; + } + } + + /** + * Log method entry. + * + * @param argArray + * supplied parameters + */ + public void entry(Object... argArray) { + if (logger.isTraceEnabled(ENTRY_MARKER)) { + String messagePattern = null; + if (argArray.length <= ENTRY_MESSAGE_ARRAY_LEN) { + messagePattern = ENTRY_MESSAGE_ARRAY[argArray.length]; + } else { + messagePattern = buildMessagePattern(argArray.length); + } + String formattedMessage = MessageFormatter.arrayFormat(messagePattern, + argArray); + ((LocationAwareLogger) logger).log(ENTRY_MARKER, FQCN, + LocationAwareLogger.TRACE_INT, formattedMessage, null); + } + } + + /** + * Log method exit + */ + public void exit() { + if (logger.isTraceEnabled(ENTRY_MARKER)) { + ((LocationAwareLogger) logger).log(EXIT_MARKER, FQCN, + LocationAwareLogger.TRACE_INT, EXIT_MESSAGE_0, null); + } + } + + /** + * Log method exit + * + * @param result + * The result of the method being exited + */ + public void exit(Object result) { + if (logger.isTraceEnabled(ENTRY_MARKER)) { + String formattedMessage = MessageFormatter.format(EXIT_MESSAGE_0, result); + ((LocationAwareLogger) logger).log(EXIT_MARKER, FQCN, + LocationAwareLogger.TRACE_INT, formattedMessage, null); + } + } + + /** + * Log an exception being thrown + * + * @param throwable + * the exception being caught. + */ + public void throwing(Throwable throwable) { + ((LocationAwareLogger) logger).log(THROWING_MARKER, FQCN, + LocationAwareLogger.ERROR_INT, "throwing", throwable); + } + + /** + * Log an exception being caught + * + * @param throwable + * the exception being caught. + */ + public void catching(Throwable throwable) { + ((LocationAwareLogger) logger).log(CATCHING_MARKER, FQCN, + LocationAwareLogger.ERROR_INT, "catching", throwable); + } + + private static String buildMessagePattern(int len) { + StringBuilder sb = new StringBuilder(); + sb.append(" entry with ("); + for (int i = 0; i < len; i++) { + sb.append("{}"); + if (i != len - 1) + sb.append(", "); + } + sb.append(')'); + return sb.toString(); + } + +} diff --git a/slf4j-ext/src/test/java/org/slf4j/LoggerXTest.java b/slf4j-ext/src/test/java/org/slf4j/LoggerXTest.java index cb7af227..7d73f6a8 100644 --- a/slf4j-ext/src/test/java/org/slf4j/LoggerXTest.java +++ b/slf4j-ext/src/test/java/org/slf4j/LoggerXTest.java @@ -7,6 +7,7 @@ public class LoggerXTest extends TestCase { Logger logger = LoggerFactory.getLogger(this.getClass()); public void testSmoke() { - LoggerX.entering(logger); + XLogger xLogger = new XLogger(logger); + xLogger.entry(logger); } } diff --git a/slf4j-site/src/site/pages/faq.html b/slf4j-site/src/site/pages/faq.html index 2eb3515a..f59eeb87 100644 --- a/slf4j-site/src/site/pages/faq.html +++ b/slf4j-site/src/site/pages/faq.html @@ -597,8 +597,7 @@ debug(String msg, Throwable t);

less than 1% of the time it takes to actually log a statement.

-

Better alternative based on parameterized - messages

+

Better yet, use parameterized messages

There exists a very convenient alternative based on message formats. Assuming entry is an object, you can write: @@ -642,7 +641,13 @@ logger.debug("The new entry is {}.", entry);

logger.debug("Value {} was inserted between {} and {}.", new Object[] {newVal, below, above});

-

+

+ +

Array type arguments, including multi-dimensional arrays, + are also supported. However, cyclical or recursive arrays are + not suported and will result in a stack overflow + error.

+

SLF4J uses its own message formatting implementation which differs from that of the Java platform. This is justified by the fact that SLF4J's implementation performs several orders diff --git a/slf4j-site/src/site/pages/news.html b/slf4j-site/src/site/pages/news.html index aa4ea824..768c28e0 100644 --- a/slf4j-site/src/site/pages/news.html +++ b/slf4j-site/src/site/pages/news.html @@ -55,12 +55,16 @@ prefix='';

-

Added support for array values in parameters. For example,

-

log.debug("a:{},i:{}", "A", new int[] {1, 2}});

-

will print as "a:A,i:[1, 2]" instead of "a:A,i:[I@6ca1c" as - previously. This enhancement was proposed by "lizongbo" +

Added support for array values, including multi-dimensional + arrays, as parameters. For example,

+

log.debug("{} {}", "A", new int[] {1, 2}});

+

will print as "A [1, 2]" instead of "A [I@6ca1c" as + previously. This enhancement was proposed by "lizongbo". Cyclical or + recursive arrays are not supported. Such arrays will cause + a stack overflow error.

+

Added missing getInstance methods to the Category class in the log4j-over-slf4j module, fixing bug 95