Repository: logging-log4j2 Updated Branches: refs/heads/master 566449e9d -> 38cc8121b
LOG4J2-1255 - Add Messages to entry and exit tracing Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/fcb2d1fd Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/fcb2d1fd Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/fcb2d1fd Branch: refs/heads/master Commit: fcb2d1fde32b4250acb4c7b13e9e5cd899b792fc Parents: 566449e Author: Ralph Goers <[email protected]> Authored: Sun Feb 7 14:20:54 2016 -0700 Committer: Ralph Goers <[email protected]> Committed: Sun Feb 7 14:20:54 2016 -0700 ---------------------------------------------------------------------- log4j-api/pom.xml | 12 + .../java/org/apache/logging/log4j/Logger.java | 196 ++++++++++++---- .../logging/log4j/spi/AbstractLogger.java | 229 ++++++++++++++++++- .../org/apache/logging/log4j/LoggerTest.java | 51 +++++ .../logging/log4j/message/JsonMessage.java | 58 +++++ src/changes/changes.xml | 3 + src/site/xdoc/manual/flowtracing.xml | 39 +++- 7 files changed, 517 insertions(+), 71 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fcb2d1fd/log4j-api/pom.xml ---------------------------------------------------------------------- diff --git a/log4j-api/pom.xml b/log4j-api/pom.xml index 2f9e52e..0291d96 100644 --- a/log4j-api/pom.xml +++ b/log4j-api/pom.xml @@ -64,6 +64,18 @@ <artifactId>commons-lang3</artifactId> <scope>test</scope> </dependency> + <!-- Required for JSON support --> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + <scope>test</scope> + </dependency> + <!-- Required for JSON support --> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <scope>test</scope> + </dependency> </dependencies> <build> <plugins> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fcb2d1fd/log4j-api/src/main/java/org/apache/logging/log4j/Logger.java ---------------------------------------------------------------------- diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/Logger.java b/log4j-api/src/main/java/org/apache/logging/log4j/Logger.java index 63eb500..347718a 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/Logger.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/Logger.java @@ -30,7 +30,7 @@ import org.apache.logging.log4j.util.Supplier; * gets its own Logger named after its fully qualified class name (the default Logger name when obtained through the * {@link LogManager#getLogger()} method). Thus, the simplest way to use this would be like so: * </p> - * + * * <pre> * public class MyClass { * private static final Logger LOGGER = LogManager.getLogger(); @@ -49,7 +49,7 @@ import org.apache.logging.log4j.util.Supplier; * Since 2.4, methods have been added to the {@code Logger} interface to support lambda expressions. The new methods * allow client code to lazily log messages without explicitly checking if the requested log level is enabled. For * example, previously one would write: - * + * * <pre> * // pre-Java 8 style optimization: explicitly check the log level * // to make sure the expensiveOperation() method is only called if necessary @@ -59,7 +59,7 @@ import org.apache.logging.log4j.util.Supplier; * </pre> * <p> * With Java 8, the same effect can be achieved with a lambda expression: - * + * * <pre> * // Java-8 style optimization: no need to explicitly check the log level: * // the lambda expression is not evaluated if the TRACE level is not enabled @@ -320,7 +320,7 @@ public interface Logger { /** * Logs entry to a method along with its parameters. For example, - * + * * <pre> * public void doSomething(String foo, int bar) { * LOGGER.entry(foo, bar); @@ -332,11 +332,7 @@ public interface Logger { * bytecode manipulation tools. It can be rather tedious (and messy) to use this type of method manually. * </p> * - * @param params The parameters to the method. TODO Use of varargs results in array creation which can be a - * substantial portion of no-op case. LogMF/LogSF provides several overrides to avoid vararg except in - * edge cases. (RG) LogMF and LogSF implement these in LogXF which calls logger.callAppenders. - * callAppenders is part of the implementation and cannot be used by the API. Adding more methods here - * and in AbstractLogger is sufficient. + * @param params The parameters to the method. */ void entry(Object... params); @@ -413,11 +409,6 @@ public interface Logger { * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() - * - * TODO Likely to misinterpret existing log4j client code that intended to call info(Object,Throwable). Incurs - * array creation expense on every call. (RG) I assume you meant error, not info. It isn't possible to be - * misinterpreted as the previous method is for that signature. Methods should be added to avoid varargs for 1, - * 2 or 3 parameters. */ void error(Marker marker, String message, Object... params); @@ -529,11 +520,6 @@ public interface Logger { * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() - * - * TODO Likely to misinterpret existing log4j client code that intended to call info(Object,Throwable). Incurs - * array creation expense on every call. (RG) I assume you meant error, not info. It isn't possible to be - * misinterpreted as the previous method is for that signature. Methods should be added to avoid varargs for 1, - * 2 or 3 parameters. */ void error(String message, Object... params); @@ -583,7 +569,7 @@ public interface Logger { /** * Logs exiting from a method with the result. This may be coded as: - * + * * <pre> * return LOGGER.exit(myResult); * </pre> @@ -667,11 +653,6 @@ public interface Logger { * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() - * - * TODO Likely to misinterpret existing log4j client code that intended to call info(Object,Throwable). Incurs - * array creation expense on every call.(RG) I assume you meant fatal, not info. It isn't possible to be - * misinterpreted as the previous method is for that signature. Methods should be added to avoid varargs for 1, - * 2 or 3 parameters. */ void fatal(Marker marker, String message, Object... params); @@ -783,11 +764,6 @@ public interface Logger { * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() - * - * TODO Likely to misinterpret existing log4j client code that intended to call info(Object,Throwable). Incurs - * array creation expense on every call.(RG) I assume you meant fatal, not info. It isn't possible to be - * misinterpreted as the previous method is for that signature. Methods should be added to avoid varargs for 1, - * 2 or 3 parameters. */ void fatal(String message, Object... params); @@ -924,10 +900,6 @@ public interface Logger { * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() - * - * TODO Likely to misinterpret existing log4j client code that intended to call info(Object,Throwable). Incurs - * array creation expense on every call. (RG) It isn't possible to be misinterpreted as the previous method is - * for that signature. Methods should be added to avoid varargs for 1, 2 or 3 parameters. */ void info(Marker marker, String message, Object... params); @@ -1039,10 +1011,6 @@ public interface Logger { * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() - * - * TODO Likely to misinterpret existing log4j client code that intended to call info(Object,Throwable). Incurs - * array creation expense on every call. (RG) It isn't possible to be misinterpreted as the previous method is - * for that signature. Methods should be added to avoid varargs for 1, 2 or 3 parameters. */ void info(String message, Object... params); @@ -1470,7 +1438,7 @@ public interface Logger { /** * Logs an exception or error to be thrown. This may be coded as: - * + * * <pre> * throw logger.throwing(Level.DEBUG, myException); * </pre> @@ -1484,7 +1452,7 @@ public interface Logger { /** * Logs an exception or error to be thrown. This may be coded as: - * + * * <pre> * throw logger.throwing(myException); * </pre> @@ -1726,6 +1694,144 @@ public interface Logger { void trace(Supplier<?> msgSupplier, Throwable t); /** + * Logs entry to a method. Used when the method in question has no parameters or when the parameters should not be + * logged. + */ + void traceEntry(); + + /** + * Logs entry to a method along with its parameters. For example, + * + * <pre> + * public void doSomething(String foo, int bar) { + * LOGGER.traceEntry("Parameters: {} and {}", foo, bar); + * // do something + * } + * </pre> + * + * @param format The format String for the parameters. + * @param params The parameters to the method. + */ + void traceEntry(final String format, final Object... params); + + /** + * Logs entry to a method along with its parameters. For example, + * + * <pre> + * public void doSomething(Request foo) { + * LOGGER.traceEntry(()->gson.toJson(foo)); + * // do something + * } + * </pre> + * + * @param paramSuppliers The Suppliers for the parameters to the method. + */ + void traceEntry(final Supplier<?>... paramSuppliers); + + /** + * Logs entry to a method along with its parameters. For example, + * + * <pre> + * public void doSomething(String foo, int bar) { + * LOGGER.traceEntry("Parameters: {} and {}", ()->gson.toJson(foo), ()-> bar); + * // do something + * } + * </pre> + * + * @param format The format String for the parameters. + * @param paramSuppliers The Suppliers for the parameters to the method. + */ + void traceEntry(final String format, final Supplier<?>... paramSuppliers); + + /** + * Logs entry to a method using a Message to describe the parameters. + * <pre> + * public void doSomething(Request foo) { + * LOGGER.traceEntry(new JsonMessage(foo)); + * // do something + * } + * </pre> + * + * @param message The message. + */ + void traceEntry(final Message message); + + /** + * Logs entry to a method using a Message to describe the parameters. + * <pre> + * public void doSomething(Request foo) { + * LOGGER.traceEntry(new JsonMessage(foo)); + * // do something + * } + * </pre> + * + * @param msgSupplier The Supplier of the Message. + */ + void traceEntry(final MessageSupplier msgSupplier); + + /** + * Logs exit from a method. Used for methods that do not return anything. + */ + void traceExit(); + + /** + * Logs exiting from a method with the result. This may be coded as: + * + * <pre> + * return LOGGER.traceExit(myResult); + * </pre> + * + * @param <R> The type of the parameter and object being returned. + * @param result The result being returned from the method call. + * @return the result. + */ + <R> R traceExit(R result); + + /** + * Logs exiting from a method with the result. This may be coded as: + * + * <pre> + * return LOGGER.traceExit("Result: {}", myResult); + * </pre> + * + * @param <R> The type of the parameter and object being returned. + * @param format The format String for the result. + * @param result The result being returned from the method call. + * @return the result. + */ + <R> R traceExit(final String format, final R result); + + /** + * Logs exiting from a method with the result. Used when construction of the Message might be + * expensive. This may be coded as: + * + * <pre> + * return LOGGER.traceExit(myResult, () -> new ParameterizedMessage("MyResult: field1: {}, field2: {}", + * myResult.field1.toString(), myResult.field2.toString()); + * </pre> + * + * @param <R> The type of the parameter and object being returned. + * @param result The result being returned from the method call. + * @param messageSupplier The supplier of the Message. + * @return the result. + */ + <R> R traceExit(final R result, final MessageSupplier messageSupplier); + + /** + * Logs exiting from a method with the result. Allows custom formatting of the result. This may be coded as: + * + * <pre> + * return LOGGER.traceExit(myResult, new JsonMessage(myResult)); + * </pre> + * + * @param <R> The type of the parameter and object being returned. + * @param result The result being returned from the method call. + * @param message The Message containing the formatted result. + * @return the result. + */ + <R> R traceExit(final R result, final Message message); + + /** * Logs a message with the specific Marker at the {@link Level#WARN WARN} level. * * @param marker the marker data specific to this log statement @@ -1798,11 +1904,6 @@ public interface Logger { * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() - * - * TODO Likely to misinterpret existing log4j client code that intended to call info(Object,Throwable). Incurs - * array creation expense on every call. (RG) I assume you meant warn, not info. It isn't possible to be - * misinterpreted as the previous method is for that signature.Methods should be added to avoid varargs for 1, - * 2 or 3 parameters. */ void warn(Marker marker, String message, Object... params); @@ -1914,11 +2015,6 @@ public interface Logger { * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() - * - * TODO Likely to misinterpret existing log4j client code that intended to call info(Object,Throwable). Incurs - * array creation expense on every call. (RG) I assume you meant warn, not info. It isn't possible to be - * misinterpreted as the previous method is for that signature.Methods should be added to avoid varargs for 1, - * 2 or 3 parameters. */ void warn(String message, Object... params); http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fcb2d1fd/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java ---------------------------------------------------------------------- diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java index dea99c7..ab74188 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java @@ -24,6 +24,7 @@ import org.apache.logging.log4j.MarkerManager; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.message.MessageFactory; import org.apache.logging.log4j.message.ParameterizedMessageFactory; +import org.apache.logging.log4j.message.SimpleMessage; import org.apache.logging.log4j.message.StringFormattedMessage; import org.apache.logging.log4j.status.StatusLogger; import org.apache.logging.log4j.util.LambdaUtil; @@ -294,9 +295,47 @@ public abstract class AbstractLogger implements ExtendedLogger, Serializable { logIfEnabled(FQCN, Level.DEBUG, null, msgSupplier, t); } + /** + * Logs entry to a method with location information. + * + * @param fqcn The fully qualified class name of the <b>caller</b>. + * @param format Format String for the parameters. + * @param paramSuppliers The Suppliers of the parameters. + */ + protected void enter(final String fqcn, final String format, final Supplier<?>... paramSuppliers) { + if (isEnabled(Level.TRACE, ENTRY_MARKER, (Object) null, null)) { + logMessage(fqcn, Level.TRACE, ENTRY_MARKER, entryMsg(format, paramSuppliers.length, paramSuppliers), null); + } + } + + /** + * Logs entry to a method with location information. + * + * @param fqcn The fully qualified class name of the <b>caller</b>. + * @param format The format String for the parameters. + * @param params The parameters to the method. + */ + protected void enter(final String fqcn, final String format, final Object... params) { + if (isEnabled(Level.TRACE, ENTRY_MARKER, (Object) null, null)) { + logMessage(fqcn, Level.TRACE, ENTRY_MARKER, entryMsg(format, params.length, params), null); + } + } + + /** + * Logs entry to a method with location information. + * + * @param fqcn The fully qualified class name of the <b>caller</b>. + * @param msgSupplier The Supplier of the Message. + */ + protected void enter(final String fqcn, final MessageSupplier msgSupplier) { + if (isEnabled(Level.TRACE, ENTRY_MARKER, (Object) null, null)) { + logMessage(fqcn, Level.TRACE, ENTRY_MARKER, new EntryMessage(msgSupplier.get()), null); + } + } + @Override public void entry() { - entry(FQCN); + entry(FQCN, (String) null); } @Override @@ -312,15 +351,28 @@ public abstract class AbstractLogger implements ExtendedLogger, Serializable { */ protected void entry(final String fqcn, final Object... params) { if (isEnabled(Level.TRACE, ENTRY_MARKER, (Object) null, null)) { - logIfEnabled(fqcn, Level.TRACE, ENTRY_MARKER, entryMsg(params.length, params), null); + logMessage(fqcn, Level.TRACE, ENTRY_MARKER, entryMsg(null, params.length, params), null); } } protected Message entryMsg(final int count, final Object... params) { + return entryMsg(null, count, params); + } + + protected Message entryMsg(final String format, final int count, final Object... params) { if (count == 0) { - return messageFactory.newMessage("entry"); + if (format == null) { + return messageFactory.newMessage("entry"); + } else { + return messageFactory.newMessage("entry: " + format); + } + } + final StringBuilder sb = new StringBuilder("entry"); + if (format != null) { + sb.append(": ").append(format); + return messageFactory.newMessage(sb.toString(), params); } - final StringBuilder sb = new StringBuilder("entry params("); + sb.append(" params("); for (int i = 0; i < params.length; i++) { Object parm = params[i]; sb.append(parm != null ? parm.toString() : "null"); @@ -332,6 +384,14 @@ public abstract class AbstractLogger implements ExtendedLogger, Serializable { return messageFactory.newMessage(sb.toString()); } + protected Message entryMsg(final String format, final int count, final Supplier<?>... paramSuppliers) { + Object[] params = new Object[count]; + for (int i = 0; i < count; i++) { + params[i] = paramSuppliers[i].get(); + } + return entryMsg(format, count, params); + } + @Override public void error(final Marker marker, final Message msg) { logIfEnabled(FQCN, Level.ERROR, marker, msg, null); @@ -454,7 +514,7 @@ public abstract class AbstractLogger implements ExtendedLogger, Serializable { @Override public void exit() { - exit(FQCN, null); + exit(FQCN, (Object) null); } @Override @@ -471,17 +531,36 @@ public abstract class AbstractLogger implements ExtendedLogger, Serializable { * @return the return value passed to this method. */ protected <R> R exit(final String fqcn, final R result) { - if (isEnabled(Level.TRACE, EXIT_MARKER, (Object) null, null)) { - logIfEnabled(fqcn, Level.TRACE, EXIT_MARKER, exitMsg(result), null); - } + logIfEnabled(fqcn, Level.TRACE, EXIT_MARKER, exitMsg(null, result), null); + return result; + } + + /** + * Logs exiting from a method with the result and location information. + * + * @param fqcn The fully qualified class name of the <b>caller</b>. + * @param <R> The type of the parameter and object being returned. + * @param result The result being returned from the method call. + * @return the return value passed to this method. + */ + protected <R> R exit(final String fqcn, final String format, final R result) { + logIfEnabled(fqcn, Level.TRACE, EXIT_MARKER, exitMsg(format, result), null); return result; } - protected Message exitMsg(final Object result) { + protected Message exitMsg(final String format, final Object result) { if (result == null) { - return messageFactory.newMessage("exit"); + if (format == null) { + return messageFactory.newMessage("exit"); + } + return messageFactory.newMessage("exit: " + format); + } else { + if (format == null) { + return messageFactory.newMessage("exit with(" + result + ')'); + } + return messageFactory.newMessage("exit: " + format, result); } - return messageFactory.newMessage("exit with(" + result + ')'); + } @Override @@ -1195,6 +1274,73 @@ public abstract class AbstractLogger implements ExtendedLogger, Serializable { } @Override + public void traceEntry() { + enter(FQCN, null, null); + } + + @Override + public void traceEntry(final String format, final Object... params) { + enter(FQCN, format, params); + } + + + @Override + public void traceEntry(final Supplier<?>... paramSuppliers) { + enter(FQCN, null, paramSuppliers); + } + + @Override + public void traceEntry(final String format, final Supplier<?>... paramSuppliers) { + enter(FQCN, format, paramSuppliers); + } + + + @Override + public void traceEntry(final Message message) { + enter(FQCN, new MessageSupplier() { @Override public Message get() { return message; }}); + } + + @Override + public void traceEntry(final MessageSupplier msgSupplier) { + enter(FQCN, msgSupplier); + } + + @Override + public void traceExit() { + exit(FQCN, null, null); + } + + @Override + public <R> R traceExit(final R result) { + return exit(FQCN, null, result); + } + + @Override + public <R> R traceExit(final String format, final R result) { + return exit(FQCN, format, result); + } + + + @Override + public <R> R traceExit(final R result, final MessageSupplier messageSupplier) { + if (isEnabled(Level.TRACE, EXIT_MARKER, messageSupplier, null)) { + logMessage(FQCN, Level.TRACE, EXIT_MARKER, new MessageSupplier() { + public Message get() { return new ExitMessage(messageSupplier.get()); }; }, null); + } + return result; + } + + @Override + public <R> R traceExit(final R result, final Message message) { + if (isEnabled(Level.TRACE, EXIT_MARKER, message, null)) { + logMessage(FQCN, Level.TRACE, EXIT_MARKER, new MessageSupplier() { + public Message get() { return new ExitMessage(message); }; }, null); + } + return result; + } + + + @Override public void warn(final Marker marker, final Message msg) { logIfEnabled(FQCN, Level.WARN, marker, msg, null); } @@ -1313,4 +1459,65 @@ public abstract class AbstractLogger implements ExtendedLogger, Serializable { public void warn(final MessageSupplier msgSupplier, final Throwable t) { logIfEnabled(FQCN, Level.WARN, null, msgSupplier, t); } + + private static class FlowMessage implements Message { + + private static final long serialVersionUID = 7580175170272152912L; + private Message message; + private final String text; + + FlowMessage(String text, Message message) { + this.message = message; + this.text = text; + } + + @Override + public String getFormattedMessage() { + if (message != null) { + return text + ": " + message.getFormattedMessage(); + } + return text; + } + + @Override + public String getFormat() { + if (message != null) { + return text + ": " + message.getFormat(); + } + return text; + } + + @Override + public Object[] getParameters() { + if (message != null) { + return message.getParameters(); + } + return null; + } + + @Override + public Throwable getThrowable() { + if (message != null) { + return message.getThrowable(); + } + return null; + } + } + + private static class EntryMessage extends FlowMessage { + + EntryMessage(Message message) { + super("entry", message); + } + + } + + + private static class ExitMessage extends FlowMessage { + + ExitMessage(Message message) { + super("exit", message); + } + + } } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fcb2d1fd/log4j-api/src/test/java/org/apache/logging/log4j/LoggerTest.java ---------------------------------------------------------------------- diff --git a/log4j-api/src/test/java/org/apache/logging/log4j/LoggerTest.java b/log4j-api/src/test/java/org/apache/logging/log4j/LoggerTest.java index a2d4ade..702146f 100644 --- a/log4j-api/src/test/java/org/apache/logging/log4j/LoggerTest.java +++ b/log4j-api/src/test/java/org/apache/logging/log4j/LoggerTest.java @@ -20,10 +20,13 @@ import java.util.Date; import java.util.List; import java.util.Locale; +import org.apache.logging.log4j.message.JsonMessage; +import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.message.ParameterizedMessageFactory; import org.apache.logging.log4j.message.SimpleMessageFactory; import org.apache.logging.log4j.message.StringFormatterMessageFactory; import org.apache.logging.log4j.message.StructuredDataMessage; +import org.apache.logging.log4j.util.MessageSupplier; import org.apache.logging.log4j.util.Strings; import org.junit.Before; import org.junit.Test; @@ -58,6 +61,27 @@ public class LoggerTest { } @Test + public void jsonFlow1() { + logger.traceEntry(new MessageSupplier() { + @Override + public Message get() { + return new JsonMessage(System.getProperties()); + } + }); + final Response response = new Response(-1, "Generic error"); + logger.traceExit(response, new MessageSupplier() { + @Override public Message get() { + return new JsonMessage(response); + } + }); + assertEquals(2, results.size()); + assertThat("Incorrect Entry", results.get(0), startsWith("ENTRY[ FLOW ] TRACE entry")); + assertThat("Missing entry data", results.get(0), containsString("\"java.runtime.name\":")); + assertThat("incorrect Exit", results.get(1), startsWith("EXIT[ FLOW ] TRACE exit")); + assertThat("Missing exit data", results.get(1), containsString("\"message\":\"Generic error\"")); + } + + @Test public void catching() { try { throw new NullPointerException(); @@ -397,4 +421,31 @@ public class LoggerTest { assertThat("Incorrect Throwing", results.get(0), startsWith("THROWING[ EXCEPTION ] ERROR throwing java.lang.IllegalArgumentException: Test Exception")); } + + + private class Response { + int status; + String message; + + public Response(int status, String message) { + this.status = status; + this.message = message; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + } } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fcb2d1fd/log4j-api/src/test/java/org/apache/logging/log4j/message/JsonMessage.java ---------------------------------------------------------------------- diff --git a/log4j-api/src/test/java/org/apache/logging/log4j/message/JsonMessage.java b/log4j-api/src/test/java/org/apache/logging/log4j/message/JsonMessage.java new file mode 100644 index 0000000..9183c94 --- /dev/null +++ b/log4j-api/src/test/java/org/apache/logging/log4j/message/JsonMessage.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.logging.log4j.message; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Converts an Object to a JSON String. + */ +public class JsonMessage implements Message { + + private static final ObjectMapper mapper = new ObjectMapper(); + private final Object object; + + public JsonMessage(final Object object) { + this.object = object; + } + + @Override + public String getFormattedMessage() { + try { + return mapper.writeValueAsString(object); + } catch (JsonProcessingException ex) { + System.err.println("Caught exception: " + ex.getMessage()); + return object.toString(); + } + } + + @Override + public String getFormat() { + return object.toString(); + } + + @Override + public Object[] getParameters() { + return new Object[] {object}; + } + + @Override + public Throwable getThrowable() { + return null; + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fcb2d1fd/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index e2cc4c4..a302ce3 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -24,6 +24,9 @@ </properties> <body> <release version="2.6" date="201Y-MM-DD" description="GA Release 2.6"> + <action issue="LOG4J2-1255" dev="rgoers" type="update"> + Add enhanced entry and exit methods. + </action> <action issue="LOG4J2-124" dev="rgoers" type="add"> Add shutdown methods to LogManager. </action> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fcb2d1fd/src/site/xdoc/manual/flowtracing.xml ---------------------------------------------------------------------- diff --git a/src/site/xdoc/manual/flowtracing.xml b/src/site/xdoc/manual/flowtracing.xml index a7a015f..666e81b 100644 --- a/src/site/xdoc/manual/flowtracing.xml +++ b/src/site/xdoc/manual/flowtracing.xml @@ -40,18 +40,26 @@ <li>help educate new developers in learning the application.</li> </ul> <p> - The two most used methods are the entry() and exit() methods. entry() should be placed at the - beginning of methods, except perhaps for simple getters and setters. entry() can be called - passing from 0 to 4 parameters. Typically these will be parameters passed to the method. - The entry() method logs with a level of TRACE and uses a Marker with a name of "ENTER" which - is also a "FLOW" Marker. + The most used methods are the entry() or traceEntry() and exit() or traceExit() methods. entry() + or traceEntry() should be placed at the beginning of methods, except perhaps for simple + getters and setters. entry() can be calledpassing from 0 to 4 parameters. Typically these will be + parameters passed to the method. traceEntry() can be passed a format String and a variable list of + parameters, or a Message. The entry() and traceEntry() methods log with a level of TRACE and uses + a Marker with a name of "ENTER" which is also a "FLOW" Marker and all message strings will begin + with "event", even if a format String or Message is used. </p> + <p>The main difference between the entry and traceEntry methods is that the entry method accepts a + variable list of objects where presumably each is a method parameter. The traceEntry method + accepts a format string followed by a variable list of objects, presumably included in the + format String. It is not possible to have a single method that includes both of these as it would + be ambiguous whether the first String is a parameter or a format String.</p> <p> - The exit() method should be placed before any return statement or as the last statement of - methods without a return. exit() can be called with or without a parameter. Typically, methods - that return void will use exit() while methods that return an Object will use exit(Object obj). - The exit() method logs with a level of TRACE and uses a Marker with a name of "EXIT" which is - also a "FLOW" Marker. + An exit() or traceExit() method should be placed before any return statement or as the last statement of + methods without a return. exit() and traceExit() can be called with or without a parameter. Typically, + methods that return void will use exit() or traceExit() while methods that return an Object will use + exit(Object obj) or traceExit(object, new SomeMessage(object)). The exit() and traceExit() methods log + with a level of TRACE and uses a Marker with a name of "EXIT" which is also a "FLOW" Marker and all + message strings will begin with "exit", even if a format String or Message is used. </p> <p> The throwing() method can be used by an application when it is throwing an exception that is @@ -87,6 +95,17 @@ public class TestService { }; private Random rand = new Random(1); + public void setMessages(String[] messages) { + logger.traceEntry(new JsonMessage(messages)); + this.messages = messages; + logger.traceExit(); + } + + public String[] getMessages() { + logger.traceEntry(); + return logger.traceExit(messages, new JsonMessage(messages)); + } + public String retrieveMessage() { logger.entry();
