Skip to content
Permalink
Browse files

Fixed problem of sending jamon an unserializable and automon specific…

… class as part of the jamon details.
  • Loading branch information...
stevensouza committed Jul 6, 2019
1 parent 3a081ad commit e7f4c2abe68e3afbcad566ef47db2ed34a6b7e5e
@@ -29,28 +29,20 @@ public void stop(Monitor mon) {
@Override
public void stop(Monitor mon, Throwable throwable) {
mon.stop();
// NOT sure put(throwable) is needed. note what i would like to do is pass in a standard object wrapper that
// can be serialized so when it's toString method is called the more upated argumentslist verrsion of toString is called.
// all objects i have seen have implementations of toString that add data. i.e. {}, [], key=, value=
// tried entryset, list, map, set, eventobject

// THIS SHOULD DO IT...
/*
AtomicReference<String> ar=new AtomicReference<>("steve");
System.out.println(ar);
ar.set("souza");
System.out.println(ar);
*/
//put(throwable);
put(throwable);
// note the following 'get' always succeeds because of the above 'put'
// don't want to use AutoExpirable so could either do string or throwable. if
// argnames and values are set then use AutoExpirable.toString. if not use
// throwable. note can't depend in a clustered environment for AutoExpirable being
// on all clusters so can't serialize that.
mon.getMonKey().setDetails(throwable);
// Note the jamonDetails MUST be serializable and contain classes not in a library
// but available in the jdk. This is becuase there is no guarantee all servers in the
// jamon cluster have for example AutoMon available for deserialization of the
// MonitorComposite object. In the following case we are saving an AtomicReference that
// contains a Throwable. Both of these classes are Serializable and in the jdk.
// Note if exception tracking is enabled then this stack trace will be overridden with a
// string version of the stack trace AND any variables and values passed to the method
// in the traceException method below as it is called after this method.
mon.getMonKey().setDetails(get(throwable).setJamonDetails(throwable));
}


@Override
public void exception(JoinPoint jp, Throwable throwable) {
// note for the jamon implementation the order of the following methods is important. That way the stacktrace can be available
@@ -62,13 +54,12 @@ public void exception(JoinPoint jp, Throwable throwable) {
// Return the AutomonExpirable just put in the map via the call to exception
@Override
protected void trackException(JoinPoint jp, Throwable throwable) {
AutomonExpirable exceptionContext = populateArgNamesAndValues_InExceptionContext(jp, throwable);
AutomonExpirable exceptionContext = populateExceptionContext(jp, throwable);
// Multiple monitors are tracked for the exception such as one of the specific exception and one that represents
// all exceptions.
String exceptionContextStr = exceptionContext.toString();
List<String> labels = getLabels(throwable);
for (String label : labels) {
MonKey key = new MonKeyImp(label, exceptionContextStr, "Exception");
MonKey key = new MonKeyImp(label, exceptionContext.getJamonDetails(), "Exception");
MonitorFactory.add(key, 1);
}
}
@@ -81,10 +72,12 @@ protected void trackException(JoinPoint jp, Throwable throwable) {
* @param throwable
* @return
*/
private AutomonExpirable populateArgNamesAndValues_InExceptionContext(JoinPoint jp, Throwable throwable) {
private AutomonExpirable populateExceptionContext(JoinPoint jp, Throwable throwable) {
AutomonExpirable exceptionContext = get(throwable);
if (exceptionContext.getArgNamesAndValues() == null) {
exceptionContext.setArgNamesAndValues(Utils.getArgNameValuePairs(jp));
// note this will replace the jamon details of Throwable that was set in the stop method above.
exceptionContext.setJamonDetails(exceptionContext.toString());
}

return exceptionContext;
@@ -1,6 +1,8 @@
package org.automon.utils;

import java.io.Serializable;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

/**
* Starts with {@link org.automon.utils.TimeExpirable} behavior and adds the ability to store the exception and argument name and values
@@ -10,6 +12,16 @@
private Throwable throwable;
private List<String> argNamesAndValues;

// holds a reference that will be displayed in jamon fifo buffers etc. Because
// jamon can be clustered with hazelcast the data must be serializable hence
// that is what the AtomicReference must hold. Also not that AtomicReference is not
// required, but what is required is the ability to hold a serializable object in a serializable
// container that has its toString method just return the underlying objects string.
// For example List would surround the returned string in []. The class must also be part of
// the jdk and not require any extra classes as for example automon might not be available on
// all servers in the jamon cluster.
private final AtomicReference jamonDetails = new AtomicReference();;

public AutomonExpirable() {
}

@@ -33,6 +45,16 @@ public void setThrowable(Throwable throwable) {
this.throwable = throwable;
}

public AtomicReference setJamonDetails(Serializable details) {
jamonDetails.set(details);
return jamonDetails;
}

public AtomicReference getJamonDetails() {
return jamonDetails;
}


public String toString() {
return new StringBuilder().
append(Utils.argNameValuePairsToString(argNamesAndValues)).
@@ -54,6 +54,9 @@ public void testStopWithException() throws Exception {
assertThat(mon.getLabel()).describedAs("The label should match passed in label").isEqualTo(SharedConstants.LABEL);
assertThat(mon.getActive()).describedAs("The monitor should not be running").isEqualTo(0);
assertThat(mon.getHits()).describedAs("The monitor should have finished and recorded hits").isEqualTo(1);
Map<Throwable, AutomonExpirable> map = openMon.getExceptionsMap();
assertThat(map.size()).isEqualTo(1);
map.forEach((throwable,automonExpirable)->assertThat(automonExpirable.getJamonDetails().get()).isInstanceOf(RuntimeException.class));
}

@Test
@@ -66,6 +69,9 @@ public void testException() throws Exception {
Map<Throwable, AutomonExpirable> map = openMon.getExceptionsMap();
assertThat(map.get(SharedConstants.EXCEPTION).getThrowable()).describedAs("Throwable should have been set").isEqualTo(SharedConstants.EXCEPTION);
assertThat(map.get(SharedConstants.EXCEPTION).getArgNamesAndValues()).describedAs("Arg names and values should have been set").isNotNull();
assertThat(map.size()).isEqualTo(1);
map.forEach((throwable,automonExpirable)->assertThat(automonExpirable.getJamonDetails().get()).isInstanceOf(String.class));

}

}
@@ -2,8 +2,10 @@

import org.junit.Test;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

import static org.assertj.core.api.Assertions.assertThat;

@@ -15,6 +17,7 @@ public void testDefaultState() throws Exception {
assertThat(expirable.getArgNamesAndValues()).isNull();
assertThat(expirable.getThrowable()).isNull();
assertThat(expirable.toString()).isNotNull();
assertThat(expirable.getJamonDetails()).isNotNull();
}

@Test
@@ -51,4 +54,17 @@ public void testThrowableAndArgs() throws Exception {
assertThat(expirable.toString()).contains("fname: Steve");
assertThat(expirable.toString()).contains("java.lang.RuntimeException: my exception", getClass().getName());
}

@Test
public void testJamonDetailsDefault() {
AutomonExpirable expirable = new AutomonExpirable();
assertThat(expirable.getJamonDetails()).isNotNull();
}

@Test
public void testJamonDetailsSet() {
AutomonExpirable expirable = new AutomonExpirable();
AtomicReference<Object> reference = expirable.setJamonDetails("steve");
assertThat(reference.get()).isEqualTo("steve");
}
}

0 comments on commit e7f4c2a

Please sign in to comment.
You can’t perform that action at this time.