1515
1616import java .lang .instrument .Instrumentation ;
1717import java .lang .reflect .Field ;
18+ import java .util .ArrayList ;
1819import java .util .List ;
1920import java .util .Map ;
2021import java .util .concurrent .CompletableFuture ;
2122import java .util .concurrent .ConcurrentHashMap ;
23+ import java .util .concurrent .atomic .AtomicLong ;
2224
2325import static graphql .agent .GraphQLJavaAgent .ExecutionData .DFResultType .DONE_CANCELLED ;
2426import static graphql .agent .GraphQLJavaAgent .ExecutionData .DFResultType .DONE_EXCEPTIONALLY ;
3133public class GraphQLJavaAgent {
3234
3335 public static class ExecutionData {
34- public Map <ResultPath , String > resultPathToDataLoaderUsed = new ConcurrentHashMap <>();
35- public Map <DataLoader , String > dataLoaderToName = new ConcurrentHashMap <>();
36+ public final AtomicLong startExecutionTime = new AtomicLong ();
37+ public final AtomicLong endExecutionTime = new AtomicLong ();
38+ public final Map <ResultPath , String > resultPathToDataLoaderUsed = new ConcurrentHashMap <>();
39+ public final Map <DataLoader , String > dataLoaderToName = new ConcurrentHashMap <>();
3640
3741 private final Map <ResultPath , Long > timePerPath = new ConcurrentHashMap <>();
3842 private final Map <ResultPath , DFResultType > dfResultTypes = new ConcurrentHashMap <>();
3943
44+ public static class BatchLoadingCall {
45+ public BatchLoadingCall (int resultCount ) {
46+ this .resultCount = resultCount ;
47+ }
48+
49+ public int resultCount ;
50+ }
51+
52+ public final Map <String , List <BatchLoadingCall >> dataLoaderNameToBatchCall = new ConcurrentHashMap <>();
53+
54+ public String print (String executionId ) {
55+ StringBuilder s = new StringBuilder ();
56+ s .append ("==========================" ).append ("\n " );
57+ s .append ("Summary for execution with id " ).append (executionId ).append ("\n " );
58+ s .append ("==========================" ).append ("\n " );
59+ s .append ("Execution time in ms:" ).append ((endExecutionTime .get () - startExecutionTime .get ()) / 1_000_000L ).append ("\n " );
60+ s .append ("Fields count: " ).append (timePerPath .keySet ().size ()).append ("\n " );
61+ s .append ("Blocking fields count: " ).append (dfResultTypes .values ().stream ().filter (dfResultType -> dfResultType != PENDING ).count ()).append ("\n " );
62+ s .append ("Nonblocking fields count: " ).append (dfResultTypes .values ().stream ().filter (dfResultType -> dfResultType == PENDING ).count ()).append ("\n " );
63+ s .append ("DataLoaders used: " ).append (dataLoaderToName .size ()).append ("\n " );
64+ s .append ("DataLoader names: " ).append (dataLoaderToName .values ()).append ("\n " );
65+ s .append ("BatchLoader calls details: " ).append ("\n " );
66+ s .append ("==========================" ).append ("\n " );
67+ for (String dataLoaderName : dataLoaderNameToBatchCall .keySet ()) {
68+ s .append ("DataLoader: '" ).append (dataLoaderName ).append ("' called " ).append (dataLoaderNameToBatchCall .get (dataLoaderName ).size ()).append (" times, " ).append ("\n " );
69+ for (BatchLoadingCall batchLoadingCall : dataLoaderNameToBatchCall .get (dataLoaderName )) {
70+ s .append ("Batch call with " ).append (batchLoadingCall .resultCount ).append (" results" ).append ("\n " );
71+ }
72+ }
73+ s .append ("Field details:" ).append ("\n " );
74+ s .append ("===============" ).append ("\n " );
75+ for (ResultPath path : timePerPath .keySet ()) {
76+ s .append ("Field: '" ).append (path ).append ("' took: " ).append (timePerPath .get (path )).append (" nano seconds, " ).append ("\n " );
77+ s .append ("Result type: " ).append (dfResultTypes .get (path )).append ("\n " );
78+ }
79+ s .append ("==========================" ).append ("\n " );
80+ s .append ("==========================" ).append ("\n " );
81+ return s .toString ();
82+
83+ }
84+
4085 @ Override
4186 public String toString () {
4287 return "ExecutionData{" +
@@ -166,9 +211,11 @@ public static void dispatch(@Advice.This(typing = Assigner.Typing.DYNAMIC) Objec
166211 DataLoader dataLoader = (DataLoader ) field .get (dataLoaderHelper );
167212 // System.out.println("dataLoader: " + dataLoader);
168213 ExecutionId executionId = GraphQLJavaAgent .dataLoaderToExecutionId .get (dataLoader );
169- String dataLoaderName = GraphQLJavaAgent .executionIdToData .get (executionId ).dataLoaderToName .get (dataLoader );
214+ GraphQLJavaAgent .ExecutionData executionData = GraphQLJavaAgent .executionIdToData .get (executionId );
215+ String dataLoaderName = executionData .dataLoaderToName .get (dataLoader );
170216
171- System .out .println ("dataloader " + dataLoaderName + " dispatch result size:" + dispatchResult .getKeysCount ());
217+ executionData .dataLoaderNameToBatchCall .putIfAbsent (dataLoaderName , new ArrayList <>());
218+ executionData .dataLoaderNameToBatchCall .get (dataLoaderName ).add (new GraphQLJavaAgent .ExecutionData .BatchLoadingCall (dispatchResult .getKeysCount ()));
172219
173220 } catch (Exception e ) {
174221 e .printStackTrace ();
@@ -204,9 +251,11 @@ class ExecutionAdvice {
204251
205252 @ Advice .OnMethodEnter
206253 public static void executeOperationEnter (@ Advice .Argument (0 ) ExecutionContext executionContext ) {
254+ GraphQLJavaAgent .ExecutionData executionData = new GraphQLJavaAgent .ExecutionData ();
255+ executionData .startExecutionTime .set (System .nanoTime ());
207256 System .out .println ("execution started for: " + executionContext .getExecutionId ());
208257 executionContext .getGraphQLContext ().put (EXECUTION_TRACKING_KEY , new ExecutionTrackingResult ());
209- GraphQLJavaAgent . ExecutionData executionData = new GraphQLJavaAgent . ExecutionData ();
258+
210259 GraphQLJavaAgent .executionIdToData .put (executionContext .getExecutionId (), executionData );
211260
212261 DataLoaderRegistry dataLoaderRegistry = executionContext .getDataLoaderRegistry ();
@@ -220,12 +269,15 @@ public static void executeOperationEnter(@Advice.Argument(0) ExecutionContext ex
220269 @ Advice .OnMethodExit
221270 public static void executeOperationExit (@ Advice .Argument (0 ) ExecutionContext executionContext ) {
222271 ExecutionId executionId = executionContext .getExecutionId ();
223- System .out .println ("execution finished for: " + executionId + " with data " + GraphQLJavaAgent .executionIdToData .get (executionId ));
224- // cleanup
225- // GraphQLJavaAgent.executionDataMap.get(executionId).dataLoaderToName.forEach((dataLoader, s) -> {
226- // GraphQLJavaAgent.dataLoaderToExecutionId.remove(dataLoader);
227- // });
228- // GraphQLJavaAgent.executionDataMap.remove(executionContext.getExecutionId());
272+ GraphQLJavaAgent .ExecutionData executionData = GraphQLJavaAgent .executionIdToData .get (executionId );
273+ executionData .endExecutionTime .set (System .nanoTime ());
274+ System .out .println ("execution finished for: " + executionId + " with data " + executionData );
275+ System .out .println (executionData .print (executionId .toString ()));
276+ // cleanup
277+ // GraphQLJavaAgent.executionDataMap.get(executionId).dataLoaderToName.forEach((dataLoader, s) -> {
278+ // GraphQLJavaAgent.dataLoaderToExecutionId.remove(dataLoader);
279+ // });
280+ // GraphQLJavaAgent.executionDataMap.remove(executionContext.getExecutionId());
229281 }
230282}
231283
0 commit comments