[
https://issues.apache.org/jira/browse/LOG4J2-1255?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15102470#comment-15102470
]
Gary Gregory commented on LOG4J2-1255:
--------------------------------------
Here's how I do it. You can omit the API counting stuff (TRACE_ENTER_MAP).
{code:java}
package ...
import java.util.Arrays;
import java.util.IllegalFormatException;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.spi.AbstractLogger;
import org.apache.logging.log4j.status.StatusLogger;
/**
* Performs flow logging with more information than stock Log4j.
*/
public final class DvFlowLogger {
private static final String _FLOW_ENTER = "Enter";
private static final String _FLOW_EXIT = "Exit";
private static final String _RETURN_SEPARATOR = " : ";
private static final String _STRING_SEPARATOR = "\"";
private static boolean CountTraceEnter = false;
/**
* Caches flow loggers like Log4j caches Loggers.
*/
private static final Map<Logger, DvFlowLogger> loggerMap = new
WeakHashMap<>();
private static final int RETURN_BUFFER_MIN_SIZE = 1 + _FLOW_EXIT.length() +
_RETURN_SEPARATOR.length();
private static final ConcurrentHashMap<String, Integer> TRACE_ENTER_MAP =
new ConcurrentHashMap<>();
public static void clearTraceEnterMap() {
TRACE_ENTER_MAP.clear();
}
public static DvFlowLogger createFlowLogger(final Logger logger) {
// Caches flow loggers like Log4j caches Loggers.
// Do not bother with synchronization for now.
DvFlowLogger dvFlowLogger = loggerMap.get(logger);
if (dvFlowLogger != null) {
return dvFlowLogger;
}
dvFlowLogger = new DvFlowLogger(logger);
loggerMap.put(logger, dvFlowLogger);
return dvFlowLogger;
}
public static boolean getCountTraceEnter() {
return CountTraceEnter;
}
public static Map<String, Integer> getTraceEnterMap() {
return TRACE_ENTER_MAP;
}
public static void logTraceEnterMap(final Logger logger) {
if (logger == null || !logger.isDebugEnabled()) {
return;
}
logger.debug("JDBC API trace enter map size: %,d",
TRACE_ENTER_MAP.size());
final Map<String, Integer> sortedMap = new TreeMap<>(TRACE_ENTER_MAP);
for (final Map.Entry<String, Integer> entry : sortedMap.entrySet()) {
logger.debug("%s = %s", entry.getKey(), entry.getValue());
}
}
public static void setCountTraceEnter(final boolean countTraceEnter) {
CountTraceEnter = countTraceEnter;
}
private final Logger logger;
public DvFlowLogger(final Logger logger) {
super();
Objects.requireNonNull(logger, "Logger must not be null");
this.logger = logger;
}
StringBuilder appendMethodFlow(final StringBuilder sb, final String flow,
final String method) {
sb.append(flow);
sb.append(' ');
sb.append(method);
return sb;
}
private void countTraceEnter(final Object self, final String method) {
if (!CountTraceEnter) {
return;
}
// Update pattern found here:
http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap2.shtml
// TODO Review
final String key = self.getClass().getSimpleName() + "." + method;
Integer oldVal, newVal;
do {
oldVal = TRACE_ENTER_MAP.get(key);
newVal = oldVal == null ? 1 : oldVal + 1;
if (oldVal == null) {
TRACE_ENTER_MAP.put(key, newVal);
oldVal = newVal;
}
} while (!TRACE_ENTER_MAP.replace(key, oldVal, newVal));
}
public Logger getLogger() {
return logger;
}
String toFormattedMethod(final Object obj, final String messagePattern,
final Object... args) {
final String simpleName = DvLoggerFactory.toSimpleName(obj);
final String formattedMethod = toFormattedString(messagePattern, args);
final StringBuilder sb = new StringBuilder(simpleName.length() + 12 +
formattedMethod.length());
sb.append(simpleName);
sb.append('@');
sb.append(Integer.toHexString(Objects.hashCode(obj)));
sb.append('.');
sb.append(formattedMethod);
return sb.toString();
}
String toFormattedString(final String messagePattern, final Object... args)
{
if (args != null) {
try {
return String.format(messagePattern, args);
} catch (final IllegalFormatException e) {
StatusLogger.getLogger().error("Unable to format msg: " +
messagePattern, e);
}
}
return messagePattern;
}
String toMethodEntry(final String method) {
return toMethodFlow(_FLOW_ENTER, method);
}
String toMethodExit(final String method) {
return toMethodFlow(_FLOW_EXIT, method);
}
String toMethodExit(final String method, final Object value) {
final String valueToString = value instanceof CharSequence ?
_STRING_SEPARATOR + value + _STRING_SEPARATOR : String.valueOf(value);
final int capacity = method.length() + RETURN_BUFFER_MIN_SIZE +
valueToString.length();
return appendMethodFlow(new StringBuilder(capacity), _FLOW_EXIT,
method).append(_RETURN_SEPARATOR).append(valueToString).toString();
}
String toMethodFlow(final String flow, final String method) {
final int capacity = flow.length() + 1 + method.length();
return appendMethodFlow(new StringBuilder(capacity), flow,
method).toString();
}
public String traceEntry(final Object obj, final String method) {
countTraceEnter(obj, method);
if (logger.isTraceEnabled()) {
final String formattedMethod = toFormattedMethod(obj, method);
logger.trace(AbstractLogger.ENTRY_MARKER,
toMethodEntry(formattedMethod));
return formattedMethod;
}
return method;
}
public String traceEntry(final Object obj, final String method, final
Object... args) {
countTraceEnter(obj, method);
if (logger.isTraceEnabled()) {
final String formattedMethod = toFormattedMethod(obj, method, args);
logger.trace(AbstractLogger.ENTRY_MARKER,
toMethodEntry(formattedMethod));
return formattedMethod;
}
return method;
}
public String traceEntry(final Object obj, final String method, final
Object arg0) {
countTraceEnter(obj, method);
if (logger.isTraceEnabled()) {
final String formattedMethod = toFormattedMethod(obj, method, arg0);
logger.trace(AbstractLogger.ENTRY_MARKER,
toMethodEntry(formattedMethod));
return formattedMethod;
}
return method;
}
public String traceEntry(final Object obj, final String method, final
Object arg0, final int[] arg1) {
countTraceEnter(obj, method);
if (logger.isTraceEnabled()) {
final String formattedMethod = toFormattedMethod(obj, method, arg0,
Arrays.toString(arg1));
logger.trace(AbstractLogger.ENTRY_MARKER,
toMethodEntry(formattedMethod));
return formattedMethod;
}
return method;
}
public String traceEntry(final Object obj, final String method, final
Object arg0, final Object arg1) {
countTraceEnter(obj, method);
if (logger.isTraceEnabled()) {
final String formattedMethod = toFormattedMethod(obj, method, arg0,
arg1);
logger.trace(AbstractLogger.ENTRY_MARKER,
toMethodEntry(formattedMethod));
return formattedMethod;
}
return method;
}
public String traceEntry(final Object obj, final String method, final
Object arg0, final Object arg1, final Object arg2) {
countTraceEnter(obj, method);
if (logger.isTraceEnabled()) {
final String formattedMethod = toFormattedMethod(obj, method, arg0,
arg1, arg2);
logger.trace(AbstractLogger.ENTRY_MARKER,
toMethodEntry(formattedMethod));
return formattedMethod;
}
return method;
}
public String traceEntry(final Object obj, final String method, final
Object arg0, final String[] arg1) {
countTraceEnter(obj, method);
if (logger.isTraceEnabled()) {
final String formattedMethod = toFormattedMethod(obj, method, arg0,
Arrays.toString(arg1));
logger.trace(AbstractLogger.ENTRY_MARKER,
toMethodEntry(formattedMethod));
return formattedMethod;
}
return method;
}
public void traceExit(final String method) {
if (logger.isTraceEnabled()) {
logger.trace(AbstractLogger.EXIT_MARKER, toMethodExit(method));
}
}
public <T> T traceExit(final String method, final T value) {
if (logger.isTraceEnabled()) {
logger.trace(AbstractLogger.EXIT_MARKER, toMethodExit(method,
value));
}
return value;
}
}
{code}
> Logger.entry and Logger.exit should support Messages.
> -----------------------------------------------------
>
> Key: LOG4J2-1255
> URL: https://issues.apache.org/jira/browse/LOG4J2-1255
> Project: Log4j 2
> Issue Type: Improvement
> Components: API
> Affects Versions: 2.5
> Reporter: Ralph Goers
> Assignee: Ralph Goers
>
> Logger.entry and Logger.exit currently do not support Message objects. This
> reduces the flexibility of what can be logged on entry and exit to methods.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]