0
# Console Log Management
1
2
Manages console log operations, log entries, and provides conversion between CDP log formats and Selenium's logging system. This domain enables comprehensive monitoring of browser console output including different log levels and sources.
3
4
## Capabilities
5
6
### V102Log Class
7
8
Main class for console log management. Implements the idealized Log interface to provide v102-specific implementations for log monitoring and entry processing.
9
10
```java { .api }
11
/**
12
* Manages console log operations and entries
13
*/
14
public class V102Log implements org.openqa.selenium.devtools.idealized.log.Log {
15
/**
16
* Enables the Log domain to start receiving log entries
17
* @return Command to enable log domain
18
*/
19
public Command<Void> enable();
20
21
/**
22
* Clears all existing log entries
23
* @return Command to clear log entries
24
*/
25
public Command<Void> clear();
26
27
/**
28
* Returns the log entry added event for monitoring new log entries
29
* @return Event for log entry notifications with idealized log entry format
30
*/
31
public Event<org.openqa.selenium.devtools.idealized.log.model.LogEntry> entryAdded();
32
}
33
```
34
35
**Usage Examples:**
36
37
### Basic Log Monitoring
38
39
```java
40
import org.openqa.selenium.chrome.ChromeDriver;
41
import org.openqa.selenium.devtools.DevTools;
42
import org.openqa.selenium.devtools.v102.V102Domains;
43
import org.openqa.selenium.devtools.idealized.log.model.LogEntry;
44
import java.util.logging.Level;
45
46
// Setup
47
ChromeDriver driver = new ChromeDriver();
48
DevTools devTools = driver.getDevTools();
49
devTools.createSession();
50
V102Domains domains = new V102Domains(devTools);
51
52
// Enable log domain
53
devTools.send(domains.log().enable());
54
55
// Listen for log entries
56
devTools.addListener(domains.log().entryAdded(), (logEntry) -> {
57
System.out.println(String.format(
58
"[%s] %s: %s",
59
logEntry.getSource(),
60
logEntry.getEntry().getLevel(),
61
logEntry.getEntry().getMessage()
62
));
63
});
64
65
// Navigate to a page that generates console output
66
driver.get("https://example.com");
67
68
// Execute JavaScript that logs messages
69
driver.executeScript("console.log('This is an info message');");
70
driver.executeScript("console.warn('This is a warning message');");
71
driver.executeScript("console.error('This is an error message');");
72
73
// Clear log entries
74
devTools.send(domains.log().clear());
75
76
// Cleanup
77
driver.quit();
78
```
79
80
### Log Level Filtering
81
82
```java
83
import java.util.logging.Level;
84
85
// Monitor only specific log levels
86
devTools.addListener(domains.log().entryAdded(), (logEntry) -> {
87
Level level = logEntry.getEntry().getLevel();
88
String message = logEntry.getEntry().getMessage();
89
String source = logEntry.getSource();
90
91
switch (level.getName()) {
92
case "SEVERE": // Error level
93
System.err.println("ERROR [" + source + "]: " + message);
94
break;
95
case "WARNING": // Warning level
96
System.out.println("WARN [" + source + "]: " + message);
97
break;
98
case "INFO": // Info level
99
System.out.println("INFO [" + source + "]: " + message);
100
break;
101
case "FINEST": // Verbose level
102
System.out.println("VERBOSE [" + source + "]: " + message);
103
break;
104
default:
105
System.out.println("LOG [" + source + "] " + level + ": " + message);
106
}
107
});
108
```
109
110
### Log Collection and Analysis
111
112
```java
113
import java.util.concurrent.CopyOnWriteArrayList;
114
import java.time.Instant;
115
116
// Collect logs for analysis
117
List<LogEntry> collectedLogs = new CopyOnWriteArrayList<>();
118
119
devTools.addListener(domains.log().entryAdded(), (logEntry) -> {
120
collectedLogs.add(logEntry);
121
122
// Analyze log patterns
123
String message = logEntry.getEntry().getMessage();
124
if (message.contains("error") || message.contains("failed")) {
125
System.err.println("Potential issue detected: " + message);
126
}
127
});
128
129
// Perform test actions
130
driver.get("https://complex-app.com");
131
// ... perform various actions ...
132
133
// Analyze collected logs
134
System.out.println("Total log entries: " + collectedLogs.size());
135
136
long errorCount = collectedLogs.stream()
137
.filter(entry -> entry.getEntry().getLevel() == Level.SEVERE)
138
.count();
139
140
long warningCount = collectedLogs.stream()
141
.filter(entry -> entry.getEntry().getLevel() == Level.WARNING)
142
.count();
143
144
System.out.println("Errors: " + errorCount + ", Warnings: " + warningCount);
145
146
// Clear collected logs for next test
147
collectedLogs.clear();
148
devTools.send(domains.log().clear());
149
```
150
151
### Source-Based Log Filtering
152
153
```java
154
// Filter logs by source
155
devTools.addListener(domains.log().entryAdded(), (logEntry) -> {
156
String source = logEntry.getSource();
157
String message = logEntry.getEntry().getMessage();
158
159
switch (source) {
160
case "javascript":
161
System.out.println("JS: " + message);
162
break;
163
case "network":
164
System.out.println("NET: " + message);
165
break;
166
case "storage":
167
System.out.println("STORAGE: " + message);
168
break;
169
case "appcache":
170
System.out.println("APPCACHE: " + message);
171
break;
172
case "rendering":
173
System.out.println("RENDER: " + message);
174
break;
175
case "security":
176
System.out.println("SECURITY: " + message);
177
break;
178
case "deprecation":
179
System.out.println("DEPRECATED: " + message);
180
break;
181
case "worker":
182
System.out.println("WORKER: " + message);
183
break;
184
case "violation":
185
System.out.println("VIOLATION: " + message);
186
break;
187
case "intervention":
188
System.out.println("INTERVENTION: " + message);
189
break;
190
case "recommendation":
191
System.out.println("RECOMMENDATION: " + message);
192
break;
193
default:
194
System.out.println("OTHER [" + source + "]: " + message);
195
}
196
});
197
```
198
199
## Log Level Conversion
200
201
The V102Log class provides automatic conversion between CDP log levels and Java logging levels:
202
203
### CDP to Java Level Mapping
204
205
```java { .api }
206
/**
207
* Internal level conversion (handled automatically by V102Log)
208
*/
209
private Level fromCdpLevel(LogEntry.Level level) {
210
switch (level.toString()) {
211
case "verbose":
212
return Level.FINEST; // Most detailed
213
case "info":
214
return Level.INFO; // General information
215
case "warning":
216
return Level.WARNING; // Warning messages
217
case "error":
218
return Level.SEVERE; // Error messages
219
default:
220
return Level.INFO; // Default fallback
221
}
222
}
223
```
224
225
### Timestamp Handling
226
227
```java { .api }
228
/**
229
* Internal timestamp conversion (handled automatically by V102Log)
230
*/
231
private long fromCdpTimestamp(Timestamp timestamp) {
232
try {
233
return Long.parseLong(timestamp.toString());
234
} catch (NumberFormatException e) {
235
return System.currentTimeMillis(); // Fallback to current time
236
}
237
}
238
```
239
240
## CDP Protocol Classes
241
242
The V102Log class interacts with generated CDP protocol classes:
243
244
### Log Domain
245
246
```java { .api }
247
// Generated CDP log classes (available at runtime)
248
class Log {
249
static Command<Void> enable();
250
static Command<Void> clear();
251
static Event<LogEntry> entryAdded();
252
}
253
254
// CDP log entry representation
255
class LogEntry {
256
enum Level {
257
VERBOSE, INFO, WARNING, ERROR
258
}
259
260
String getSource();
261
Level getLevel();
262
String getText();
263
Timestamp getTimestamp();
264
Optional<String> getUrl();
265
Optional<Integer> getLineNumber();
266
Optional<StackTrace> getStackTrace();
267
}
268
269
// Timestamp representation
270
class Timestamp {
271
String toString();
272
JsonElement toJson();
273
}
274
```
275
276
### Selenium Integration Types
277
278
```java { .api }
279
// Idealized log entry for Selenium integration
280
class org.openqa.selenium.devtools.idealized.log.model.LogEntry {
281
/**
282
* Creates idealized log entry with source and standard log entry
283
*/
284
LogEntry(String source, org.openqa.selenium.logging.LogEntry entry);
285
286
String getSource();
287
org.openqa.selenium.logging.LogEntry getEntry();
288
}
289
290
// Standard Selenium log entry
291
class org.openqa.selenium.logging.LogEntry {
292
LogEntry(Level level, long timestamp, String message);
293
294
Level getLevel();
295
long getTimestamp();
296
String getMessage();
297
}
298
299
// Java logging levels
300
enum Level {
301
FINEST, // Verbose
302
INFO, // Info
303
WARNING, // Warning
304
SEVERE // Error
305
}
306
```
307
308
### Event Processing Flow
309
310
The log processing follows this flow:
311
312
1. **CDP Log Entry**: Browser generates log entry with CDP-specific format
313
2. **Event Notification**: V102Log receives CDP LogEntry via entryAdded event
314
3. **Level Conversion**: CDP level converted to Java logging Level
315
4. **Timestamp Conversion**: CDP timestamp converted to milliseconds
316
5. **Idealized Entry**: Creates Selenium idealized LogEntry
317
6. **Event Dispatch**: Dispatches converted entry to listeners
318
319
## Advanced Log Management Patterns
320
321
### Log Buffering
322
323
```java
324
import java.util.concurrent.BlockingQueue;
325
import java.util.concurrent.LinkedBlockingQueue;
326
327
// Buffer logs for batch processing
328
BlockingQueue<LogEntry> logBuffer = new LinkedBlockingQueue<>();
329
330
devTools.addListener(domains.log().entryAdded(), (logEntry) -> {
331
logBuffer.offer(logEntry);
332
});
333
334
// Process logs in background thread
335
Thread logProcessor = new Thread(() -> {
336
while (!Thread.currentThread().isInterrupted()) {
337
try {
338
LogEntry entry = logBuffer.take(); // Blocks until available
339
processLogEntry(entry);
340
} catch (InterruptedException e) {
341
Thread.currentThread().interrupt();
342
break;
343
}
344
}
345
});
346
logProcessor.start();
347
```
348
349
### Log Persistence
350
351
```java
352
import java.io.FileWriter;
353
import java.io.IOException;
354
import java.time.Instant;
355
import java.time.format.DateTimeFormatter;
356
357
// Write logs to file
358
FileWriter logFile = new FileWriter("console-logs.txt", true);
359
360
devTools.addListener(domains.log().entryAdded(), (logEntry) -> {
361
try {
362
String timestamp = DateTimeFormatter.ISO_INSTANT
363
.format(Instant.ofEpochMilli(logEntry.getEntry().getTimestamp()));
364
365
String logLine = String.format(
366
"%s [%s] %s: %s%n",
367
timestamp,
368
logEntry.getSource(),
369
logEntry.getEntry().getLevel(),
370
logEntry.getEntry().getMessage()
371
);
372
373
logFile.write(logLine);
374
logFile.flush();
375
} catch (IOException e) {
376
System.err.println("Failed to write log entry: " + e.getMessage());
377
}
378
});
379
380
// Remember to close file when done
381
// logFile.close();
382
```
383
384
### Conditional Log Monitoring
385
386
```java
387
// Monitor logs only during specific operations
388
boolean monitoringEnabled = false;
389
390
devTools.addListener(domains.log().entryAdded(), (logEntry) -> {
391
if (monitoringEnabled) {
392
// Process log entry only when monitoring is enabled
393
handleLogEntry(logEntry);
394
}
395
});
396
397
// Enable monitoring for specific operation
398
monitoringEnabled = true;
399
driver.get("https://test-app.com");
400
performCriticalOperation();
401
monitoringEnabled = false;
402
403
// Clear logs after operation
404
devTools.send(domains.log().clear());
405
```