mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-02 11:52:28 +01:00
Merge pull request #762 from rafaelweingartner/cglibThrowableRenderer
Proposal for an improved CglibThrowableRendererFollowing our discussions on mailing list, here is a PR with a proposal for an improvement on CglibThrowableRenderer. We would still have to define a number to limit the stack traces of causes (I randomly chose 3, just to get the code running). The test case is also not good in my opinion, but I ran out of ideas (waiting for suggestions on that). * pr/762: Changed the test case to test each of the log traces in the array list. Proposal for an improved CglibThrowableRenderer Signed-off-by: Rajani Karuturi <rajani.karuturi@citrix.com>
This commit is contained in:
commit
e8979c0e65
@ -19,16 +19,17 @@
|
||||
|
||||
package com.cloud.utils.log;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.log4j.spi.ThrowableRenderer;
|
||||
|
||||
/**
|
||||
* This renderer removes all the Cglib generated methods from the call
|
||||
* This renderer removes all the CGLib generated methods from the call
|
||||
*
|
||||
* Unfortunately, I had to copy out the EnhancedThrowableRenderer from
|
||||
* the apach libraries because EnhancedThrowableRenderer is a final class.
|
||||
* Unfortunately, I had to copy out there-write the EnhancedThrowableRenderer from
|
||||
* the Apache libraries because EnhancedThrowableRenderer is a final class.
|
||||
* simply override doRender. Not sure what the developers are thinking there
|
||||
* making it final.
|
||||
*
|
||||
@ -37,48 +38,45 @@ import org.apache.log4j.spi.ThrowableRenderer;
|
||||
*
|
||||
*/
|
||||
public class CglibThrowableRenderer implements ThrowableRenderer {
|
||||
/**
|
||||
* Construct new instance.
|
||||
*/
|
||||
public CglibThrowableRenderer() {
|
||||
super();
|
||||
|
||||
private final static int MAX_NUMBER_OF_STACK_TRACES_ON_LOG_FOR_CAUSE = 3;
|
||||
@Override
|
||||
public String[] doRender(Throwable th) {
|
||||
List<String> lines = new ArrayList<String>();
|
||||
lines.add(th.toString());
|
||||
addStackTraceToList(th, lines, 0);
|
||||
do {
|
||||
th = th.getCause();
|
||||
if (th != null) {
|
||||
lines.add("Caused by: " + th.toString());
|
||||
addStackTraceToList(th, lines, MAX_NUMBER_OF_STACK_TRACES_ON_LOG_FOR_CAUSE);
|
||||
}
|
||||
} while (th != null);
|
||||
return lines.toArray(new String[lines.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] doRender(final Throwable th) {
|
||||
try {
|
||||
ArrayList<String> lines = new ArrayList<String>();
|
||||
Throwable throwable = th;
|
||||
lines.add(throwable.toString());
|
||||
int start = 0;
|
||||
do {
|
||||
StackTraceElement[] elements = throwable.getStackTrace();
|
||||
for (int i = 0; i < elements.length - start; i++) {
|
||||
StackTraceElement element = elements[i];
|
||||
String filename = element.getFileName();
|
||||
String method = element.getMethodName();
|
||||
if ((filename != null && filename.equals("<generated>")) || (method != null && method.equals("invokeSuper"))) {
|
||||
continue;
|
||||
}
|
||||
lines.add("\tat " + element.toString());
|
||||
}
|
||||
if (start != 0) {
|
||||
lines.add("\t... " + start + " more");
|
||||
}
|
||||
throwable = throwable.getCause();
|
||||
if (throwable != null) {
|
||||
lines.add("Caused by: " + throwable.toString());
|
||||
start = elements.length - 1;
|
||||
}
|
||||
} while (throwable != null);
|
||||
return lines.toArray(new String[lines.size()]);
|
||||
} catch (Exception ex) {
|
||||
PrintWriter pw = new PrintWriter(System.err);
|
||||
ex.printStackTrace(pw);
|
||||
pw = new PrintWriter(System.out);
|
||||
ex.printStackTrace(pw);
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
/**
|
||||
* This method adds the stack traces retrieved from {@link Throwable#getStackTrace()}
|
||||
* The maxNumberOfStack attribute indicates the number of stacks that will be added,
|
||||
* if that value is 0, then all of the stack traces will be added, otherwise the stack traces will be limited to that number
|
||||
* @param th
|
||||
* @param lines
|
||||
* @param maxNumberOfStack
|
||||
*/
|
||||
private void addStackTraceToList(Throwable th, List<String> lines, int maxNumberOfStack) {
|
||||
StackTraceElement[] elements = th.getStackTrace();
|
||||
if (maxNumberOfStack == 0 || maxNumberOfStack > elements.length) {
|
||||
maxNumberOfStack = elements.length;
|
||||
}
|
||||
for (int i = 0; i < maxNumberOfStack; i++) {
|
||||
StackTraceElement element = elements[i];
|
||||
if (StringUtils.contains(element.getClassName(), "net.sf.cglib.proxy")) {
|
||||
continue;
|
||||
}
|
||||
lines.add("\tat " + element.toString());
|
||||
}
|
||||
if (maxNumberOfStack < elements.length) {
|
||||
lines.add("\t... " + (elements.length - maxNumberOfStack) + " more");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,85 @@
|
||||
//
|
||||
// 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 com.cloud.utils.log;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import net.sf.cglib.proxy.Enhancer;
|
||||
import net.sf.cglib.proxy.MethodInterceptor;
|
||||
import net.sf.cglib.proxy.MethodProxy;
|
||||
|
||||
public class CglibThrowableRendererTest {
|
||||
|
||||
CglibThrowableRenderer cglibThrowableRenderer = new CglibThrowableRenderer();
|
||||
|
||||
@Test
|
||||
public void testDoRendere() {
|
||||
SampleClass sampleClass = (SampleClass)Enhancer.create(SampleClass.class, new MyInvocationHandler());
|
||||
try {
|
||||
sampleClass.theFirstMethodThatCapturesAnException();
|
||||
} catch (Exception e) {
|
||||
String[] exceptions = cglibThrowableRenderer.doRender(e);
|
||||
assertThatTheTraceListDoesNotContainsCgLibLogs(exceptions);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertThatTheTraceListDoesNotContainsCgLibLogs(String[] exceptions) {
|
||||
for (String s : exceptions) {
|
||||
Assert.assertEquals(false, isCgLibLogTrace(s));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCgLibLogTrace(String s) {
|
||||
return StringUtils.contains(s, "net.sf.cglib.proxy");
|
||||
}
|
||||
|
||||
static class SampleClass {
|
||||
public void theFirstMethodThatCapturesAnException() {
|
||||
try {
|
||||
methodThatCapturesAndThrowsException();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void methodThatCapturesAndThrowsException() throws Exception {
|
||||
try {
|
||||
methodThatThrowsAnError();
|
||||
} catch (Error e) {
|
||||
throw new Exception("Throws an exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void methodThatThrowsAnError() {
|
||||
throw new Error("Exception to test the CglibThrowableRenderer.");
|
||||
}
|
||||
}
|
||||
|
||||
static class MyInvocationHandler implements MethodInterceptor {
|
||||
@Override
|
||||
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
|
||||
return proxy.invoke(new SampleClass(), args);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user