/*
* IronJacamar, a Java EE Connector Architecture implementation
* Copyright 2016, Red Hat Inc, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the Eclipse Public License 1.0 as
* published by the Free Software Foundation.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Eclipse
* Public License for more details.
*
* You should have received a copy of the Eclipse Public License
* along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.ironjacamar.core.tracer;
import org.ironjacamar.Version;
import java.io.CharArrayWriter;
import java.io.PrintWriter;
import org.jboss.logging.Logger;
/**
* The tracer class
*
* @author <a href="mailto:jesper.pedersen@ironjacamar.org">Jesper Pedersen</a>
*/
public class Tracer
{
/** Tracer logger */
private static Logger log = Logger.getLogger(Tracer.class);
/** Is the tracer enabled */
private static boolean enabled = log.isTraceEnabled();
/** Are callstacks recorded */
private static boolean recordCallstacks = false;
/** Is the tracer confidential */
private static boolean confidential = false;
static
{
log.tracef("%s", new TraceEvent(Version.VERSION, "NONE", TraceEvent.VERSION, "NONE"));
String value = SecurityActions.getSystemProperty("ironjacamar.tracer.callstacks");
if (value != null && !value.trim().equals(""))
{
try
{
recordCallstacks = Boolean.valueOf(value);
}
catch (Throwable t)
{
// Assume record callstacks
recordCallstacks = true;
}
}
value = SecurityActions.getSystemProperty("ironjacamar.tracer.confidential");
if (value != null && !value.trim().equals(""))
{
try
{
confidential = Boolean.valueOf(value);
}
catch (Throwable t)
{
// Assume confidential
confidential = true;
}
}
}
/**
* Is enabled
* @return The value
*/
public static boolean isEnabled()
{
return enabled;
}
/**
* Set enabled
* @param v The value
*/
public static void setEnabled(boolean v)
{
enabled = v;
}
/**
* Should callstacks be recorded
* @return The value
*/
public static boolean isRecordCallstacks()
{
return recordCallstacks && !confidential;
}
/**
* Is confidential
* @return The value
*/
public static boolean isConfidential()
{
return confidential;
}
/**
* Get connection listener
* @param poolName The name of the pool
* @param mcp The managed connection pool
* @param cl The connection listener
* @param pooled Is the connection pooled
* @param interleaving Interleaving flag
* @param callstack The call stack
*/
public static synchronized void getConnectionListener(String poolName, Object mcp, Object cl,
boolean pooled, boolean interleaving,
Throwable callstack)
{
if (!interleaving)
{
if (pooled)
{
log.tracef("%s", new TraceEvent(poolName, Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.GET_CONNECTION_LISTENER,
Integer.toHexString(System.identityHashCode(cl)),
!confidential && callstack != null ? toString(callstack) : ""));
}
else
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.GET_CONNECTION_LISTENER_NEW,
Integer.toHexString(System.identityHashCode(cl)),
!confidential && callstack != null ? toString(callstack) : ""));
}
}
else
{
if (pooled)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.GET_INTERLEAVING_CONNECTION_LISTENER,
Integer.toHexString(System.identityHashCode(cl)),
!confidential && callstack != null ? toString(callstack) : ""));
}
else
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.GET_INTERLEAVING_CONNECTION_LISTENER_NEW,
Integer.toHexString(System.identityHashCode(cl)),
!confidential && callstack != null ? toString(callstack) : ""));
}
}
}
/**
* Return connection listener
* @param poolName The name of the pool
* @param mcp The managed connection pool
* @param cl The connection listener
* @param kill Kill the listener
* @param interleaving Interleaving flag
* @param callstack The call stack
*/
public static synchronized void returnConnectionListener(String poolName, Object mcp,
Object cl, boolean kill, boolean interleaving,
Throwable callstack)
{
if (!interleaving)
{
if (!kill)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.RETURN_CONNECTION_LISTENER,
Integer.toHexString(System.identityHashCode(cl)),
!confidential && callstack != null ? toString(callstack) : ""));
}
else
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.RETURN_CONNECTION_LISTENER_WITH_KILL,
Integer.toHexString(System.identityHashCode(cl)),
!confidential && callstack != null ? toString(callstack) : ""));
}
}
else
{
if (!kill)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.RETURN_INTERLEAVING_CONNECTION_LISTENER,
Integer.toHexString(System.identityHashCode(cl)),
!confidential && callstack != null ? toString(callstack) : ""));
}
else
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.RETURN_INTERLEAVING_CONNECTION_LISTENER_WITH_KILL,
Integer.toHexString(System.identityHashCode(cl)),
!confidential && callstack != null ? toString(callstack) : ""));
}
}
}
/**
* Clear connection listener
* @param poolName The name of the pool
* @param mcp The managed connection pool
* @param cl The connection listener
*/
public static synchronized void clearConnectionListener(String poolName, Object mcp, Object cl)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.CLEAR_CONNECTION_LISTENER,
Integer.toHexString(System.identityHashCode(cl))));
}
/**
* Enlist connection listener
* @param poolName The name of the pool
* @param mcp The managed connection pool
* @param cl The connection listener
* @param tx The transaction
* @param success Outcome
* @param interleaving Interleaving flag
*/
public static synchronized void enlistConnectionListener(String poolName, Object mcp, Object cl,
String tx,
boolean success, boolean interleaving)
{
if (!interleaving)
{
if (success)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.ENLIST_CONNECTION_LISTENER,
Integer.toHexString(System.identityHashCode(cl)),
tx.replace('-', '_')));
}
else
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.ENLIST_CONNECTION_LISTENER_FAILED,
Integer.toHexString(System.identityHashCode(cl)),
tx.replace('-', '_')));
}
}
else
{
if (success)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.ENLIST_INTERLEAVING_CONNECTION_LISTENER,
Integer.toHexString(System.identityHashCode(cl)),
tx.replace('-', '_')));
}
else
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.ENLIST_INTERLEAVING_CONNECTION_LISTENER_FAILED,
Integer.toHexString(System.identityHashCode(cl)),
tx.replace('-', '_')));
}
}
}
/**
* Delist connection listener
* @param poolName The name of the pool
* @param mcp The managed connection pool
* @param cl The connection listener
* @param tx The transaction
* @param success Is successful
* @param rollbacked Is the transaction rollbacked
* @param interleaving Interleaving flag
*/
public static synchronized void delistConnectionListener(String poolName, Object mcp, Object cl, String tx,
boolean success, boolean rollbacked, boolean interleaving)
{
if (!rollbacked)
{
if (!interleaving)
{
if (success)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.DELIST_CONNECTION_LISTENER,
Integer.toHexString(System.identityHashCode(cl)),
tx.replace('-', '_')));
}
else
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.DELIST_CONNECTION_LISTENER_FAILED,
Integer.toHexString(System.identityHashCode(cl)),
tx.replace('-', '_')));
}
}
else
{
if (success)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.DELIST_INTERLEAVING_CONNECTION_LISTENER,
Integer.toHexString(System.identityHashCode(cl)),
tx.replace('-', '_')));
}
else
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.DELIST_INTERLEAVING_CONNECTION_LISTENER_FAILED,
Integer.toHexString(System.identityHashCode(cl)),
tx.replace('-', '_')));
}
}
}
else
{
if (success)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.DELIST_ROLLEDBACK_CONNECTION_LISTENER,
Integer.toHexString(System.identityHashCode(cl)),
tx.replace('-', '_')));
}
else
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.DELIST_ROLLEDBACK_CONNECTION_LISTENER_FAILED,
Integer.toHexString(System.identityHashCode(cl)),
tx.replace('-', '_')));
}
}
}
/**
* Get connection
* @param poolName The name of the pool
* @param mcp The managed connection pool
* @param cl The connection listener
* @param connection The connection
*/
public static synchronized void getConnection(String poolName, Object mcp, Object cl, Object connection)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.GET_CONNECTION,
Integer.toHexString(System.identityHashCode(cl)),
Integer.toHexString(System.identityHashCode(connection))));
}
/**
* Return connection
* @param poolName The name of the pool
* @param mcp The managed connection pool
* @param cl The connection listener
* @param connection The connection
*/
public static synchronized void returnConnection(String poolName, Object mcp, Object cl, Object connection)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.RETURN_CONNECTION,
Integer.toHexString(System.identityHashCode(cl)),
Integer.toHexString(System.identityHashCode(connection))));
}
/**
* Clear connection
* @param poolName The name of the pool
* @param mcp The managed connection pool
* @param cl The connection listener
* @param connection The connection
*/
public static synchronized void clearConnection(String poolName, Object mcp, Object cl, Object connection)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.CLEAR_CONNECTION,
Integer.toHexString(System.identityHashCode(cl)),
Integer.toHexString(System.identityHashCode(connection))));
}
/**
* Exception
* @param poolName The name of the pool
* @param mcp The managed connection pool
* @param cl The connection listener
* @param exception The exception
*/
public static synchronized void exception(String poolName, Object mcp, Object cl, Throwable exception)
{
if (!confidential)
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.EXCEPTION,
Integer.toHexString(System.identityHashCode(cl)),
toString(exception)));
}
/**
* Create connection listener
* @param poolName The name of the pool
* @param mcp The managed connection pool
* @param cl The connection listener
* @param mc The managed connection
* @param get A GET operation
* @param prefill A PREFILL operation
* @param incrementer An INCREMENTER operation
* @param callstack The call stack
*/
public static synchronized void createConnectionListener(String poolName, Object mcp, Object cl, Object mc,
boolean get, boolean prefill, boolean incrementer,
Throwable callstack)
{
if (get)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.CREATE_CONNECTION_LISTENER_GET,
Integer.toHexString(System.identityHashCode(cl)),
Integer.toHexString(System.identityHashCode(mc)),
!confidential && callstack != null ? toString(callstack) : ""));
}
else if (prefill)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.CREATE_CONNECTION_LISTENER_PREFILL,
Integer.toHexString(System.identityHashCode(cl)),
Integer.toHexString(System.identityHashCode(mc)),
!confidential && callstack != null ? toString(callstack) : ""));
}
else if (incrementer)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.CREATE_CONNECTION_LISTENER_INCREMENTER,
Integer.toHexString(System.identityHashCode(cl)),
Integer.toHexString(System.identityHashCode(mc)),
!confidential && callstack != null ? toString(callstack) : ""));
}
}
/**
* Destroy connection listener
* @param poolName The name of the pool
* @param mcp The managed connection pool
* @param cl The connection listener
* @param ret A RETURN operation
* @param idle An IDLE operation
* @param invalid An INVALID operation
* @param flush A FLUSH operation
* @param error An ERROR operation
* @param prefill A PREFILL operation
* @param incrementer An INCREMENTER operation
* @param callstack The call stack
*/
public static synchronized void destroyConnectionListener(String poolName, Object mcp, Object cl,
boolean ret, boolean idle, boolean invalid,
boolean flush, boolean error,
boolean prefill, boolean incrementer,
Throwable callstack)
{
if (ret)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.DESTROY_CONNECTION_LISTENER_RETURN,
Integer.toHexString(System.identityHashCode(cl)),
!confidential && callstack != null ? toString(callstack) : ""));
}
else if (idle)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.DESTROY_CONNECTION_LISTENER_IDLE,
Integer.toHexString(System.identityHashCode(cl)),
!confidential && callstack != null ? toString(callstack) : ""));
}
else if (invalid)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.DESTROY_CONNECTION_LISTENER_INVALID,
Integer.toHexString(System.identityHashCode(cl)),
!confidential && callstack != null ? toString(callstack) : ""));
}
else if (flush)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.DESTROY_CONNECTION_LISTENER_FLUSH,
Integer.toHexString(System.identityHashCode(cl)),
!confidential && callstack != null ? toString(callstack) : ""));
}
else if (error)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.DESTROY_CONNECTION_LISTENER_ERROR,
Integer.toHexString(System.identityHashCode(cl)),
!confidential && callstack != null ? toString(callstack) : ""));
}
else if (prefill)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.DESTROY_CONNECTION_LISTENER_PREFILL,
Integer.toHexString(System.identityHashCode(cl)),
!confidential && callstack != null ? toString(callstack) : ""));
}
else if (incrementer)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.DESTROY_CONNECTION_LISTENER_INCREMENTER,
Integer.toHexString(System.identityHashCode(cl)),
!confidential && callstack != null ? toString(callstack) : ""));
}
}
/**
* Create managed connection pool
* @param poolName The name of the pool
* @param mcp The managed connection pool
*/
public static synchronized void createManagedConnectionPool(String poolName, Object mcp)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.MANAGED_CONNECTION_POOL_CREATE,
"NONE"));
}
/**
* Destroy managed connection pool
* @param poolName The name of the pool
* @param mcp The managed connection pool
*/
public static synchronized void destroyManagedConnectionPool(String poolName, Object mcp)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.MANAGED_CONNECTION_POOL_DESTROY,
"NONE"));
}
/**
* Push CCM context
* @param key The frame key
* @param callstack The call stack
*/
public static synchronized void pushCCMContext(String key, Throwable callstack)
{
log.tracef("%s", new TraceEvent("CachedConnectionManager", "NONE", TraceEvent.PUSH_CCM_CONTEXT,
"NONE", key, callstack != null ? toString(callstack) : ""));
}
/**
* Pop CCM context
* @param key The frame key
* @param callstack The call stack
*/
public static synchronized void popCCMContext(String key, Throwable callstack)
{
log.tracef("%s", new TraceEvent("CachedConnectionManager", "NONE", TraceEvent.POP_CCM_CONTEXT,
"NONE", key, callstack != null ? toString(callstack) : ""));
}
/**
* Register CCM connection
* @param poolName The name of the pool
* @param mcp The managed connection pool
* @param cl The connection listener
* @param connection The connection
* @param key The frame key
*/
public static synchronized void registerCCMConnection(String poolName, Object mcp, Object cl,
Object connection, String key)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.REGISTER_CCM_CONNECTION,
Integer.toHexString(System.identityHashCode(cl)),
Integer.toHexString(System.identityHashCode(connection)),
key));
}
/**
* Unregister CCM connection
* @param poolName The name of the pool
* @param mcp The managed connection pool
* @param cl The connection listener
* @param connection The connection
* @param key The frame key
*/
public static synchronized void unregisterCCMConnection(String poolName, Object mcp, Object cl,
Object connection, String key)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.UNREGISTER_CCM_CONNECTION,
Integer.toHexString(System.identityHashCode(cl)),
Integer.toHexString(System.identityHashCode(connection)),
key));
}
/**
* Unknown CCM connection
* @param poolName The name of the pool
* @param mcp The managed connection pool
* @param cl The connection listener
* @param connection The connection
* @param key The frame key
*/
public static synchronized void unknownCCMConnection(String poolName, Object mcp, Object cl,
Object connection, String key)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.UNKNOWN_CCM_CONNECTION,
Integer.toHexString(System.identityHashCode(cl)),
Integer.toHexString(System.identityHashCode(connection)),
key));
}
/**
* Close CCM connection
* @param poolName The name of the pool
* @param mcp The managed connection pool
* @param cl The connection listener
* @param connection The connection
* @param key The frame key
*/
public static synchronized void closeCCMConnection(String poolName, Object mcp, Object cl,
Object connection, String key)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.CLOSE_CCM_CONNECTION,
Integer.toHexString(System.identityHashCode(cl)),
Integer.toHexString(System.identityHashCode(connection)),
key));
}
/**
* CCM user transaction
* @param poolName The name of the pool
* @param mcp The managed connection pool
* @param cl The connection listener
* @param connection The connection
* @param key The frame key
*/
public static synchronized void ccmUserTransaction(String poolName, Object mcp, Object cl,
Object connection, String key)
{
log.tracef("%s", new TraceEvent(poolName,
Integer.toHexString(System.identityHashCode(mcp)),
TraceEvent.CCM_USER_TRANSACTION,
Integer.toHexString(System.identityHashCode(cl)),
Integer.toHexString(System.identityHashCode(connection)),
key));
}
/**
* Throwable to string
* @param exception The exception
* @return The string representation
*/
private static synchronized String toString(Throwable exception)
{
CharArrayWriter caw = new CharArrayWriter();
PrintWriter pw = new PrintWriter(caw, true);
exception.printStackTrace(pw);
pw.flush();
char[] data = caw.toCharArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.length; i++)
{
char c = data[i];
if (c == '\n')
{
sb = sb.append('|');
}
else if (c == '\r')
{
sb = sb.append('/');
}
else if (c == '\t')
{
sb = sb.append('\\');
}
else if (c == ' ')
{
sb = sb.append('_');
}
else
{
sb = sb.append(c);
}
}
return sb.toString();
}
}