Skip to content

Commit

Permalink
feat: Apply different fields to call, return, sql, etc
Browse files Browse the repository at this point in the history
return events don't duplicate the function call fields.
http_server_request and sql_query don't need function call fields either.

Delivers #50
Delivers #44
  • Loading branch information
kgilpin committed Jul 29, 2021
1 parent a24f056 commit 3d8db1f
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 51 deletions.
60 changes: 35 additions & 25 deletions src/main/java/com/appland/appmap/output/v1/Event.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.alibaba.fastjson.annotation.JSONField;
import javassist.CtBehavior;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;

Expand Down Expand Up @@ -66,37 +65,38 @@ private synchronized Integer issueId() {
}

/**
* Constructs a blank event and issues a unique ID.
* Creates a copy of an existing call event. Does not copy runtime information such as
* {@link Parameters} or return value.
*
* @param master The event to copy information from
*/
public Event() {
this.setId(issueId());
public static Event functionCallEvent(Event master) {
Event event = new Event();
event.setEvent("call");
event.setThreadId(Thread.currentThread().getId());
event.setMethodId(master.methodId);
event.setDefinedClass(master.definedClass);
event.setPath(master.path);
event.setLineNumber(master.lineNumber);
event.setStatic(master.isStatic);
return event;
}

/**
* Creates a copy of an existing event. Does not copy runtime information such as
* {@link Parameters} or return value.
* @param master The event to copy information from
* Creates a return event. All the event properties except for the id are
* left to be filled in later.
*/
public Event(Event master) {
this.setId(issueId())
.setMethodId(master.methodId)
.setDefinedClass(master.definedClass)
.setPath(master.path)
.setLineNumber(master.lineNumber)
.setStatic(master.isStatic);
public static Event functionReturnEvent() {
Event event = new Event();
event.setEvent("return");
return event;
}

/**
* Creates an event from a reflective Method.
* @param method Method to gather information from
* @param eventType The type of this event ("call", "return", etc.)
* Constructs a blank event and issues a unique ID.
*/
public Event(Method method, String eventType) {
this.setId(issueId())
.setMethodId(method.getName())
.setDefinedClass(method.getDeclaringClass().getName())
.setEvent(eventType)
.setThreadId(Thread.currentThread().getId());
public Event() {
this.setId(issueId());
}

/**
Expand Down Expand Up @@ -303,6 +303,7 @@ public Event setParameters(Parameters parameters) {
* @see <a href="https://github.com/applandinc/appmap#http-server-request-attributes">GitHub: AppMap - HTTP server request attributes</a>
*/
public Event setHttpServerRequest(String method, String path, String protocol) {
clearFunctionFields();
this.httpServerRequest = new HttpServerRequest()
.setMethod(method)
.setPath(path)
Expand Down Expand Up @@ -345,6 +346,7 @@ public Event setHttpServerResponse(Integer status, String mimeType) {
* @see <a href="https://github.com/applandinc/appmap#http-client-request-attributes">GitHub: AppMap - HTTP client request attributes</a>
*/
public Event setHttpClientRequest(String method, String path, String protocol) {
clearFunctionFields();
this.httpClientRequest = new HttpClientRequest()
.setMethod(method)
.setPath(path)
Expand Down Expand Up @@ -374,7 +376,7 @@ public Event setHttpClientResponse(Integer status, String mimeType) {
*/
public Event addMessageParam(Value val) {
if (this.message == null) {
this.message = new ArrayList<Value>();
this.message = new ArrayList<>();
}

this.message.add(val);
Expand All @@ -401,6 +403,7 @@ public Event addMessageParam(String name, Object val) {
* @see <a href="https://github.com/applandinc/appmap#sql-query-attributes">GitHub: AppMap - SQL query attributes</a>
*/
public Event setSqlQuery(String databaseType, String sql) {
clearFunctionFields();
this.sqlQuery = new SqlQuery(databaseType, sql);
return this;
}
Expand All @@ -409,7 +412,6 @@ public Event setSqlQuery(String databaseType, String sql) {
* Convert all referenced Objects to Strings. This mitigates the risk of null pointer exceptions
* or reading otherwise invalid state when later serializing this event. This should always be
* called once an event has been finalized.
* @return
*/
public Event freeze() {
if (this.parameters != null) {
Expand All @@ -434,4 +436,12 @@ public Event freeze() {

return this;
}

void clearFunctionFields() {
methodId = null;
definedClass = null;
path = null;
lineNumber = null;
isStatic = null;
}
}
39 changes: 20 additions & 19 deletions src/main/java/com/appland/appmap/record/EventTemplateRegistry.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
* for performance.
*/
public class EventTemplateRegistry {
private static EventTemplateRegistry instance = new EventTemplateRegistry();
private static final EventTemplateRegistry instance = new EventTemplateRegistry();
private static final Recorder recorder = Recorder.getInstance();

private ArrayList<Event> eventTemplates = new ArrayList<Event>();
private final ArrayList<Event> eventTemplates = new ArrayList<>();

private EventTemplateRegistry() { }

Expand All @@ -43,7 +43,7 @@ public Integer register(CtBehavior behavior) {
* have a {@link CodeObject} registered with the global {@link Recorder} instance.
* @param event The {@link Event} template to be registered
* @param behavior The behavior used to create the {@link Event} template
* @returns The behavior ordinal (an index to the {@link Event} template)
* @return The behavior ordinal (an index to the {@link Event} template)
*/
public synchronized Integer register(Event event, CtBehavior behavior) {
recorder.registerCodeObject(CodeObject.createTree(behavior));
Expand All @@ -68,25 +68,28 @@ public Event getTemplate(Integer templateId) {
/**
* Clones an {@link Event} template and sets the {@code event} field.
* @param templateId The behavior ordinal
* @param eventAction The value of the {@code event} field ({@code call}, {@code return}, etc.)
* @return A copy of the event template with the {@code event} field set
* @throws UnknownEventException If no template exists for the behavior ordinal given
*/
public Event cloneEventTemplate(int templateId, String eventAction)
throws UnknownEventException {
Event event = null;
public Event buildCallEvent(int templateId) {
Event eventTemplate = lookupEventTemplate(templateId);
Event event = Event.functionCallEvent(eventTemplate);
for (Value param : eventTemplate.parameters) {
event.addParameter(param);
}
return event;
}

try {
Event eventTemplate = eventTemplates.get(templateId);
event = new Event(eventTemplate)
.setThreadId(Thread.currentThread().getId())
.setEvent(eventAction);
/**
* Prepares a return event.
*/
public Event buildReturnEvent() {
return Event.functionReturnEvent();
}

if (eventAction.equals("call")) {
for (Value param : eventTemplate.parameters) {
event.addParameter(param);
}
}
Event lookupEventTemplate(int templateId) {
try {
return eventTemplates.get(templateId);
} catch (IndexOutOfBoundsException e) {
final String msg = String.format("unknown template for ordinal %d - have we been loaded by a non-system class loader?", templateId);

Expand All @@ -97,7 +100,5 @@ public Event cloneEventTemplate(int templateId, String eventAction)

throw new UnknownEventException(msg);
}

return event;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,23 @@ public void testRegister() throws Exception {
}
}

@Test
public void testCloneEventTemplate() throws UnknownEventException, Exception {
CtClass myClass = new ClassBuilder("testCloneEventTemplateClass")
CtClass buildCloneableEventTemplate() throws Exception {
return new ClassBuilder("testCloneEventTemplateClass")
.beginMethod()
.setName("registeredMethod")
.setName("registeredMethod")
.endMethod()
.ctClass();
}

Integer index = registry.register(myClass.getDeclaredMethod("registeredMethod"));
assertTrue(registry.cloneEventTemplate(index, "") != null);
@Test
public void testCloneEventTemplate() throws Exception {
Integer index = registry.register(buildCloneableEventTemplate().getDeclaredMethod("registeredMethod"));
assertTrue(registry.buildCallEvent(index) != null);
}

@Test
public void testUnknownEventTemplate() throws Exception {
thrown.expect(UnknownEventException.class);
registry.cloneEventTemplate(Integer.MAX_VALUE, "");
registry.buildCallEvent(Integer.MAX_VALUE);
}
}

0 comments on commit 3d8db1f

Please sign in to comment.