-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Obtain a checkpoint AppMap #91
Conversation
Stream all events to a temp file; removing the Memory recorder. Recording is returned as an object, which can be deleted, or renamed, or read into a Writer. ActiveSessionException is sometimes meaningful, but usually it's just like a RuntimeException. So, a lot of this behavior has been removed. The main explicit check that remains is to see if a recording is or is not in progress when certain actions are performed. Other types of unexpected errors are not client-caused and therefore they are just runtime exceptions and will probably result in a 500 error to the client. Because events are written into a temp file, the name of the AppMap file (if any), is not needed until the recording is stopped.
Setting System property appmap.debug=true also enables the other debug settings (hooks, http).
Method wrappers invoke base method as 'invokeWrappedMethod' rather than 'invoke'
parent_id is now set on 'return' events.
@@ -67,10 +62,17 @@ public static void premain(String agentArgs, Instrumentation inst) { | |||
metadata.recorderName = "remote_recording"; | |||
metadata.scenarioName = appmapName; | |||
|
|||
recorder.start(fileName, metadata); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fileName is not needed until stop
.
public static final Boolean DebugLocals = (System.getProperty("appmap.debug.locals") != null); | ||
public static final Boolean DebugHttp = Debug || System.getProperty("appmap.debug.http") != null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems more intuitive to me to have appmap.debug
also enable these settings.
*/ | ||
public Event() { | ||
this.setId(issueId()); | ||
public static Event functionCallEvent(Event master) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Function calls need all this info, but returns don't.
@@ -177,7 +201,7 @@ public static void doFilterJakarta(Event event, Object[] args) throws ExitEarly | |||
junit = true; | |||
} | |||
} | |||
IRecordingSession.Metadata metadata = new IRecordingSession.Metadata(); | |||
RecordingSession.Metadata metadata = new RecordingSession.Metadata(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's only one type of RecordingSession now - it streams events to a temp file.
final String fileName = String.join("_", event.definedClass, event.methodId) | ||
.replaceAll("[^a-zA-Z0-9-_]", "_"); | ||
IRecordingSession.Metadata metadata = getMetadata(event); | ||
metadata.feature = identifierToSentence(event.methodId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
feature and featureGroup are deprecated.
} | ||
|
||
/** | ||
* Closes outstanding JSON objects and closes the writer. | ||
* @throws IOException If a writer error occurs | ||
*/ | ||
public void finalize() throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't want to override finalize
- it's used in garbage collection.
Event lastEvent; | ||
// Avoid accepting new events on a thread that's already processing an event. | ||
boolean isProcessing; | ||
Stack<Event> callStack = new Stack<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is used to populate parent_id
.
throws ActiveSessionException { | ||
if (this.hasActiveSession()) { | ||
throw new ActiveSessionException(ERROR_SESSION_PRESENT); | ||
static class ActiveSession { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrap the active session in an interface for safety and consistency.
|
||
ThreadState ts = threadState(); | ||
|
||
// We don't want re-entrant events on the same thread. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But I don't see why we'd need to block other threads here.
ts.callStack.push(event); | ||
} else if ( event.event.equals("return") ) { | ||
if ( ts.callStack.isEmpty() ) { | ||
Logger.println("Discarding 'return' event because the call stack is empty for this thread"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could happen if a recording is started and the first event that's recorded is a return
.
return false; | ||
} | ||
|
||
private static <V> V tryClass(CtClass cls, String member, ClassAccessor<V> accessor) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By testing each access, we don't abort the isChildOf
entirely if one access attempt raises an exception.
} catch (NotFoundException e) { | ||
if (Properties.DebugHooks) { | ||
Logger.println("could not resolve class hierarchy"); | ||
Logger.println(e); | ||
Logger.printf("NotFoundException resolving %s of class %s: %s\n", member, cls.getName(), e.getMessage()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If these messages are benign, we may want to suppress them even more.
@@ -27,7 +27,7 @@ ${@:-run_bats} | |||
bats_ret=$? | |||
|
|||
kill ${JVM_PID} | |||
wait -f ${JVM_PID} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-f
was causing a failure in Travis - not sure why.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like -f
is a new feature in bash 5.
@@ -121,9 +122,8 @@ load 'helper' | |||
# Sanity check the events and classmap | |||
assert_json_eq '.events | length' 6 | |||
|
|||
assert_json_eq '.classMap | length' 2 | |||
assert_json_eq '[.classMap[0] | recurse | .name?] | join(".")' javax.servlet.http.HttpServlet.service |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HTTP server request no longer includes defined_class or method_id.
FWIW, doesn't look like GH understands "Delivers", but there are some alternatives to link a PR to an issue: https://docs.github.com/en/github/writing-on-github/working-with-advanced-formatting/using-keywords-in-issues-and-pull-requests#linking-a-pull-request-to-an-issue . |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks good. There's a fair bit of overlap among the commits, you might want to do some history cleanup before you merge.
@@ -27,7 +27,7 @@ ${@:-run_bats} | |||
bats_ret=$? | |||
|
|||
kill ${JVM_PID} | |||
wait -f ${JVM_PID} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like -f
is a new feature in bash 5.
I’m not sure how to do history cleanup efficiently. Believe it or not I did
try and organize it some and this is the result.
Are there tools that make it easy? Git CLI doesn’t seem to, particularly.
…On Fri, Jul 30, 2021 at 1:32 PM Alan Potter ***@***.***> wrote:
***@***.**** approved this pull request.
Code looks good. There's a fair bit of overlap among the commits, you
might want to do some history cleanup before you merge.
------------------------------
In test/entrypoint
<#91 (comment)>:
> @@ -27,7 +27,7 @@ ${@:-run_bats}
bats_ret=$?
kill ${JVM_PID}
-wait -f ${JVM_PID}
Looks like -f is a new feature in bash 5.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#91 (review)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAVC63INR7QG4Z6JW55VQTT2LO4XANCNFSM5BCX5QQQ>
.
|
Not really, no. There are a number of GUI tools that say they let you do an interactive rebase, but they're really not any better than the command line.... If it was me, I'd consider doing Lately I've been using Sourcetree to stage subsets of files before committing. I find it makes it easy to see and stage changes in files, and also to revert hunks if I need to. I haven't used it as much, but GitLens also seems pretty good. |
🎉 This PR is included in version 1.3.0 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
A checkpoint AppMap returns an appmap JSON, but also leaves the current recording in progress.
This can be used to get an AppMap as an intermediate result, then continue the program execution without erasing the events that led up to that point.
Also:
or read into a Writer.
like a RuntimeException. So, a lot of this behavior has been removed.
The main explicit check that remains is to see if a recording is or is
not in progress when certain actions are performed. Other types of
unexpected errors are not client-caused and therefore they are just
runtime exceptions and will probably result in a 500 error to the
client.
(if any), is not needed until the recording is stopped.
Resolves #78
Resolves #50
Resolves #44