From 8e08cb5cc8d7f8377669a1086b714937f2ff7a47 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Fri, 26 Apr 2024 04:46:44 +0200 Subject: [PATCH] IDEMPIERE-6125 Allow monitoring null transactions on idempiereMonitor (#2332) * IDEMPIERE-6125 Allow monitoring null transactions on idempiereMonitor * - add warning --- .../src/org/compiere/db/StatementProxy.java | 6 +++ .../org/compiere/model/SystemProperties.java | 11 ++++++ .../src/org/compiere/util/Trx.java | 37 +++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/org.adempiere.base/src/org/compiere/db/StatementProxy.java b/org.adempiere.base/src/org/compiere/db/StatementProxy.java index 9fd61a7d8e..2da803be93 100644 --- a/org.adempiere.base/src/org/compiere/db/StatementProxy.java +++ b/org.adempiere.base/src/org/compiere/db/StatementProxy.java @@ -25,6 +25,7 @@ import java.util.logging.Level; import javax.sql.RowSet; import org.adempiere.exceptions.DBException; +import org.compiere.model.SystemProperties; import org.compiere.util.CCachedRowSet; import org.compiere.util.CLogger; import org.compiere.util.CStatementVO; @@ -133,8 +134,11 @@ public class StatementProxy implements InvocationHandler { } } Method m = p_stmt.getClass().getMethod(name, method.getParameterTypes()); + String nullTrxName = null; try { + if (SystemProperties.isTraceNullTrxConnection() && p_vo.getTrxName() == null) + nullTrxName = Trx.registerNullTrx(); return m.invoke(p_stmt, args); } catch (InvocationTargetException e) @@ -143,6 +147,8 @@ public class StatementProxy implements InvocationHandler { } finally { + if (nullTrxName != null && p_vo.getTrxName() == null) + Trx.unregisterNullTrx(nullTrxName); if (log.isLoggable(Level.FINE) && logSql != null && logOperation != null) { log.fine((DisplayType.getDateFormat(DisplayType.DateTime)).format(new Date(System.currentTimeMillis()))+","+logOperation+","+logSql+","+(p_vo.getTrxName() != null ? p_vo.getTrxName() : "")+" (end)"); diff --git a/org.adempiere.base/src/org/compiere/model/SystemProperties.java b/org.adempiere.base/src/org/compiere/model/SystemProperties.java index d9d368d27f..db44544c79 100644 --- a/org.adempiere.base/src/org/compiere/model/SystemProperties.java +++ b/org.adempiere.base/src/org/compiere/model/SystemProperties.java @@ -55,6 +55,7 @@ public class SystemProperties { private static final String PropertyFile = "PropertyFile"; private static final String PropertyHomeFile = "PropertyHomeFile"; private static final String TestOCI = "TestOCI"; + private static final String TRACE_NULL_TRX_CONNECTION = "TRACE_NULL_TRX_CONNECTION"; private static final String ZK_THEME = MSysConfig.ZK_THEME; private static final String ZkUnitTest = "ZkUnitTest"; @@ -258,4 +259,14 @@ public class SystemProperties { return "true".equals(System.getProperty(ZkUnitTest)); } + /** + * TRACE_NULL_TRX_CONNECTION=true to allow tracing null transactions on idempiereMonitor + * WARNING! this setting can have a big performance impact, it is disabled by default + * use it with care in production just temporarily to trace problematic connection slowness or leaks + * @return + */ + public static boolean isTraceNullTrxConnection() { + return "true".equals(System.getProperty(TRACE_NULL_TRX_CONNECTION)); + } + } diff --git a/org.adempiere.base/src/org/compiere/util/Trx.java b/org.adempiere.base/src/org/compiere/util/Trx.java index 8dd3302b41..0ae8b2d17c 100644 --- a/org.adempiere.base/src/org/compiere/util/Trx.java +++ b/org.adempiere.base/src/org/compiere/util/Trx.java @@ -34,6 +34,7 @@ import java.util.logging.Level; import org.adempiere.exceptions.AdempiereException; import org.adempiere.exceptions.DBException; import org.compiere.Adempiere; +import org.compiere.db.StatementProxy; import org.compiere.model.MSysConfig; import org.compiere.model.PO; @@ -876,4 +877,40 @@ public class Trx }, 2, TimeUnit.SECONDS); } } + + /** + * Register a null trx + * @return + */ + public static String registerNullTrx() { + String nullTrxName = "NullTrx_" + UUID.randomUUID().toString(); + Trx nullTrx = new Trx(nullTrxName); + nullTrx.trace = new Exception(); + nullTrx.m_startTime = System.currentTimeMillis(); + String displayName = null; + StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); + Optional stackName = walker.walk(frames -> frames.map( + stackFrame -> stackFrame.getClassName() + "." + + stackFrame.getMethodName() + ":" + + stackFrame.getLineNumber()) + .filter(f -> ! (f.startsWith(Trx.class.getName() + ".") || f.startsWith(StatementProxy.class.getName() + ".") || f.startsWith("jdk.proxy") || f.startsWith("org.compiere.util.DB."))) + .findFirst()); + displayName = (stackName.orElse(null)); + if (displayName != null) + nullTrx.setDisplayName(displayName); + s_cache.put(nullTrxName, nullTrx); + return nullTrxName; + } + + /** + * Unregister a null trx + * @param nullTrxName + */ + public static void unregisterNullTrx(String nullTrxName) { + Trx nullTrx = s_cache.get(nullTrxName); + nullTrx.setDisplayName(null); + nullTrx.trace = null; + s_cache.remove(nullTrxName); + } + } // Trx