0
# Log Management
1
2
Browser console and log event collection with level filtering and timestamp handling for comprehensive logging support. Provides access to browser-side logging events for monitoring and debugging web applications.
3
4
## Capabilities
5
6
### Log Handler
7
8
Creates a log management handler for Chrome DevTools Protocol v99.
9
10
```java { .api }
11
/**
12
* Log management implementation for CDP v99
13
* Implements the idealized Log interface
14
*/
15
public class V99Log implements org.openqa.selenium.devtools.idealized.log.Log;
16
```
17
18
### Log Domain Control
19
20
Enable and disable browser log collection.
21
22
```java { .api }
23
/**
24
* Enable log domain for collecting browser logs
25
* @return Command to enable log collection
26
*/
27
public Command<Void> enable();
28
29
/**
30
* Clear all browser console logs
31
* @return Command to clear logs
32
*/
33
public Command<Void> clear();
34
```
35
36
### Log Event Monitoring
37
38
Monitor browser log entries as they are generated.
39
40
```java { .api }
41
/**
42
* Get event handler for new log entries
43
* @return Event for log entry additions
44
*/
45
public Event<LogEntry> entryAdded();
46
```
47
48
## Protocol Types
49
50
### Log Entry
51
52
```java { .api }
53
/**
54
* Browser log entry from CDP
55
*/
56
public class LogEntry {
57
/**
58
* Get log entry source (console, network, etc.)
59
* @return Log source
60
*/
61
public LogSource getSource();
62
63
/**
64
* Get log level (verbose, info, warning, error)
65
* @return Log level
66
*/
67
public Level getLevel();
68
69
/**
70
* Get log message text
71
* @return Message string
72
*/
73
public String getText();
74
75
/**
76
* Get timestamp when log entry was created
77
* @return Timestamp
78
*/
79
public Timestamp getTimestamp();
80
81
/**
82
* Get URL where log entry originated
83
* @return Optional URL
84
*/
85
public Optional<String> getUrl();
86
87
/**
88
* Get line number where log entry originated
89
* @return Optional line number
90
*/
91
public Optional<Integer> getLineNumber();
92
93
/**
94
* Get stack trace if available
95
* @return Optional stack trace
96
*/
97
public Optional<StackTrace> getStackTrace();
98
99
/**
100
* Get network request ID if log is network-related
101
* @return Optional network request ID
102
*/
103
public Optional<NetworkRequestId> getNetworkRequestId();
104
105
/**
106
* Get worker ID if log originated from web worker
107
* @return Optional worker ID
108
*/
109
public Optional<WorkerId> getWorkerId();
110
111
/**
112
* Get additional arguments for the log entry
113
* @return Optional list of remote objects
114
*/
115
public Optional<List<RemoteObject>> getArgs();
116
}
117
118
/**
119
* Log entry source types
120
*/
121
public enum LogSource {
122
XML("xml"),
123
JAVASCRIPT("javascript"),
124
NETWORK("network"),
125
STORAGE("storage"),
126
APPCACHE("appcache"),
127
RENDERING("rendering"),
128
SECURITY("security"),
129
DEPRECATION("deprecation"),
130
WORKER("worker"),
131
VIOLATION("violation"),
132
INTERVENTION("intervention"),
133
RECOMMENDATION("recommendation"),
134
OTHER("other");
135
}
136
137
/**
138
* Log level enumeration
139
*/
140
public enum Level {
141
VERBOSE("verbose"),
142
INFO("info"),
143
WARNING("warning"),
144
ERROR("error");
145
}
146
```
147
148
### Selenium Log Integration
149
150
```java { .api }
151
/**
152
* Selenium log entry (converted from CDP log entry)
153
*/
154
public class org.openqa.selenium.devtools.idealized.log.model.LogEntry {
155
/**
156
* Create Selenium log entry
157
* @param source - Log source string
158
* @param entry - Selenium logging LogEntry
159
*/
160
public LogEntry(String source, org.openqa.selenium.logging.LogEntry entry);
161
162
/**
163
* Get log source
164
* @return Source string
165
*/
166
public String getSource();
167
168
/**
169
* Get Selenium log entry
170
* @return Selenium LogEntry
171
*/
172
public org.openqa.selenium.logging.LogEntry getLogEntry();
173
}
174
175
/**
176
* Standard Selenium log entry
177
*/
178
public class org.openqa.selenium.logging.LogEntry {
179
/**
180
* Get log level
181
* @return Java logging Level
182
*/
183
public Level getLevel();
184
185
/**
186
* Get timestamp in milliseconds
187
* @return Timestamp
188
*/
189
public long getTimestamp();
190
191
/**
192
* Get log message
193
* @return Message string
194
*/
195
public String getMessage();
196
}
197
```
198
199
## Implementation Details
200
201
### Level Conversion
202
203
The V99Log implementation converts CDP log levels to Java logging levels:
204
205
```java { .api }
206
/**
207
* Convert CDP log level to Java logging level
208
* @param level - CDP log level
209
* @return Java logging Level
210
*/
211
private Level fromCdpLevel(LogEntry.Level level);
212
```
213
214
**Level Mapping:**
215
- `verbose` → `Level.FINEST`
216
- `info` → `Level.INFO`
217
- `warning` → `Level.WARNING`
218
- `error` → `Level.SEVERE`
219
- unknown → `Level.INFO` (default)
220
221
### Timestamp Conversion
222
223
```java { .api }
224
/**
225
* Convert CDP timestamp to milliseconds
226
* @param timestamp - CDP timestamp
227
* @return Milliseconds since epoch
228
*/
229
private long fromCdpTimestamp(Timestamp timestamp);
230
```
231
232
## Usage Examples
233
234
### Basic Log Monitoring
235
236
```java
237
import org.openqa.selenium.devtools.DevTools;
238
import org.openqa.selenium.devtools.v99.V99Domains;
239
import org.openqa.selenium.logging.LogEntry;
240
241
DevTools devTools = ...; // from ChromeDriver
242
V99Domains domains = new V99Domains(devTools);
243
244
// Enable log collection
245
devTools.send(domains.log().enable());
246
247
// Listen for log entries
248
devTools.addListener(domains.log().entryAdded(), logEntry -> {
249
String source = logEntry.getSource();
250
LogEntry seleniumLogEntry = logEntry.getLogEntry();
251
252
System.out.printf("[%s] %s - %s: %s%n",
253
new Date(seleniumLogEntry.getTimestamp()),
254
source,
255
seleniumLogEntry.getLevel(),
256
seleniumLogEntry.getMessage()
257
);
258
});
259
260
// Navigate to page - logs will be captured
261
driver.get("https://example.com");
262
```
263
264
### Log Level Filtering
265
266
```java
267
devTools.send(domains.log().enable());
268
269
devTools.addListener(domains.log().entryAdded(), logEntry -> {
270
LogEntry seleniumEntry = logEntry.getLogEntry();
271
Level level = seleniumEntry.getLevel();
272
273
// Only process warnings and errors
274
if (level == Level.WARNING || level == Level.SEVERE) {
275
System.err.printf("IMPORTANT: [%s] %s: %s%n",
276
logEntry.getSource(),
277
level,
278
seleniumEntry.getMessage()
279
);
280
281
// Could trigger alerts, save to special log, etc.
282
handleImportantLogEntry(logEntry);
283
}
284
});
285
```
286
287
### Source-Based Log Processing
288
289
```java
290
devTools.send(domains.log().enable());
291
292
devTools.addListener(domains.log().entryAdded(), logEntry -> {
293
String source = logEntry.getSource();
294
LogEntry seleniumEntry = logEntry.getLogEntry();
295
296
switch (source) {
297
case "network":
298
handleNetworkLog(seleniumEntry);
299
break;
300
case "javascript":
301
handleJavaScriptLog(seleniumEntry);
302
break;
303
case "security":
304
handleSecurityLog(seleniumEntry);
305
break;
306
case "deprecation":
307
handleDeprecationLog(seleniumEntry);
308
break;
309
default:
310
handleGenericLog(source, seleniumEntry);
311
}
312
});
313
314
private void handleNetworkLog(LogEntry entry) {
315
// Process network-related logs
316
if (entry.getLevel() == Level.SEVERE) {
317
System.err.println("Network Error: " + entry.getMessage());
318
}
319
}
320
321
private void handleSecurityLog(LogEntry entry) {
322
// Security logs are always important
323
System.err.println("SECURITY: " + entry.getMessage());
324
// Could trigger security alerts, audit logging, etc.
325
}
326
```
327
328
### Log Collection and Analysis
329
330
```java
331
import java.util.concurrent.ConcurrentLinkedQueue;
332
import java.util.Map;
333
import java.util.concurrent.ConcurrentHashMap;
334
335
// Collect logs for later analysis
336
Queue<org.openqa.selenium.devtools.idealized.log.model.LogEntry> collectedLogs =
337
new ConcurrentLinkedQueue<>();
338
Map<String, AtomicInteger> logCounts = new ConcurrentHashMap<>();
339
340
devTools.send(domains.log().enable());
341
342
devTools.addListener(domains.log().entryAdded(), logEntry -> {
343
// Collect all logs
344
collectedLogs.offer(logEntry);
345
346
// Count by source
347
String source = logEntry.getSource();
348
logCounts.computeIfAbsent(source, k -> new AtomicInteger(0)).incrementAndGet();
349
350
// Count by level
351
Level level = logEntry.getLogEntry().getLevel();
352
logCounts.computeIfAbsent(level.toString(), k -> new AtomicInteger(0)).incrementAndGet();
353
});
354
355
// After test execution, analyze collected logs
356
public void analyzeLogs() {
357
System.out.println("Log Analysis:");
358
System.out.println("Total logs: " + collectedLogs.size());
359
360
logCounts.forEach((key, count) -> {
361
System.out.println(key + ": " + count.get());
362
});
363
364
// Find all error-level logs
365
List<org.openqa.selenium.devtools.idealized.log.model.LogEntry> errors =
366
collectedLogs.stream()
367
.filter(entry -> entry.getLogEntry().getLevel() == Level.SEVERE)
368
.collect(Collectors.toList());
369
370
if (!errors.isEmpty()) {
371
System.err.println("Found " + errors.size() + " error-level logs:");
372
errors.forEach(error -> {
373
System.err.println(" " + error.getSource() + ": " +
374
error.getLogEntry().getMessage());
375
});
376
}
377
}
378
```
379
380
### Log Clearing
381
382
```java
383
// Clear logs before starting a test
384
devTools.send(domains.log().clear());
385
devTools.send(domains.log().enable());
386
387
// Perform test operations
388
performTestSteps();
389
390
// Clear logs between test phases
391
devTools.send(domains.log().clear());
392
393
// Continue with next test phase
394
performNextTestPhase();
395
```
396
397
### Integration with Selenium Logging
398
399
```java
400
import org.openqa.selenium.logging.LogType;
401
import org.openqa.selenium.logging.LoggingPreferences;
402
import org.openqa.selenium.chrome.ChromeOptions;
403
404
// Configure Chrome logging preferences
405
LoggingPreferences loggingPrefs = new LoggingPreferences();
406
loggingPrefs.enable(LogType.BROWSER, Level.ALL);
407
loggingPrefs.enable(LogType.PERFORMANCE, Level.INFO);
408
409
ChromeOptions options = new ChromeOptions();
410
options.setCapability("goog:loggingPrefs", loggingPrefs);
411
412
WebDriver driver = new ChromeDriver(options);
413
414
// Use both DevTools log monitoring and standard Selenium logs
415
DevTools devTools = ((ChromeDriver) driver).getDevTools();
416
devTools.createSession();
417
418
V99Domains domains = new V99Domains(devTools);
419
devTools.send(domains.log().enable());
420
421
// DevTools log monitoring (real-time)
422
devTools.addListener(domains.log().entryAdded(), logEntry -> {
423
// Real-time log processing
424
processLogEntryRealTime(logEntry);
425
});
426
427
// Standard Selenium log retrieval (after page load)
428
LogEntries browserLogs = driver.manage().logs().get(LogType.BROWSER);
429
for (LogEntry entry : browserLogs) {
430
// Process accumulated logs
431
processLogEntryBatch(entry);
432
}
433
```
434
435
## Error Handling
436
437
Log management operations can encounter various issues:
438
439
- **Log domain not enabled**: Enable log domain before monitoring
440
- **High log volume**: Filter logs to prevent overwhelming the system
441
- **Memory issues**: Large numbers of collected logs can consume memory
442
- **Timestamp parsing**: Invalid timestamps fall back to current time
443
444
Handle errors through proper exception handling and resource management:
445
446
```java
447
try {
448
devTools.send(domains.log().enable());
449
450
// Set up log monitoring
451
setupLogMonitoring();
452
453
// Perform operations
454
runTestOperations();
455
456
} catch (DevToolsException e) {
457
System.err.println("Failed to enable log monitoring: " + e.getMessage());
458
} finally {
459
// Note: CDP Log domain doesn't have explicit disable
460
// It's cleaned up when DevTools session ends
461
}
462
```
463
464
## Performance Considerations
465
466
- **Log volume**: High-frequency applications can generate many log entries
467
- **Memory usage**: Collecting logs consumes memory; clear periodically if needed
468
- **Processing overhead**: Log event handlers should be efficient
469
- **Network impact**: Remote debugging increases log-related network traffic
470
- **Storage**: Long-running tests may need log rotation or cleanup strategies