CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-seleniumhq-selenium--selenium-devtools-v101

Java bindings for Chrome DevTools Protocol version 101, enabling browser automation and debugging capabilities through CDP integration

Pending
Overview
Eval results
Files

logging.mddocs/

Browser Logging

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.

Capabilities

V101Log

Browser logging implementation that provides commands for enabling, clearing, and monitoring browser logs.

/**
 * Browser logging functionality for CDP version 101
 * Implements the Log interface for managing browser-generated log messages
 */
public class V101Log implements Log {
    
    /**
     * Creates a new log handler instance
     */
    public V101Log();
    
    /**
     * Enable the log domain to start receiving log entries
     * @return Command to enable browser logging
     */
    public Command<Void> enable();
    
    /**
     * Clear all browser logs
     * @return Command to clear the browser log buffer
     */
    public Command<Void> clear();
    
    /**
     * Get an event stream for new log entries
     * @return Event that fires when new log entries are added
     */
    public Event<LogEntry> entryAdded();
}

Usage Examples:

import org.openqa.selenium.devtools.v101.V101Log;
import org.openqa.selenium.devtools.idealized.log.model.LogEntry;

// Create log handler
V101Log log = new V101Log();

// Enable logging
devTools.send(log.enable());

// Listen for new log entries
devTools.addListener(log.entryAdded(), entry -> {
    System.out.println("Browser Log [" + entry.getSource() + "]: " + 
                      entry.getLogEntry().getMessage());
    System.out.println("Level: " + entry.getLogEntry().getLevel());
    System.out.println("Timestamp: " + new Date(entry.getLogEntry().getMillis()));
});

// Clear existing logs
devTools.send(log.clear());

// Navigate to generate logs
driver.get("https://example.com");

// Perform actions that generate browser logs
driver.executeScript("console.error('This will appear in browser logs');");

// Network requests will also generate logs
driver.findElement(By.tagName("body")).click();

LogEntry

Represents a browser log entry with source information and standard Java logging details.

/**
 * Represents a browser log entry with source and standard logging information
 * Wraps the browser log data in familiar Java logging structures
 */
public class LogEntry {
    
    /**
     * Get the source of the log entry (console, network, security, etc.)
     * @return String indicating the log source
     */
    public String getSource();
    
    /**
     * Get the standard Java log entry with level, timestamp, and message
     * @return java.util.logging.LogEntry with formatted log data
     */
    public java.util.logging.LogEntry getLogEntry();
}

Log Sources:

  • "console" - Browser console messages
  • "network" - Network-related log messages
  • "security" - Security-related warnings and errors
  • "deprecation" - Deprecation warnings
  • "worker" - Web worker log messages
  • "violation" - Performance and security violations
  • "intervention" - Browser interventions (blocking actions)
  • "recommendation" - Browser recommendations

Usage Example:

devTools.addListener(log.entryAdded(), entry -> {
    java.util.logging.LogEntry logEntry = entry.getLogEntry();
    
    // Process logs based on source
    switch (entry.getSource()) {
        case "console":
            handleConsoleLog(logEntry);
            break;
        case "network":
            handleNetworkLog(logEntry);
            break;
        case "security":
            handleSecurityLog(logEntry);
            break;
        case "deprecation":
            handleDeprecationWarning(logEntry);
            break;
        default:
            handleGenericLog(entry.getSource(), logEntry);
    }
});

private void handleSecurityLog(java.util.logging.LogEntry logEntry) {
    if (logEntry.getLevel().intValue() >= Level.SEVERE.intValue()) {
        System.err.println("🔒 SECURITY ISSUE: " + logEntry.getMessage());
        // Could trigger security test failure
    }
}

private void handleNetworkLog(java.util.logging.LogEntry logEntry) {
    if (logEntry.getMessage().contains("failed")) {
        System.err.println("🌐 NETWORK ERROR: " + logEntry.getMessage());
    }
}

Java Logging Integration

The log entries use standard Java logging levels and can be integrated with existing logging frameworks.

/**
 * Standard Java logging levels used by browser log entries
 */
public enum Level {
    FINEST,   // Verbose browser logs
    FINE,     // Debug-level browser logs
    INFO,     // Informational browser logs  
    WARNING,  // Browser warnings
    SEVERE    // Browser errors
}

