or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

entry-point.mdevents.mdindex.mdjavascript.mdlogging.mdnetwork.mdtarget.md

logging.mddocs/

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

```