Chrome DevTools Protocol bindings for Selenium WebDriver version 111
—
Log domain implementation for browser log capture and management. Provides access to browser console logs with level filtering, timestamp information, and automatic conversion between CDP log formats and Java logging standards.
Enable and disable browser logging capture.
public Command<Void> enable();
public Command<Void> clear();Usage example:
v111Log log = domains.log();
// Enable log capture
devTools.send(log.enable());
// Clear existing logs
devTools.send(log.clear());
// Later disable when done (optional - usually left enabled)
// Note: There's no disable() method, logs remain enabled once startedMonitor log entries added to the browser console and receive them as structured events.
public Event<org.openqa.selenium.devtools.idealized.log.model.LogEntry> entryAdded();Usage example:
// Listen for log entries
devTools.addListener(log.entryAdded(), logEntry -> {
System.out.printf("[%s] %s: %s%n",
logEntry.getSource(),
logEntry.getEntry().getLevel(),
logEntry.getEntry().getMessage());
// Access timestamp
long timestamp = logEntry.getEntry().getTimestamp();
System.out.println("Logged at: " + Instant.ofEpochMilli(timestamp));
});
// Browser actions that generate logs:
// - JavaScript errors: throw new Error("Something failed");
// - Network errors: fetch('/nonexistent-endpoint');
// - Security violations: Access denied errors
// - Extension messages: Chrome extension loggingThe logging domain automatically converts CDP log levels to Java logging levels:
// CDP levels -> Java levels mapping:
// "verbose" -> Level.FINEST
// "info" -> Level.INFO
// "warning" -> Level.WARNING
// "error" -> Level.SEVERE
// default -> Level.INFOUsage example with level filtering:
devTools.addListener(log.entryAdded(), logEntry -> {
LogEntry entry = logEntry.getEntry();
Level level = entry.getLevel();
// Only process errors and warnings
if (level.intValue() >= Level.WARNING.intValue()) {
System.err.println("Important log: " + entry.getMessage());
// Could save to file, send alert, etc.
if (level.equals(Level.SEVERE)) {
alertErrorMonitoring(entry);
}
}
});Automatic conversion of CDP timestamps to Java milliseconds with fallback handling:
private long fromCdpTimestamp(Timestamp timestamp) {
try {
return Long.parseLong(timestamp.toString());
} catch (NumberFormatException e) {
return System.currentTimeMillis(); // Fallback to current time
}
}public class BrowserLogMonitor {
private final DevTools devTools;
private final v111Log log;
private final List<LogEntry> collectedLogs = new ArrayList<>();
public void startMonitoring() {
// Enable logging
devTools.send(log.enable());
// Clear any existing logs
devTools.send(log.clear());
// Set up log collection
devTools.addListener(log.entryAdded(), this::handleLogEntry);
}
private void handleLogEntry(org.openqa.selenium.devtools.idealized.log.model.LogEntry logEntry) {
LogEntry entry = logEntry.getEntry();
String source = logEntry.getSource();
// Collect log for later analysis
collectedLogs.add(entry);
// Real-time processing based on level
Level level = entry.getLevel();
String message = entry.getMessage();
switch (level.getName()) {
case "SEVERE":
System.err.println("[ERROR] " + source + ": " + message);
// Could trigger alerts, save to error log file, etc.
handleError(source, message, entry.getTimestamp());
break;
case "WARNING":
System.out.println("[WARN] " + source + ": " + message);
break;
case "INFO":
if (isVerboseLogging()) {
System.out.println("[INFO] " + source + ": " + message);
}
break;
case "FINEST":
if (isDebugLogging()) {
System.out.println("[DEBUG] " + source + ": " + message);
}
break;
}
}
public List<LogEntry> getErrorLogs() {
return collectedLogs.stream()
.filter(log -> log.getLevel().equals(Level.SEVERE))
.collect(Collectors.toList());
}
public List<LogEntry> getLogsAfter(long timestamp) {
return collectedLogs.stream()
.filter(log -> log.getTimestamp() > timestamp)
.collect(Collectors.toList());
}
public void clearCollectedLogs() {
collectedLogs.clear();
devTools.send(log.clear()); // Clear browser logs too
}
}// Idealized log entry (what you receive in events)
class org.openqa.selenium.devtools.idealized.log.model.LogEntry {
public LogEntry(String source, org.openqa.selenium.logging.LogEntry entry);
public String getSource(); // Log source: "javascript", "network", "security", etc.
public org.openqa.selenium.logging.LogEntry getEntry(); // Standard Selenium log entry
}
// Standard Selenium log entry
class org.openqa.selenium.logging.LogEntry {
public Level getLevel(); // Java logging level
public long getTimestamp(); // Timestamp in milliseconds
public String getMessage(); // Log message text
}// CDP-specific log entry (internal)
class LogEntry {
public enum Level {
VERBOSE, INFO, WARNING, ERROR
}
public Level getLevel(); // CDP log level
public String getText(); // Log message
public String getSource(); // Log source
public Timestamp getTimestamp(); // CDP timestamp
}
class Timestamp {
// CDP timestamp representation
// Converted to long milliseconds by the domain
}Common log sources you'll encounter:
The Log domain is complementary to the Events domain:
For comprehensive monitoring, use both:
// Monitor broad browser logs
devTools.addListener(log.entryAdded(), this::handleBrowserLog);
// Monitor specific console API calls
devTools.addListener(events.consoleEvent(), this::handleConsoleCall);Install with Tessl CLI
npx tessl i tessl/maven-org-seleniumhq-selenium--selenium-devtools-v111