modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java
| 47 +++++++++-
1 file changed, 44 insertions(+), 3 deletions(-)
New commits:
commit 74aa8d05d1ca8cc2c0055453ac108e49e640aa20
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Sep 16 14:29:14 2011 -0400
add configurability to the logging of the hibernate detach utility. with this checkin,
the following happens:
1. by default, we only log at DEBUG level the number of objects detached and the
duration it took IF it took longer than 10s
2. you can have it log a more detailed message at a certain threshold if you set the
sysprop "rhq.server.hibernate-detach-utility.dump-stack-thresholds"
you set it to two numbers separated by a :, for example "5000:10000"
means a message will be logged at the WARN
level IF the detach took longer that 5000ms OR the number of objects detached was
over 10K.
We log the duration, number of objects AND the class of the object being detached
(we can't log the object's toString because
that would be very long, especially for very large PageList of compound objects).
We also log the full stack trace so we know where the object came from.
diff --git
a/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java
b/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java
index 23f73ee..08c02e2 100644
---
a/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java
+++
b/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java
@@ -89,6 +89,11 @@ public class HibernateDetachUtility {
private static final String THROW_EXCEPTION_ON_DEPTH_LIMIT_SYSPROP =
"rhq.server.hibernate-detach-utility.throw-exception-on-depth-limit";
private static final int depthAllowed;
private static final boolean throwExceptionOnDepthLimit;
+ private static final String DUMP_STACK_THRESHOLDS_SYSPROP =
"rhq.server.hibernate-detach-utility.dump-stack-thresholds"; // e.g.
"5000:10000" (millis:num-objects)
+ private static final boolean dumpStackOnThresholdLimit;
+ private static final long millisThresholdLimit;
+ private static final int sizeThresholdLimit;
+
static {
int value;
try {
@@ -107,6 +112,32 @@ public class HibernateDetachUtility {
booleanValue = true;
}
throwExceptionOnDepthLimit = booleanValue;
+
+ boolean tmp_dumpStackOnThresholdLimit;
+ long tmp_millisThresholdLimit;
+ int tmp_sizeThresholdLimit;
+ String prop = null;
+ try {
+ prop = System.getProperty(DUMP_STACK_THRESHOLDS_SYSPROP);
+ if (prop != null) {
+ String[] nums = prop.split(":");
+ tmp_dumpStackOnThresholdLimit = true;
+ tmp_millisThresholdLimit = Long.parseLong(nums[0]);
+ tmp_sizeThresholdLimit = Integer.parseInt(nums[1]);
+ } else {
+ tmp_dumpStackOnThresholdLimit = false;
+ tmp_millisThresholdLimit = Long.MAX_VALUE;
+ tmp_sizeThresholdLimit = Integer.MAX_VALUE;
+ }
+ } catch (Throwable t) {
+ LOG.warn("Bad value for [" + DUMP_STACK_THRESHOLDS_SYSPROP +
"]=[" + prop + "]: " + t.toString());
+ tmp_dumpStackOnThresholdLimit = true; // they wanted to set it to something,
so give them some defaults
+ tmp_millisThresholdLimit = 5000L; // 5 seconds
+ tmp_sizeThresholdLimit = 10000; // 10K objects
+ }
+ dumpStackOnThresholdLimit = tmp_dumpStackOnThresholdLimit;
+ millisThresholdLimit = tmp_millisThresholdLimit;
+ sizeThresholdLimit = tmp_sizeThresholdLimit;
}
public static void nullOutUninitializedFields(Object value, SerializationType
serializationType) throws Exception {
@@ -115,11 +146,21 @@ public class HibernateDetachUtility {
Map<Integer, List<Object>> checkedObjectCollisionMap = new
HashMap<Integer, List<Object>>();
nullOutUninitializedFields(value, checkedObjectMap, checkedObjectCollisionMap, 0,
serializationType);
long duration = System.currentTimeMillis() - start;
- if (duration > 1000) {
- LOG.info("Detached [" + checkedObjectMap.size() + "] objects
in [" + duration + "]ms");
+
+ if (dumpStackOnThresholdLimit) {
+ int numObjectsProcessed = checkedObjectMap.size();
+ if (duration > millisThresholdLimit || numObjectsProcessed >
sizeThresholdLimit) {
+ String rootObjectString = (value != null) ? value.getClass().toString() :
"null";
+ LOG.warn("Detached [" + numObjectsProcessed + "] objects
in [" + duration + "]ms from root object ["
+ + rootObjectString + "]", new Throwable("HIBERNATE
DETACH UTILITY STACK TRACE"));
+ }
} else {
- LOG.debug("Detached [" + checkedObjectMap.size() + "] objects
in [" + duration + "]ms");
+ // 10s is really long, log SOMETHING
+ if (duration > 10000L && LOG.isDebugEnabled()) {
+ LOG.debug("Detached [" + checkedObjectMap.size() + "]
objects in [" + duration + "]ms");
+ }
}
+
// help the garbage collector be clearing these before we leave
checkedObjectMap.clear();
checkedObjectCollisionMap.clear();
Show replies by date