0
# Execution Monitoring
1
2
Execution monitoring provides advanced capabilities for observing, profiling, and debugging polyglot execution environments. It enables detailed execution events, performance metrics, and instrumentation across all supported languages with minimal performance overhead.
3
4
## Capabilities
5
6
### Execution Listener
7
8
Monitor execution events across polyglot contexts.
9
10
```java { .api }
11
public final class ExecutionListener implements AutoCloseable {
12
public static ExecutionListener.Builder newBuilder();
13
public ExecutionListener attach(Engine engine);
14
public void close();
15
}
16
17
public static final class ExecutionListener.Builder {
18
public ExecutionListener.Builder onEnter(Consumer<ExecutionEvent> callback);
19
public ExecutionListener.Builder onReturn(Consumer<ExecutionEvent> callback);
20
public ExecutionListener.Builder expressions(boolean enabled);
21
public ExecutionListener.Builder statements(boolean enabled);
22
public ExecutionListener.Builder roots(boolean enabled);
23
public ExecutionListener.Builder sourceFilter(Predicate<Source> filter);
24
public ExecutionListener.Builder rootNameFilter(Predicate<String> filter);
25
public ExecutionListener build();
26
}
27
```
28
29
**Usage:**
30
31
```java
32
// Basic execution monitoring
33
ExecutionListener listener = ExecutionListener.newBuilder()
34
.onEnter(event -> {
35
System.out.println("Entering: " + event.getLocation());
36
})
37
.onReturn(event -> {
38
System.out.println("Returning: " + event.getReturnValue());
39
})
40
.statements(true)
41
.expressions(true)
42
.build();
43
44
try (Engine engine = Engine.create()) {
45
ExecutionListener attached = listener.attach(engine);
46
47
try (Context context = Context.newBuilder("js").engine(engine).build()) {
48
// All execution in this context will be monitored
49
context.eval("js", "function add(a, b) { return a + b; } add(2, 3);");
50
}
51
52
attached.close();
53
}
54
```
55
56
### Execution Events
57
58
Access detailed information about execution events.
59
60
```java { .api }
61
public final class ExecutionEvent {
62
public SourceSection getLocation();
63
public Value getReturnValue();
64
public RuntimeException getException();
65
public List<Value> getInputValues();
66
public boolean hasReturnValue();
67
public boolean hasException();
68
}
69
```
70
71
**Usage:**
72
73
```java
74
ExecutionListener listener = ExecutionListener.newBuilder()
75
.onEnter(event -> {
76
SourceSection location = event.getLocation();
77
System.out.println("Executing at " + location.getSource().getName() +
78
":" + location.getStartLine());
79
80
// Access input values (function parameters, etc.)
81
List<Value> inputs = event.getInputValues();
82
System.out.println("Input values: " + inputs);
83
})
84
.onReturn(event -> {
85
if (event.hasReturnValue()) {
86
Value returnValue = event.getReturnValue();
87
System.out.println("Returned: " + returnValue);
88
}
89
90
if (event.hasException()) {
91
RuntimeException exception = event.getException();
92
System.out.println("Exception: " + exception.getMessage());
93
}
94
})
95
.statements(true)
96
.build();
97
```
98
99
### Filtered Monitoring
100
101
Monitor specific sources or functions only.
102
103
```java
104
// Monitor only specific sources
105
ExecutionListener sourceFiltered = ExecutionListener.newBuilder()
106
.sourceFilter(source -> source.getName().endsWith(".js"))
107
.onEnter(event -> System.out.println("JS execution: " + event.getLocation()))
108
.statements(true)
109
.build();
110
111
// Monitor only specific function names
112
ExecutionListener functionFiltered = ExecutionListener.newBuilder()
113
.rootNameFilter(name -> name.equals("criticalFunction"))
114
.onEnter(event -> System.out.println("Critical function called"))
115
.roots(true)
116
.build();
117
118
// Monitor expressions only (no statements)
119
ExecutionListener expressionOnly = ExecutionListener.newBuilder()
120
.expressions(true)
121
.statements(false)
122
.onReturn(event -> {
123
if (event.hasReturnValue()) {
124
System.out.println("Expression result: " + event.getReturnValue());
125
}
126
})
127
.build();
128
```
129
130
## Advanced Monitoring Patterns
131
132
### Performance Profiling
133
134
Create custom profilers using execution monitoring:
135
136
```java
137
public class SimpleProfiler {
138
private final Map<String, Long> executionTimes = new ConcurrentHashMap<>();
139
private final Map<String, AtomicLong> callCounts = new ConcurrentHashMap<>();
140
private final ThreadLocal<Long> enterTime = new ThreadLocal<>();
141
142
public ExecutionListener createListener() {
143
return ExecutionListener.newBuilder()
144
.onEnter(event -> {
145
enterTime.set(System.nanoTime());
146
})
147
.onReturn(event -> {
148
long duration = System.nanoTime() - enterTime.get();
149
String location = getLocationKey(event.getLocation());
150
151
executionTimes.merge(location, duration, Long::sum);
152
callCounts.computeIfAbsent(location, k -> new AtomicLong(0)).incrementAndGet();
153
})
154
.statements(true)
155
.roots(true)
156
.build();
157
}
158
159
public void printProfile() {
160
System.out.println("Execution Profile:");
161
executionTimes.entrySet().stream()
162
.sorted(Map.Entry.<String, Long>comparingByValue().reversed())
163
.forEach(entry -> {
164
String location = entry.getKey();
165
long totalTime = entry.getValue();
166
long callCount = callCounts.get(location).get();
167
long avgTime = totalTime / callCount;
168
169
System.out.printf("%s: %d calls, %d ns total, %d ns avg%n",
170
location, callCount, totalTime, avgTime);
171
});
172
}
173
174
private String getLocationKey(SourceSection location) {
175
return location.getSource().getName() + ":" + location.getStartLine();
176
}
177
}
178
179
// Usage
180
SimpleProfiler profiler = new SimpleProfiler();
181
ExecutionListener listener = profiler.createListener();
182
183
try (Engine engine = Engine.create()) {
184
ExecutionListener attached = listener.attach(engine);
185
186
try (Context context = Context.newBuilder("js").engine(engine).build()) {
187
context.eval("js", "function fib(n) { return n < 2 ? n : fib(n-1) + fib(n-2); } fib(10);");
188
}
189
190
profiler.printProfile();
191
attached.close();
192
}
193
```
194
195
### Code Coverage Analysis
196
197
Track code coverage across polyglot execution:
198
199
```java
200
public class CoverageAnalyzer {
201
private final Set<String> executedLines = ConcurrentHashMap.newKeySet();
202
private final Map<String, Set<Integer>> sourceLines = new ConcurrentHashMap<>();
203
204
public ExecutionListener createListener() {
205
return ExecutionListener.newBuilder()
206
.onEnter(event -> {
207
SourceSection location = event.getLocation();
208
String sourceName = location.getSource().getName();
209
int lineNumber = location.getStartLine();
210
211
executedLines.add(sourceName + ":" + lineNumber);
212
213
// Track all lines in this source
214
sourceLines.computeIfAbsent(sourceName, k -> ConcurrentHashMap.newKeySet())
215
.add(lineNumber);
216
})
217
.statements(true)
218
.build();
219
}
220
221
public void printCoverage() {
222
System.out.println("Code Coverage Report:");
223
sourceLines.forEach((sourceName, lines) -> {
224
long totalLines = lines.size();
225
long executedCount = lines.stream()
226
.map(line -> sourceName + ":" + line)
227
.mapToLong(key -> executedLines.contains(key) ? 1 : 0)
228
.sum();
229
230
double coverage = (double) executedCount / totalLines * 100;
231
System.out.printf("%s: %.1f%% (%d/%d lines)%n",
232
sourceName, coverage, executedCount, totalLines);
233
});
234
}
235
}
236
```
237
238
### Exception Tracking
239
240
Monitor and analyze exceptions across polyglot execution:
241
242
```java
243
public class ExceptionTracker {
244
private final List<ExceptionInfo> exceptions = new CopyOnWriteArrayList<>();
245
246
public ExecutionListener createListener() {
247
return ExecutionListener.newBuilder()
248
.onReturn(event -> {
249
if (event.hasException()) {
250
RuntimeException exception = event.getException();
251
SourceSection location = event.getLocation();
252
253
exceptions.add(new ExceptionInfo(
254
exception.getClass().getSimpleName(),
255
exception.getMessage(),
256
location.getSource().getName(),
257
location.getStartLine(),
258
System.currentTimeMillis()
259
));
260
}
261
})
262
.statements(true)
263
.expressions(true)
264
.build();
265
}
266
267
public void printExceptionSummary() {
268
Map<String, Long> exceptionCounts = exceptions.stream()
269
.collect(Collectors.groupingBy(
270
ExceptionInfo::getType,
271
Collectors.counting()
272
));
273
274
System.out.println("Exception Summary:");
275
exceptionCounts.entrySet().stream()
276
.sorted(Map.Entry.<String, Long>comparingByValue().reversed())
277
.forEach(entry -> {
278
System.out.printf("%s: %d occurrences%n", entry.getKey(), entry.getValue());
279
});
280
}
281
282
private static class ExceptionInfo {
283
private final String type;
284
private final String message;
285
private final String source;
286
private final int line;
287
private final long timestamp;
288
289
// Constructor and getters...
290
}
291
}
292
```
293
294
### Real-time Monitoring
295
296
Create real-time monitoring dashboards:
297
298
```java
299
public class RealTimeMonitor {
300
private final AtomicLong executionCount = new AtomicLong(0);
301
private final AtomicLong exceptionCount = new AtomicLong(0);
302
private final ConcurrentHashMap<String, AtomicLong> languageStats = new ConcurrentHashMap<>();
303
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
304
305
public ExecutionListener createListener() {
306
// Start periodic reporting
307
scheduler.scheduleAtFixedRate(this::printStats, 0, 5, TimeUnit.SECONDS);
308
309
return ExecutionListener.newBuilder()
310
.onEnter(event -> {
311
executionCount.incrementAndGet();
312
313
String language = event.getLocation().getSource().getLanguage();
314
languageStats.computeIfAbsent(language, k -> new AtomicLong(0))
315
.incrementAndGet();
316
})
317
.onReturn(event -> {
318
if (event.hasException()) {
319
exceptionCount.incrementAndGet();
320
}
321
})
322
.statements(true)
323
.build();
324
}
325
326
private void printStats() {
327
System.out.println("=== Real-time Stats ===");
328
System.out.println("Total executions: " + executionCount.get());
329
System.out.println("Total exceptions: " + exceptionCount.get());
330
System.out.println("By language:");
331
languageStats.forEach((lang, count) -> {
332
System.out.println(" " + lang + ": " + count.get());
333
});
334
System.out.println();
335
}
336
337
public void shutdown() {
338
scheduler.shutdown();
339
}
340
}
341
```
342
343
### Multi-Context Monitoring
344
345
Monitor execution across multiple contexts:
346
347
```java
348
public class MultiContextMonitor {
349
private final Map<Context, String> contextNames = new ConcurrentHashMap<>();
350
private final Map<String, AtomicLong> contextStats = new ConcurrentHashMap<>();
351
352
public void registerContext(Context context, String name) {
353
contextNames.put(context, name);
354
contextStats.put(name, new AtomicLong(0));
355
}
356
357
public ExecutionListener createListener() {
358
return ExecutionListener.newBuilder()
359
.onEnter(event -> {
360
Context currentContext = Context.getCurrent();
361
String contextName = contextNames.get(currentContext);
362
if (contextName != null) {
363
contextStats.get(contextName).incrementAndGet();
364
}
365
})
366
.statements(true)
367
.build();
368
}
369
370
public void printContextStats() {
371
System.out.println("Context Execution Stats:");
372
contextStats.forEach((name, count) -> {
373
System.out.println(name + ": " + count.get() + " statements");
374
});
375
}
376
}
377
```
378
379
## Integration with Development Tools
380
381
### IDE Integration
382
383
Export execution data for IDE consumption:
384
385
```java
386
public class IDEIntegration {
387
public void exportExecutionTrace(List<ExecutionEvent> events, Path outputFile) {
388
try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(outputFile))) {
389
writer.println("timestamp,source,line,event_type,value");
390
391
events.forEach(event -> {
392
SourceSection location = event.getLocation();
393
writer.printf("%d,%s,%d,%s,%s%n",
394
System.currentTimeMillis(),
395
location.getSource().getName(),
396
location.getStartLine(),
397
event.hasReturnValue() ? "return" : "enter",
398
event.hasReturnValue() ? event.getReturnValue().toString() : ""
399
);
400
});
401
} catch (IOException e) {
402
throw new RuntimeException("Failed to export execution trace", e);
403
}
404
}
405
}
406
```
407
408
### Performance Testing
409
410
Integrate with performance testing frameworks:
411
412
```java
413
public class PerformanceTestIntegration {
414
public void runPerformanceTest(String testName, Runnable test) {
415
ExecutionListener listener = ExecutionListener.newBuilder()
416
.onEnter(event -> recordMetric("execution.enter", 1))
417
.onReturn(event -> {
418
recordMetric("execution.return", 1);
419
if (event.hasException()) {
420
recordMetric("execution.exception", 1);
421
}
422
})
423
.statements(true)
424
.build();
425
426
try (Engine engine = Engine.create()) {
427
ExecutionListener attached = listener.attach(engine);
428
429
long startTime = System.nanoTime();
430
test.run();
431
long duration = System.nanoTime() - startTime;
432
433
recordMetric("test.duration", duration);
434
attached.close();
435
}
436
}
437
438
private void recordMetric(String name, long value) {
439
// Integration with metrics collection system
440
// MetricsRegistry.record(name, value);
441
}
442
}
443
```
444
445
## Performance Considerations
446
447
- **Selective Monitoring**: Only monitor what you need; excessive monitoring can impact performance
448
- **Filtering**: Use source and root name filters to reduce monitoring overhead
449
- **Async Processing**: Process monitoring data asynchronously to minimize execution impact
450
- **Memory Management**: Be careful with data collection in long-running applications
451
- **Sampling**: Consider sampling for high-frequency applications
452
453
## Thread Safety
454
455
All monitoring components are thread-safe and can be used across multiple contexts and threads simultaneously. However, be careful with shared data structures and consider using concurrent collections for custom monitoring implementations.