/**
 * Standard Java LogEntry with browser log data
 */
public class java.util.logging.LogEntry {
    public Level getLevel();
    public long getMillis();
    public String getMessage();
    public String getLoggerName();
    public String getSourceClassName();
    public String getSourceMethodName();
}

Integration with Logging Frameworks:

import java.util.logging.Logger;
import java.util.logging.Handler;
import java.util.logging.LogRecord;

// Create a custom handler for browser logs
Logger browserLogger = Logger.getLogger("browser-logs");

devTools.addListener(log.entryAdded(), entry -> {
    java.util.logging.LogEntry browserLog = entry.getLogEntry();
    
    // Create a LogRecord for standard Java logging
    LogRecord record = new LogRecord(browserLog.getLevel(), browserLog.getMessage());
    record.setMillis(browserLog.getMillis());
    record.setLoggerName("browser." + entry.getSource());
    record.setSourceClassName("Browser");
    record.setSourceMethodName(entry.getSource());
    
    // Publish to standard logging system
    browserLogger.log(record);
});

// Or integrate with SLF4J
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Logger slf4jLogger = LoggerFactory.getLogger("browser-logs");

devTools.addListener(log.entryAdded(), entry -> {
    java.util.logging.LogEntry browserLog = entry.getLogEntry();
    String message = "[" + entry.getSource() + "] " + browserLog.getMessage();
    
    switch (browserLog.getLevel().intValue()) {
        case 1000: // SEVERE
            slf4jLogger.error(message);
            break;
        case 900:  // WARNING
            slf4jLogger.warn(message);
            break;
        case 800:  // INFO
            slf4jLogger.info(message);
            break;
        default:   // FINE, FINER, FINEST
            slf4jLogger.debug(message);
    }
});

CDP Protocol Types

The underlying CDP Log domain types used by V101Log:

/**
 * CDP Log.LogEntry event data
 * Raw log entry data from the Chrome DevTools Protocol
 */
public class org.openqa.selenium.devtools.v101.log.model.LogEntry {
    public String getSource();
    public Level getLevel();
    public String getText();
    public Timestamp getTimestamp();
    public Optional<String> getUrl();
    public Optional<Integer> getLineNumber();
    public Optional<StackTrace> getStackTrace();
    public Optional<Integer> getNetworkRequestId();
    public Optional<String> getWorkerId();
    public Optional<List<String>> getArgs();
}

/**
 * CDP log level enumeration
 */
public enum Level {
    VERBOSE("verbose"),
    INFO("info"), 
    WARNING("warning"),
    ERROR("error");
    
    public String toString();
}

/**
 * CDP timestamp representation
 */
public class Timestamp {
    public JsonElement toJson();
    public String toString();
}

Log Domain Commands

The V101Log class internally uses these CDP Log domain commands:

// From org.openqa.selenium.devtools.v101.log.Log
public static Command<Void> enable();
public static Command<Void> disable();
public static Command<Void> clear();
public static Event<LogEntry> entryAdded();

Advanced Usage Patterns

Log Filtering and Categorization

// Sophisticated log processing with filtering and categorization
public class BrowserLogAnalyzer {
    private final Map<String, List<LogEntry>> logsBySource = new ConcurrentHashMap<>();
    private final Map<Level, AtomicInteger> logCounts = new ConcurrentHashMap<>();
    
    public void setupLogMonitoring(DevTools devTools, V101Log log) {
        devTools.send(log.enable());
        
        devTools.addListener(log.entryAdded(), this::processLogEntry);
    }
    
    private void processLogEntry(LogEntry entry) {
        String source = entry.getSource();
        java.util.logging.LogEntry logEntry = entry.getLogEntry();
        Level level = logEntry.getLevel();
        
        // Categorize by source
        logsBySource.computeIfAbsent(source, k -> new ArrayList<>()).add(entry);
        
        // Count by level
        logCounts.computeIfAbsent(level, k -> new AtomicInteger(0)).incrementAndGet();
        
        // Filter and process specific log types
        if ("security".equals(source) && level.intValue() >= Level.WARNING.intValue()) {
            handleSecurityIssue(entry);
        }
        
        if ("network".equals(source) && logEntry.getMessage().contains("blocked")) {
            handleBlockedRequest(entry);
        }
        
        if ("deprecation".equals(source)) {
            handleDeprecationWarning(entry);
        }
    }
    
