Closed zermelo-wisen closed 1 month ago
Fixes #103.
The main objective of this PR is to enhance the AppMap-Node agent's ability to track asynchronous operations accurately. The previous implementation faced challenges in correctly maintaining the context of asynchronous computations, leading to inaccurate call hierarchies.
Here are some changes made to achieve this:
AppMapStream.ts
emit
to push
:
emit
function is renamed to push
to better reflect its role in managing the event buffer and syncing.Recording.ts
Integration of AsyncLocalStorage
:
AsyncLocalStorage
from node:async_hooks
to help preserve the context across asynchronous operations.rootBuffer
, asyncStorage
, fork
, run
, and getContext
methods to manage the asynchronous execution context.Context-Sensitive Event Emission:
emit
function checks whether the recording is running before emitting events.AsyncLocalStorage
) to manage buffered events, preserving the call hierarchy and ensuring accurate representation.Enhanced Finish and Abandon Methods:
AppMapStream.test.ts
and Recording.test.ts
emit
to push
.prisma.ts
Before the async tracking feature
After the async tracking feature:
Added the ability to control async tracking via the async_tracking_timout
filed in configuration file and the APPMAP_ASYNC_TRACKING_TIMEOUT
environment variable. The environment variable takes precedence over the config file value. If neither is set, a default timeout of 3000 milliseconds is applied. Setting the value to 0 disables async tracking entirely.
Effects of the timeout value can easily be seen with this test:
:tada: This PR is included in version 2.24.0 :tada:
The release is available on:
Your semantic-release bot :package::rocket:
Implement Async Tracking in AppMap-Node Agent Using AsyncLocalStorage
Problem
The current implementation of the AppMap-Node agent struggles with proper asynchronous tracking, leading to misleading call hierarchies. Specifically, the agent does not maintain the correct context of asynchronous computations, resulting in inaccuracies when representing operations that involve
Promise
or other asynchronous constructs.For example:
In this case, the call to
bar(1)
is incorrectly represented as coming afterbar(2)
because thefoo()
's context is lost early.Analysis
The main issues with the current implementation are:
Promise
settlements are observed.We need to update the tracking mechanism to keep the context alive throughout the async function's execution and ensure that events are accurately reported.
Proposed Changes
Context Preservation:
AsyncLocalStorage
to preserve the execution context across asynchronous operations.await
or callback procedures, maintain the correct parent context in the generated AppMaps.Event Streaming:
Detailed Changes
Update
Recording.ts
:AsyncLocalStorage
to store context information.Adjust Event Generation Logic:
fixupPromise
function correctly associates the context of async operations.Modify Event Emission:
Tests and Validation:
test/jest/asyncLib.test.js
and other relevant test files to validate the accuracy of the reported call hierarchies.Making these adjustments will significantly improve the accuracy of asynchronous tracking in the AppMap-Node agent, providing clearer and more accurate call hierarchies and execution flows in AppMaps.
Resolves #103