0
# Browser Logging
1
2
The logging domain provides browser-level logging functionality for capturing and managing browser console logs, network logs, and other browser-generated log messages separate from JavaScript console events.
3
4
## Capabilities
5
6
### V101Log
7
8
Browser logging implementation that provides commands for enabling, clearing, and monitoring browser logs.
9
10
```java { .api }
11
/**
12
* Browser logging functionality for CDP version 101
13
* Implements the Log interface for managing browser-generated log messages
14
*/
15
public class V101Log implements Log {
16
17
/**
18
* Creates a new log handler instance
19
*/
20
public V101Log();
21
22
/**
23
* Enable the log domain to start receiving log entries
24
* @return Command to enable browser logging
25
*/
26
public Command<Void> enable();
27
28
/**
29
* Clear all browser logs
30
* @return Command to clear the browser log buffer
31
*/
32
public Command<Void> clear();
33
34
/**
35
* Get an event stream for new log entries
36
* @return Event that fires when new log entries are added
37
*/
38
public Event<LogEntry> entryAdded();
39
}
40
```
41
42
**Usage Examples:**
43
44
```java
45
import org.openqa.selenium.devtools.v101.V101Log;
46
import org.openqa.selenium.devtools.idealized.log.model.LogEntry;
47
48
// Create log handler
49
V101Log log = new V101Log();
50
51
// Enable logging
52
devTools.send(log.enable());
53
54
// Listen for new log entries
55
devTools.addListener(log.entryAdded(), entry -> {
56
System.out.println("Browser Log [" + entry.getSource() + "]: " +
57
entry.getLogEntry().getMessage());
58
System.out.println("Level: " + entry.getLogEntry().getLevel());
59
System.out.println("Timestamp: " + new Date(entry.getLogEntry().getMillis()));
60
});
61
62
// Clear existing logs
63
devTools.send(log.clear());
64
65
// Navigate to generate logs
66
driver.get("https://example.com");
67
68
// Perform actions that generate browser logs
69
driver.executeScript("console.error('This will appear in browser logs');");
70
71
// Network requests will also generate logs
72
driver.findElement(By.tagName("body")).click();
73
```
74
75
### LogEntry
76
77
Represents a browser log entry with source information and standard Java logging details.
78
79
```java { .api }
80
/**
81
* Represents a browser log entry with source and standard logging information
82
* Wraps the browser log data in familiar Java logging structures
83
*/
84
public class LogEntry {
85
86
/**
87
* Get the source of the log entry (console, network, security, etc.)
88
* @return String indicating the log source
89
*/
90
public String getSource();
91
92
/**
93
* Get the standard Java log entry with level, timestamp, and message
94
* @return java.util.logging.LogEntry with formatted log data
95
*/
96
public java.util.logging.LogEntry getLogEntry();
97
}
98
```
99
100
**Log Sources:**
101
102
- `"console"` - Browser console messages
103
- `"network"` - Network-related log messages
104
- `"security"` - Security-related warnings and errors
105
- `"deprecation"` - Deprecation warnings
106
- `"worker"` - Web worker log messages
107
- `"violation"` - Performance and security violations
108
- `"intervention"` - Browser interventions (blocking actions)
109
- `"recommendation"` - Browser recommendations
110
111
**Usage Example:**
112
113
```java
114
devTools.addListener(log.entryAdded(), entry -> {
115
java.util.logging.LogEntry logEntry = entry.getLogEntry();
116
117
// Process logs based on source
118
switch (entry.getSource()) {
119
case "console":
120
handleConsoleLog(logEntry);
121
break;
122
case "network":
123
handleNetworkLog(logEntry);
124
break;
125
case "security":
126
handleSecurityLog(logEntry);
127
break;
128
case "deprecation":
129
handleDeprecationWarning(logEntry);
130
break;
131
default:
132
handleGenericLog(entry.getSource(), logEntry);
133
}
134
});
135
136
private void handleSecurityLog(java.util.logging.LogEntry logEntry) {
137
if (logEntry.getLevel().intValue() >= Level.SEVERE.intValue()) {
138
System.err.println("π SECURITY ISSUE: " + logEntry.getMessage());
139
// Could trigger security test failure
140
}
141
}
142
143
private void handleNetworkLog(java.util.logging.LogEntry logEntry) {
144
if (logEntry.getMessage().contains("failed")) {
145
System.err.println("π NETWORK ERROR: " + logEntry.getMessage());
146
}
147
}
148
```
149
150
### Java Logging Integration
151
152
The log entries use standard Java logging levels and can be integrated with existing logging frameworks.
153
154
```java { .api }
155
/**
156
* Standard Java logging levels used by browser log entries
157
*/
158
public enum Level {
159
FINEST, // Verbose browser logs
160
FINE, // Debug-level browser logs
161
INFO, // Informational browser logs
162
WARNING, // Browser warnings
163
SEVERE // Browser errors
164
}
165
166
/**
167
* Standard Java LogEntry with browser log data
168
*/
169
public class java.util.logging.LogEntry {
170
public Level getLevel();
171
public long getMillis();
172
public String getMessage();
173
public String getLoggerName();
174
public String getSourceClassName();
175
public String getSourceMethodName();
176
}
177
```
178
179
**Integration with Logging Frameworks:**
180
181
```java
182
import java.util.logging.Logger;
183
import java.util.logging.Handler;
184
import java.util.logging.LogRecord;
185
186
// Create a custom handler for browser logs
187
Logger browserLogger = Logger.getLogger("browser-logs");
188
189
devTools.addListener(log.entryAdded(), entry -> {
190
java.util.logging.LogEntry browserLog = entry.getLogEntry();
191
192
// Create a LogRecord for standard Java logging
193
LogRecord record = new LogRecord(browserLog.getLevel(), browserLog.getMessage());
194
record.setMillis(browserLog.getMillis());
195
record.setLoggerName("browser." + entry.getSource());
196
record.setSourceClassName("Browser");
197
record.setSourceMethodName(entry.getSource());
198
199
// Publish to standard logging system
200
browserLogger.log(record);
201
});
202
203
// Or integrate with SLF4J
204
import org.slf4j.Logger;
205
import org.slf4j.LoggerFactory;
206
207
Logger slf4jLogger = LoggerFactory.getLogger("browser-logs");
208
209
devTools.addListener(log.entryAdded(), entry -> {
210
java.util.logging.LogEntry browserLog = entry.getLogEntry();
211
String message = "[" + entry.getSource() + "] " + browserLog.getMessage();
212
213
switch (browserLog.getLevel().intValue()) {
214
case 1000: // SEVERE
215
slf4jLogger.error(message);
216
break;
217
case 900: // WARNING
218
slf4jLogger.warn(message);
219
break;
220
case 800: // INFO
221
slf4jLogger.info(message);
222
break;
223
default: // FINE, FINER, FINEST
224
slf4jLogger.debug(message);
225
}
226
});
227
```
228
229
### CDP Protocol Types
230
231
The underlying CDP Log domain types used by V101Log:
232
233
```java { .api }
234
/**
235
* CDP Log.LogEntry event data
236
* Raw log entry data from the Chrome DevTools Protocol
237
*/
238
public class org.openqa.selenium.devtools.v101.log.model.LogEntry {
239
public String getSource();
240
public Level getLevel();
241
public String getText();
242
public Timestamp getTimestamp();
243
public Optional<String> getUrl();
244
public Optional<Integer> getLineNumber();
245
public Optional<StackTrace> getStackTrace();
246
public Optional<Integer> getNetworkRequestId();
247
public Optional<String> getWorkerId();
248
public Optional<List<String>> getArgs();
249
}
250
251
/**
252
* CDP log level enumeration
253
*/
254
public enum Level {
255
VERBOSE("verbose"),
256
INFO("info"),
257
WARNING("warning"),
258
ERROR("error");
259
260
public String toString();
261
}
262
263
/**
264
* CDP timestamp representation
265
*/
266
public class Timestamp {
267
public JsonElement toJson();
268
public String toString();
269
}
270
```
271
272
### Log Domain Commands
273
274
The V101Log class internally uses these CDP Log domain commands:
275
276
```java { .api }
277
// From org.openqa.selenium.devtools.v101.log.Log
278
public static Command<Void> enable();
279
public static Command<Void> disable();
280
public static Command<Void> clear();
281
public static Event<LogEntry> entryAdded();
282
```
283
284
## Advanced Usage Patterns
285
286
### Log Filtering and Categorization
287
288
```java
289
// Sophisticated log processing with filtering and categorization
290
public class BrowserLogAnalyzer {
291
private final Map<String, List<LogEntry>> logsBySource = new ConcurrentHashMap<>();
292
private final Map<Level, AtomicInteger> logCounts = new ConcurrentHashMap<>();
293
294
public void setupLogMonitoring(DevTools devTools, V101Log log) {
295
devTools.send(log.enable());
296
297
devTools.addListener(log.entryAdded(), this::processLogEntry);
298
}
299
300
private void processLogEntry(LogEntry entry) {
301
String source = entry.getSource();
302
java.util.logging.LogEntry logEntry = entry.getLogEntry();
303
Level level = logEntry.getLevel();
304
305
// Categorize by source
306
logsBySource.computeIfAbsent(source, k -> new ArrayList<>()).add(entry);
307
308
// Count by level
309
logCounts.computeIfAbsent(level, k -> new AtomicInteger(0)).incrementAndGet();
310
311
// Filter and process specific log types
312
if ("security".equals(source) && level.intValue() >= Level.WARNING.intValue()) {
313
handleSecurityIssue(entry);
314
}
315
316
if ("network".equals(source) && logEntry.getMessage().contains("blocked")) {
317
handleBlockedRequest(entry);
318
}
319
320
if ("deprecation".equals(source)) {
321
handleDeprecationWarning(entry);
322
}
323
}
324
325
public void printLogSummary() {
326
System.out.println("=== Browser Log Summary ===");
327
logCounts.forEach((level, count) -> {
328
System.out.println(level + ": " + count.get() + " entries");
329
});
330
331
System.out.println("\n=== Logs by Source ===");
332
logsBySource.forEach((source, logs) -> {
333
System.out.println(source + ": " + logs.size() + " entries");
334
});
335
}
336
337
private void handleSecurityIssue(LogEntry entry) {
338
System.err.println("π SECURITY: " + entry.getLogEntry().getMessage());
339
// Could fail tests or trigger alerts
340
}
341
342
private void handleBlockedRequest(LogEntry entry) {
343
System.out.println("π« BLOCKED: " + entry.getLogEntry().getMessage());
344
// Could indicate CSP or CORS issues
345
}
346
347
private void handleDeprecationWarning(LogEntry entry) {
348
System.out.println("β οΈ DEPRECATED: " + entry.getLogEntry().getMessage());
349
// Could track deprecated API usage
350
}
351
}
352
```
353
354
### Performance Monitoring Through Logs
355
356
```java
357
// Monitor browser performance through log analysis
358
public class PerformanceLogMonitor {
359
private final List<String> performanceIssues = new ArrayList<>();
360
361
public void setupPerformanceMonitoring(DevTools devTools, V101Log log) {
362
devTools.send(log.enable());
363
364
devTools.addListener(log.entryAdded(), entry -> {
365
String message = entry.getLogEntry().getMessage().toLowerCase();
366
367
// Detect performance-related log entries
368
if (message.contains("slow") ||
369
message.contains("timeout") ||
370
message.contains("performance") ||
371
message.contains("long task")) {
372
373
performanceIssues.add(entry.getLogEntry().getMessage());
374
375
System.out.println("β‘ PERFORMANCE ISSUE: " + entry.getLogEntry().getMessage());
376
}
377
378
// Detect memory-related issues
379
if (message.contains("memory") || message.contains("heap")) {
380
System.out.println("πΎ MEMORY ISSUE: " + entry.getLogEntry().getMessage());
381
}
382
383
// Detect layout thrashing
384
if (message.contains("layout") || message.contains("reflow")) {
385
System.out.println("π LAYOUT ISSUE: " + entry.getLogEntry().getMessage());
386
}
387
});
388
}
389
390
public List<String> getPerformanceIssues() {
391
return new ArrayList<>(performanceIssues);
392
}
393
394
public void clearPerformanceIssues() {
395
performanceIssues.clear();
396
}
397
}
398
```
399
400
### Log Persistence and Analysis
401
402
```java
403
// Persist logs for analysis and reporting
404
public class LogPersistence {
405
private final PrintWriter logWriter;
406
private final String testName;
407
408
public LogPersistence(String testName) throws IOException {
409
this.testName = testName;
410
this.logWriter = new PrintWriter(new FileWriter(testName + "-browser-logs.txt"));
411
}
412
413
public void setupLogPersistence(DevTools devTools, V101Log log) {
414
devTools.send(log.enable());
415
416
devTools.addListener(log.entryAdded(), entry -> {
417
java.util.logging.LogEntry logEntry = entry.getLogEntry();
418
419
// Write structured log data
420
logWriter.printf("[%s] %s %s: %s%n",
421
new Date(logEntry.getMillis()).toString(),
422
entry.getSource().toUpperCase(),
423
logEntry.getLevel(),
424
logEntry.getMessage()
425
);
426
logWriter.flush();
427
});
428
}
429
430
public void close() {
431
if (logWriter != null) {
432
logWriter.close();
433
}
434
}
435
436
// Generate summary report
437
public void generateReport() throws IOException {
438
try (PrintWriter reportWriter = new PrintWriter(new FileWriter(testName + "-log-summary.txt"))) {
439
reportWriter.println("Browser Log Summary for: " + testName);
440
reportWriter.println("Generated: " + new Date());
441
442
// Could include statistics, error counts, performance metrics
443
reportWriter.println("Log analysis would go here...");
444
}
445
}
446
}
447
448
// Usage in test
449
LogPersistence logPersistence = new LogPersistence("test-checkout-flow");
450
try {
451
logPersistence.setupLogPersistence(devTools, log);
452
453
// Run test...
454
455
} finally {
456
logPersistence.generateReport();
457
logPersistence.close();
458
}
459
```