    public void printLogSummary() {
        System.out.println("=== Browser Log Summary ===");
        logCounts.forEach((level, count) -> {
            System.out.println(level + ": " + count.get() + " entries");
        });
        
        System.out.println("\n=== Logs by Source ===");
        logsBySource.forEach((source, logs) -> {
            System.out.println(source + ": " + logs.size() + " entries");
        });
    }
    
    private void handleSecurityIssue(LogEntry entry) {
        System.err.println("🔒 SECURITY: " + entry.getLogEntry().getMessage());
        // Could fail tests or trigger alerts
    }
    
    private void handleBlockedRequest(LogEntry entry) {
        System.out.println("🚫 BLOCKED: " + entry.getLogEntry().getMessage());
        // Could indicate CSP or CORS issues
    }
    
    private void handleDeprecationWarning(LogEntry entry) {
        System.out.println("⚠️  DEPRECATED: " + entry.getLogEntry().getMessage());
        // Could track deprecated API usage
    }
}

Performance Monitoring Through Logs

// Monitor browser performance through log analysis
public class PerformanceLogMonitor {
    private final List<String> performanceIssues = new ArrayList<>();
    
    public void setupPerformanceMonitoring(DevTools devTools, V101Log log) {
        devTools.send(log.enable());
        
        devTools.addListener(log.entryAdded(), entry -> {
            String message = entry.getLogEntry().getMessage().toLowerCase();
            
            // Detect performance-related log entries
            if (message.contains("slow") || 
                message.contains("timeout") ||
                message.contains("performance") ||
                message.contains("long task")) {
                
                performanceIssues.add(entry.getLogEntry().getMessage());
                
                System.out.println("⚡ PERFORMANCE ISSUE: " + entry.getLogEntry().getMessage());
            }
            
            // Detect memory-related issues
            if (message.contains("memory") || message.contains("heap")) {
                System.out.println("💾 MEMORY ISSUE: " + entry.getLogEntry().getMessage());
            }
            
            // Detect layout thrashing
            if (message.contains("layout") || message.contains("reflow")) {
                System.out.println("📐 LAYOUT ISSUE: " + entry.getLogEntry().getMessage());
            }
        });
    }
    
    public List<String> getPerformanceIssues() {
        return new ArrayList<>(performanceIssues);
    }
    
    public void clearPerformanceIssues() {
        performanceIssues.clear();
    }
}

Log Persistence and Analysis

// Persist logs for analysis and reporting
public class LogPersistence {
    private final PrintWriter logWriter;
    private final String testName;
    
    public LogPersistence(String testName) throws IOException {
        this.testName = testName;
        this.logWriter = new PrintWriter(new FileWriter(testName + "-browser-logs.txt"));
    }
    
    public void setupLogPersistence(DevTools devTools, V101Log log) {
        devTools.send(log.enable());
        
        devTools.addListener(log.entryAdded(), entry -> {
            java.util.logging.LogEntry logEntry = entry.getLogEntry();
            
            // Write structured log data
            logWriter.printf("[%s] %s %s: %s%n",
                new Date(logEntry.getMillis()).toString(),
                entry.getSource().toUpperCase(),
                logEntry.getLevel(),
                logEntry.getMessage()
            );
            logWriter.flush();
        });
    }
    
    public void close() {
        if (logWriter != null) {
            logWriter.close();
        }
    }
    
    // Generate summary report
    public void generateReport() throws IOException {
        try (PrintWriter reportWriter = new PrintWriter(new FileWriter(testName + "-log-summary.txt"))) {
            reportWriter.println("Browser Log Summary for: " + testName);
            reportWriter.println("Generated: " + new Date());
            
            // Could include statistics, error counts, performance metrics
            reportWriter.println("Log analysis would go here...");
        }
    }
}

// Usage in test
LogPersistence logPersistence = new LogPersistence("test-checkout-flow");
try {
    logPersistence.setupLogPersistence(devTools, log);
    
    // Run test...
    
} finally {
    logPersistence.generateReport();
    logPersistence.close();
}

Install with Tessl CLI

npx tessl i tessl/maven-org-seleniumhq-selenium--selenium-devtools-v101

docs

entry-point.md

events.md

index.md

javascript.md

logging.md

network.md

target.md

tile.json