0
# Browser Logging
1
2
Browser log capture and management for the Chrome DevTools Protocol v85. This functionality allows you to access browser logs with different severity levels and timestamps for debugging and monitoring purposes.
3
4
## Capabilities
5
6
### V85Log Class
7
8
The main class for browser log management implementing the idealized Log interface.
9
10
```java { .api }
11
/**
12
* Browser logging functionality for Chrome DevTools v85
13
*/
14
public class V85Log implements org.openqa.selenium.devtools.idealized.log.Log {
15
/**
16
* Creates a new V85Log instance
17
*/
18
public V85Log();
19
}
20
```
21
22
### Log Control
23
24
Enable, disable, and clear browser logs.
25
26
```java { .api }
27
/**
28
* Enables browser log collection
29
* @return Command to enable logging
30
*/
31
public Command<Void> enable();
32
33
/**
34
* Clears all collected browser logs
35
* @return Command to clear logs
36
*/
37
public Command<Void> clear();
38
```
39
40
**Usage Example:**
41
42
```java
43
import org.openqa.selenium.devtools.v85.V85Log;
44
45
V85Log log = domains.log();
46
47
// Enable log collection
48
devTools.send(log.enable());
49
50
// Clear existing logs
51
devTools.send(log.clear());
52
```
53
54
### Log Event Monitoring
55
56
Monitor new log entries as they are added by the browser.
57
58
```java { .api }
59
/**
60
* Event fired when a new log entry is added
61
* @return Event for new log entries
62
*/
63
public Event<org.openqa.selenium.devtools.idealized.log.model.LogEntry> entryAdded();
64
```
65
66
**Usage Example:**
67
68
```java
69
// Listen for new log entries
70
devTools.addListener(log.entryAdded(), logEntry -> {
71
System.out.printf("[%s] %s: %s%n",
72
new Date(logEntry.getEntry().getTimestamp()),
73
logEntry.getEntry().getLevel(),
74
logEntry.getEntry().getMessage()
75
);
76
77
// Handle specific log levels
78
if (logEntry.getEntry().getLevel() == Level.SEVERE) {
79
handleSevereError(logEntry);
80
}
81
});
82
```
83
84
### Complete Logging Setup
85
86
```java
87
import org.openqa.selenium.chrome.ChromeDriver;
88
import org.openqa.selenium.devtools.DevTools;
89
import org.openqa.selenium.devtools.v85.V85Domains;
90
import java.util.logging.Level;
91
92
ChromeDriver driver = new ChromeDriver();
93
DevTools devTools = driver.getDevTools();
94
devTools.createSession();
95
96
V85Domains domains = new V85Domains(devTools);
97
V85Log log = domains.log();
98
99
// Enable logging
100
devTools.send(log.enable());
101
102
// Set up log monitoring
103
devTools.addListener(log.entryAdded(), logEntry -> {
104
var entry = logEntry.getEntry();
105
106
// Format log message
107
String formattedLog = String.format(
108
"[%s] %s - %s: %s",
109
new Date(entry.getTimestamp()),
110
logEntry.getSource(),
111
entry.getLevel(),
112
entry.getMessage()
113
);
114
115
// Route to appropriate handler based on level
116
switch (entry.getLevel()) {
117
case SEVERE:
118
System.err.println("ERROR: " + formattedLog);
119
logToErrorSystem(formattedLog);
120
break;
121
122
case WARNING:
123
System.out.println("WARN: " + formattedLog);
124
logToWarningSystem(formattedLog);
125
break;
126
127
case INFO:
128
System.out.println("INFO: " + formattedLog);
129
break;
130
131
case FINEST:
132
if (debugMode) {
133
System.out.println("DEBUG: " + formattedLog);
134
}
135
break;
136
137
default:
138
System.out.println("LOG: " + formattedLog);
139
}
140
});
141
142
// Navigate to page - logs will be captured
143
driver.get("https://example.com");
144
145
// Clear logs when needed
146
devTools.send(log.clear());
147
```
148
149
## Log Level Conversion
150
151
The V85Log class automatically converts Chrome DevTools Protocol log levels to Java logging levels:
152
153
```java { .api }
154
/**
155
* Converts CDP log level to Java logging level
156
* @param level - CDP log level
157
* @return Java logging Level
158
*/
159
private Level fromCdpLevel(LogEntry.Level level);
160
```
161
162
**Level Mapping:**
163
- `verbose` → `Level.FINEST`
164
- `info` → `Level.INFO`
165
- `warning` → `Level.WARNING`
166
- `error` → `Level.SEVERE`
167
- Default → `Level.INFO`
168
169
## Timestamp Handling
170
171
```java { .api }
172
/**
173
* Converts CDP timestamp to Java long timestamp
174
* @param timestamp - CDP timestamp
175
* @return Java timestamp in milliseconds, or current time if parsing fails
176
*/
177
private long fromCdpTimestamp(Timestamp timestamp);
178
```
179
180
## CDP Model Classes
181
182
### LogEntry (CDP)
183
184
Raw log entry from the Chrome DevTools Protocol.
185
186
```java { .api }
187
/**
188
* Log entry from Chrome DevTools Protocol
189
*/
190
public class LogEntry {
191
/**
192
* Gets the log message source
193
* @return Log source (e.g., "javascript", "network", "storage")
194
*/
195
public Source getSource();
196
197
/**
198
* Gets the log level
199
* @return Log severity level
200
*/
201
public Level getLevel();
202
203
/**
204
* Gets the log message text
205
* @return Log message content
206
*/
207
public String getText();
208
209
/**
210
* Gets the timestamp when the log was created
211
* @return Log timestamp
212
*/
213
public Timestamp getTimestamp();
214
215
/**
216
* Gets the URL where the log originated (if applicable)
217
* @return Source URL
218
*/
219
public Optional<String> getUrl();
220
221
/**
222
* Gets the line number where the log originated (if applicable)
223
* @return Line number in source
224
*/
225
public Optional<Integer> getLineNumber();
226
227
/**
228
* Gets the stack trace for the log entry (if applicable)
229
* @return Stack trace information
230
*/
231
public Optional<StackTrace> getStackTrace();
232
233
/**
234
* Log severity levels in CDP
235
*/
236
public enum Level {
237
VERBOSE, INFO, WARNING, ERROR
238
}
239
240
/**
241
* Log sources in CDP
242
*/
243
public enum Source {
244
XML, JAVASCRIPT, NETWORK, STORAGE, APPCACHE, RENDERING,
245
SECURITY, DEPRECATION, WORKER, VIOLATION, INTERVENTION,
246
RECOMMENDATION, OTHER
247
}
248
}
249
```
250
251
### LogEntry (Idealized)
252
253
Selenium's idealized log entry that wraps CDP log data.
254
255
```java { .api }
256
/**
257
* Selenium's idealized log entry wrapper
258
*/
259
public class org.openqa.selenium.devtools.idealized.log.model.LogEntry {
260
/**
261
* Creates a new idealized log entry
262
* @param source - Log source as string
263
* @param entry - Java LogEntry with level, timestamp, and message
264
*/
265
public LogEntry(String source, org.openqa.selenium.logging.LogEntry entry);
266
267
/**
268
* Gets the log source
269
* @return Source of the log entry
270
*/
271
public String getSource();
272
273
/**
274
* Gets the wrapped Java log entry
275
* @return Java LogEntry with standard logging information
276
*/
277
public org.openqa.selenium.logging.LogEntry getEntry();
278
}
279
```
280
281
### Selenium LogEntry
282
283
Standard Selenium log entry used by the idealized interface.
284
285
```java { .api }
286
/**
287
* Standard Selenium log entry
288
*/
289
public class org.openqa.selenium.logging.LogEntry {
290
/**
291
* Gets the log level
292
* @return Java logging Level
293
*/
294
public Level getLevel();
295
296
/**
297
* Gets the timestamp in milliseconds
298
* @return Timestamp when log was created
299
*/
300
public long getTimestamp();
301
302
/**
303
* Gets the log message
304
* @return Log message text
305
*/
306
public String getMessage();
307
}
308
```
309
310
## Advanced Log Filtering
311
312
```java
313
// Filter logs by source and level
314
devTools.addListener(log.entryAdded(), logEntry -> {
315
String source = logEntry.getSource();
316
Level level = logEntry.getEntry().getLevel();
317
String message = logEntry.getEntry().getMessage();
318
319
// Only process JavaScript errors and network issues
320
if (source.equals("javascript") && level == Level.SEVERE) {
321
handleJavaScriptError(logEntry);
322
} else if (source.equals("network") && (level == Level.WARNING || level == Level.SEVERE)) {
323
handleNetworkIssue(logEntry);
324
}
325
326
// Filter by message content
327
if (message.contains("404") || message.contains("Failed to load")) {
328
handleResourceError(logEntry);
329
}
330
});
331
332
// Batch log processing
333
private final List<LogEntry> logBuffer = new ArrayList<>();
334
private final Timer logProcessor = new Timer();
335
336
devTools.addListener(log.entryAdded(), logEntry -> {
337
synchronized (logBuffer) {
338
logBuffer.add(logEntry);
339
340
// Process logs in batches every 5 seconds
341
if (logBuffer.size() == 1) {
342
logProcessor.schedule(new TimerTask() {
343
@Override
344
public void run() {
345
processBatchedLogs();
346
}
347
}, 5000);
348
}
349
}
350
});
351
352
private void processBatchedLogs() {
353
synchronized (logBuffer) {
354
if (!logBuffer.isEmpty()) {
355
// Process all buffered logs
356
logBuffer.forEach(this::processLogEntry);
357
logBuffer.clear();
358
}
359
}
360
}
361
```
362
363
## Log Persistence
364
365
```java
366
// Save logs to file
367
private final FileWriter logWriter = new FileWriter("browser-logs.txt", true);
368
369
devTools.addListener(log.entryAdded(), logEntry -> {
370
try {
371
String logLine = String.format(
372
"%s [%s] %s: %s%n",
373
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(logEntry.getEntry().getTimestamp())),
374
logEntry.getSource().toUpperCase(),
375
logEntry.getEntry().getLevel(),
376
logEntry.getEntry().getMessage()
377
);
378
379
logWriter.write(logLine);
380
logWriter.flush();
381
} catch (IOException e) {
382
System.err.println("Failed to write log: " + e.getMessage());
383
}
384
});
385
386
// Remember to close the writer when done
387
// logWriter.close();
388
```